diff --git a/couchpotato/core/downloaders/transmission/main.py b/couchpotato/core/downloaders/transmission/main.py index 66cceb2f..620b0d60 100644 --- a/couchpotato/core/downloaders/transmission/main.py +++ b/couchpotato/core/downloaders/transmission/main.py @@ -96,6 +96,7 @@ class Transmission(Downloader): 'fields': ['id', 'name', 'hashString', 'percentDone', 'status', 'eta', 'isStalled', 'isFinished', 'downloadDir', 'uploadRatio', 'secondsSeeding', 'seedIdleLimit', 'files'] } + session = self.trpc.get_session() queue = self.trpc.get_alltorrents(return_params) if not (queue and queue.get('torrents')): log.debug('Nothing in queue or error') @@ -103,13 +104,9 @@ class Transmission(Downloader): for torrent in queue['torrents']: if torrent['hashString'] in ids: - log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / isStalled=%s / eta=%s / uploadRatio=%s / isFinished=%s', - (torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent.get('isStalled', 'N/A'), 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']))) - + log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / isStalled=%s / eta=%s / uploadRatio=%s / isFinished=%s / incomplete-dir-enabled=%s / incomplete-dir=%s', + (torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent.get('isStalled', 'N/A'), torrent['eta'], torrent['uploadRatio'], torrent['isFinished'], session['incomplete-dir-enabled'], session['incomplete-dir'])) + status = 'busy' if torrent.get('isStalled') and not torrent['percentDone'] == 1 and self.conf('stalled_as_failed'): status = 'failed' @@ -117,7 +114,16 @@ class Transmission(Downloader): status = 'completed' elif torrent['status'] in [5, 6]: status = 'seeding' - + + if session['incomplete-dir-enabled'] and status == 'busy': + torrent_folder = session['incomplete-dir'] + else: + torrent_folder = torrent['downloadDir'] + + torrent_files = [] + for file_item in torrent['files']: + torrent_files.append(sp(os.path.join(torrent_folder, file_item['name']))) + release_downloads.append({ 'id': torrent['hashString'], 'name': torrent['name'], @@ -125,7 +131,7 @@ class Transmission(Downloader): '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'])), + 'folder': sp(torrent_folder if len(torrent_files) == 1 else os.path.join(torrent_folder, torrent['name'])), 'files': '|'.join(torrent_files) }) diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 43850f8f..614d7768 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -212,6 +212,10 @@ class Renamer(Plugin): done_status, active_status, downloaded_status, snatched_status, seeding_status = \ fireEvent('status.get', ['done', 'active', 'downloaded', 'snatched', 'seeding'], single = True) + # Tag release folder as failed_rename in case no groups were found. This prevents check_snatched from removing the release from the downloader. + if not groups and self.statusInfoComplete(release_download): + self.tagRelease(release_download = release_download, tag = 'failed_rename') + for group_identifier in groups: group = groups[group_identifier] @@ -527,6 +531,7 @@ class Renamer(Plugin): # Rename all files marked group['renamed_files'] = [] + failed_rename = False for src in rename_files: if rename_files[src]: dst = rename_files[src] @@ -539,8 +544,17 @@ class Renamer(Plugin): self.moveFile(src, dst, forcemove = not self.downloadIsTorrent(release_download) or self.fileIsAdded(src, group)) group['renamed_files'].append(dst) except: - log.error('Failed moving the file "%s" : %s', (os.path.basename(src), traceback.format_exc())) - self.tagRelease(group = group, tag = 'failed_rename') + log.error('Failed ranaming the file "%s" : %s', (os.path.basename(src), traceback.format_exc())) + failed_rename = True + break + + # If renaming failed tag the release folder as failed and continue with next group. Note that all old files have already been deleted. + if failed_rename: + self.tagRelease(group = group, tag = 'failed_rename') + continue + # If renaming succeeded, make sure it is not tagged as failed (scanner didn't return a group, but a download_ID was provided in an earlier attempt) + else: + self.untagRelease(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(media_folder) and self.downloadIsTorrent(release_download): @@ -1053,7 +1067,7 @@ Remove it if you want it to be renamed (again, or at least let it try again) return src in group['before_rename'] def statusInfoComplete(self, release_download): - return release_download['id'] and release_download['downloader'] and release_download['folder'] + return release_download.get('id') and release_download.get('downloader') and release_download.get('folder') def movieInFromFolder(self, media_folder): return media_folder and isSubFolder(media_folder, sp(self.conf('from'))) or not media_folder diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index f2ef9199..89967df1 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -1,4 +1,5 @@ from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.helpers.encoding import ss from couchpotato.core.helpers.variable import tryFloat, mergeDicts, md5, \ possibleTitles, getTitle from couchpotato.core.logger import CPLog @@ -84,7 +85,7 @@ class Provider(Plugin): if data and len(data) > 0: try: - data = XMLTree.fromstring(data) + data = XMLTree.fromstring(ss(data)) return self.getElements(data, item_path) except: log.error('Failed to parsing %s: %s', (self.getName(), traceback.format_exc()))