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