You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.8 KiB
121 lines
3.8 KiB
12 years ago
|
import pprint
|
||
|
from caper import Caper
|
||
|
from couchpotato import CPLog, tryInt
|
||
|
from couchpotato.core.event import addEvent, fireEvent
|
||
|
from couchpotato.core.helpers.variable import possibleTitles
|
||
|
from couchpotato.core.plugins.base import Plugin
|
||
|
|
||
|
log = CPLog(__name__)
|
||
|
|
||
|
|
||
|
class Matcher(Plugin):
|
||
|
def __init__(self):
|
||
|
self.caper = Caper()
|
||
|
|
||
|
addEvent('matcher.parse', self.parse)
|
||
|
addEvent('matcher.best', self.best)
|
||
|
|
||
|
addEvent('matcher.correct_title', self.correctTitle)
|
||
|
addEvent('matcher.correct_identifier', self.correctIdentifier)
|
||
|
addEvent('matcher.correct_quality', self.correctQuality)
|
||
|
|
||
|
def parse(self, release):
|
||
|
return self.caper.parse(release['name'])
|
||
|
|
||
|
def best(self, release, media, quality):
|
||
|
rel_info = fireEvent('matcher.parse', release, single = True)
|
||
|
|
||
|
if len(rel_info.chains) < 1:
|
||
|
log.info2('Wrong: %s, unable to parse release name (no chains)', release['name'])
|
||
|
return False
|
||
|
|
||
|
for chain in rel_info.chains:
|
||
|
if fireEvent('searcher.correct_match', chain, release, media, quality, single = True):
|
||
|
return chain
|
||
|
|
||
|
return None
|
||
|
|
||
|
def chainMatches(self, chain, group, tags):
|
||
|
found_tags = []
|
||
|
|
||
|
for match in chain.info[group]:
|
||
|
for ck, cv in match.items():
|
||
|
if ck in tags and self.cleanMatchValue(cv) in tags[ck]:
|
||
|
found_tags.append(ck)
|
||
|
|
||
|
|
||
|
if set(tags.keys()) == set(found_tags):
|
||
|
return True
|
||
|
|
||
|
return set([key for key, value in tags.items() if None not in value]) == set(found_tags)
|
||
|
|
||
|
def cleanMatchValue(self, value):
|
||
|
value = value.lower()
|
||
|
value = value.strip()
|
||
|
|
||
|
for ch in [' ', '-', '.']:
|
||
|
value = value.replace(ch, '')
|
||
|
|
||
|
return value
|
||
|
|
||
|
def dictIsSubset(self, a, b):
|
||
|
return all([k in b and b[k] == v for k, v in a.items()])
|
||
|
|
||
|
def correctIdentifier(self, chain, media):
|
||
|
required_id = fireEvent('searcher.get_media_identifier', media['library'], single = True)
|
||
|
|
||
|
if 'identifier' not in chain.info:
|
||
|
return False
|
||
|
|
||
|
# TODO could be handled better?
|
||
|
if len(chain.info['identifier']) != 1:
|
||
|
return False
|
||
|
identifier = chain.info['identifier'][0]
|
||
|
|
||
|
# TODO air by date episodes
|
||
|
|
||
|
# TODO this should support identifiers with characters 'a', 'b', etc..
|
||
|
for k, v in identifier.items():
|
||
|
identifier[k] = tryInt(v, None)
|
||
|
|
||
|
if not self.dictIsSubset(required_id, identifier):
|
||
|
log.info2('Wrong: required identifier %s does not match release identifier %s', (str(required_id), str(identifier)))
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
def correctTitle(self, chain, media):
|
||
|
root_library = fireEvent('searcher.get_media_root', media['library'], single = True)
|
||
|
|
||
|
if 'show_name' not in chain.info or not len(chain.info['show_name']):
|
||
|
log.info('Wrong: missing show name in parsed result')
|
||
|
return False
|
||
|
|
||
|
chain_words = [x.lower() for x in chain.info['show_name']]
|
||
|
|
||
|
# Check show titles match
|
||
|
for title in root_library['info']['titles']:
|
||
|
for valid_words in [x.split(' ') for x in possibleTitles(title)]:
|
||
|
|
||
|
if valid_words == chain_words:
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
def correctQuality(self, chain, quality, quality_map):
|
||
|
if quality['identifier'] not in quality_map:
|
||
|
log.info2('Wrong: unknown preferred quality %s', quality['identifier'])
|
||
|
return False
|
||
|
|
||
|
if 'video' not in chain.info:
|
||
|
log.info2('Wrong: no video tags found')
|
||
|
return False
|
||
|
|
||
|
video_tags = quality_map[quality['identifier']]
|
||
|
|
||
|
if not self.chainMatches(chain, 'video', video_tags):
|
||
|
log.info2('Wrong: %s tags not in chain', video_tags)
|
||
|
return False
|
||
|
|
||
|
return True
|