Extended providers to support multiple media types
- 'cat_ids' now support media type groups - 'type' extended to allow a list of support media types - Added 'searcher.get_search_title' to return a title for media to be used in searches.
This commit is contained in:
1 parent
bc51e263e1
commit
5fdf4d9085
5 files changed
+102
-34
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
|
import collections
|
||||||
from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss
|
from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
import hashlib
|
import hashlib
|
||||||
@@ -163,6 +164,11 @@ def natsortKey(s):
|
|||||||
def natcmp(a, b):
|
def natcmp(a, b):
|
||||||
return cmp(natsortKey(a), natsortKey(b))
|
return cmp(natsortKey(a), natsortKey(b))
|
||||||
|
|
||||||
|
def toIterable(value):
|
||||||
|
if isinstance(value, collections.Iterable):
|
||||||
|
return value
|
||||||
|
return [value]
|
||||||
|
|
||||||
def getTitle(library_dict):
|
def getTitle(library_dict):
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
addEvent('movie.searcher.correct_movie', self.correctMovie)
|
addEvent('movie.searcher.correct_movie', self.correctMovie)
|
||||||
addEvent('movie.searcher.try_next_release', self.tryNextRelease)
|
addEvent('movie.searcher.try_next_release', self.tryNextRelease)
|
||||||
addEvent('movie.searcher.could_be_released', self.couldBeReleased)
|
addEvent('movie.searcher.could_be_released', self.couldBeReleased)
|
||||||
|
addEvent('searcher.get_search_title', self.getSearchTitle)
|
||||||
|
|
||||||
addApiView('movie.searcher.try_next', self.tryNextReleaseView, docs = {
|
addApiView('movie.searcher.try_next', self.tryNextReleaseView, docs = {
|
||||||
'desc': 'Marks the snatched results as ignored and try the next best release',
|
'desc': 'Marks the snatched results as ignored and try the next best release',
|
||||||
@@ -434,5 +435,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
log.error('Failed searching for next release: %s', traceback.format_exc())
|
log.error('Failed searching for next release: %s', traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def getSearchTitle(self, media):
|
||||||
|
if media['type'] == 'movie':
|
||||||
|
return getTitle(media['library'])
|
||||||
|
|
||||||
class SearchSetupError(Exception):
|
class SearchSetupError(Exception):
|
||||||
pass
|
pass
|
||||||
@@ -17,12 +17,27 @@ class ShowSearcher(Plugin):
|
|||||||
super(ShowSearcher, self).__init__()
|
super(ShowSearcher, self).__init__()
|
||||||
|
|
||||||
addEvent('show.searcher.single', self.single)
|
addEvent('show.searcher.single', self.single)
|
||||||
|
addEvent('searcher.get_search_title', self.getSearchTitle)
|
||||||
|
|
||||||
def _get_search_protocols(self):
|
def _lookupMedia(self, media):
|
||||||
try:
|
db = get_session()
|
||||||
return fireEvent('searcher.protocols', single = True)
|
|
||||||
except SearchSetupError:
|
media_library = db.query(Media).filter_by(id = media['id']).first().library
|
||||||
return None
|
|
||||||
|
show = None
|
||||||
|
season = None
|
||||||
|
episode = None
|
||||||
|
|
||||||
|
if media['type'] == 'episode':
|
||||||
|
show = media_library.parent.parent
|
||||||
|
season = media_library.parent
|
||||||
|
episode = media_library
|
||||||
|
|
||||||
|
if media['type'] == 'season':
|
||||||
|
show = media_library.parent
|
||||||
|
season = media_library
|
||||||
|
|
||||||
|
return show, season, episode
|
||||||
|
|
||||||
def single(self, media, search_protocols = None):
|
def single(self, media, search_protocols = None):
|
||||||
if media['type'] == 'show':
|
if media['type'] == 'show':
|
||||||
@@ -30,8 +45,10 @@ class ShowSearcher(Plugin):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Find out search type
|
# Find out search type
|
||||||
search_protocols = self._get_search_protocols() if not search_protocols else None
|
try:
|
||||||
if search_protocols is None:
|
if not search_protocols:
|
||||||
|
search_protocols = fireEvent('searcher.protocols', single = True)
|
||||||
|
except SearchSetupError:
|
||||||
return
|
return
|
||||||
|
|
||||||
done_status = fireEvent('status.get', 'done', single = True)
|
done_status = fireEvent('status.get', 'done', single = True)
|
||||||
@@ -54,18 +71,7 @@ class ShowSearcher(Plugin):
|
|||||||
#fireEvent('episode.delete', episode['id'], single = True)
|
#fireEvent('episode.delete', episode['id'], single = True)
|
||||||
return
|
return
|
||||||
|
|
||||||
media_library = db.query(Media).filter_by(id = media['id']).first().library
|
show, season, episode = self._lookupMedia(media)
|
||||||
|
|
||||||
show = None
|
|
||||||
season = None
|
|
||||||
episode = None
|
|
||||||
if media['type'] == 'episode':
|
|
||||||
show = media_library.parent.parent
|
|
||||||
season = media_library.parent
|
|
||||||
episode = media_library
|
|
||||||
if media['type'] == 'season':
|
|
||||||
show = media_library.parent
|
|
||||||
season = media_library
|
|
||||||
|
|
||||||
fireEvent('notify.frontend', type = 'show.searcher.started.%s' % media['id'], data = True, message = 'Searching for "%s"' % default_title)
|
fireEvent('notify.frontend', type = 'show.searcher.started.%s' % media['id'], data = True, message = 'Searching for "%s"' % default_title)
|
||||||
|
|
||||||
@@ -96,3 +102,24 @@ class ShowSearcher(Plugin):
|
|||||||
results += protocol_results
|
results += protocol_results
|
||||||
|
|
||||||
log.info('%d results found' % len(results))
|
log.info('%d results found' % len(results))
|
||||||
|
|
||||||
|
def getSearchTitle(self, media):
|
||||||
|
if media['type'] not in ['season', 'episode']:
|
||||||
|
return None
|
||||||
|
|
||||||
|
show, season, episode = self._lookupMedia(media)
|
||||||
|
|
||||||
|
if show is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
name = ''
|
||||||
|
if season is not None:
|
||||||
|
name = ' S%02d' % season.season_number
|
||||||
|
|
||||||
|
if episode is not None:
|
||||||
|
name += 'E%02d' % episode.episode_number
|
||||||
|
|
||||||
|
return ''.join([
|
||||||
|
getTitle(show),
|
||||||
|
name
|
||||||
|
])
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from couchpotato.core.event import addEvent, fireEvent
|
from couchpotato.core.event import addEvent, fireEvent
|
||||||
from couchpotato.core.helpers.variable import tryFloat, mergeDicts, md5, \
|
from couchpotato.core.helpers.variable import tryFloat, mergeDicts, md5, \
|
||||||
possibleTitles, getTitle
|
possibleTitles, toIterable
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
@@ -114,7 +114,9 @@ class YarrProvider(Provider):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('provider.enabled_protocols', self.getEnabledProtocol)
|
addEvent('provider.enabled_protocols', self.getEnabledProtocol)
|
||||||
addEvent('provider.belongs_to', self.belongsTo)
|
addEvent('provider.belongs_to', self.belongsTo)
|
||||||
addEvent('provider.search.%s.%s' % (self.protocol, self.type), self.search)
|
|
||||||
|
for type in toIterable(self.type):
|
||||||
|
addEvent('provider.search.%s.%s' % (self.protocol, type), self.search)
|
||||||
|
|
||||||
def getEnabledProtocol(self):
|
def getEnabledProtocol(self):
|
||||||
if self.isEnabled():
|
if self.isEnabled():
|
||||||
@@ -183,7 +185,7 @@ class YarrProvider(Provider):
|
|||||||
|
|
||||||
return 'try_next'
|
return 'try_next'
|
||||||
|
|
||||||
def search(self, movie, quality):
|
def search(self, media, quality):
|
||||||
|
|
||||||
if self.isDisabled():
|
if self.isDisabled():
|
||||||
return []
|
return []
|
||||||
@@ -195,15 +197,15 @@ class YarrProvider(Provider):
|
|||||||
|
|
||||||
# Create result container
|
# Create result container
|
||||||
imdb_results = hasattr(self, '_search')
|
imdb_results = hasattr(self, '_search')
|
||||||
results = ResultList(self, movie, quality, imdb_results = imdb_results)
|
results = ResultList(self, media, quality, imdb_results = imdb_results)
|
||||||
|
|
||||||
# Do search based on imdb id
|
# Do search based on imdb id
|
||||||
if imdb_results:
|
if imdb_results:
|
||||||
self._search(movie, quality, results)
|
self._search(media, quality, results)
|
||||||
# Search possible titles
|
# Search possible titles
|
||||||
else:
|
else:
|
||||||
for title in possibleTitles(getTitle(movie['library'])):
|
for title in possibleTitles(fireEvent('searcher.get_search_title', media, single = True)):
|
||||||
self._searchOnTitle(title, movie, quality, results)
|
self._searchOnTitle(title, media, quality, results)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -244,9 +246,16 @@ class YarrProvider(Provider):
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def getCatId(self, identifier):
|
def getCatId(self, identifier, media_type = 'movie'):
|
||||||
|
|
||||||
for cats in self.cat_ids:
|
cat_ids = self.cat_ids
|
||||||
|
|
||||||
|
if type(toIterable(cat_ids[0][0])[0]) is str:
|
||||||
|
for group_type, group_cat_ids in cat_ids:
|
||||||
|
if media_type in toIterable(group_type):
|
||||||
|
cat_ids = group_cat_ids
|
||||||
|
|
||||||
|
for cats in cat_ids:
|
||||||
ids, qualities = cats
|
ids, qualities = cats
|
||||||
if identifier in qualities:
|
if identifier in qualities:
|
||||||
return ids
|
return ids
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ log = CPLog(__name__)
|
|||||||
|
|
||||||
class IPTorrents(TorrentProvider):
|
class IPTorrents(TorrentProvider):
|
||||||
|
|
||||||
|
type = ['movie', 'season', 'episode']
|
||||||
|
|
||||||
urls = {
|
urls = {
|
||||||
'test' : 'http://www.iptorrents.com/',
|
'test' : 'http://www.iptorrents.com/',
|
||||||
'base_url' : 'http://www.iptorrents.com',
|
'base_url' : 'http://www.iptorrents.com',
|
||||||
@@ -19,16 +21,26 @@ class IPTorrents(TorrentProvider):
|
|||||||
}
|
}
|
||||||
|
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
([48], ['720p', '1080p', 'bd50']),
|
('movie', [
|
||||||
([72], ['cam', 'ts', 'tc', 'r5', 'scr']),
|
([48], ['720p', '1080p', 'bd50']),
|
||||||
([7], ['dvdrip', 'brrip']),
|
([72], ['cam', 'ts', 'tc', 'r5', 'scr']),
|
||||||
([6], ['dvdr']),
|
([7], ['dvdrip', 'brrip']),
|
||||||
|
([6], ['dvdr']),
|
||||||
|
]),
|
||||||
|
(['season'], [
|
||||||
|
([65], ['hdtv', '480p', '720p', '1080p']),
|
||||||
|
]),
|
||||||
|
(['episode'], [
|
||||||
|
([5], ['720p', '1080p']),
|
||||||
|
([78], ['480p']),
|
||||||
|
([4, 79], ['hdtv'])
|
||||||
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 #seconds
|
||||||
cat_backup_id = None
|
cat_backup_id = None
|
||||||
|
|
||||||
def _searchOnTitle(self, title, movie, quality, results):
|
def _searchOnTitle(self, title, media, quality, results):
|
||||||
|
|
||||||
freeleech = '' if not self.conf('freeleech') else '&free=on'
|
freeleech = '' if not self.conf('freeleech') else '&free=on'
|
||||||
|
|
||||||
@@ -36,7 +48,16 @@ class IPTorrents(TorrentProvider):
|
|||||||
current_page = 1
|
current_page = 1
|
||||||
while current_page <= pages and not self.shuttingDown():
|
while current_page <= pages and not self.shuttingDown():
|
||||||
|
|
||||||
url = self.urls['search'] % (self.getCatId(quality['identifier'])[0], freeleech, tryUrlencode('%s %s' % (title.replace(':', ''), movie['library']['year'])), current_page)
|
query = title.replace(':', '')
|
||||||
|
if media['type'] == 'movie':
|
||||||
|
query = '%s %s' % (title.replace(':', ''), media['library']['year'])
|
||||||
|
|
||||||
|
cat_id = self.getCatId(quality['identifier'], media['type'])[0]
|
||||||
|
if not cat_id:
|
||||||
|
log.warning('Unable to find category for quality %s and media type %s', (quality['identifier'], media['type']))
|
||||||
|
return
|
||||||
|
|
||||||
|
url = self.urls['search'] % (cat_id, freeleech, tryUrlencode(query), current_page)
|
||||||
data = self.getHTMLData(url, opener = self.login_opener)
|
data = self.getHTMLData(url, opener = self.login_opener)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
|
|||||||
Reference in new issue
Block a user