Split ShowMatcher into Episode and Season matchers, updated correctIdentifier method so there should be less false matches now.

This commit is contained in:
Dean Gardiner
2013-12-09 13:32:43 +13:00
parent 93aa5b1920
commit 319c9e979a
4 changed files with 77 additions and 29 deletions

View File

@@ -1,3 +1,4 @@
from couchpotato.core.event import addEvent
from couchpotato.core.helpers.encoding import simplifyString
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
@@ -6,6 +7,15 @@ log = CPLog(__name__)
class MatcherBase(Plugin):
type = None
def __init__(self):
if self.type:
addEvent('%s.matcher.correct' % self.type, self.correct)
def correct(self, chain, release, media, quality):
raise NotImplementedError()
def flattenInfo(self, info):
flat_info = {}

View File

@@ -26,11 +26,8 @@ class SeasonLibraryPlugin(LibraryBase):
if library.get('type') != 'season':
return
season_num = tryInt(library['season_number'], None)
return {
'season': season_num,
'episode': None
'season': tryInt(library['season_number'], None)
}
def add(self, attrs = {}, update_after = True):

View File

@@ -2,14 +2,18 @@ from couchpotato import CPLog
from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.helpers.variable import dictIsSubset, tryInt, toIterable
from couchpotato.core.media._base.matcher.base import MatcherBase
from couchpotato.core.providers.base import MultiProvider
log = CPLog(__name__)
class ShowMatcher(MatcherBase):
class ShowMatcher(MultiProvider):
type = ['show', 'season', 'episode']
def getTypes(self):
return [Season, Episode]
class Base(MatcherBase):
# TODO come back to this later, think this could be handled better, this is starting to get out of hand....
quality_map = {
'bluray_1080p': {'resolution': ['1080p'], 'source': ['bluray']},
@@ -30,11 +34,9 @@ class ShowMatcher(MatcherBase):
}
def __init__(self):
super(ShowMatcher, self).__init__()
super(Base, self).__init__()
for type in toIterable(self.type):
addEvent('%s.matcher.correct' % type, self.correct)
addEvent('%s.matcher.correct_identifier' % type, self.correctIdentifier)
addEvent('%s.matcher.correct_identifier' % self.type, self.correctIdentifier)
def correct(self, chain, release, media, quality):
log.info("Checking if '%s' is valid", release['name'])
@@ -44,7 +46,7 @@ class ShowMatcher(MatcherBase):
log.info('Wrong: %s, quality does not match', release['name'])
return False
if not fireEvent('show.matcher.correct_identifier', chain, media):
if not fireEvent('%s.matcher.correct_identifier' % self.type, chain, media):
log.info('Wrong: %s, identifier does not match', release['name'])
return False
@@ -55,32 +57,71 @@ class ShowMatcher(MatcherBase):
return True
def correctIdentifier(self, chain, media):
required_id = fireEvent('library.identifier', media['library'], single = True)
raise NotImplementedError()
def getChainIdentifier(self, chain):
if 'identifier' not in chain.info:
return None
identifier = self.flattenInfo(chain.info['identifier'])
# Try cast values to integers
for key, value in identifier.items():
if isinstance(value, list):
if len(value) <= 1:
value = value[0]
else:
log.warning('Wrong: identifier contains multiple season or episode values, unsupported')
return None
identifier[key] = tryInt(value, value)
return identifier
class Episode(Base):
type = 'episode'
def correctIdentifier(self, chain, media):
identifier = self.getChainIdentifier(chain)
if not identifier:
log.info2('Wrong: release identifier is not valid (unsupported or missing identifier)')
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)
# TODO - Parse episode ranges from identifier to determine if they are multi-part episodes
if any([x in identifier for x in ['episode_from', 'episode_to']]):
log.info2('Wrong: releases with identifier ranges are not supported yet')
return False
# 'episode' is required in identifier for subset matching
if 'episode' not in identifier:
identifier['episode'] = None
required = fireEvent('library.identifier', media['library'], single = True)
if not dictIsSubset(required_id, identifier):
log.info2('Wrong: required identifier %s does not match release identifier %s', (str(required_id), str(identifier)))
# TODO - Support air by date episodes
# TODO - Support episode parts
if identifier != required:
log.info2('Wrong: required identifier (%s) does not match release identifier (%s)', (required, identifier))
return False
return True
class Season(Base):
type = 'season'
def correctIdentifier(self, chain, media):
identifier = self.getChainIdentifier(chain)
if not identifier:
log.info2('Wrong: release identifier is not valid (unsupported or missing identifier)')
return False
# TODO - Parse episode ranges from identifier to determine if they are season packs
if any([x in identifier for x in ['episode_from', 'episode_to']]):
log.info2('Wrong: releases with identifier ranges are not supported yet')
return False
required = fireEvent('library.identifier', media['library'], single = True)
if identifier != required:
log.info2('Wrong: required identifier (%s) does not match release identifier (%s)', (required, identifier))
return False
return True

View File

@@ -193,7 +193,7 @@ class ShowSearcher(Plugin):
if identifier['season']:
title += ' S%02d' % identifier['season']
if identifier['episode']:
if identifier.get('episode'):
title += 'E%02d' % identifier['episode']
return title