From dbeaab052d40b3feba93c97e4210c5ba8426bc35 Mon Sep 17 00:00:00 2001 From: mano3m Date: Tue, 13 May 2014 22:44:12 +0200 Subject: [PATCH 01/13] Wait before marking media as done --- couchpotato/core/media/movie/searcher.py | 32 ++++++++++++++++------ couchpotato/core/plugins/profile/main.py | 4 +++ couchpotato/core/plugins/profile/static/profile.js | 11 +++++++- couchpotato/core/plugins/quality/main.py | 10 +++++-- couchpotato/core/plugins/release/main.py | 7 +---- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 1053ec3..9048d17 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -1,4 +1,5 @@ -from datetime import date +from datetime import date, timedelta +from operator import itemgetter import random import re import time @@ -139,6 +140,27 @@ class MovieSearcher(SearcherBase, MovieTypeBase): fireEvent('media.delete', movie['_id'], single = True) return + db = get_db() + profile = db.get('id', movie['profile_id']) + + # Find out if we need to stop searching because 'stop_after' is met. Compare with the newest release found. + done_releases = [release for release in previous_releases if release.get('status') == 'done'] + + if done_releases: + done_release = sorted(done_releases, key = itemgetter('last_edit'), reverse = True)[0] + if fireEvent('quality.isfinish', {'identifier': done_release['quality'], 'is_3d': done_release.get('is_3d', False)}, profile, timedelta(seconds = time.time() - done_release['last_edit']).days, single = True): + + log.debug('No better quality than %s%s found for %s days, marking movie %s as done.', \ + (done_release['quality'], ' 3D' if done_release.get('is_3d', False) else '', profile['stop_after'][0], default_title)) + + # Mark media done + mdia = db.get('id', movie['_id']) + mdia['status'] = 'done' + mdia['last_edit'] = int(time.time()) + db.update(mdia) + + return + fireEvent('notify.frontend', type = 'movie.searcher.started', data = {'_id': movie['_id']}, message = 'Searching for "%s"' % default_title) # Ignore eta once every 7 days @@ -149,13 +171,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): ignore_eta = True Env.prop(prop_name, value = time.time()) - db = get_db() - - profile = db.get('id', movie['profile_id']) ret = False - index = 0 - for q_identifier in profile.get('qualities'): + for index, q_identifier in enumerate(profile.get('qualities', [])): quality_custom = { 'index': index, 'quality': q_identifier, @@ -164,8 +182,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): '3d': profile['3d'][index] if profile.get('3d') else False } - index += 1 - could_not_be_released = not self.couldBeReleased(q_identifier in pre_releases, release_dates, movie['info']['year']) if not alway_search and could_not_be_released: too_early_to_search.append(q_identifier) diff --git a/couchpotato/core/plugins/profile/main.py b/couchpotato/core/plugins/profile/main.py index 1098719..489c34d 100644 --- a/couchpotato/core/plugins/profile/main.py +++ b/couchpotato/core/plugins/profile/main.py @@ -88,6 +88,7 @@ class ProfilePlugin(Plugin): 'core': kwargs.get('core', False), 'qualities': [], 'wait_for': [], + 'stop_after': [], 'finish': [], '3d': [] } @@ -97,6 +98,7 @@ class ProfilePlugin(Plugin): for type in kwargs.get('types', []): profile['qualities'].append(type.get('quality')) profile['wait_for'].append(tryInt(kwargs.get('wait_for', 0))) + profile['stop_after'].append(tryInt(kwargs.get('stop_after', 0))) profile['finish'].append((tryInt(type.get('finish')) == 1) if order > 0 else True) profile['3d'].append(tryInt(type.get('3d'))) order += 1 @@ -217,6 +219,7 @@ class ProfilePlugin(Plugin): 'qualities': profile.get('qualities'), 'finish': [], 'wait_for': [], + 'stop_after': [], '3d': [] } @@ -224,6 +227,7 @@ class ProfilePlugin(Plugin): for q in profile.get('qualities'): pro['finish'].append(True) pro['wait_for'].append(0) + pro['stop_after'].append(0) pro['3d'].append(threed.pop() if threed else False) db.insert(pro) diff --git a/couchpotato/core/plugins/profile/static/profile.js b/couchpotato/core/plugins/profile/static/profile.js index c62b137..2bdd950 100644 --- a/couchpotato/core/plugins/profile/static/profile.js +++ b/couchpotato/core/plugins/profile/static/profile.js @@ -51,7 +51,15 @@ var Profile = new Class({ new Element('div.formHint', { 'html': "Search these qualities (2 minimum), from top to bottom. Use the checkbox, to stop searching after it found this quality." }) - ) + ), + new Element('div.stop_after.ctrlHolder').adopt( + new Element('span', {'text':'Stop searching for better than first checked quality after'}), + new Element('input.inlay.xsmall', { + 'type':'text', + 'value': data.stop_after && data.stop_after.length > 0 ? data.stop_after[0] : 0 + }), + new Element('span', {'text':'day(s).'}) + ) ); self.makeSortable(); @@ -117,6 +125,7 @@ var Profile = new Class({ 'id' : self.data._id, 'label' : self.el.getElement('.quality_label input').get('value'), 'wait_for' : self.el.getElement('.wait_for input').get('value'), + 'stop_after' : self.el.getElement('.stop_after input').get('value'), 'types': [] }; diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index dd820cf..40ef8cf 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -379,13 +379,17 @@ class QualityPlugin(Plugin): if score.get(q.get('identifier')): score[q.get('identifier')]['score'] -= 1 - def isFinish(self, quality, profile): + def isFinish(self, quality, profile, release_age = 0): if not isinstance(profile, dict) or not profile.get('qualities'): return False try: - quality_order = [i for i, identifier in enumerate(profile['qualities']) if identifier == quality['identifier'] and bool(profile['3d'][i] if profile.get('3d') else 0) == bool(quality.get('is_3d', 0))][0] - return profile['finish'][quality_order] + index = [i for i, identifier in enumerate(profile['qualities']) if identifier == quality['identifier'] and bool(profile['3d'][i] if profile.get('3d') else False) == bool(quality.get('is_3d', False))][0] + + if index == 0 or profile['finish'][index] and int(release_age) >= int(profile['stop_after'][0]): + return True + + return False except: return False diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index cb16c5a..df710c3 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -331,12 +331,7 @@ class Release(Plugin): if media['status'] == 'active': profile = db.get('id', media['profile_id']) - finished = False - if rls['quality'] in profile['qualities']: - nr = profile['qualities'].index(rls['quality']) - finished = profile['finish'][nr] - - if finished: + if fireEvent('quality.isfinish', {'identifier': rls['quality'], 'is_3d': rls.get('is_3d', False)}, profile, single = True): log.info('Renamer disabled, marking media as finished: %s', log_movie) # Mark release done From e55302592ae20b2d0295246170e8227b611ebdcf Mon Sep 17 00:00:00 2001 From: mano3m Date: Mon, 2 Jun 2014 19:04:04 +0200 Subject: [PATCH 02/13] Improve description --- couchpotato/core/plugins/profile/static/profile.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/plugins/profile/static/profile.js b/couchpotato/core/plugins/profile/static/profile.js index 2bdd950..5ce6eaf 100644 --- a/couchpotato/core/plugins/profile/static/profile.js +++ b/couchpotato/core/plugins/profile/static/profile.js @@ -44,6 +44,7 @@ var Profile = new Class({ 'value': data.wait_for && data.wait_for.length > 0 ? data.wait_for[0] : 0 }), new Element('span', {'text':'day(s) for a better quality.'}) + // "Wait the entered number of days for a checked quality, before downloading a lower quality release." ), new Element('div.qualities.ctrlHolder').adopt( new Element('label', {'text': 'Search for'}), @@ -52,14 +53,15 @@ var Profile = new Class({ 'html': "Search these qualities (2 minimum), from top to bottom. Use the checkbox, to stop searching after it found this quality." }) ), - new Element('div.stop_after.ctrlHolder').adopt( - new Element('span', {'text':'Stop searching for better than first checked quality after'}), - new Element('input.inlay.xsmall', { - 'type':'text', - 'value': data.stop_after && data.stop_after.length > 0 ? data.stop_after[0] : 0 - }), - new Element('span', {'text':'day(s).'}) - ) + new Element('div.stop_after.ctrlHolder').adopt( + new Element('span', {'text':'Keep searching'}), + new Element('input.inlay.xsmall', { + 'type':'text', + 'value': data.stop_after && data.stop_after.length > 0 ? data.stop_after[0] : 0 + }), + new Element('span', {'text':'day(s) for a better checked quality.'}) + // "After a checked quality is found and downloaded, continue searching for even better quality releases for the entered number of days." + ) ); self.makeSortable(); @@ -125,7 +127,7 @@ var Profile = new Class({ 'id' : self.data._id, 'label' : self.el.getElement('.quality_label input').get('value'), 'wait_for' : self.el.getElement('.wait_for input').get('value'), - 'stop_after' : self.el.getElement('.stop_after input').get('value'), + 'stop_after' : self.el.getElement('.stop_after input').get('value'), 'types': [] }; From 03dff14ee95202e2e0e52fb1f075abe183511125 Mon Sep 17 00:00:00 2001 From: mano3m Date: Mon, 2 Jun 2014 19:52:41 +0200 Subject: [PATCH 03/13] Massive bug fix --- couchpotato/core/plugins/release/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index df710c3..f9c563f 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -102,7 +102,7 @@ class Release(Plugin): # Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the move elif rel['status'] in ['snatched', 'downloaded']: - self.updateStatus(rel['_id'], status = 'ignore') + self.updateStatus(rel['_id'], status = 'ignored') fireEvent('media.untag', media.get('_id'), 'recent', single = True) From f01449f14c75b677f8b3551da5a02d948ffa9413 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Jun 2014 15:50:50 +0200 Subject: [PATCH 04/13] Rename scanned files for done media properly --- couchpotato/core/plugins/quality/main.py | 6 +++--- couchpotato/core/plugins/renamer.py | 29 +++++++++++++++-------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 40ef8cf..8f1484d 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -381,7 +381,7 @@ class QualityPlugin(Plugin): def isFinish(self, quality, profile, release_age = 0): if not isinstance(profile, dict) or not profile.get('qualities'): - return False + profile = fireEvent('profile.default', single = True) try: index = [i for i, identifier in enumerate(profile['qualities']) if identifier == quality['identifier'] and bool(profile['3d'][i] if profile.get('3d') else False) == bool(quality.get('is_3d', False))][0] @@ -395,14 +395,14 @@ class QualityPlugin(Plugin): def isHigher(self, quality, compare_with, profile = None): if not isinstance(profile, dict) or not profile.get('qualities'): - profile = {'qualities': self.order} + profile = fireEvent('profile.default', single = True) # Try to find quality in profile, if not found: a quality we do not want is lower than anything else try: quality_order = [i for i, identifier in enumerate(profile['qualities']) if identifier == quality['identifier'] and bool(profile['3d'][i] if profile.get('3d') else 0) == bool(quality.get('is_3d', 0))][0] except: log.debug('Quality %s not found in profile identifiers %s', (quality['identifier'] + (' 3D' if quality.get('is_3d', 0) else ''), \ - [identifier + ('3D' if (profile['3d'][i] if profile.get('3d') else 0) else '') for i, identifier in enumerate(profile['qualities'])])) + [identifier + (' 3D' if (profile['3d'][i] if profile.get('3d') else 0) else '') for i, identifier in enumerate(profile['qualities'])])) return 'lower' # Try to find compare quality in profile, if not found: anything is higher than a not wanted quality diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 8b57103..2a6c4a8 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -446,22 +446,23 @@ class Renamer(Plugin): # Before renaming, remove the lower quality files remove_leftovers = True - # Mark movie "done" once it's found the quality with the finish check + # Get media quality profile profile = None - try: - if media.get('status') == 'active' and media.get('profile_id'): - profile = db.get('id', media['profile_id']) - if fireEvent('quality.isfinish', group['meta_data']['quality'], profile, single = True): - mdia = db.get('id', media['_id']) - mdia['status'] = 'done' - mdia['last_edit'] = int(time.time()) - db.update(mdia) + if media.get('profile_id'): + profile = db.get('id', media['profile_id']) + else: + log.debug('Media has no quality profile: %s', media_title) - # List movie on dashboard - fireEvent('media.tag', media['_id'], 'recent', single = True) + # Mark movie "done" once it's found the quality with the finish check + if media.get('status') == 'active': + if fireEvent('quality.isfinish', group['meta_data']['quality'], profile, single = True): + mdia = db.get('id', media['_id']) + mdia['status'] = 'done' + mdia['last_edit'] = int(time.time()) + db.update(mdia) - except: - log.error('Failed marking movie finished: %s', (traceback.format_exc())) + # List movie on dashboard + fireEvent('media.tag', media['_id'], 'recent', single = True) # Mark media for dashboard mark_as_recent = False @@ -474,7 +475,7 @@ class Renamer(Plugin): # This is where CP removes older, lesser quality releases or releases that are not wanted anymore is_higher = fireEvent('quality.ishigher', \ - group['meta_data']['quality'], {'identifier': release['quality'], 'is_3d': release.get('is_3d', 0)}, profile, single = True) + group['meta_data']['quality'], {'identifier': release['quality'], 'is_3d': release.get('is_3d', False)}, profile, single = True) if is_higher == 'higher': log.info('Removing lesser or not wanted quality %s for %s.', (media_title, release.get('quality'))) From 5af5749d4ad3d30514b3ca53d61a7e07273eb3cf Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 7 Jun 2014 16:04:54 +0200 Subject: [PATCH 05/13] Catch missing deleted profile error @RuudBurger should we reset the profile of the media to default or None in case this happens or leave it the way it is? --- couchpotato/core/plugins/renamer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 2a6c4a8..1e35b84 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -449,7 +449,10 @@ class Renamer(Plugin): # Get media quality profile profile = None if media.get('profile_id'): - profile = db.get('id', media['profile_id']) + try: + profile = db.get('id', media['profile_id']) + except: + log.error('Error getting quality profile for %s: %s', (media_title, traceback.format_exc())) else: log.debug('Media has no quality profile: %s', media_title) From 9f6036c8d61783213cb40882e34b939d26542428 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 14 Jun 2014 23:18:19 +0200 Subject: [PATCH 06/13] Redo status update for media --- couchpotato/core/media/_base/media/main.py | 25 +++++++++++---------- couchpotato/core/media/movie/searcher.py | 35 ++++++++++-------------------- couchpotato/core/plugins/release/main.py | 2 +- couchpotato/core/plugins/renamer.py | 15 +++++-------- 4 files changed, 31 insertions(+), 46 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index dc9e97a..84bc564 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -1,3 +1,6 @@ +from datetime import timedelta +from operator import itemgetter +import time import traceback from string import ascii_lowercase @@ -452,20 +455,20 @@ class MediaPlugin(MediaBase): if not m['profile_id']: m['status'] = 'done' else: - move_to_wanted = True + m['status'] = 'active' try: - profile = db.get('id', m['profile_id']) - media_releases = fireEvent('release.for_media', m['_id'], single = True) + profile = db.get('id', m['profile_id']) + media_releases = fireEvent('release.for_media', m['_id'], single = True) + done_releases = [release for release in media_releases if release.get('status') == 'done'] - for q_identifier in profile['qualities']: - index = profile['qualities'].index(q_identifier) + if done_releases: + # Only look at latest added release + release = sorted(done_releases, key = itemgetter('last_edit'), reverse = True)[0] - for release in media_releases: - if q_identifier == release['quality'] and (release.get('status') == 'done' and profile['finish'][index]): - move_to_wanted = False - - m['status'] = 'active' if move_to_wanted else 'done' + # Check if we are finished with the media + if fireEvent('quality.isfinish', {'identifier': release['quality'], 'is_3d': release.get('is_3d', False)}, profile, timedelta(seconds = time.time() - release['last_edit']).days, single = True): + m['status'] = 'done' except RecordNotFound: log.debug('Failed restatus: %s', traceback.format_exc()) @@ -473,7 +476,7 @@ class MediaPlugin(MediaBase): if previous_status != m['status']: db.update(m) - return True + return m['status'] except: log.error('Failed restatus: %s', traceback.format_exc()) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index 9048d17..e8b6a52 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -121,8 +121,19 @@ class MovieSearcher(SearcherBase, MovieTypeBase): if not movie['profile_id'] or (movie['status'] == 'done' and not manual): log.debug('Movie doesn\'t have a profile or already done, assuming in manage tab.') + fireEvent('media.restatus', movie['_id']) return + default_title = getTitle(movie) + if not default_title: + log.error('No proper info found for movie, removing it from library to stop it from causing more issues.') + fireEvent('media.delete', movie['_id'], single = True) + return + + # Update media status and check if it is still not done (due to the stop searching after feature + if fireEvent('media.restatus', movie['_id'], single = True) == 'done': + log.debug('No better quality found, marking movie %s as done.', default_title) + pre_releases = fireEvent('quality.pre_releases', single = True) release_dates = fireEvent('movie.update_release_dates', movie['_id'], merge = True) @@ -134,33 +145,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): ignore_eta = manual total_result_count = 0 - default_title = getTitle(movie) - if not default_title: - log.error('No proper info found for movie, removing it from library to cause it from having more issues.') - fireEvent('media.delete', movie['_id'], single = True) - return - db = get_db() profile = db.get('id', movie['profile_id']) - # Find out if we need to stop searching because 'stop_after' is met. Compare with the newest release found. - done_releases = [release for release in previous_releases if release.get('status') == 'done'] - - if done_releases: - done_release = sorted(done_releases, key = itemgetter('last_edit'), reverse = True)[0] - if fireEvent('quality.isfinish', {'identifier': done_release['quality'], 'is_3d': done_release.get('is_3d', False)}, profile, timedelta(seconds = time.time() - done_release['last_edit']).days, single = True): - - log.debug('No better quality than %s%s found for %s days, marking movie %s as done.', \ - (done_release['quality'], ' 3D' if done_release.get('is_3d', False) else '', profile['stop_after'][0], default_title)) - - # Mark media done - mdia = db.get('id', movie['_id']) - mdia['status'] = 'done' - mdia['last_edit'] = int(time.time()) - db.update(mdia) - - return - fireEvent('notify.frontend', type = 'movie.searcher.started', data = {'_id': movie['_id']}, message = 'Searching for "%s"' % default_title) # Ignore eta once every 7 days diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index f9c563f..ab0a022 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -100,7 +100,7 @@ class Release(Plugin): if rel['status'] in ['available']: self.delete(rel['_id']) - # Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the move + # Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the media elif rel['status'] in ['snatched', 'downloaded']: self.updateStatus(rel['_id'], status = 'ignored') diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 1e35b84..c0ee28d 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -452,20 +452,15 @@ class Renamer(Plugin): try: profile = db.get('id', media['profile_id']) except: + # Set profile to None as it does not exist anymore + media['profile_id'] = None + db.update(media) log.error('Error getting quality profile for %s: %s', (media_title, traceback.format_exc())) else: log.debug('Media has no quality profile: %s', media_title) - # Mark movie "done" once it's found the quality with the finish check - if media.get('status') == 'active': - if fireEvent('quality.isfinish', group['meta_data']['quality'], profile, single = True): - mdia = db.get('id', media['_id']) - mdia['status'] = 'done' - mdia['last_edit'] = int(time.time()) - db.update(mdia) - - # List movie on dashboard - fireEvent('media.tag', media['_id'], 'recent', single = True) + # # List movie on dashboard + # fireEvent('media.tag', media['_id'], 'recent', single = True) # Mark media for dashboard mark_as_recent = False From 424a3cd892054d574ecc6ffc81e39c470a7e4ead Mon Sep 17 00:00:00 2001 From: mano3m Date: Sat, 14 Jun 2014 23:30:44 +0200 Subject: [PATCH 07/13] Clean-up --- couchpotato/core/media/movie/_base/main.py | 2 +- couchpotato/core/media/movie/searcher.py | 13 ++++++------- couchpotato/core/plugins/quality/main.py | 3 ++- couchpotato/core/plugins/release/main.py | 2 +- couchpotato/core/plugins/renamer.py | 5 +++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index 07c4751..336d803 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -236,7 +236,7 @@ class MovieBase(MovieTypeBase): db.update(m) - fireEvent('media.restatus', m['_id']) + fireEvent('media.restatus', m['_id'], single = True) m = db.get('id', media_id) diff --git a/couchpotato/core/media/movie/searcher.py b/couchpotato/core/media/movie/searcher.py index e8b6a52..7d92c57 100644 --- a/couchpotato/core/media/movie/searcher.py +++ b/couchpotato/core/media/movie/searcher.py @@ -1,5 +1,4 @@ -from datetime import date, timedelta -from operator import itemgetter +from datetime import date import random import re import time @@ -121,7 +120,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): if not movie['profile_id'] or (movie['status'] == 'done' and not manual): log.debug('Movie doesn\'t have a profile or already done, assuming in manage tab.') - fireEvent('media.restatus', movie['_id']) + fireEvent('media.restatus', movie['_id'], single = True) return default_title = getTitle(movie) @@ -145,9 +144,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): ignore_eta = manual total_result_count = 0 - db = get_db() - profile = db.get('id', movie['profile_id']) - fireEvent('notify.frontend', type = 'movie.searcher.started', data = {'_id': movie['_id']}, message = 'Searching for "%s"' % default_title) # Ignore eta once every 7 days @@ -158,6 +154,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): ignore_eta = True Env.prop(prop_name, value = time.time()) + db = get_db() + + profile = db.get('id', movie['profile_id']) ret = False for index, q_identifier in enumerate(profile.get('qualities', [])): @@ -192,7 +191,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): # Don't search for quality lower then already available. if has_better_quality > 0: log.info('Better quality (%s) already available or snatched for %s', (q_identifier, default_title)) - fireEvent('media.restatus', movie['_id']) + fireEvent('media.restatus', movie['_id'], single = True) break quality = fireEvent('quality.single', identifier = q_identifier, single = True) diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 8f1484d..856cc22 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -381,7 +381,8 @@ class QualityPlugin(Plugin): def isFinish(self, quality, profile, release_age = 0): if not isinstance(profile, dict) or not profile.get('qualities'): - profile = fireEvent('profile.default', single = True) + # No profile so anything (scanned) is good enough + return True try: index = [i for i, identifier in enumerate(profile['qualities']) if identifier == quality['identifier'] and bool(profile['3d'][i] if profile.get('3d') else False) == bool(quality.get('is_3d', False))][0] diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index ab0a022..628bd69 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -164,7 +164,7 @@ class Release(Plugin): release['files'] = dict((k, [toUnicode(x) for x in v]) for k, v in group['files'].items() if v) db.update(release) - fireEvent('media.restatus', media['_id']) + fireEvent('media.restatus', media['_id'], single = True) return True except: diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index c0ee28d..824aa79 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -453,8 +453,9 @@ class Renamer(Plugin): profile = db.get('id', media['profile_id']) except: # Set profile to None as it does not exist anymore - media['profile_id'] = None - db.update(media) + mdia = db.get('id', media['_id']) + mdia['profile_id'] = None + db.update(mdia) log.error('Error getting quality profile for %s: %s', (media_title, traceback.format_exc())) else: log.debug('Media has no quality profile: %s', media_title) From 40e910192e5fe046540883090bf861650256d34f Mon Sep 17 00:00:00 2001 From: mano3m Date: Fri, 20 Jun 2014 19:25:01 +0200 Subject: [PATCH 08/13] Fix tagging --- couchpotato/core/media/_base/media/main.py | 3 +++ couchpotato/core/plugins/release/main.py | 7 +------ couchpotato/core/plugins/renamer.py | 3 --- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 84bc564..f8efb7c 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -476,6 +476,9 @@ class MediaPlugin(MediaBase): if previous_status != m['status']: db.update(m) + # Tag media as recent + self.tag(media_id, 'recent') + return m['status'] except: log.error('Failed restatus: %s', traceback.format_exc()) diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 628bd69..404dede 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -338,12 +338,7 @@ class Release(Plugin): self.updateStatus(rls['_id'], status = 'done') # Mark media done - mdia = db.get('id', media['_id']) - mdia['status'] = 'done' - mdia['last_edit'] = int(time.time()) - db.update(mdia) - - fireEvent('media.tag', media['_id'], 'recent', single = True) + fireEvent('media.restatus', media['_id'], single = True) return True diff --git a/couchpotato/core/plugins/renamer.py b/couchpotato/core/plugins/renamer.py index 824aa79..6c6d6b8 100644 --- a/couchpotato/core/plugins/renamer.py +++ b/couchpotato/core/plugins/renamer.py @@ -460,9 +460,6 @@ class Renamer(Plugin): else: log.debug('Media has no quality profile: %s', media_title) - # # List movie on dashboard - # fireEvent('media.tag', media['_id'], 'recent', single = True) - # Mark media for dashboard mark_as_recent = False From b4e25d434501512f0d7a06384b798d5a8a9e1650 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 23 Jun 2014 21:50:23 +0200 Subject: [PATCH 09/13] Indent fixes --- couchpotato/core/media/_base/media/main.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index f8efb7c..c0639d2 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -458,17 +458,17 @@ class MediaPlugin(MediaBase): m['status'] = 'active' try: - profile = db.get('id', m['profile_id']) - media_releases = fireEvent('release.for_media', m['_id'], single = True) - done_releases = [release for release in media_releases if release.get('status') == 'done'] + profile = db.get('id', m['profile_id']) + media_releases = fireEvent('release.for_media', m['_id'], single = True) + done_releases = [release for release in media_releases if release.get('status') == 'done'] - if done_releases: - # Only look at latest added release - release = sorted(done_releases, key = itemgetter('last_edit'), reverse = True)[0] + if done_releases: + # Only look at latest added release + release = sorted(done_releases, key = itemgetter('last_edit'), reverse = True)[0] - # Check if we are finished with the media - if fireEvent('quality.isfinish', {'identifier': release['quality'], 'is_3d': release.get('is_3d', False)}, profile, timedelta(seconds = time.time() - release['last_edit']).days, single = True): - m['status'] = 'done' + # Check if we are finished with the media + if fireEvent('quality.isfinish', {'identifier': release['quality'], 'is_3d': release.get('is_3d', False)}, profile, timedelta(seconds = time.time() - release['last_edit']).days, single = True): + m['status'] = 'done' except RecordNotFound: log.debug('Failed restatus: %s', traceback.format_exc()) From 508649e6b6d4f387fa556d1b7246572d6e1150a9 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 23 Jun 2014 21:51:14 +0200 Subject: [PATCH 10/13] Optimize import --- couchpotato/__init__.py | 7 ++++--- couchpotato/core/downloaders/rtorrent_.py | 1 - couchpotato/core/media/movie/suggestion/main.py | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/couchpotato/__init__.py b/couchpotato/__init__.py index fb6b4dc..daa93bc 100644 --- a/couchpotato/__init__.py +++ b/couchpotato/__init__.py @@ -1,3 +1,7 @@ +import os +import time +import traceback + from couchpotato.api import api_docs, api_docs_missing, api from couchpotato.core.event import fireEvent from couchpotato.core.helpers.variable import md5, tryInt @@ -5,9 +9,6 @@ from couchpotato.core.logger import CPLog from couchpotato.environment import Env from tornado import template from tornado.web import RequestHandler, authenticated -import os -import time -import traceback log = CPLog(__name__) diff --git a/couchpotato/core/downloaders/rtorrent_.py b/couchpotato/core/downloaders/rtorrent_.py index 822501a..7474697 100644 --- a/couchpotato/core/downloaders/rtorrent_.py +++ b/couchpotato/core/downloaders/rtorrent_.py @@ -5,7 +5,6 @@ from urlparse import urlparse import os from couchpotato.core._base.downloader.main import DownloaderBase, ReleaseDownloadList - from couchpotato.core.event import addEvent from couchpotato.core.helpers.encoding import sp from couchpotato.core.helpers.variable import cleanHost, splitString diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index c2cc907..146a6a0 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -1,4 +1,3 @@ -from couchpotato import get_db from couchpotato.api import addApiView from couchpotato.core.event import fireEvent from couchpotato.core.helpers.variable import splitString, removeDuplicate, getIdentifier From d2271055274f0fa8d048dfa6b19e375070c1216b Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 23 Jun 2014 22:04:42 +0200 Subject: [PATCH 11/13] Make keep search advanced --- .../core/plugins/profile/static/profile.css | 5 ++--- couchpotato/core/plugins/profile/static/profile.js | 24 ++++++++++------------ couchpotato/static/style/settings.css | 4 +++- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/couchpotato/core/plugins/profile/static/profile.css b/couchpotato/core/plugins/profile/static/profile.css index f8a1b42..edab831 100644 --- a/couchpotato/core/plugins/profile/static/profile.css +++ b/couchpotato/core/plugins/profile/static/profile.css @@ -43,9 +43,8 @@ } .profile .wait_for { - position: absolute; - right: 60px; - top: 0; + padding-top: 0; + padding-bottom: 20px; } .profile .wait_for input { diff --git a/couchpotato/core/plugins/profile/static/profile.js b/couchpotato/core/plugins/profile/static/profile.js index 5ce6eaf..20c706d 100644 --- a/couchpotato/core/plugins/profile/static/profile.js +++ b/couchpotato/core/plugins/profile/static/profile.js @@ -37,15 +37,6 @@ var Profile = new Class({ 'placeholder': 'Profile name' }) ), - new Element('div.wait_for.ctrlHolder').adopt( - new Element('span', {'text':'Wait'}), - new Element('input.inlay.xsmall', { - 'type':'text', - 'value': data.wait_for && data.wait_for.length > 0 ? data.wait_for[0] : 0 - }), - new Element('span', {'text':'day(s) for a better quality.'}) - // "Wait the entered number of days for a checked quality, before downloading a lower quality release." - ), new Element('div.qualities.ctrlHolder').adopt( new Element('label', {'text': 'Search for'}), self.type_container = new Element('ol.types'), @@ -53,14 +44,21 @@ var Profile = new Class({ 'html': "Search these qualities (2 minimum), from top to bottom. Use the checkbox, to stop searching after it found this quality." }) ), - new Element('div.stop_after.ctrlHolder').adopt( - new Element('span', {'text':'Keep searching'}), + new Element('div.wait_for.ctrlHolder').adopt( + // "Wait the entered number of days for a checked quality, before downloading a lower quality release." + new Element('span', {'text':'Wait'}), new Element('input.inlay.xsmall', { 'type':'text', - 'value': data.stop_after && data.stop_after.length > 0 ? data.stop_after[0] : 0 + 'value': data.wait_for && data.wait_for.length > 0 ? data.wait_for[0] : 0 }), - new Element('span', {'text':'day(s) for a better checked quality.'}) + new Element('span', {'text':'day(s) for a better quality '}), + new Element('span.advanced', {'text':'and keep searching'}), // "After a checked quality is found and downloaded, continue searching for even better quality releases for the entered number of days." + new Element('input.inlay.xsmall.advanced', { + 'type':'text', + 'value': data.stop_after && data.stop_after.length > 0 ? data.stop_after[0] : 0 + }), + new Element('span.advanced', {'text':'day(s) for a better (checked) quality.'}) ) ); diff --git a/couchpotato/static/style/settings.css b/couchpotato/static/style/settings.css index 50b305e..7fb1df2 100644 --- a/couchpotato/static/style/settings.css +++ b/couchpotato/static/style/settings.css @@ -75,6 +75,8 @@ color: #edc07f; } .page.show_advanced .advanced { display: block; } + .page.show_advanced span.advanced, + .page.show_advanced input.advanced { display: inline; } .page.settings .tab_content { display: none; @@ -176,7 +178,7 @@ padding: 6px 0 0; } - .page .xsmall { width: 20px !important; text-align: center; } + .page .xsmall { width: 25px !important; text-align: center; } .page .enabler { display: block; From 4008cce12f5705886fe210407a378ba277d6ec91 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 23 Jun 2014 23:37:17 +0200 Subject: [PATCH 12/13] Manually get media with status --- couchpotato/core/media/_base/media/main.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index c0639d2..06f1661 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -167,8 +167,15 @@ class MediaPlugin(MediaBase): status = list(status if isinstance(status, (list, tuple)) else [status]) for s in status: - for ms in db.get_many('media_status', s, with_doc = with_doc): - yield ms['doc'] if with_doc else ms + for ms in db.get_many('media_status', s): + if with_doc: + try: + doc = db.get('id', ms['_id']) + yield doc + except RecordNotFound: + log.debug('Record not found, skipping: %s', ms['_id']) + else: + yield ms def withIdentifiers(self, identifiers, with_doc = False): From 5425fcae9eb65b66a8892e29e91690b9225863e1 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 23 Jun 2014 23:40:36 +0200 Subject: [PATCH 13/13] Manually get with_status releases --- couchpotato/core/plugins/release/main.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 404dede..b92816c 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -3,7 +3,7 @@ import os import time import traceback -from CodernityDB.database import RecordDeleted +from CodernityDB.database import RecordDeleted, RecordNotFound from couchpotato import md5, get_db from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, addEvent @@ -501,8 +501,15 @@ class Release(Plugin): status = list(status if isinstance(status, (list, tuple)) else [status]) for s in status: - for ms in db.get_many('release_status', s, with_doc = with_doc): - yield ms['doc'] if with_doc else ms + for ms in db.get_many('release_status', s): + if with_doc: + try: + doc = db.get('id', ms['_id']) + yield doc + except RecordNotFound: + log.debug('Record not found, skipping: %s', ms['_id']) + else: + yield ms def forMedia(self, media_id):