You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

239 lines
8.4 KiB

from base64 import b64encode
from couchpotato.core.helpers.variable import tryInt, tryFloat
from couchpotato.core.downloaders.base import Downloader, StatusList
from couchpotato.core.helpers.encoding import isInt
from couchpotato.core.logger import CPLog
from couchpotato.environment import Env
from datetime import timedelta
from synchronousdeluge import DelugeClient
import os.path
import traceback
log = CPLog(__name__)
class Deluge(Downloader):
protocol = ['torrent', 'torrent_magnet']
log = CPLog(__name__)
drpc = None
def connect(self):
# Load host from config and split out port.
host = self.conf('host').split(':')
if not isInt(host[1]):
log.error('Config properties are not filled in correctly, port is missing.')
return False
if not self.drpc:
self.drpc = DelugeRPC(host[0], port = host[1], username = self.conf('username'), password = self.conf('password'))
return self.drpc
def download(self, data, movie, filedata = None):
log.info('Sending "%s" (%s) to Deluge.', (data.get('name'), data.get('protocol')))
if not self.connect():
return False
if not filedata and data.get('protocol') == 'torrent':
log.error('Failed sending torrent, no data')
return False
# Set parameters for Deluge
options = {
'add_paused': self.conf('paused', default = 0),
'label': self.conf('label')
}
if self.conf('directory'):
if os.path.isdir(self.conf('directory')):
options['download_location'] = self.conf('directory')
else:
log.error('Download directory from Deluge settings: %s doesn\'t exist', self.conf('directory'))
if self.conf('completed_directory'):
if os.path.isdir(self.conf('completed_directory')):
options['move_completed'] = 1
options['move_completed_path'] = self.conf('completed_directory')
else:
log.error('Download directory from Deluge settings: %s doesn\'t exist', self.conf('directory'))
if data.get('seed_ratio'):
options['stop_at_ratio'] = 1
options['stop_ratio'] = tryFloat(data.get('seed_ratio'))
# Deluge only has seed time as a global option. Might be added in
# in a future API release.
# if data.get('seed_time'):
# Send request to Deluge
if data.get('protocol') == 'torrent_magnet':
remote_torrent = self.drpc.add_torrent_magnet(data.get('url'), options)
else:
remote_torrent = self.drpc.add_torrent_file(movie, b64encode(filedata), options)
if not remote_torrent:
log.error('Failed sending torrent to Deluge')
return False
log.info('Torrent sent to Deluge successfully.')
return self.downloadReturnId(remote_torrent)
def getAllDownloadStatus(self):
log.debug('Checking Deluge download status.')
if not self.connect():
return False
statuses = StatusList(self)
queue = self.drpc.get_alltorrents()
if not (queue and queue.get('torrents')):
log.debug('Nothing in queue or error')
return False
for torrent_id in queue:
item = queue[torrent_id]
log.debug('name=%s / id=%s / save_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / conf_ratio=%s/ is_seed=%s / is_finished=%s', (item['name'], item['hash'], item['save_path'], item['hash'], item['progress'], item['state'], item['eta'], item['ratio'], self.conf('ratio'), item['is_seed'], item['is_finished']))
if not os.path.isdir(Env.setting('from', 'renamer')):
log.error('Renamer "from" folder doesn\'t to exist.')
return
status = 'busy'
# Deluge seems to set both is_seed and is_finished once everything has been downloaded.
if item['is_seed'] or item['is_finished']:
status = 'seeding'
elif item['is_seed'] and item['is_finished'] and item['paused']:
status = 'completed'
download_dir = item['save_path']
if item['move_on_completed']:
download_dir = item['move_completed_path']
statuses.append({
'id': item['hash'],
'name': item['name'],
'status': status,
'original_status': item['state'],
'seed_ratio': item['ratio'],
'timeleft': str(timedelta(seconds = item['eta'])),
'folder': os.path.join(download_dir, item['name']),
})
return statuses
def pause(self, item, pause = True):
if pause:
return self.drpc.pause_torrent([item['id']])
else:
return self.drpc.resume_torrent([item['id']])
def removeFailed(self, item):
log.info('%s failed downloading, deleting...', item['name'])
return self.drpc.remove_torrent(item['id'], True)
def processComplete(self, item, delete_files = False):
log.debug('Requesting Deluge to remove the torrent %s%s.', (item['name'], ' and cleanup the downloaded files' if delete_files else ''))
return self.drpc.remove_torrent(item['id'], remove_local_data = delete_files)
class DelugeRPC(object):
host = 'localhost'
port = 58846
username = None
password = None
client = None
def __init__(self, host = 'localhost', port = 58846, username = None, password = None):
super(DelugeRPC, self).__init__()
self.host = host
self.port = port
self.username = username
self.password = password
def connect(self):
self.client = DelugeClient()
self.client.connect(self.host, int(self.port), self.username, self.password)
def add_torrent_magnet(self, torrent, options):
torrent_id = False
try:
self.connect()
torrent_id = self.client.core.add_torrent_magnet(torrent, options).get()
if options['label']:
self.client.label.set_torrent(torrent_id, options['label']).get()
except Exception, err:
log.error('Failed to add torrent magnet: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
return torrent_id
def add_torrent_file(self, movie, torrent, options):
torrent_id = False
try:
self.connect()
torrent_id = self.client.core.add_torrent_file(movie, torrent, options).get()
if options['label']:
self.client.label.set_torrent(torrent_id, options['label']).get()
except Exception, err:
log.error('Failed to add torrent file: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
return torrent_id
def get_alltorrents(self):
ret = False
try:
self.connect()
ret = self.client.core.get_torrents_status({}, {}).get()
except Exception, err:
log.error('Failed to get all torrents: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
return ret
def pause_torrent(self, torrent_ids):
try:
self.connect()
self.client.core.pause_torrent(torrent_ids).get()
except Exception, err:
log.error('Failed to pause torrent: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
def resume_torrent(self, torrent_ids):
try:
self.connect()
self.client.core.resume_torrent(torrent_ids).get()
except Exception, err:
log.error('Failed to resume torrent: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
def remove_torrent(self, torrent_id, remove_local_data):
ret = False
try:
self.connect()
ret = self.client.core.remove_torrent(torrent_id, remove_local_data).get()
except Exception, err:
log.error('Failed to remove torrent: %s %s', err, traceback.format_exc())
finally:
if self.client:
self.disconnect()
return ret
def disconnect(self):
self.client.disconnect()