diff --git a/couchpotato/core/media/_base/matcher/base.py b/couchpotato/core/media/_base/matcher/base.py index c4b59b2..8651126 100644 --- a/couchpotato/core/media/_base/matcher/base.py +++ b/couchpotato/core/media/_base/matcher/base.py @@ -17,16 +17,42 @@ class MatcherBase(Plugin): raise NotImplementedError() def flattenInfo(self, info): - flat_info = {} + # Flatten dictionary of matches (chain info) + if isinstance(info, dict): + return dict([(key, self.flattenInfo(value)) for key, value in info.items()]) + + # Flatten matches + result = None for match in info: - for key, value in match.items(): - if key not in flat_info: - flat_info[key] = [] + if isinstance(match, dict): + if result is None: + result = {} + + for key, value in match.items(): + if key not in result: + result[key] = [] + + result[key].append(value) + else: + if result is None: + result = [] + + result.append(match) + + return result + + def constructFromRaw(self, match): + if not match: + return None - flat_info[key].append(value) + parts = [ + ''.join([ + y for y in x[1:] if y + ]) for x in match + ] - return flat_info + return ''.join(parts)[:-1].strip() def simplifyValue(self, value): if not value: diff --git a/couchpotato/core/media/_base/matcher/main.py b/couchpotato/core/media/_base/matcher/main.py index 9cc8c1a..12e3d6a 100644 --- a/couchpotato/core/media/_base/matcher/main.py +++ b/couchpotato/core/media/_base/matcher/main.py @@ -16,6 +16,9 @@ class Matcher(MatcherBase): addEvent('matcher.parse', self.parse) addEvent('matcher.match', self.match) + addEvent('matcher.flatten_info', self.flattenInfo) + addEvent('matcher.construct_from_raw', self.constructFromRaw) + addEvent('matcher.correct_title', self.correctTitle) addEvent('matcher.correct_quality', self.correctQuality) diff --git a/couchpotato/core/providers/nzb/nzbindex/main.py b/couchpotato/core/providers/nzb/nzbindex/main.py index abc59a5..7343542 100644 --- a/couchpotato/core/providers/nzb/nzbindex/main.py +++ b/couchpotato/core/providers/nzb/nzbindex/main.py @@ -38,6 +38,35 @@ class Base(NZBProvider, RSS): enclosure = self.getElement(nzb, 'enclosure').attrib nzbindex_id = int(self.getTextElement(nzb, "link").split('/')[4]) + title = self.getTextElement(nzb, "title") + + match = fireEvent('matcher.parse', title, parser='usenet', single = True) + if not match.chains: + log.info('Unable to parse release with title "%s"', title) + continue + + # TODO should we consider other lower-weight chains here? + info = fireEvent('matcher.flatten_info', match.chains[0].info, single = True) + + release_name = fireEvent('matcher.construct_from_raw', info.get('release_name'), single = True) + + file_name = info.get('detail', {}).get('file_name') + file_name = file_name[0] if file_name else None + + title = release_name or file_name + + # Strip extension from parsed title (if one exists) + ext_pos = title.rfind('.') + + # Assume extension if smaller than 4 characters + # TODO this should probably be done a better way + if len(title[ext_pos + 1:]) <= 4: + title = title[:ext_pos] + + if not title: + log.info('Unable to find release name from match') + continue + try: description = self.getTextElement(nzb, "description") except: @@ -52,7 +81,7 @@ class Base(NZBProvider, RSS): results.append({ 'id': nzbindex_id, - 'name': self.getTextElement(nzb, "title"), + 'name': title, 'age': self.calculateAge(int(time.mktime(parse(self.getTextElement(nzb, "pubDate")).timetuple()))), 'size': tryInt(enclosure['length']) / 1024 / 1024, 'url': enclosure['url'], @@ -74,7 +103,7 @@ class Base(NZBProvider, RSS): class Movie(MovieProvider, Base): - def buildUrl(self, media): + def buildUrl(self, media, quality): title = fireEvent('searcher.get_search_title', media['library'], single = True) year = media['library']['year']