diff --git a/couchpotato/core/downloaders/base.py b/couchpotato/core/downloaders/base.py index b99aacc..b6894ed 100644 --- a/couchpotato/core/downloaders/base.py +++ b/couchpotato/core/downloaders/base.py @@ -57,13 +57,18 @@ class Downloader(Provider): return return self.download(data = data, media = media, filedata = filedata) - def _getAllDownloadStatus(self): + def _getAllDownloadStatus(self, download_ids): if self.isDisabled(manual = True, data = {}): return - return self.getAllDownloadStatus() + ids = [download_id['id'] for download_id in download_ids if download_id['downloader'] == self.getName()] - def getAllDownloadStatus(self): + if ids: + return self.getAllDownloadStatus(ids) + else: + return + + def getAllDownloadStatus(self, ids): return def _removeFailed(self, release_download): diff --git a/couchpotato/core/downloaders/deluge/main.py b/couchpotato/core/downloaders/deluge/main.py index 454a501..57c1958 100644 --- a/couchpotato/core/downloaders/deluge/main.py +++ b/couchpotato/core/downloaders/deluge/main.py @@ -86,7 +86,7 @@ class Deluge(Downloader): log.info('Torrent sent to Deluge successfully.') return self.downloadReturnId(remote_torrent) - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking Deluge download status.') @@ -103,38 +103,39 @@ class Deluge(Downloader): for torrent_id in queue: torrent = queue[torrent_id] - log.debug('name=%s / id=%s / save_path=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused'])) - - # Deluge has no easy way to work out if a torrent is stalled or failing. - #status = 'failed' - status = 'busy' - if torrent['is_seed'] and tryFloat(torrent['ratio']) < tryFloat(torrent['stop_ratio']): - # We have torrent['seeding_time'] to work out what the seeding time is, but we do not - # have access to the downloader seed_time, as with deluge we have no way to pass it - # when the torrent is added. So Deluge will only look at the ratio. - # See above comment in download(). - status = 'seeding' - elif torrent['is_seed'] and torrent['is_finished'] and torrent['paused'] and torrent['state'] == 'Paused': - status = 'completed' - - download_dir = sp(torrent['save_path']) - if torrent['move_on_completed']: - download_dir = torrent['move_completed_path'] - - torrent_files = [] - for file_item in torrent['files']: - torrent_files.append(sp(os.path.join(download_dir, file_item['path']))) - - release_downloads.append({ - 'id': torrent['hash'], - 'name': torrent['name'], - 'status': status, - 'original_status': torrent['state'], - 'seed_ratio': torrent['ratio'], - 'timeleft': str(timedelta(seconds = torrent['eta'])), - 'folder': sp(download_dir if len(torrent_files) == 1 else os.path.join(download_dir, torrent['name'])), - 'files': '|'.join(torrent_files), - }) + if torrent['hash'] in ids: + log.debug('name=%s / id=%s / save_path=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused'])) + + # Deluge has no easy way to work out if a torrent is stalled or failing. + #status = 'failed' + status = 'busy' + if torrent['is_seed'] and tryFloat(torrent['ratio']) < tryFloat(torrent['stop_ratio']): + # We have torrent['seeding_time'] to work out what the seeding time is, but we do not + # have access to the downloader seed_time, as with deluge we have no way to pass it + # when the torrent is added. So Deluge will only look at the ratio. + # See above comment in download(). + status = 'seeding' + elif torrent['is_seed'] and torrent['is_finished'] and torrent['paused'] and torrent['state'] == 'Paused': + status = 'completed' + + download_dir = sp(torrent['save_path']) + if torrent['move_on_completed']: + download_dir = torrent['move_completed_path'] + + torrent_files = [] + for file_item in torrent['files']: + torrent_files.append(sp(os.path.join(download_dir, file_item['path']))) + + release_downloads.append({ + 'id': torrent['hash'], + 'name': torrent['name'], + 'status': status, + 'original_status': torrent['state'], + 'seed_ratio': torrent['ratio'], + 'timeleft': str(timedelta(seconds = torrent['eta'])), + 'folder': sp(download_dir if len(torrent_files) == 1 else os.path.join(download_dir, torrent['name'])), + 'files': '|'.join(torrent_files), + }) return release_downloads diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index 1cc2648..482da2c 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -67,7 +67,7 @@ class NZBGet(Downloader): log.error('NZBGet could not add %s to the queue.', nzb_name) return False - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking NZBGet download status.') @@ -102,51 +102,54 @@ class NZBGet(Downloader): release_downloads = ReleaseDownloadList(self) for nzb in groups: - log.debug('Found %s in NZBGet download queue', nzb['NZBFilename']) try: nzb_id = [param['Value'] for param in nzb['Parameters'] if param['Name'] == 'couchpotato'][0] except: nzb_id = nzb['NZBID'] - - timeleft = -1 - try: - if nzb['ActiveDownloads'] > 0 and nzb['DownloadRate'] > 0 and not (status['DownloadPaused'] or status['Download2Paused']): - timeleft = str(timedelta(seconds = nzb['RemainingSizeMB'] / status['DownloadRate'] * 2 ^ 20)) - except: - pass - - release_downloads.append({ - 'id': nzb_id, - 'name': nzb['NZBFilename'], - 'original_status': 'DOWNLOADING' if nzb['ActiveDownloads'] > 0 else 'QUEUED', - # Seems to have no native API function for time left. This will return the time left after NZBGet started downloading this item - 'timeleft': timeleft, - }) + if nzb_id in ids: + log.debug('Found %s in NZBGet download queue', nzb['NZBFilename']) + timeleft = -1 + try: + if nzb['ActiveDownloads'] > 0 and nzb['DownloadRate'] > 0 and not (status['DownloadPaused'] or status['Download2Paused']): + timeleft = str(timedelta(seconds = nzb['RemainingSizeMB'] / status['DownloadRate'] * 2 ^ 20)) + except: + pass + + release_downloads.append({ + 'id': nzb_id, + 'name': nzb['NZBFilename'], + 'original_status': 'DOWNLOADING' if nzb['ActiveDownloads'] > 0 else 'QUEUED', + # Seems to have no native API function for time left. This will return the time left after NZBGet started downloading this item + 'timeleft': timeleft, + }) for nzb in queue: # 'Parameters' is not passed in rpc.postqueue - log.debug('Found %s in NZBGet postprocessing queue', nzb['NZBFilename']) - release_downloads.append({ - 'id': nzb['NZBID'], - 'name': nzb['NZBFilename'], - 'original_status': nzb['Stage'], - 'timeleft': str(timedelta(seconds = 0)) if not status['PostPaused'] else -1, - }) + if nzb['NZBID'] in ids: + log.debug('Found %s in NZBGet postprocessing queue', nzb['NZBFilename']) + release_downloads.append({ + 'id': nzb['NZBID'], + 'name': nzb['NZBFilename'], + 'original_status': nzb['Stage'], + 'timeleft': str(timedelta(seconds = 0)) if not status['PostPaused'] else -1, + }) for nzb in history: - log.debug('Found %s in NZBGet history. ParStatus: %s, ScriptStatus: %s, Log: %s', (nzb['NZBFilename'] , nzb['ParStatus'], nzb['ScriptStatus'] , nzb['Log'])) try: nzb_id = [param['Value'] for param in nzb['Parameters'] if param['Name'] == 'couchpotato'][0] except: nzb_id = nzb['NZBID'] - release_downloads.append({ - 'id': nzb_id, - 'name': nzb['NZBFilename'], - 'status': 'completed' if nzb['ParStatus'] in ['SUCCESS', 'NONE'] and nzb['ScriptStatus'] in ['SUCCESS', 'NONE'] else 'failed', - 'original_status': nzb['ParStatus'] + ', ' + nzb['ScriptStatus'], - 'timeleft': str(timedelta(seconds = 0)), - 'folder': sp(nzb['DestDir']) - }) + + if nzb_id in ids: + log.debug('Found %s in NZBGet history. ParStatus: %s, ScriptStatus: %s, Log: %s', (nzb['NZBFilename'] , nzb['ParStatus'], nzb['ScriptStatus'] , nzb['Log'])) + release_downloads.append({ + 'id': nzb_id, + 'name': nzb['NZBFilename'], + 'status': 'completed' if nzb['ParStatus'] in ['SUCCESS', 'NONE'] and nzb['ScriptStatus'] in ['SUCCESS', 'NONE'] else 'failed', + 'original_status': nzb['ParStatus'] + ', ' + nzb['ScriptStatus'], + 'timeleft': str(timedelta(seconds = 0)), + 'folder': sp(nzb['DestDir']) + }) return release_downloads diff --git a/couchpotato/core/downloaders/nzbvortex/main.py b/couchpotato/core/downloaders/nzbvortex/main.py index 9e16048..bcf8cae 100644 --- a/couchpotato/core/downloaders/nzbvortex/main.py +++ b/couchpotato/core/downloaders/nzbvortex/main.py @@ -8,9 +8,11 @@ from uuid import uuid4 import hashlib import httplib import json +import os import socket import ssl import sys +import time import traceback import urllib2 @@ -32,35 +34,37 @@ class NZBVortex(Downloader): nzb_filename = self.createFileName(data, filedata, media) self.call('nzb/add', params = {'file': (nzb_filename, filedata)}, multipart = True) + time.sleep(10) raw_statuses = self.call('nzb') - nzb_id = [nzb['id'] for nzb in raw_statuses.get('nzbs', []) if nzb['name'] == nzb_filename][0] + nzb_id = [nzb['id'] for nzb in raw_statuses.get('nzbs', []) if os.path.basename(item['nzbFileName']) == nzb_filename][0] return self.downloadReturnId(nzb_id) except: log.error('Something went wrong sending the NZB file: %s', traceback.format_exc()) return False - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): raw_statuses = self.call('nzb') release_downloads = ReleaseDownloadList(self) for nzb in raw_statuses.get('nzbs', []): - - # Check status - status = 'busy' - if nzb['state'] == 20: - status = 'completed' - elif nzb['state'] in [21, 22, 24]: - status = 'failed' - - release_downloads.append({ - 'id': nzb['id'], - 'name': nzb['uiTitle'], - 'status': status, - 'original_status': nzb['state'], - 'timeleft':-1, - 'folder': sp(nzb['destinationPath']), - }) + if nzb['id'] in ids: + + # Check status + status = 'busy' + if nzb['state'] == 20: + status = 'completed' + elif nzb['state'] in [21, 22, 24]: + status = 'failed' + + release_downloads.append({ + 'id': nzb['id'], + 'name': nzb['uiTitle'], + 'status': status, + 'original_status': nzb['state'], + 'timeleft':-1, + 'folder': sp(nzb['destinationPath']), + }) return release_downloads diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 0281c49..2cbfd90 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -143,7 +143,7 @@ class rTorrent(Downloader): log.error('Failed to send torrent to rTorrent: %s', err) return False - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking rTorrent download status.') if not self.connect(): @@ -155,27 +155,28 @@ class rTorrent(Downloader): release_downloads = ReleaseDownloadList(self) for torrent in torrents: - torrent_files = [] - for file_item in torrent.get_files(): - torrent_files.append(sp(os.path.join(torrent.directory, file_item.path))) - - status = 'busy' - if torrent.complete: - if torrent.active: - status = 'seeding' - else: - status = 'completed' - - release_downloads.append({ - 'id': torrent.info_hash, - 'name': torrent.name, - 'status': status, - 'seed_ratio': torrent.ratio, - 'original_status': torrent.state, - 'timeleft': str(timedelta(seconds = float(torrent.left_bytes) / torrent.down_rate)) if torrent.down_rate > 0 else -1, - 'folder': sp(torrent.directory), - 'files': '|'.join(torrent_files) - }) + if torrent.info_hash in ids: + torrent_files = [] + for file_item in torrent.get_files(): + torrent_files.append(sp(os.path.join(torrent.directory, file_item.path))) + + status = 'busy' + if torrent.complete: + if torrent.active: + status = 'seeding' + else: + status = 'completed' + + release_downloads.append({ + 'id': torrent.info_hash, + 'name': torrent.name, + 'status': status, + 'seed_ratio': torrent.ratio, + 'original_status': torrent.state, + 'timeleft': str(timedelta(seconds = float(torrent.left_bytes) / torrent.down_rate)) if torrent.down_rate > 0 else -1, + 'folder': sp(torrent.directory), + 'files': '|'.join(torrent_files) + }) return release_downloads diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py index d934e6c..808ceab 100644 --- a/couchpotato/core/downloaders/sabnzbd/main.py +++ b/couchpotato/core/downloaders/sabnzbd/main.py @@ -64,7 +64,7 @@ class Sabnzbd(Downloader): log.error('Error getting data from SABNZBd: %s', sab_data) return False - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking SABnzbd download status.') @@ -91,35 +91,36 @@ class Sabnzbd(Downloader): # Get busy releases for nzb in queue.get('slots', []): - status = 'busy' - if 'ENCRYPTED / ' in nzb['filename']: - status = 'failed' - - release_downloads.append({ - 'id': nzb['nzo_id'], - 'name': nzb['filename'], - 'status': status, - 'original_status': nzb['status'], - 'timeleft': nzb['timeleft'] if not queue['paused'] else -1, - }) + if nzb['nzo_id'] in ids: + status = 'busy' + if 'ENCRYPTED / ' in nzb['filename']: + status = 'failed' + + release_downloads.append({ + 'id': nzb['nzo_id'], + 'name': nzb['filename'], + 'status': status, + 'original_status': nzb['status'], + 'timeleft': nzb['timeleft'] if not queue['paused'] else -1, + }) # Get old releases for nzb in history.get('slots', []): - - status = 'busy' - if nzb['status'] == 'Failed' or (nzb['status'] == 'Completed' and nzb['fail_message'].strip()): - status = 'failed' - elif nzb['status'] == 'Completed': - status = 'completed' - - release_downloads.append({ - 'id': nzb['nzo_id'], - 'name': nzb['name'], - 'status': status, - 'original_status': nzb['status'], - 'timeleft': str(timedelta(seconds = 0)), - 'folder': sp(os.path.dirname(nzb['storage']) if os.path.isfile(nzb['storage']) else nzb['storage']), - }) + if nzb['nzo_id'] in ids: + status = 'busy' + if nzb['status'] == 'Failed' or (nzb['status'] == 'Completed' and nzb['fail_message'].strip()): + status = 'failed' + elif nzb['status'] == 'Completed': + status = 'completed' + + release_downloads.append({ + 'id': nzb['nzo_id'], + 'name': nzb['name'], + 'status': status, + 'original_status': nzb['status'], + 'timeleft': str(timedelta(seconds = 0)), + 'folder': sp(os.path.dirname(nzb['storage']) if os.path.isfile(nzb['storage']) else nzb['storage']), + }) return release_downloads diff --git a/couchpotato/core/downloaders/transmission/main.py b/couchpotato/core/downloaders/transmission/main.py index c5a55d4..46b5f3b 100644 --- a/couchpotato/core/downloaders/transmission/main.py +++ b/couchpotato/core/downloaders/transmission/main.py @@ -83,7 +83,7 @@ class Transmission(Downloader): log.info('Torrent sent to Transmission successfully.') return self.downloadReturnId(remote_torrent['torrent-added']['hashString']) - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking Transmission download status.') @@ -102,31 +102,32 @@ class Transmission(Downloader): return False for torrent in queue['torrents']: - log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / eta=%s / uploadRatio=%s / isFinished=%s', - (torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent['eta'], torrent['uploadRatio'], torrent['isFinished'])) - - torrent_files = [] - for file_item in torrent['files']: - torrent_files.append(sp(os.path.join(torrent['downloadDir'], file_item['name']))) - - status = 'busy' - if torrent.get('isStalled') and self.conf('stalled_as_failed'): - status = 'failed' - elif torrent['status'] == 0 and torrent['percentDone'] == 1: - status = 'completed' - elif torrent['status'] in [5, 6]: - status = 'seeding' - - release_downloads.append({ - 'id': torrent['hashString'], - 'name': torrent['name'], - 'status': status, - 'original_status': torrent['status'], - 'seed_ratio': torrent['uploadRatio'], - 'timeleft': str(timedelta(seconds = torrent['eta'])), - 'folder': sp(torrent['downloadDir'] if len(torrent_files) == 1 else os.path.join(torrent['downloadDir'], torrent['name'])), - 'files': '|'.join(torrent_files) - }) + if torrent['hashString'] in ids: + log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / eta=%s / uploadRatio=%s / isFinished=%s', + (torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent['eta'], torrent['uploadRatio'], torrent['isFinished'])) + + torrent_files = [] + for file_item in torrent['files']: + torrent_files.append(sp(os.path.join(torrent['downloadDir'], file_item['name']))) + + status = 'busy' + if torrent.get('isStalled') and self.conf('stalled_as_failed'): + status = 'failed' + elif torrent['status'] == 0 and torrent['percentDone'] == 1: + status = 'completed' + elif torrent['status'] in [5, 6]: + status = 'seeding' + + release_downloads.append({ + 'id': torrent['hashString'], + 'name': torrent['name'], + 'status': status, + 'original_status': torrent['status'], + 'seed_ratio': torrent['uploadRatio'], + 'timeleft': str(timedelta(seconds = torrent['eta'])), + 'folder': sp(torrent['downloadDir'] if len(torrent_files) == 1 else os.path.join(torrent['downloadDir'], torrent['name'])), + 'files': '|'.join(torrent_files) + }) return release_downloads diff --git a/couchpotato/core/downloaders/utorrent/main.py b/couchpotato/core/downloaders/utorrent/main.py index 18b607f..056cd15 100644 --- a/couchpotato/core/downloaders/utorrent/main.py +++ b/couchpotato/core/downloaders/utorrent/main.py @@ -105,7 +105,7 @@ class uTorrent(Downloader): return self.downloadReturnId(torrent_hash) - def getAllDownloadStatus(self): + def getAllDownloadStatus(self, ids): log.debug('Checking uTorrent download status.') @@ -130,47 +130,48 @@ class uTorrent(Downloader): # Get torrents for torrent in queue['torrents']: - - #Get files of the torrent - torrent_files = [] - try: - torrent_files = json.loads(self.utorrent_api.get_files(torrent[0])) - torrent_files = [sp(os.path.join(torrent[26], torrent_file[0])) for torrent_file in torrent_files['files'][1]] - except: - log.debug('Failed getting files from torrent: %s', torrent[2]) - - status_flags = { - "STARTED" : 1, - "CHECKING" : 2, - "CHECK-START" : 4, - "CHECKED" : 8, - "ERROR" : 16, - "PAUSED" : 32, - "QUEUED" : 64, - "LOADED" : 128 - } - - status = 'busy' - if (torrent[1] & status_flags["STARTED"] or torrent[1] & status_flags["QUEUED"]) and torrent[4] == 1000: - status = 'seeding' - elif (torrent[1] & status_flags["ERROR"]): - status = 'failed' - elif torrent[4] == 1000: - status = 'completed' - - if not status == 'busy': - self.removeReadOnly(torrent_files) - - release_downloads.append({ - 'id': torrent[0], - 'name': torrent[2], - 'status': status, - 'seed_ratio': float(torrent[7]) / 1000, - 'original_status': torrent[1], - 'timeleft': str(timedelta(seconds = torrent[10])), - 'folder': sp(torrent[26]), - 'files': '|'.join(torrent_files) - }) + if torrent[0] in ids: + + #Get files of the torrent + torrent_files = [] + try: + torrent_files = json.loads(self.utorrent_api.get_files(torrent[0])) + torrent_files = [sp(os.path.join(torrent[26], torrent_file[0])) for torrent_file in torrent_files['files'][1]] + except: + log.debug('Failed getting files from torrent: %s', torrent[2]) + + status_flags = { + "STARTED" : 1, + "CHECKING" : 2, + "CHECK-START" : 4, + "CHECKED" : 8, + "ERROR" : 16, + "PAUSED" : 32, + "QUEUED" : 64, + "LOADED" : 128 + } + + status = 'busy' + if (torrent[1] & status_flags["STARTED"] or torrent[1] & status_flags["QUEUED"]) and torrent[4] == 1000: + status = 'seeding' + elif (torrent[1] & status_flags["ERROR"]): + status = 'failed' + elif torrent[4] == 1000: + status = 'completed' + + if not status == 'busy': + self.removeReadOnly(torrent_files) + + release_downloads.append({ + 'id': torrent[0], + 'name': torrent[2], + 'status': status, + 'seed_ratio': float(torrent[7]) / 1000, + 'original_status': torrent[1], + 'timeleft': str(timedelta(seconds = torrent[10])), + 'folder': sp(torrent[26]), + 'files': '|'.join(torrent_files) + }) return release_downloads diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 0853929..1a4726b 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -811,9 +811,20 @@ Remove it if you want it to be renamed (again, or at least let it try again) self.checking_snatched = False return True - release_downloads = fireEvent('download.status', merge = True) + # Collect all download information with the download IDs from the releases + download_ids = [] + try: + for rel in rels: + rel_dict = rel.to_dict({'info': {}}) + if rel_dict['info'].get('download_id'): + download_ids.append({'id': rel_dict['info']['download_id'], 'downloader': rel_dict['info']['download_downloader']}) + except: + log.error('Error getting download IDs from database') + return False + + release_downloads = fireEvent('download.status', download_ids, merge = True) if not release_downloads: - log.debug('Download status functionality is not implemented for active downloaders.') + log.debug('Download status functionality is not implemented for any active downloaders.') fireEvent('renamer.scan') self.checking_snatched = False