From c9980539f05cc6e57ec8a0ad2d878f3dfadd8af2 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 24 Nov 2013 15:21:19 +0100 Subject: [PATCH 01/13] Improve black hole support Also scan the 'from' folder if Black hole is used together with another downloader. --- couchpotato/core/downloaders/blackhole/main.py | 4 ++-- couchpotato/core/plugins/release/main.py | 2 +- couchpotato/core/plugins/renamer/main.py | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/downloaders/blackhole/main.py b/couchpotato/core/downloaders/blackhole/main.py index 9374051..5216370 100644 --- a/couchpotato/core/downloaders/blackhole/main.py +++ b/couchpotato/core/downloaders/blackhole/main.py @@ -51,10 +51,10 @@ class Blackhole(Downloader): with open(full_path, 'wb') as f: f.write(filedata) os.chmod(full_path, Env.getPermission('file')) - return True + return self.downloadReturnId('') else: log.info('File %s already exists.', full_path) - return True + return self.downloadReturnId('') except: log.error('Failed to download to blackhole %s', traceback.format_exc()) diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index be85c87..1177980 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -288,7 +288,7 @@ class Release(Plugin): value = toUnicode(download_result.get(key)) ) rls.info.append(rls_info) - db.commit() + db.commit() log_movie = '%s (%s) in %s' % (getTitle(media['library']), media['library']['year'], rls.quality.label) snatch_message = 'Snatched "%s": %s' % (data.get('name'), log_movie) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 119d82b..435ebc1 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -827,6 +827,11 @@ Remove it if you want it to be renamed (again, or at least let it try again) fireEvent('release.update_status', rel.id, status = ignored_status, single = True) continue + if not rel_dict['info'].get('download_id'): + log.debug('Download status functionality is not implemented for downloader (%s) of release %s.', (rel_dict['info'].get('download_downloader', 'unknown'), rel_dict['info']['name'])) + scan_required = True + continue + # check status nzbname = self.createNzbName(rel_dict['info'], movie_dict) From 951b7b84250d6f0dfae273c8a1d092663addddf4 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 24 Nov 2013 19:58:43 +0100 Subject: [PATCH 02/13] Update Synology and Pneumatic As per black hole improvement --- couchpotato/core/downloaders/pneumatic/main.py | 4 ++-- couchpotato/core/downloaders/synology/main.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/downloaders/pneumatic/main.py b/couchpotato/core/downloaders/pneumatic/main.py index 0c2c46d..863cdb0 100644 --- a/couchpotato/core/downloaders/pneumatic/main.py +++ b/couchpotato/core/downloaders/pneumatic/main.py @@ -41,11 +41,11 @@ class Pneumatic(Downloader): strm_file.write(strmContent) strm_file.close() - return True + return self.downloadReturnId('') else: log.info('File %s already exists.', fullPath) - return True + return self.downloadReturnId('') except: log.error('Failed to download .strm: %s', traceback.format_exc()) diff --git a/couchpotato/core/downloaders/synology/main.py b/couchpotato/core/downloaders/synology/main.py index 79b8e87..5d192fc 100644 --- a/couchpotato/core/downloaders/synology/main.py +++ b/couchpotato/core/downloaders/synology/main.py @@ -42,7 +42,7 @@ class Synology(Downloader): except: log.error('Exception while adding torrent: %s', traceback.format_exc()) finally: - return response + return self.downloadReturnId('') if response else False def getEnabledProtocol(self): if self.conf('use_for') == 'both': From 640664494ea0ce707e5ef6e140477fb6ea6c6d66 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 24 Nov 2013 16:49:15 +0100 Subject: [PATCH 03/13] Increase check_snatched readability - Reduce rested if statements - Add more comments --- couchpotato/core/plugins/renamer/main.py | 233 ++++++++++++++++--------------- 1 file changed, 124 insertions(+), 109 deletions(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 435ebc1..cee12ab 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -806,131 +806,147 @@ Remove it if you want it to be renamed (again, or at least let it try again) Release.status_id.in_([snatched_status.get('id'), seeding_status.get('id'), missing_status.get('id')]) ).all() + if not rels: + #No releases found that need status checking + self.checking_snatched = False + return True + + release_downloads = fireEvent('download.status', merge = True) + if not release_downloads: + log.debug('Download status functionality is not implemented for active downloaders.') + fireEvent('renamer.scan') + + self.checking_snatched = False + return True + scan_releases = [] scan_required = False - if rels: - log.debug('Checking status snatched releases...') + log.debug('Checking status snatched releases...') - release_downloads = fireEvent('download.status', merge = True) - if not release_downloads: - log.debug('Download status functionality is not implemented for active downloaders.') - scan_required = True - else: - try: - for rel in rels: - rel_dict = rel.to_dict({'info': {}}) - movie_dict = fireEvent('media.get', media_id = rel.movie_id, single = True) + try: + for rel in rels: + rel_dict = rel.to_dict({'info': {}}) + movie_dict = fireEvent('media.get', media_id = rel.movie_id, single = True) + + if not isinstance(rel_dict['info'], (dict)): + log.error('Faulty release found without any info, ignoring.') + fireEvent('release.update_status', rel.id, status = ignored_status, single = True) + continue - if not isinstance(rel_dict['info'], (dict)): - log.error('Faulty release found without any info, ignoring.') + # Check if download ID is available + if not rel_dict['info'].get('download_id'): + log.debug('Download status functionality is not implemented for downloader (%s) of release %s.', (rel_dict['info'].get('download_downloader', 'unknown'), rel_dict['info']['name'])) + scan_required = True + + # Continue with next release + continue + + # Find release in downloaders + nzbname = self.createNzbName(rel_dict['info'], movie_dict) + + for release_download in release_downloads: + found_release = False + if rel_dict['info'].get('download_id'): + if release_download['id'] == rel_dict['info']['download_id'] and release_download['downloader'] == rel_dict['info']['download_downloader']: + log.debug('Found release by id: %s', release_download['id']) + found_release = True + break + else: + if release_download['name'] == nzbname or rel_dict['info']['name'] in release_download['name'] or getImdb(release_download['name']) == movie_dict['library']['identifier']: + log.debug('Found release by release name or imdb ID: %s', release_download['name']) + found_release = True + break + + if not found_release: + log.info('%s not found in downloaders', nzbname) + + #Check status if already missing and for how long, if > 1 week, set to ignored else to missing + if rel.status_id == missing_status.get('id'): + if rel.last_edit < int(time.time()) - 7 * 24 * 60 * 60: fireEvent('release.update_status', rel.id, status = ignored_status, single = True) - continue - - if not rel_dict['info'].get('download_id'): - log.debug('Download status functionality is not implemented for downloader (%s) of release %s.', (rel_dict['info'].get('download_downloader', 'unknown'), rel_dict['info']['name'])) - scan_required = True - continue - - # check status - nzbname = self.createNzbName(rel_dict['info'], movie_dict) - - found = False - for release_download in release_downloads: - found_release = False - if rel_dict['info'].get('download_id'): - if release_download['id'] == rel_dict['info']['download_id'] and release_download['downloader'] == rel_dict['info']['download_downloader']: - log.debug('Found release by id: %s', release_download['id']) - found_release = True - else: - if release_download['name'] == nzbname or rel_dict['info']['name'] in release_download['name'] or getImdb(release_download['name']) == movie_dict['library']['identifier']: - found_release = True + else: + # Set the release to missing + fireEvent('release.update_status', rel.id, status = missing_status, single = True) - if found_release: - timeleft = 'N/A' if release_download['timeleft'] == -1 else release_download['timeleft'] - log.debug('Found %s: %s, time to go: %s', (release_download['name'], release_download['status'].upper(), timeleft)) + # Continue with next release + continue - if release_download['status'] == 'busy': - # Set the release to snatched if it was missing before - fireEvent('release.update_status', rel.id, status = snatched_status, single = True) + # Log that we found the release + timeleft = 'N/A' if release_download['timeleft'] == -1 else release_download['timeleft'] + log.debug('Found %s: %s, time to go: %s', (release_download['name'], release_download['status'].upper(), timeleft)) - # Tag folder if it is in the 'from' folder and it will not be processed because it is still downloading - if self.movieInFromFolder(release_download['folder']): - self.tagRelease(release_download = release_download, tag = 'downloading') + # Check status of release + if release_download['status'] == 'busy': + # Set the release to snatched if it was missing before + fireEvent('release.update_status', rel.id, status = snatched_status, single = True) - elif release_download['status'] == 'seeding': - #If linking setting is enabled, process release - if self.conf('file_action') != 'move' and not rel.status_id == seeding_status.get('id') and self.statusInfoComplete(release_download): - log.info('Download of %s completed! It is now being processed while leaving the original files alone for seeding. Current ratio: %s.', (release_download['name'], release_download['seed_ratio'])) + # Tag folder if it is in the 'from' folder and it will not be processed because it is still downloading + if self.movieInFromFolder(release_download['folder']): + self.tagRelease(release_download = release_download, tag = 'downloading') - # Remove the downloading tag - self.untagRelease(release_download = release_download, tag = 'downloading') + elif release_download['status'] == 'seeding': + #If linking setting is enabled, process release + if self.conf('file_action') != 'move' and not rel.status_id == seeding_status.get('id') and self.statusInfoComplete(release_download): + log.info('Download of %s completed! It is now being processed while leaving the original files alone for seeding. Current ratio: %s.', (release_download['name'], release_download['seed_ratio'])) - # Scan and set the torrent to paused if required - release_download.update({'pause': True, 'scan': True, 'process_complete': False}) - scan_releases.append(release_download) - else: - #let it seed - log.debug('%s is seeding with ratio: %s', (release_download['name'], release_download['seed_ratio'])) + # Remove the downloading tag + self.untagRelease(release_download = release_download, tag = 'downloading') - # Set the release to seeding - fireEvent('release.update_status', rel.id, status = seeding_status, single = True) - - elif release_download['status'] == 'failed': - # Set the release to failed - fireEvent('release.update_status', rel.id, status = failed_status, single = True) - - fireEvent('download.remove_failed', release_download, single = True) - - if self.conf('next_on_failed'): - fireEvent('movie.searcher.try_next_release', media_id = rel.movie_id) - elif release_download['status'] == 'completed': - log.info('Download of %s completed!', release_download['name']) - if self.statusInfoComplete(release_download): - - # If the release has been seeding, process now the seeding is done - if rel.status_id == seeding_status.get('id'): - if self.conf('file_action') != 'move': - # Set the release to done as the movie has already been renamed - fireEvent('release.update_status', rel.id, status = downloaded_status, single = True) - - # Allow the downloader to clean-up - release_download.update({'pause': False, 'scan': False, 'process_complete': True}) - scan_releases.append(release_download) - else: - # Scan and Allow the downloader to clean-up - release_download.update({'pause': False, 'scan': True, 'process_complete': True}) - scan_releases.append(release_download) - - else: - # Set the release to snatched if it was missing before - fireEvent('release.update_status', rel.id, status = snatched_status, single = True) - - # Remove the downloading tag - self.untagRelease(release_download = release_download, tag = 'downloading') - - # Scan and Allow the downloader to clean-up - release_download.update({'pause': False, 'scan': True, 'process_complete': True}) - scan_releases.append(release_download) - else: - scan_required = True - - found = True - break + # Scan and set the torrent to paused if required + release_download.update({'pause': True, 'scan': True, 'process_complete': False}) + scan_releases.append(release_download) + else: + #let it seed + log.debug('%s is seeding with ratio: %s', (release_download['name'], release_download['seed_ratio'])) + + # Set the release to seeding + fireEvent('release.update_status', rel.id, status = seeding_status, single = True) + + elif release_download['status'] == 'failed': + # Set the release to failed + fireEvent('release.update_status', rel.id, status = failed_status, single = True) + + fireEvent('download.remove_failed', release_download, single = True) + + if self.conf('next_on_failed'): + fireEvent('movie.searcher.try_next_release', media_id = rel.movie_id) + + elif release_download['status'] == 'completed': + log.info('Download of %s completed!', release_download['name']) - if not found: - log.info('%s not found in downloaders', nzbname) + #Make sure the downloader sent over a path to look in + if self.statusInfoComplete(release_download): - #Check status if already missing and for how long, if > 1 week, set to ignored else to missing - if rel.status_id == missing_status.get('id'): - if rel.last_edit < int(time.time()) - 7 * 24 * 60 * 60: - fireEvent('release.update_status', rel.id, status = ignored_status, single = True) + # If the release has been seeding, process now the seeding is done + if rel.status_id == seeding_status.get('id'): + if self.conf('file_action') != 'move': + # Set the release to done as the movie has already been renamed + fireEvent('release.update_status', rel.id, status = downloaded_status, single = True) + + # Allow the downloader to clean-up + release_download.update({'pause': False, 'scan': False, 'process_complete': True}) + scan_releases.append(release_download) else: - # Set the release to missing - fireEvent('release.update_status', rel.id, status = missing_status, single = True) + # Scan and Allow the downloader to clean-up + release_download.update({'pause': False, 'scan': True, 'process_complete': True}) + scan_releases.append(release_download) - except: - log.error('Failed checking for release in downloader: %s', traceback.format_exc()) + else: + # Set the release to snatched if it was missing before + fireEvent('release.update_status', rel.id, status = snatched_status, single = True) + + # Remove the downloading tag + self.untagRelease(release_download = release_download, tag = 'downloading') + + # Scan and Allow the downloader to clean-up + release_download.update({'pause': False, 'scan': True, 'process_complete': True}) + scan_releases.append(release_download) + else: + scan_required = True + + except: + log.error('Failed checking for release in downloader: %s', traceback.format_exc()) # The following can either be done here, or inside the scanner if we pass it scan_items in one go for release_download in scan_releases: @@ -953,7 +969,6 @@ Remove it if you want it to be renamed (again, or at least let it try again) fireEvent('renamer.scan') self.checking_snatched = False - return True def extendReleaseDownload(self, release_download): From 231c5b8ca1b31f017f46993ef777fa181c458eac Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 24 Nov 2013 20:01:31 +0100 Subject: [PATCH 04/13] Renamer rename to media --- couchpotato/core/plugins/renamer/main.py | 90 ++++++++++++++++---------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index cee12ab..0853929 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -30,10 +30,10 @@ class Renamer(Plugin): 'desc': 'For the renamer to check for new files to rename in a folder', 'params': { 'async': {'desc': 'Optional: Set to 1 if you dont want to fire the renamer.scan asynchronous.'}, - 'movie_folder': {'desc': 'Optional: The folder of the movie to scan. Keep empty for default renamer folder.'}, - 'files': {'desc': 'Optional: Provide the release files if more releases are in the same movie_folder, delimited with a \'|\'. Note that no dedicated release folder is expected for releases with one file.'}, + 'media_folder': {'desc': 'Optional: The folder of the media to scan. Keep empty for default renamer folder.'}, + 'files': {'desc': 'Optional: Provide the release files if more releases are in the same media_folder, delimited with a \'|\'. Note that no dedicated release folder is expected for releases with one file.'}, 'downloader' : {'desc': 'Optional: The downloader the release has been downloaded with. \'download_id\' is required with this option.'}, - 'download_id': {'desc': 'Optional: The nzb/torrent ID of the release in movie_folder. \'downloader\' is required with this option.'}, + 'download_id': {'desc': 'Optional: The nzb/torrent ID of the release in media_folder. \'downloader\' is required with this option.'}, 'status': {'desc': 'Optional: The status of the release: \'completed\' (default) or \'seeding\''}, }, }) @@ -64,13 +64,13 @@ class Renamer(Plugin): def scanView(self, **kwargs): async = tryInt(kwargs.get('async', 0)) - movie_folder = sp(kwargs.get('movie_folder')) + media_folder = sp(kwargs.get('media_folder')) downloader = kwargs.get('downloader') download_id = kwargs.get('download_id') files = '|'.join([sp(filename) for filename in splitString(kwargs.get('files'), '|')]) status = kwargs.get('status', 'completed') - release_download = {'folder': movie_folder} if movie_folder else None + release_download = {'folder': media_folder} if media_folder else None if release_download: release_download.update({'id': download_id, 'downloader': downloader, 'status': status, 'files': files} if download_id else {}) @@ -95,8 +95,8 @@ class Renamer(Plugin): from_folder = sp(self.conf('from')) to_folder = sp(self.conf('to')) - # Get movie folder to process - movie_folder = release_download.get('folder') + # Get media folder to process + media_folder = release_download.get('folder') # Get all folders that should not be processed no_process = [to_folder] @@ -115,39 +115,39 @@ class Renamer(Plugin): else: for item in no_process: if '%s%s' % (from_folder, os.path.sep) in item: - log.error('To protect your data, the movie libraries can\'t be inside of or the same as the "from" folder.') + log.error('To protect your data, the media libraries can\'t be inside of or the same as the "from" folder.') return - # Check to see if the no_process folders are inside the provided movie_folder - if movie_folder and not os.path.isdir(movie_folder): - log.debug('The provided movie folder %s does not exist. Trying to find it in the \'from\' folder.', movie_folder) + # Check to see if the no_process folders are inside the provided media_folder + if media_folder and not os.path.isdir(media_folder): + log.debug('The provided media folder %s does not exist. Trying to find it in the \'from\' folder.', media_folder) # Update to the from folder if len(splitString(release_download.get('files'), '|')) == 1: - new_movie_folder = from_folder + new_media_folder = from_folder else: - new_movie_folder = os.path.join(from_folder, os.path.basename(movie_folder)) + new_media_folder = os.path.join(from_folder, os.path.basename(media_folder)) - if not os.path.isdir(new_movie_folder): - log.error('The provided movie folder %s does not exist and could also not be found in the \'from\' folder.', movie_folder) + if not os.path.isdir(new_media_folder): + log.error('The provided media folder %s does not exist and could also not be found in the \'from\' folder.', media_folder) return # Update the files - new_files = [os.path.join(new_movie_folder, os.path.relpath(filename, movie_folder)) for filename in splitString(release_download.get('files'), '|')] + new_files = [os.path.join(new_media_folder, os.path.relpath(filename, media_folder)) for filename in splitString(release_download.get('files'), '|')] if new_files and not os.path.isfile(new_files[0]): - log.error('The provided movie folder %s does not exist and its files could also not be found in the \'from\' folder.', movie_folder) + log.error('The provided media folder %s does not exist and its files could also not be found in the \'from\' folder.', media_folder) return # Update release_download info to the from folder - log.debug('Release %s found in the \'from\' folder.', movie_folder) - release_download['folder'] = new_movie_folder + log.debug('Release %s found in the \'from\' folder.', media_folder) + release_download['folder'] = new_media_folder release_download['files'] = '|'.join(new_files) - movie_folder = new_movie_folder + media_folder = new_media_folder - if movie_folder: + if media_folder: for item in no_process: - if '%s%s' % (movie_folder, os.path.sep) in item: - log.error('To protect your data, the movie libraries can\'t be inside of or the same as the provided movie folder.') + if '%s%s' % (media_folder, os.path.sep) in item: + log.error('To protect your data, the media libraries can\'t be inside of or the same as the provided media folder.') return # Make sure a checkSnatched marked all downloads/seeds as such @@ -156,26 +156,26 @@ class Renamer(Plugin): self.renaming_started = True - # make sure the movie folder name is included in the search + # make sure the media folder name is included in the search folder = None files = [] - if movie_folder: - log.info('Scanning movie folder %s...', movie_folder) - folder = os.path.dirname(movie_folder) + if media_folder: + log.info('Scanning media folder %s...', media_folder) + folder = os.path.dirname(media_folder) if release_download.get('files', ''): files = splitString(release_download['files'], '|') # If there is only one file in the torrent, the downloader did not create a subfolder if len(files) == 1: - folder = movie_folder + folder = media_folder else: # Get all files from the specified folder try: - for root, folders, names in os.walk(movie_folder): + for root, folders, names in os.walk(media_folder): files.extend([sp(os.path.join(root, name)) for name in names]) except: - log.error('Failed getting files from %s: %s', (movie_folder, traceback.format_exc())) + log.error('Failed getting files from %s: %s', (media_folder, traceback.format_exc())) db = get_session() @@ -185,7 +185,7 @@ class Renamer(Plugin): # Unpack any archives extr_files = None if self.conf('unrar'): - folder, movie_folder, files, extr_files = self.extractFiles(folder = folder, movie_folder = movie_folder, files = files, + folder, media_folder, files, extr_files = self.extractFiles(folder = folder, media_folder = media_folder, files = files, cleanup = self.conf('cleanup') and not self.downloadIsTorrent(release_download)) groups = fireEvent('scanner.scan', folder = folder if folder else from_folder, @@ -497,7 +497,7 @@ class Renamer(Plugin): os.remove(src) parent_dir = os.path.dirname(src) - if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and not parent_dir in [destination, movie_folder] and not from_folder in parent_dir: + if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and not parent_dir in [destination, media_folder] and not from_folder in parent_dir: delete_folders.append(parent_dir) except: @@ -529,7 +529,7 @@ class Renamer(Plugin): self.tagRelease(group = group, tag = 'failed_rename') # Tag folder if it is in the 'from' folder and it will not be removed because it is a torrent - if self.movieInFromFolder(movie_folder) and self.downloadIsTorrent(release_download): + if self.movieInFromFolder(media_folder) and self.downloadIsTorrent(release_download): self.tagRelease(group = group, tag = 'renamed_already') # Remove matching releases @@ -541,9 +541,9 @@ class Renamer(Plugin): log.error('Failed removing %s: %s', (release.identifier, traceback.format_exc())) if group['dirname'] and group['parentdir'] and not self.downloadIsTorrent(release_download): - if movie_folder: + if media_folder: # Delete the movie folder - group_folder = movie_folder + group_folder = media_folder else: # Delete the first empty subfolder in the tree relative to the 'from' folder group_folder = sp(os.path.join(from_folder, os.path.relpath(group['parentdir'], from_folder).split(os.path.sep)[0])) @@ -1015,10 +1015,10 @@ Remove it if you want it to be renamed (again, or at least let it try again) def statusInfoComplete(self, release_download): return release_download['id'] and release_download['downloader'] and release_download['folder'] - def movieInFromFolder(self, movie_folder): - return movie_folder and sp(self.conf('from')) in sp(movie_folder) or not movie_folder + def movieInFromFolder(self, media_folder): + return media_folder and sp(self.conf('from')) in sp(media_folder) or not media_folder - def extractFiles(self, folder = None, movie_folder = None, files = None, cleanup = False): + def extractFiles(self, folder = None, media_folder = None, files = None, cleanup = False): if not files: files = [] # RegEx for finding rar files @@ -1033,7 +1033,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) folder = from_folder check_file_date = True - if movie_folder: + if media_folder: check_file_date = False if not files: @@ -1129,18 +1129,18 @@ Remove it if you want it to be renamed (again, or at least let it try again) if cleanup: # Remove all left over folders - log.debug('Removing old movie folder %s...', movie_folder) - self.deleteEmptyFolder(movie_folder) + log.debug('Removing old movie folder %s...', media_folder) + self.deleteEmptyFolder(media_folder) - movie_folder = os.path.join(from_folder, os.path.relpath(movie_folder, folder)) + media_folder = os.path.join(from_folder, os.path.relpath(media_folder, folder)) folder = from_folder if extr_files: files.extend(extr_files) - # Cleanup files and folder if movie_folder was not provided - if not movie_folder: + # Cleanup files and folder if media_folder was not provided + if not media_folder: files = [] folder = None - return folder, movie_folder, files, extr_files + return folder, media_folder, files, extr_files From cff1b3abdb8f2dd6803136f57851196658125115 Mon Sep 17 00:00:00 2001 From: mano3m Date: Fri, 29 Nov 2013 22:36:46 +0100 Subject: [PATCH 05/13] Provide IDs to check to all downloaders --- couchpotato/core/downloaders/base.py | 11 ++- couchpotato/core/downloaders/deluge/main.py | 67 +++++++++--------- couchpotato/core/downloaders/nzbget/main.py | 69 +++++++++--------- couchpotato/core/downloaders/nzbvortex/main.py | 40 ++++++----- couchpotato/core/downloaders/rtorrent/main.py | 45 ++++++------ couchpotato/core/downloaders/sabnzbd/main.py | 55 ++++++++------- couchpotato/core/downloaders/transmission/main.py | 53 +++++++------- couchpotato/core/downloaders/utorrent/main.py | 85 ++++++++++++----------- couchpotato/core/plugins/renamer/main.py | 15 +++- 9 files changed, 234 insertions(+), 206 deletions(-) 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 From 008ba3985617b38cac963d1f27c4e93e9cedd948 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 30 Nov 2013 13:53:52 +0100 Subject: [PATCH 06/13] Add backwards compatibility for the renamer API --- couchpotato/core/plugins/renamer/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 1a4726b..c8abdbd 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -65,6 +65,11 @@ class Renamer(Plugin): async = tryInt(kwargs.get('async', 0)) media_folder = sp(kwargs.get('media_folder')) + + # Backwards compatibility, to be removed after a few versions :) + if not media_folder: + media_folder = sp(kwargs.get('movie_folder')) + downloader = kwargs.get('downloader') download_id = kwargs.get('download_id') files = '|'.join([sp(filename) for filename in splitString(kwargs.get('files'), '|')]) From 574255c4b68dff71518fb219781540a16417497d Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 30 Nov 2013 15:27:55 +0100 Subject: [PATCH 07/13] Don't tag .ignore files --- couchpotato/core/plugins/renamer/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index c8abdbd..8b1e0d1 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -619,6 +619,11 @@ Remove it if you want it to be renamed (again, or at least let it try again) tag_files.extend([os.path.join(root, name) for name in names]) for filename in tag_files: + + # Dont tag .ignore files + if os.path.splitext(filename)[1] == '.ignore': + continue + tag_filename = '%s.%s.ignore' % (os.path.splitext(filename)[0], tag) if not os.path.isfile(tag_filename): self.createFile(tag_filename, text) From ab413f2f3e18803ea5a33c42d6c294e5122b3f89 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Dec 2013 12:39:07 +0100 Subject: [PATCH 08/13] Dont remove historic data when doing a full scan. Fixes #2572 Note that the dashboard already takes care of this and does it the right way (keeping seeding and ignored releases). --- couchpotato/core/plugins/manage/main.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/couchpotato/core/plugins/manage/main.py b/couchpotato/core/plugins/manage/main.py index d9e2898..a764f31 100644 --- a/couchpotato/core/plugins/manage/main.py +++ b/couchpotato/core/plugins/manage/main.py @@ -1,6 +1,6 @@ from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, addEvent, fireEventAsync -from couchpotato.core.helpers.encoding import ss +from couchpotato.core.helpers.encoding import sp from couchpotato.core.helpers.variable import splitString, getTitle from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin @@ -122,12 +122,10 @@ class Manage(Plugin): releases = fireEvent('release.for_movie', id = done_movie.get('id'), single = True) for release in releases: - if len(release.get('files', [])) == 0: - fireEvent('release.delete', release['id']) - else: + if len(release.get('files', [])) > 0: for release_file in release.get('files', []): # Remove release not available anymore - if not os.path.isfile(ss(release_file['path'])): + if not os.path.isfile(sp(release_file['path'])): fireEvent('release.clean', release['id']) break From 6d4297a5fb8e9d621c2a927f8ec59e5481da1329 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Dec 2013 22:39:47 +0100 Subject: [PATCH 09/13] Extend os.path.sep to all folder checks Expands 50c5044fe8fa6f7ab624a72e8dba78453241b127 --- couchpotato/core/plugins/renamer/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 8b1e0d1..44395a6 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -502,7 +502,7 @@ class Renamer(Plugin): os.remove(src) parent_dir = os.path.dirname(src) - if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and not parent_dir in [destination, media_folder] and not from_folder in parent_dir: + if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and not '%s%s' % (parent_dir, os.path.sep) in [destination, media_folder] and not '%s%s' % (from_folder, os.path.sep) in parent_dir: delete_folders.append(parent_dir) except: @@ -1037,7 +1037,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) return release_download['id'] and release_download['downloader'] and release_download['folder'] def movieInFromFolder(self, media_folder): - return media_folder and sp(self.conf('from')) in sp(media_folder) or not media_folder + return media_folder and '%s%s' % (sp(self.conf('from')), os.path.sep) in sp(media_folder) or not media_folder def extractFiles(self, folder = None, media_folder = None, files = None, cleanup = False): if not files: files = [] From fd768df9e5cb23dce097656d0770458447582929 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 8 Dec 2013 13:54:04 +0100 Subject: [PATCH 10/13] Tabs to spaces --- couchpotato/core/plugins/renamer/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 44395a6..d74d8ed 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -931,7 +931,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) fireEvent('download.remove_failed', release_download, single = True) if self.conf('next_on_failed'): - fireEvent('movie.searcher.try_next_release', media_id = rel.movie_id) + fireEvent('movie.searcher.try_next_release', media_id = rel.movie_id) elif release_download['status'] == 'completed': log.info('Download of %s completed!', release_download['name']) From f57f2444fe44b2a3da501e4817ca692804e33418 Mon Sep 17 00:00:00 2001 From: mano3m Date: Wed, 11 Dec 2013 22:11:33 +0100 Subject: [PATCH 11/13] Improved checking Fixes #2539 ? --- couchpotato/core/plugins/renamer/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index d74d8ed..eb8fbd2 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -826,10 +826,11 @@ Remove it if you want it to be renamed (again, or at least let it try again) try: for rel in rels: rel_dict = rel.to_dict({'info': {}}) - if rel_dict['info'].get('download_id'): + if rel_dict['info'].get('download_id') and rel_dict['info'].get('download_downloader'): download_ids.append({'id': rel_dict['info']['download_id'], 'downloader': rel_dict['info']['download_downloader']}) except: log.error('Error getting download IDs from database') + self.checking_snatched = False return False release_downloads = fireEvent('download.status', download_ids, merge = True) From ea5d274f4d9b9f49645c416c52b7a05878c7f78a Mon Sep 17 00:00:00 2001 From: mano3m Date: Wed, 11 Dec 2013 22:40:01 +0100 Subject: [PATCH 12/13] Add another check --- couchpotato/core/plugins/renamer/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index eb8fbd2..b4f668f 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -857,7 +857,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) continue # Check if download ID is available - if not rel_dict['info'].get('download_id'): + if not rel_dict['info'].get('download_id') or not rel_dict['info'].get('download_downloader'): log.debug('Download status functionality is not implemented for downloader (%s) of release %s.', (rel_dict['info'].get('download_downloader', 'unknown'), rel_dict['info']['name'])) scan_required = True From 74561500b5cb19ac84ffbed00825f26e35c7cfe1 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 14 Dec 2013 21:12:10 +0100 Subject: [PATCH 13/13] Convert windows path to *nix path in sp Fixes #2594 Note that os.path.normath converts '/' to '\\' on windows machines, but unfortunately not the other way around... --- couchpotato/core/helpers/encoding.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/couchpotato/core/helpers/encoding.py b/couchpotato/core/helpers/encoding.py index e88c6ca..bcc698d 100644 --- a/couchpotato/core/helpers/encoding.py +++ b/couchpotato/core/helpers/encoding.py @@ -54,6 +54,10 @@ def sp(path, *args): if not path or len(path) == 0: return path + # convert windows path (from remote box) to *nix path + if os.path.sep == '/' and '\\' in path: + path = '/' + path.replace(':', '').replace('\\', '/') + path = os.path.normcase(os.path.normpath(ss(path, *args))) if path != os.path.sep: