Add 3d support for searching
This commit is contained in:
1 parent
98183ccc1e
commit
77a3552797
6 files changed
+71
-12
No files matched your search
@@ -17,6 +17,7 @@ class Searcher(SearcherBase):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('searcher.protocols', self.getSearchProtocols)
|
addEvent('searcher.protocols', self.getSearchProtocols)
|
||||||
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
|
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
|
||||||
|
addEvent('searcher.correct_3d', self.correct3D)
|
||||||
addEvent('searcher.correct_year', self.correctYear)
|
addEvent('searcher.correct_year', self.correctYear)
|
||||||
addEvent('searcher.correct_name', self.correctName)
|
addEvent('searcher.correct_name', self.correctName)
|
||||||
addEvent('searcher.correct_words', self.correctWords)
|
addEvent('searcher.correct_words', self.correctWords)
|
||||||
@@ -123,6 +124,17 @@ class Searcher(SearcherBase):
|
|||||||
|
|
||||||
return not (found.get(preferred_quality['identifier']) and len(found) == 1)
|
return not (found.get(preferred_quality['identifier']) and len(found) == 1)
|
||||||
|
|
||||||
|
def correct3D(self, nzb, preferred_quality = None):
|
||||||
|
if not preferred_quality: preferred_quality = {}
|
||||||
|
if not preferred_quality.get('custom'): return
|
||||||
|
|
||||||
|
threed = preferred_quality['custom'].get('3d')
|
||||||
|
|
||||||
|
# Try guessing via quality tags
|
||||||
|
guess = fireEvent('quality.guess', [nzb.get('name')], single = True)
|
||||||
|
|
||||||
|
return threed == guess.get('is_3d')
|
||||||
|
|
||||||
def correctYear(self, haystack, year, year_range):
|
def correctYear(self, haystack, year, year_range):
|
||||||
|
|
||||||
if not isinstance(haystack, (list, tuple, set)):
|
if not isinstance(haystack, (list, tuple, set)):
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ MA.Release = new Class({
|
|||||||
}).adopt(
|
}).adopt(
|
||||||
new Element('span.name', {'text': release_name, 'title': release_name}),
|
new Element('span.name', {'text': release_name, 'title': release_name}),
|
||||||
new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}),
|
new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}),
|
||||||
new Element('span.quality', {'text': quality.label || 'n/a'}),
|
new Element('span.quality', {'text': quality.label + (release.is_3d ? ' 3D' : '') || 'n/a'}),
|
||||||
new Element('span.size', {'text': info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}),
|
new Element('span.size', {'text': info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}),
|
||||||
new Element('span.age', {'text': self.get(release, 'age')}),
|
new Element('span.age', {'text': self.get(release, 'age')}),
|
||||||
new Element('span.score', {'text': self.get(release, 'score')}),
|
new Element('span.score', {'text': self.get(release, 'score')}),
|
||||||
|
|||||||
@@ -143,14 +143,17 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
|
|
||||||
ret = False
|
ret = False
|
||||||
|
|
||||||
|
index = 0
|
||||||
for q_identifier in profile.get('qualities'):
|
for q_identifier in profile.get('qualities'):
|
||||||
index = profile['qualities'].index(q_identifier)
|
|
||||||
quality_custom = {
|
quality_custom = {
|
||||||
'quality': q_identifier,
|
'quality': q_identifier,
|
||||||
'finish': profile['finish'][index],
|
'finish': profile['finish'][index],
|
||||||
'wait_for': profile['wait_for'][index]
|
'wait_for': profile['wait_for'][index],
|
||||||
|
'3d': profile['3d'][index] if profile['3d'] else False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
if not self.conf('always_search') and not self.couldBeReleased(q_identifier in pre_releases, release_dates, movie['info']['year']):
|
if not self.conf('always_search') and not self.couldBeReleased(q_identifier in pre_releases, release_dates, movie['info']['year']):
|
||||||
too_early_to_search.append(q_identifier)
|
too_early_to_search.append(q_identifier)
|
||||||
continue
|
continue
|
||||||
@@ -168,6 +171,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
quality = fireEvent('quality.single', identifier = q_identifier, single = True)
|
quality = fireEvent('quality.single', identifier = q_identifier, single = True)
|
||||||
log.info('Search for %s in %s', (default_title, quality['label']))
|
log.info('Search for %s in %s', (default_title, quality['label']))
|
||||||
|
|
||||||
|
# Extend quality with profile customs
|
||||||
|
quality['custom'] = quality_custom
|
||||||
|
|
||||||
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
||||||
if len(results) == 0:
|
if len(results) == 0:
|
||||||
log.debug('Nothing found for %s in %s', (default_title, quality['label']))
|
log.debug('Nothing found for %s in %s', (default_title, quality['label']))
|
||||||
@@ -221,13 +227,17 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
if not fireEvent('searcher.correct_words', nzb['name'], media, single = True):
|
if not fireEvent('searcher.correct_words', nzb['name'], media, single = True):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
preferred_quality = fireEvent('quality.single', identifier = quality['identifier'], single = True)
|
preferred_quality = quality if quality else fireEvent('quality.single', identifier = quality['identifier'], single = True)
|
||||||
|
|
||||||
# Contains lower quality string
|
# Contains lower quality string
|
||||||
if fireEvent('searcher.contains_other_quality', nzb, movie_year = media['info']['year'], preferred_quality = preferred_quality, single = True):
|
if fireEvent('searcher.contains_other_quality', nzb, movie_year = media['info']['year'], preferred_quality = preferred_quality, single = True):
|
||||||
log.info2('Wrong: %s, looking for %s', (nzb['name'], quality['label']))
|
log.info2('Wrong: %s, looking for %s', (nzb['name'], quality['label']))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Contains lower quality string
|
||||||
|
if not fireEvent('searcher.correct_3d', nzb, preferred_quality = preferred_quality, single = True):
|
||||||
|
log.info2('Wrong: %s, %slooking for %s in 3D', (nzb['name'], ('' if preferred_quality['custom'].get('3d') else 'NOT '), quality['label']))
|
||||||
|
return False
|
||||||
|
|
||||||
# File to small
|
# File to small
|
||||||
if nzb['size'] and tryInt(preferred_quality['size_min']) > tryInt(nzb['size']):
|
if nzb['size'] and tryInt(preferred_quality['size_min']) > tryInt(nzb['size']):
|
||||||
|
|||||||
@@ -188,11 +188,11 @@ class ProfilePlugin(Plugin):
|
|||||||
'qualities': ['dvdrip', 'dvdr']
|
'qualities': ['dvdrip', 'dvdr']
|
||||||
}, {
|
}, {
|
||||||
'label': 'Prefer 3D HD',
|
'label': 'Prefer 3D HD',
|
||||||
'qualities': ['720p', '1080p', '720p', '1080p'],
|
'qualities': ['1080p', '720p', '720p', '1080p'],
|
||||||
'3d': [True, True]
|
'3d': [True, True]
|
||||||
}, {
|
}, {
|
||||||
'label': '3D HD',
|
'label': '3D HD',
|
||||||
'qualities': ['720p', '1080p'],
|
'qualities': ['1080p', '720p'],
|
||||||
'3d': [True, True]
|
'3d': [True, True]
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
|||||||
@@ -190,14 +190,19 @@ class QualityPlugin(Plugin):
|
|||||||
# Start with 0
|
# Start with 0
|
||||||
score = {}
|
score = {}
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
score[quality.get('identifier')] = 0
|
score[quality.get('identifier')] = {
|
||||||
|
'score': 0,
|
||||||
|
'3d': {}
|
||||||
|
}
|
||||||
|
|
||||||
for cur_file in files:
|
for cur_file in files:
|
||||||
words = re.split('\W+', cur_file.lower())
|
words = re.split('\W+', cur_file.lower())
|
||||||
|
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
contains_score = self.containsTagScore(quality, words, cur_file)
|
contains_score = self.containsTagScore(quality, words, cur_file)
|
||||||
self.calcScore(score, quality, contains_score)
|
threedscore = self.contains3D(quality, words, cur_file) if quality.get('allow_3d') else (0, None)
|
||||||
|
|
||||||
|
self.calcScore(score, quality, contains_score, threedscore)
|
||||||
|
|
||||||
# Try again with loose testing
|
# Try again with loose testing
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
@@ -213,10 +218,13 @@ class QualityPlugin(Plugin):
|
|||||||
if not has_non_zero:
|
if not has_non_zero:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
heighest_quality = max(score, key = score.get)
|
heighest_quality = max(score, key = lambda p: score[p]['score'])
|
||||||
if heighest_quality:
|
if heighest_quality:
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
if quality.get('identifier') == heighest_quality:
|
if quality.get('identifier') == heighest_quality:
|
||||||
|
quality['is_3d'] = False
|
||||||
|
if score[heighest_quality].get('3d'):
|
||||||
|
quality['is_3d'] = True
|
||||||
return self.setCache(cache_key, quality)
|
return self.setCache(cache_key, quality)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -260,6 +268,23 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
|
def contains3D(self, quality, words, cur_file = ''):
|
||||||
|
cur_file = ss(cur_file)
|
||||||
|
|
||||||
|
for key in self.threed_tags:
|
||||||
|
tags = self.threed_tags.get(key, [])
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
if (isinstance(tag, tuple) and '.'.join(tag) in '.'.join(words)) or (isinstance(tag, (str, unicode)) and ss(tag.lower()) in cur_file.lower()):
|
||||||
|
log.debug('Found %s in %s', (tag, cur_file))
|
||||||
|
return 1, key
|
||||||
|
|
||||||
|
if list(set([key]) & set(words)):
|
||||||
|
log.debug('Found %s in %s', (tag, cur_file))
|
||||||
|
return 1, key
|
||||||
|
|
||||||
|
return 0, None
|
||||||
|
|
||||||
def guessLooseScore(self, quality, extra = None):
|
def guessLooseScore(self, quality, extra = None):
|
||||||
|
|
||||||
score = 0
|
score = 0
|
||||||
@@ -282,9 +307,16 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
def calcScore(self, score, quality, add_score):
|
def calcScore(self, score, quality, add_score, threedscore = (0, None)):
|
||||||
|
|
||||||
score[quality['identifier']] += add_score
|
score[quality['identifier']]['score'] += add_score
|
||||||
|
|
||||||
|
threedscore, threedtag = threedscore
|
||||||
|
if threedscore and threedtag:
|
||||||
|
if threedscore not in score[quality['identifier']]['3d']:
|
||||||
|
score[quality['identifier']]['3d'][threedtag] = 0
|
||||||
|
|
||||||
|
score[quality['identifier']]['3d'][threedtag] += threedscore
|
||||||
|
|
||||||
# Set order for allow calculation (and cache)
|
# Set order for allow calculation (and cache)
|
||||||
if not self.cached_order:
|
if not self.cached_order:
|
||||||
@@ -294,7 +326,7 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
if add_score != 0:
|
if add_score != 0:
|
||||||
for allow in quality.get('allow', []):
|
for allow in quality.get('allow', []):
|
||||||
score[allow] -= 40 if self.cached_order[allow] < self.cached_order[quality['identifier']] else 5
|
score[allow]['score'] -= 40 if self.cached_order[allow] < self.cached_order[quality['identifier']] else 5
|
||||||
|
|
||||||
def doTest(self):
|
def doTest(self):
|
||||||
|
|
||||||
|
|||||||
@@ -343,6 +343,10 @@ class Release(Plugin):
|
|||||||
|
|
||||||
found_releases = []
|
found_releases = []
|
||||||
|
|
||||||
|
is_3d = False
|
||||||
|
try: is_3d = quality['custom']['3d']
|
||||||
|
except: pass
|
||||||
|
|
||||||
for rel in search_results:
|
for rel in search_results:
|
||||||
|
|
||||||
rel_identifier = md5(rel['url'])
|
rel_identifier = md5(rel['url'])
|
||||||
@@ -353,6 +357,7 @@ class Release(Plugin):
|
|||||||
'identifier': rel_identifier,
|
'identifier': rel_identifier,
|
||||||
'media_id': media.get('_id'),
|
'media_id': media.get('_id'),
|
||||||
'quality': quality.get('identifier'),
|
'quality': quality.get('identifier'),
|
||||||
|
'is_3d': is_3d,
|
||||||
'status': rel.get('status', 'available'),
|
'status': rel.get('status', 'available'),
|
||||||
'last_edit': int(time.time()),
|
'last_edit': int(time.time()),
|
||||||
'info': {}
|
'info': {}
|
||||||
|
|||||||
Reference in new issue
Block a user