From aa394f59ae8fe3c74f4ef5a1e8e592147fd67363 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 6 Dec 2013 00:49:33 +1300 Subject: [PATCH 1/4] Updated Caper to v0.2.4 --- libs/caper/__init__.py | 2 +- libs/caper/helpers.py | 12 ++++++++++++ libs/caper/matcher.py | 7 +++++-- libs/caper/parsers/scene.py | 5 ++++- libs/caper/result.py | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libs/caper/__init__.py b/libs/caper/__init__.py index 3384d7d..0ebdccc 100644 --- a/libs/caper/__init__.py +++ b/libs/caper/__init__.py @@ -19,7 +19,7 @@ from caper.parsers.anime import AnimeParser from caper.parsers.scene import SceneParser -__version_info__ = ('0', '2', '3') +__version_info__ = ('0', '2', '4') __version_branch__ = 'master' __version__ = "%s%s" % ( diff --git a/libs/caper/helpers.py b/libs/caper/helpers.py index 1a127c3..2b27e57 100644 --- a/libs/caper/helpers.py +++ b/libs/caper/helpers.py @@ -51,6 +51,18 @@ def clean_dict(target, remove=None): return target +def update_dict(a, b): + for key, value in b.items(): + if key not in a: + a[key] = value + elif isinstance(a[key], dict) and isinstance(value, dict): + update_dict(a[key], value) + elif isinstance(a[key], list): + a[key].append(value) + else: + a[key] = [a[key], value] + + def xrange_six(start, stop=None, step=None): if stop is not None and step is not None: if PY3: diff --git a/libs/caper/matcher.py b/libs/caper/matcher.py index 23fdcf9..c71da97 100644 --- a/libs/caper/matcher.py +++ b/libs/caper/matcher.py @@ -14,13 +14,16 @@ import re from logr import Logr -from caper.helpers import is_list_type +from caper.helpers import is_list_type, update_dict class FragmentMatcher(object): def __init__(self, pattern_groups): self.regex = {} + self.construct_patterns(pattern_groups) + + def construct_patterns(self, pattern_groups): for group_name, patterns in pattern_groups: if group_name not in self.regex: self.regex[group_name] = [] @@ -120,7 +123,7 @@ class FragmentMatcher(object): match = fragment_pattern.match(cur_fragment.value) if match: - result.update(match.groupdict()) + update_dict(result, match.groupdict()) else: success = False break diff --git a/libs/caper/parsers/scene.py b/libs/caper/parsers/scene.py index 224a282..44274eb 100644 --- a/libs/caper/parsers/scene.py +++ b/libs/caper/parsers/scene.py @@ -77,9 +77,12 @@ PATTERN_GROUPS = [ 'PDTV', 'DSR', 'DVDRiP', - 'WEBDL' # TODO support 'WEB.DL' tag + 'WEBDL' ]), + # For 'WEB-DL', 'WEB DL', etc... + ('(?PWEB)', '(?PDL)'), + (r'(?P%s)', [ 'x264', 'XViD' diff --git a/libs/caper/result.py b/libs/caper/result.py index 6890021..4d57f89 100644 --- a/libs/caper/result.py +++ b/libs/caper/result.py @@ -95,7 +95,7 @@ class CaperResult(object): self.chains.append(chain) for chain in self.chains: - chain.weights.append(chain.num_matched / float(max_matched)) + chain.weights.append(chain.num_matched / float(max_matched or chain.num_matched)) chain.finish() self.chains.sort(key=lambda chain: chain.weight, reverse=True) From 45484461b50e9ef442af5c893cb466b41e0ff0bd Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 6 Dec 2013 01:17:57 +1300 Subject: [PATCH 2/4] Adjusted Matcher.chainMatch to support 'WEB DL' tags --- couchpotato/core/media/show/searcher/main.py | 4 ++-- couchpotato/core/plugins/matcher/main.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/media/show/searcher/main.py b/couchpotato/core/media/show/searcher/main.py index c4aca7b..1364721 100644 --- a/couchpotato/core/media/show/searcher/main.py +++ b/couchpotato/core/media/show/searcher/main.py @@ -19,8 +19,8 @@ class ShowSearcher(Plugin): # TODO come back to this later, think this could be handled better quality_map = { - 'webdl_1080p': {'resolution': ['1080p'], 'source': ['webdl']}, - 'webdl_720p': {'resolution': ['720p'], 'source': ['webdl']}, + 'webdl_1080p': {'resolution': ['1080p'], 'source': ['webdl', ['web', 'dl']]}, + 'webdl_720p': {'resolution': ['720p'], 'source': ['webdl', ['web', 'dl']]}, 'hdtv_720p': {'resolution': ['720p'], 'source': ['hdtv']}, 'hdtv_sd': {'resolution': ['480p', None], 'source': ['hdtv']}, diff --git a/couchpotato/core/plugins/matcher/main.py b/couchpotato/core/plugins/matcher/main.py index 777f91a..2260f9f 100644 --- a/couchpotato/core/plugins/matcher/main.py +++ b/couchpotato/core/plugins/matcher/main.py @@ -40,9 +40,19 @@ class Matcher(Plugin): for match in chain.info[group]: for ck, cv in match.items(): - if ck in tags and simplifyString(cv) in tags[ck]: + if ck not in tags: + continue + + if isinstance(cv, basestring) and simplifyString(cv) in tags[ck]: found_tags.append(ck) + elif isinstance(cv, list): + simple_list = [simplifyString(x) for x in cv] + + if simple_list in tags[ck]: + found_tags.append(ck) + + log.debug('tags found: %s, required: %s' % (found_tags, tags.keys())) if set(tags.keys()) == set(found_tags): return True From 1bf6c5a82e860b1ec1e6ae40c2537c34e438fb3a Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 6 Dec 2013 13:53:56 +1300 Subject: [PATCH 3/4] Changed 'searcher.get_search_title' to accept a 'library' instead of the 'media' as a parameter. --- couchpotato/core/media/_base/searcher/main.py | 2 +- couchpotato/core/media/movie/searcher/main.py | 8 ++++---- couchpotato/core/media/show/searcher/main.py | 8 ++++---- couchpotato/core/providers/base.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/couchpotato/core/media/_base/searcher/main.py b/couchpotato/core/media/_base/searcher/main.py index 20cb78d..0f76bf8 100644 --- a/couchpotato/core/media/_base/searcher/main.py +++ b/couchpotato/core/media/_base/searcher/main.py @@ -171,7 +171,7 @@ class Searcher(SearcherBase): return False def correctWords(self, rel_name, media): - media_title = fireEvent('searcher.get_search_title', media, single = True) + media_title = fireEvent('searcher.get_search_title', media['library'], single = True) media_words = re.split('\W+', simplifyString(media_title)) rel_name = simplifyString(rel_name) diff --git a/couchpotato/core/media/movie/searcher/main.py b/couchpotato/core/media/movie/searcher/main.py index 1b1177b..744d6ce 100644 --- a/couchpotato/core/media/movie/searcher/main.py +++ b/couchpotato/core/media/movie/searcher/main.py @@ -210,7 +210,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): if media.get('type') != 'movie': return - media_title = fireEvent('searcher.get_search_title', media, single = True) + media_title = fireEvent('searcher.get_search_title', media['library'], single = True) imdb_results = kwargs.get('imdb_results', False) retention = Env.setting('retention', section = 'nzb') @@ -343,9 +343,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase): log.error('Failed searching for next release: %s', traceback.format_exc()) return False - def getSearchTitle(self, media): - if media['type'] == 'movie': - return getTitle(media['library']) + def getSearchTitle(self, library): + if library['type'] == 'movie': + return getTitle(library) class SearchSetupError(Exception): pass diff --git a/couchpotato/core/media/show/searcher/main.py b/couchpotato/core/media/show/searcher/main.py index 1364721..52406b9 100644 --- a/couchpotato/core/media/show/searcher/main.py +++ b/couchpotato/core/media/show/searcher/main.py @@ -133,11 +133,11 @@ class ShowSearcher(Plugin): return ret - def getSearchTitle(self, media): - if media['type'] not in ['show', 'season', 'episode']: + def getSearchTitle(self, library): + if library['type'] not in ['show', 'season', 'episode']: return - show, season, episode = self.getLibraries(media['library']) + show, season, episode = self.getLibraries(library) if not show: return None @@ -173,7 +173,7 @@ class ShowSearcher(Plugin): return None # Add the identifier to search title - identifier = fireEvent('library.identifier', media['library'], single = True) + identifier = fireEvent('library.identifier', library, single = True) # TODO this needs to support other identifier formats if identifier['season']: diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index 82e03ce..9f72df8 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -207,7 +207,7 @@ class YarrProvider(Provider): self._search(media, quality, results) # Search possible titles else: - for title in possibleTitles(fireEvent('searcher.get_search_title', media, single = True)): + for title in possibleTitles(fireEvent('searcher.get_search_title', media['library'], single = True)): self._searchOnTitle(title, media, quality, results) return results From 2fd54901e7dcbca0d2ee9507112bc61bf722f52d Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Fri, 6 Dec 2013 14:04:00 +1300 Subject: [PATCH 4/4] Added optional parameter 'include_identifier' to the 'searcher.get_search_title' event handler. --- couchpotato/core/media/movie/searcher/main.py | 2 +- couchpotato/core/media/show/searcher/main.py | 6 +++++- couchpotato/core/providers/base.py | 4 +++- couchpotato/core/providers/nzb/newznab/main.py | 4 ++-- couchpotato/core/providers/torrent/sceneaccess/main.py | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/couchpotato/core/media/movie/searcher/main.py b/couchpotato/core/media/movie/searcher/main.py index 744d6ce..1fffb23 100644 --- a/couchpotato/core/media/movie/searcher/main.py +++ b/couchpotato/core/media/movie/searcher/main.py @@ -343,7 +343,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase): log.error('Failed searching for next release: %s', traceback.format_exc()) return False - def getSearchTitle(self, library): + def getSearchTitle(self, library, include_identifier = False): if library['type'] == 'movie': return getTitle(library) diff --git a/couchpotato/core/media/show/searcher/main.py b/couchpotato/core/media/show/searcher/main.py index 52406b9..e0527ef 100644 --- a/couchpotato/core/media/show/searcher/main.py +++ b/couchpotato/core/media/show/searcher/main.py @@ -133,7 +133,7 @@ class ShowSearcher(Plugin): return ret - def getSearchTitle(self, library): + def getSearchTitle(self, library, include_identifier = False): if library['type'] not in ['show', 'season', 'episode']: return @@ -172,6 +172,10 @@ class ShowSearcher(Plugin): else: return None + # Return show title if we aren't including the identifier + if not include_identifier: + return title + # Add the identifier to search title identifier = fireEvent('library.identifier', library, single = True) diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index 9f72df8..6ef5938 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -207,7 +207,9 @@ class YarrProvider(Provider): self._search(media, quality, results) # Search possible titles else: - for title in possibleTitles(fireEvent('searcher.get_search_title', media['library'], single = True)): + media_title = fireEvent('searcher.get_search_title', media['library'], include_identifier = True, single = True) + + for title in possibleTitles(media_title): self._searchOnTitle(title, media, quality, results) return results diff --git a/couchpotato/core/providers/nzb/newznab/main.py b/couchpotato/core/providers/nzb/newznab/main.py index 565689b..64e999a 100644 --- a/couchpotato/core/providers/nzb/newznab/main.py +++ b/couchpotato/core/providers/nzb/newznab/main.py @@ -191,7 +191,7 @@ class Movie(MovieProvider, Base): class Season(SeasonProvider, Base): def buildUrl(self, media, api_key): - search_title = fireEvent('searcher.get_search_title', media['library']['root_library']) + search_title = fireEvent('searcher.get_search_title', media['library']) identifier = fireEvent('library.identifier', media['library']) query = tryUrlencode({ @@ -206,7 +206,7 @@ class Season(SeasonProvider, Base): class Episode(EpisodeProvider, Base): def buildUrl(self, media, api_key): - search_title = fireEvent('searcher.get_search_title', media['library']['root_library']) + search_title = fireEvent('searcher.get_search_title', media['library']) identifier = fireEvent('library.identifier', media['library']) query = tryUrlencode({ diff --git a/couchpotato/core/providers/torrent/sceneaccess/main.py b/couchpotato/core/providers/torrent/sceneaccess/main.py index 5db25ba..073e2c6 100644 --- a/couchpotato/core/providers/torrent/sceneaccess/main.py +++ b/couchpotato/core/providers/torrent/sceneaccess/main.py @@ -122,7 +122,7 @@ class Season(SeasonProvider, Base): ] def buildUrl(self, media, quality): - return self._buildUrl(fireEvent('searcher.get_search_title', media['library']['root_library']), quality['identifier']) + return self._buildUrl(fireEvent('searcher.get_search_title', media['library']), quality['identifier']) class Episode(EpisodeProvider, Base): @@ -132,4 +132,4 @@ class Episode(EpisodeProvider, Base): ] def buildUrl(self, media, quality): - return self._buildUrl(fireEvent('searcher.get_search_title', media['library']['root_library']), quality['identifier']) \ No newline at end of file + return self._buildUrl(fireEvent('searcher.get_search_title', media['library']), quality['identifier']) \ No newline at end of file