mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
Complete re-code of season/episode search code.
Switched from using standard requests to using sessions. Fixed bug in speedcd that was preventing config from saving.
This commit is contained in:
parent
18b781532c
commit
5772de9eec
36 changed files with 570 additions and 873 deletions
|
@ -178,9 +178,6 @@ TVTORRENTS = False
|
||||||
TVTORRENTS_DIGEST = None
|
TVTORRENTS_DIGEST = None
|
||||||
TVTORRENTS_HASH = None
|
TVTORRENTS_HASH = None
|
||||||
|
|
||||||
TORRENTLEECH = False
|
|
||||||
TORRENTLEECH_KEY = None
|
|
||||||
|
|
||||||
BTN = False
|
BTN = False
|
||||||
BTN_API_KEY = None
|
BTN_API_KEY = None
|
||||||
|
|
||||||
|
@ -193,6 +190,7 @@ THEPIRATEBAY_PROXY_URL = None
|
||||||
THEPIRATEBAY_BLACKLIST = None
|
THEPIRATEBAY_BLACKLIST = None
|
||||||
|
|
||||||
TORRENTLEECH = False
|
TORRENTLEECH = False
|
||||||
|
TORRENTLEECH_KEY = None
|
||||||
TORRENTLEECH_USERNAME = None
|
TORRENTLEECH_USERNAME = None
|
||||||
TORRENTLEECH_PASSWORD = None
|
TORRENTLEECH_PASSWORD = None
|
||||||
|
|
||||||
|
@ -232,6 +230,11 @@ HDBITS = False
|
||||||
HDBITS_USERNAME = None
|
HDBITS_USERNAME = None
|
||||||
HDBITS_PASSKEY = None
|
HDBITS_PASSKEY = None
|
||||||
|
|
||||||
|
SPEEDCD = False
|
||||||
|
SPEEDCD_USERNAME = None
|
||||||
|
SPEEDCD_PASSWORD = None
|
||||||
|
SPEEDCD_FREELEECH = None
|
||||||
|
|
||||||
ADD_SHOWS_WO_DIR = None
|
ADD_SHOWS_WO_DIR = None
|
||||||
CREATE_MISSING_SHOW_DIRS = None
|
CREATE_MISSING_SHOW_DIRS = None
|
||||||
RENAME_EPISODES = False
|
RENAME_EPISODES = False
|
||||||
|
|
|
@ -32,6 +32,12 @@ naming_ep_type = ("%(seasonnumber)dx%(episodenumber)02d",
|
||||||
"s%(seasonnumber)02de%(episodenumber)02d",
|
"s%(seasonnumber)02de%(episodenumber)02d",
|
||||||
"S%(seasonnumber)02dE%(episodenumber)02d",
|
"S%(seasonnumber)02dE%(episodenumber)02d",
|
||||||
"%(seasonnumber)02dx%(episodenumber)02d")
|
"%(seasonnumber)02dx%(episodenumber)02d")
|
||||||
|
|
||||||
|
sports_ep_type = ("%(seasonnumber)dx%(episodenumber)02d",
|
||||||
|
"s%(seasonnumber)02de%(episodenumber)02d",
|
||||||
|
"S%(seasonnumber)02dE%(episodenumber)02d",
|
||||||
|
"%(seasonnumber)02dx%(episodenumber)02d")
|
||||||
|
|
||||||
naming_ep_type_text = ("1x02", "s01e02", "S01E02", "01x02")
|
naming_ep_type_text = ("1x02", "s01e02", "S01E02", "01x02")
|
||||||
|
|
||||||
naming_multi_ep_type = {0: ["-%(episodenumber)02d"] * len(naming_ep_type),
|
naming_multi_ep_type = {0: ["-%(episodenumber)02d"] * len(naming_ep_type),
|
||||||
|
|
|
@ -50,20 +50,18 @@ except ImportError:
|
||||||
from xml.dom.minidom import Node
|
from xml.dom.minidom import Node
|
||||||
|
|
||||||
import sickbeard
|
import sickbeard
|
||||||
|
|
||||||
from sickbeard.exceptions import MultipleShowObjectsException, ex
|
from sickbeard.exceptions import MultipleShowObjectsException, ex
|
||||||
from sickbeard import logger, classes
|
from sickbeard import logger, classes
|
||||||
from sickbeard.common import USER_AGENT, mediaExtensions, subtitleExtensions, XML_NSMAP
|
from sickbeard.common import USER_AGENT, mediaExtensions, subtitleExtensions, XML_NSMAP
|
||||||
|
|
||||||
from sickbeard import db
|
from sickbeard import db
|
||||||
from sickbeard import encodingKludge as ek
|
from sickbeard import encodingKludge as ek
|
||||||
from sickbeard import notifiers
|
from sickbeard import notifiers
|
||||||
|
from sickbeard import exceptions
|
||||||
from lib import subliminal
|
from lib import subliminal
|
||||||
#from sickbeard.subtitles import EXTENSIONS
|
|
||||||
|
|
||||||
urllib._urlopener = classes.SickBeardURLopener()
|
urllib._urlopener = classes.SickBeardURLopener()
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
|
||||||
def indentXML(elem, level=0):
|
def indentXML(elem, level=0):
|
||||||
'''
|
'''
|
||||||
|
@ -172,6 +170,10 @@ def getURL(url, post_data=None, headers=None, params=None, json=False):
|
||||||
Returns a byte-string retrieved from the url provider.
|
Returns a byte-string retrieved from the url provider.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
global session
|
||||||
|
if not session:
|
||||||
|
session = requests.Session()
|
||||||
|
|
||||||
req_headers = ['User-Agent', USER_AGENT, 'Accept-Encoding', 'gzip,deflate']
|
req_headers = ['User-Agent', USER_AGENT, 'Accept-Encoding', 'gzip,deflate']
|
||||||
if headers:
|
if headers:
|
||||||
for cur_header in headers:
|
for cur_header in headers:
|
||||||
|
@ -191,9 +193,9 @@ Returns a byte-string retrieved from the url provider.
|
||||||
"https": sickbeard.PROXY_SETTING,
|
"https": sickbeard.PROXY_SETTING,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = requests.get(url, params=params, data=post_data, headers=dict(zip(it, it)), proxies=proxies, verify=False)
|
r = session.get(url, params=params, data=post_data, headers=dict(zip(it, it)), proxies=proxies, verify=False)
|
||||||
else:
|
else:
|
||||||
resp = requests.get(url, params=params, data=post_data, headers=dict(zip(it, it)), verify=False)
|
r = session.get(url, params=params, data=post_data, headers=dict(zip(it, it)), verify=False)
|
||||||
except requests.HTTPError, e:
|
except requests.HTTPError, e:
|
||||||
logger.log(u"HTTP error " + str(e.errno) + " while loading URL " + url, logger.WARNING)
|
logger.log(u"HTTP error " + str(e.errno) + " while loading URL " + url, logger.WARNING)
|
||||||
return None
|
return None
|
||||||
|
@ -207,9 +209,9 @@ Returns a byte-string retrieved from the url provider.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if json:
|
if json:
|
||||||
return resp.json() if resp.ok else None
|
return r.json() if r.ok else None
|
||||||
|
|
||||||
return resp.content if resp.ok else None
|
return r.content if r.ok else None
|
||||||
|
|
||||||
|
|
||||||
def _remove_file_failed(file):
|
def _remove_file_failed(file):
|
||||||
|
@ -220,8 +222,12 @@ def _remove_file_failed(file):
|
||||||
|
|
||||||
|
|
||||||
def download_file(url, filename):
|
def download_file(url, filename):
|
||||||
|
global session
|
||||||
|
if not session:
|
||||||
|
session = requests.Session()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get(url, stream=True, verify=False)
|
r = session.get(url, stream=True, verify=False)
|
||||||
with open(filename, 'wb') as fp:
|
with open(filename, 'wb') as fp:
|
||||||
for chunk in r.iter_content(chunk_size=1024):
|
for chunk in r.iter_content(chunk_size=1024):
|
||||||
if chunk:
|
if chunk:
|
||||||
|
@ -995,122 +1001,19 @@ def real_path(path):
|
||||||
"""
|
"""
|
||||||
return ek.ek(os.path.normpath, ek.ek(os.path.normcase, ek.ek(os.path.realpath, path)))
|
return ek.ek(os.path.normpath, ek.ek(os.path.normcase, ek.ek(os.path.realpath, path)))
|
||||||
|
|
||||||
def _copy(self, obj, objectmap=None):
|
def validateShow(show, season=None, episode=None):
|
||||||
"""
|
indexer_lang = show.lang
|
||||||
<Purpose>
|
|
||||||
Create a deep copy of an object without using the python 'copy' module.
|
|
||||||
Using copy.deepcopy() doesn't work because builtins like id and hasattr
|
|
||||||
aren't available when this is called.
|
|
||||||
<Arguments>
|
|
||||||
self
|
|
||||||
obj
|
|
||||||
The object to make a deep copy of.
|
|
||||||
objectmap
|
|
||||||
A mapping between original objects and the corresponding copy. This is
|
|
||||||
used to handle circular references.
|
|
||||||
<Exceptions>
|
|
||||||
TypeError
|
|
||||||
If an object is encountered that we don't know how to make a copy of.
|
|
||||||
NamespaceViolationError
|
|
||||||
If an unexpected error occurs while copying. This isn't the greatest
|
|
||||||
solution, but in general the idea is we just need to abort the wrapped
|
|
||||||
function call.
|
|
||||||
<Side Effects>
|
|
||||||
A new reference is created to every non-simple type of object. That is,
|
|
||||||
everything except objects of type str, unicode, int, etc.
|
|
||||||
<Returns>
|
|
||||||
The deep copy of obj with circular/recursive references preserved.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
# If this is a top-level call to _copy, create a new objectmap for use
|
lINDEXER_API_PARMS = sickbeard.indexerApi(show.indexer).api_params.copy()
|
||||||
# by recursive calls to _copy.
|
|
||||||
if objectmap is None:
|
|
||||||
objectmap = {}
|
|
||||||
# If this is a circular reference, use the copy we already made.
|
|
||||||
elif _saved_id(obj) in objectmap:
|
|
||||||
return objectmap[_saved_id(obj)]
|
|
||||||
|
|
||||||
# types.InstanceType is included because the user can provide an instance
|
if indexer_lang and not indexer_lang == 'en':
|
||||||
# of a class of their own in the list of callback args to settimer.
|
lINDEXER_API_PARMS['language'] = indexer_lang
|
||||||
if _is_in(type(obj), [str, unicode, int, long, float, complex, bool, frozenset,
|
|
||||||
types.NoneType, types.FunctionType, types.LambdaType,
|
|
||||||
types.MethodType, types.InstanceType]):
|
|
||||||
return obj
|
|
||||||
|
|
||||||
elif type(obj) is list:
|
t = sickbeard.indexerApi(show.indexer).indexer(**lINDEXER_API_PARMS)
|
||||||
temp_list = []
|
if season is None and episode is None:
|
||||||
# Need to save this in the objectmap before recursing because lists
|
return t
|
||||||
# might have circular references.
|
|
||||||
objectmap[_saved_id(obj)] = temp_list
|
|
||||||
|
|
||||||
for item in obj:
|
return t[show.indexerid][season][episode]
|
||||||
temp_list.append(self._copy(item, objectmap))
|
except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound):
|
||||||
|
pass
|
||||||
return temp_list
|
|
||||||
|
|
||||||
elif type(obj) is tuple:
|
|
||||||
temp_list = []
|
|
||||||
|
|
||||||
for item in obj:
|
|
||||||
temp_list.append(self._copy(item, objectmap))
|
|
||||||
|
|
||||||
# I'm not 100% confident on my reasoning here, so feel free to point
|
|
||||||
# out where I'm wrong: There's no way for a tuple to directly contain
|
|
||||||
# a circular reference to itself. Instead, it has to contain, for
|
|
||||||
# example, a dict which has the same tuple as a value. In that
|
|
||||||
# situation, we can avoid infinite recursion and properly maintain
|
|
||||||
# circular references in our copies by checking the objectmap right
|
|
||||||
# after we do the copy of each item in the tuple. The existence of the
|
|
||||||
# dictionary would keep the recursion from being infinite because those
|
|
||||||
# are properly handled. That just leaves making sure we end up with
|
|
||||||
# only one copy of the tuple. We do that here by checking to see if we
|
|
||||||
# just made a copy as a result of copying the items above. If so, we
|
|
||||||
# return the one that's already been made.
|
|
||||||
if _saved_id(obj) in objectmap:
|
|
||||||
return objectmap[_saved_id(obj)]
|
|
||||||
|
|
||||||
retval = tuple(temp_list)
|
|
||||||
objectmap[_saved_id(obj)] = retval
|
|
||||||
return retval
|
|
||||||
|
|
||||||
elif type(obj) is set:
|
|
||||||
temp_list = []
|
|
||||||
# We can't just store this list object in the objectmap because it isn't
|
|
||||||
# a set yet. If it's possible to have a set contain a reference to
|
|
||||||
# itself, this could result in infinite recursion. However, sets can
|
|
||||||
# only contain hashable items so I believe this can't happen.
|
|
||||||
|
|
||||||
for item in obj:
|
|
||||||
temp_list.append(self._copy(item, objectmap))
|
|
||||||
|
|
||||||
retval = set(temp_list)
|
|
||||||
objectmap[_saved_id(obj)] = retval
|
|
||||||
return retval
|
|
||||||
|
|
||||||
elif type(obj) is dict:
|
|
||||||
temp_dict = {}
|
|
||||||
# Need to save this in the objectmap before recursing because dicts
|
|
||||||
# might have circular references.
|
|
||||||
objectmap[_saved_id(obj)] = temp_dict
|
|
||||||
|
|
||||||
for key, value in obj.items():
|
|
||||||
temp_key = self._copy(key, objectmap)
|
|
||||||
temp_dict[temp_key] = self._copy(value, objectmap)
|
|
||||||
|
|
||||||
return temp_dict
|
|
||||||
|
|
||||||
# We don't copy certain objects. This is because copying an emulated file
|
|
||||||
# object, for example, will cause the destructor of the original one to
|
|
||||||
# be invoked, which will close the actual underlying file. As the object
|
|
||||||
# is wrapped and the client does not have access to it, it's safe to not
|
|
||||||
# wrap it.
|
|
||||||
elif isinstance(obj, (NamespaceObjectWrapper, emulfile.emulated_file,
|
|
||||||
emulcomm.emulated_socket, thread.LockType,
|
|
||||||
virtual_namespace.VirtualNamespace)):
|
|
||||||
return obj
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise TypeError("_copy is not implemented for objects of type " + str(type(obj)))
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
self._handle_violation("_copy failed on " + str(obj) + " with message " + str(e))
|
|
|
@ -343,44 +343,17 @@ class GenericMetadata():
|
||||||
"""
|
"""
|
||||||
all_eps = [ep_obj] + ep_obj.relatedEps
|
all_eps = [ep_obj] + ep_obj.relatedEps
|
||||||
|
|
||||||
indexer_lang = ep_obj.show.lang
|
# validate show
|
||||||
|
if not helpers.validateShow(ep_obj.show):
|
||||||
# get a TVDB object
|
|
||||||
try:
|
|
||||||
# There's gotta be a better way of doing this but we don't wanna
|
|
||||||
# change the language value elsewhere
|
|
||||||
lINDEXER_API_PARMS = sickbeard.indexerApi(ep_obj.show.indexer).api_params.copy()
|
|
||||||
|
|
||||||
lINDEXER_API_PARMS['actors'] = True
|
|
||||||
|
|
||||||
if indexer_lang and not indexer_lang == 'en':
|
|
||||||
lINDEXER_API_PARMS['language'] = indexer_lang
|
|
||||||
|
|
||||||
if ep_obj.show.dvdorder != 0:
|
|
||||||
lINDEXER_API_PARMS['dvdorder'] = True
|
|
||||||
|
|
||||||
t = sickbeard.indexerApi(ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)
|
|
||||||
|
|
||||||
indexer_show_obj = t[ep_obj.show.indexerid]
|
|
||||||
except sickbeard.indexer_shownotfound, e:
|
|
||||||
raise exceptions.ShowNotFoundException(e.message)
|
|
||||||
except sickbeard.indexer_error, e:
|
|
||||||
logger.log(u"Unable to connect to " + sickbeard.indexerApi(
|
|
||||||
ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# try all included episodes in case some have thumbs and others don't
|
# try all included episodes in case some have thumbs and others don't
|
||||||
for cur_ep in all_eps:
|
for cur_ep in all_eps:
|
||||||
try:
|
myEp = helpers.validateShow(cur_ep.show, cur_ep.season, cur_ep.episode)
|
||||||
myEp = indexer_show_obj[cur_ep.season][cur_ep.episode]
|
if not myEp:
|
||||||
except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound):
|
|
||||||
logger.log(u"Unable to find episode " + str(cur_ep.season) + "x" + str(
|
|
||||||
cur_ep.episode) + " on " + sickbeard.indexerApi(
|
|
||||||
ep_obj.show.indexer).name + ".. has it been removed? Should I delete from db?")
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
thumb_url = getattr(myEp, 'filename', None)
|
thumb_url = getattr(myEp, 'filename', None)
|
||||||
|
|
||||||
if thumb_url is not None:
|
if thumb_url is not None:
|
||||||
return thumb_url
|
return thumb_url
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ class NameParser(object):
|
||||||
|
|
||||||
if cached:
|
if cached:
|
||||||
if fix_scene_numbering:
|
if fix_scene_numbering:
|
||||||
cached_fixed = copy.deepcopy(cached)
|
cached_fixed = copy.copy(cached)
|
||||||
cached_fixed.fix_scene_numbering()
|
cached_fixed.fix_scene_numbering()
|
||||||
return cached_fixed
|
return cached_fixed
|
||||||
return cached
|
return cached
|
||||||
|
@ -248,7 +248,7 @@ class NameParser(object):
|
||||||
name_parser_cache.add(name, final_result)
|
name_parser_cache.add(name, final_result)
|
||||||
|
|
||||||
if fix_scene_numbering:
|
if fix_scene_numbering:
|
||||||
result_fixed = copy.deepcopy(final_result)
|
result_fixed = copy.copy(final_result)
|
||||||
result_fixed.fix_scene_numbering()
|
result_fixed.fix_scene_numbering()
|
||||||
return result_fixed
|
return result_fixed
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ class BTNProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return (title, url)
|
return (title, url)
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -210,47 +210,35 @@ class BTNProvider(generic.TorrentProvider):
|
||||||
# Search by name if we don't have tvdb or tvrage id
|
# Search by name if we don't have tvdb or tvrage id
|
||||||
current_params['series'] = sanitizeSceneName(name)
|
current_params['series'] = sanitizeSceneName(name)
|
||||||
|
|
||||||
if searchSeason:
|
whole_season_params = current_params.copy()
|
||||||
whole_season_params = current_params.copy()
|
partial_season_params = current_params.copy()
|
||||||
partial_season_params = current_params.copy()
|
# Search for entire seasons: no need to do special things for air by date shows
|
||||||
# Search for entire seasons: no need to do special things for air by date shows
|
whole_season_params['category'] = 'Season'
|
||||||
whole_season_params['category'] = 'Season'
|
whole_season_params['name'] = 'Season ' + str(season)
|
||||||
whole_season_params['name'] = 'Season ' + str(season)
|
|
||||||
|
|
||||||
search_params.append(whole_season_params)
|
search_params.append(whole_season_params)
|
||||||
|
|
||||||
# Search for episodes in the season
|
# Search for episodes in the season
|
||||||
partial_season_params['category'] = 'Episode'
|
search_params.append(self._get_episode_search_strings(show, season, episode, abd)[0])
|
||||||
|
|
||||||
if show.air_by_date:
|
|
||||||
# Search for the year of the air by date show
|
|
||||||
partial_season_params['name'] = str(season).split('-')[0]
|
|
||||||
else:
|
|
||||||
# Search for any result which has Sxx in the name
|
|
||||||
partial_season_params['name'] = 'S%02d' % int(season)
|
|
||||||
|
|
||||||
search_params.append(partial_season_params)
|
|
||||||
else:
|
|
||||||
search_params.append(current_params)
|
|
||||||
|
|
||||||
return search_params
|
return search_params
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return [{}]
|
return [{}]
|
||||||
|
|
||||||
search_params = {'category': 'Episode'}
|
search_params = {'category': 'Episode'}
|
||||||
|
|
||||||
if ep_obj.show.indexer == 1:
|
if show.indexer == 1:
|
||||||
search_params['tvdb'] = ep_obj.show.indexerid
|
search_params['tvdb'] = show.indexerid
|
||||||
elif ep_obj.show.indexer == 2:
|
elif show.indexer == 2:
|
||||||
search_params['tvrage'] = ep_obj.show.indexerid
|
search_params['tvrage'] = show.indexerid
|
||||||
else:
|
else:
|
||||||
search_params['series'] = sanitizeSceneName(ep_obj.show.name)
|
search_params['series'] = sanitizeSceneName(show.name)
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
date_str = str(ep_obj.airdate)
|
date_str = str(episode)
|
||||||
|
|
||||||
# BTN uses dots in dates, we just search for the date since that
|
# BTN uses dots in dates, we just search for the date since that
|
||||||
# combined with the series identifier should result in just one episode
|
# combined with the series identifier should result in just one episode
|
||||||
|
@ -258,7 +246,7 @@ class BTNProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Do a general name search for the episode, formatted like SXXEYY
|
# Do a general name search for the episode, formatted like SXXEYY
|
||||||
search_params['name'] = "S%02dE%02d" % (ep_obj.scene_season, ep_obj.scene_episode)
|
search_params['name'] = "S%02dE%02d" % (season, episode)
|
||||||
|
|
||||||
to_return = [search_params]
|
to_return = [search_params]
|
||||||
|
|
||||||
|
@ -266,11 +254,11 @@ class BTNProvider(generic.TorrentProvider):
|
||||||
if 'series' in search_params:
|
if 'series' in search_params:
|
||||||
|
|
||||||
# add new query string for every exception
|
# add new query string for every exception
|
||||||
name_exceptions = scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid)
|
name_exceptions = scene_exceptions.get_scene_exceptions(show.indexerid)
|
||||||
for cur_exception in name_exceptions:
|
for cur_exception in name_exceptions:
|
||||||
|
|
||||||
# don't add duplicates
|
# don't add duplicates
|
||||||
if cur_exception == ep_obj.show.name:
|
if cur_exception == show.name:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# copy all other parameters before setting the show name for this exception
|
# copy all other parameters before setting the show name for this exception
|
||||||
|
|
|
@ -46,14 +46,13 @@ class DTTProvider(generic.TorrentProvider):
|
||||||
quality = Quality.sceneQuality(url)
|
quality = Quality.sceneQuality(url)
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
def findSeasonResults(self, show, season):
|
def getSearchResults(self, show, season, ep_objs, seasonSearch=False, manualSearch=False):
|
||||||
|
return generic.TorrentProvider.getSearchResults(self, show, season, ep_objs, seasonSearch, manualSearch)
|
||||||
return generic.TorrentProvider.findSeasonResults(self, show, season)
|
|
||||||
|
|
||||||
def _dtt_show_id(self, show_name):
|
def _dtt_show_id(self, show_name):
|
||||||
return sanitizeSceneName(show_name).replace('.', '-').lower()
|
return sanitizeSceneName(show_name).replace('.', '-').lower()
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp=None, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = []
|
search_string = []
|
||||||
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
@ -62,8 +61,8 @@ class DTTProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return search_string
|
return search_string
|
||||||
|
|
||||||
def _get_episode_search_strings(self, episode):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return self._get_season_search_strings(episode.show, episode.scene_season)
|
return self._get_season_search_strings(show, season, episode, abd)
|
||||||
|
|
||||||
def _doSearch(self, search_params, show=None, age=None):
|
def _doSearch(self, search_params, show=None, age=None):
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ class EZRSSProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
def findSeasonResults(self, show, season):
|
def getSearchResults(self, show, season, ep_objs, seasonSearch=False, manualSearch=False):
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
|
@ -66,11 +66,11 @@ class EZRSSProvider(generic.TorrentProvider):
|
||||||
logger.WARNING)
|
logger.WARNING)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
results = generic.TorrentProvider.findSeasonResults(self, show, season)
|
results = generic.TorrentProvider.getSearchResults(self, show, season, ep_objs, seasonSearch, manualSearch)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
|
@ -81,22 +81,24 @@ class EZRSSProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
params['season'] = season
|
params['season'] = season
|
||||||
|
|
||||||
|
params['episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['episode']
|
||||||
|
|
||||||
return [params]
|
return [params]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return params
|
return params
|
||||||
|
|
||||||
params['show_name'] = helpers.sanitizeSceneName(ep_obj.show.name, ezrss=True).replace('.', ' ').encode('utf-8')
|
params['show_name'] = helpers.sanitizeSceneName(show.name, ezrss=True).replace('.', ' ').encode('utf-8')
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
params['date'] = str(ep_obj.airdate)
|
params['date'] = str(episode)
|
||||||
else:
|
else:
|
||||||
params['season'] = ep_obj.scene_season
|
params['season'] = season
|
||||||
params['episode'] = ep_obj.scene_episode
|
params['episode'] = episode
|
||||||
|
|
||||||
return [params]
|
return [params]
|
||||||
|
|
||||||
|
|
|
@ -214,10 +214,10 @@ class GenericProvider:
|
||||||
def _doSearch(self, search_params, show=None, age=None):
|
def _doSearch(self, search_params, show=None, age=None):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _get_title_and_url(self, item):
|
def _get_title_and_url(self, item):
|
||||||
|
@ -238,91 +238,38 @@ class GenericProvider:
|
||||||
|
|
||||||
return (title, url)
|
return (title, url)
|
||||||
|
|
||||||
def findEpisode(self, episode, manualSearch=False):
|
def getSearchResults(self, show, season, ep_objs, seasonSearch=False, manualSearch=False):
|
||||||
|
|
||||||
self._checkAuth()
|
|
||||||
|
|
||||||
logger.log(u'Searching "%s" for "%s" as "%s"'
|
|
||||||
% (self.name, episode.prettyName(), episode.scene_prettyName()))
|
|
||||||
|
|
||||||
self.cache.updateCache()
|
|
||||||
results = self.cache.searchCache(episode, manualSearch)
|
|
||||||
logger.log(u"Cache results: " + str(results), logger.DEBUG)
|
|
||||||
logger.log(u"manualSearch: " + str(manualSearch), logger.DEBUG)
|
|
||||||
|
|
||||||
# if we got some results then use them no matter what.
|
|
||||||
# OR
|
|
||||||
# return anyway unless we're doing a manual search
|
|
||||||
if results or not manualSearch:
|
|
||||||
return results
|
|
||||||
|
|
||||||
itemList = []
|
|
||||||
|
|
||||||
for cur_search_string in self._get_episode_search_strings(episode):
|
|
||||||
itemList += self._doSearch(cur_search_string, show=episode.show)
|
|
||||||
|
|
||||||
for item in itemList:
|
|
||||||
|
|
||||||
(title, url) = self._get_title_and_url(item)
|
|
||||||
|
|
||||||
# parse the file name
|
|
||||||
try:
|
|
||||||
myParser = NameParser(False)
|
|
||||||
parse_result = myParser.parse(title, True)
|
|
||||||
except InvalidNameException:
|
|
||||||
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if episode.show.air_by_date:
|
|
||||||
if parse_result.air_date != episode.airdate:
|
|
||||||
logger.log(u"Episode " + title + " didn't air on " + str(episode.airdate) + ", skipping it",
|
|
||||||
logger.DEBUG)
|
|
||||||
continue
|
|
||||||
elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers:
|
|
||||||
logger.log(u"Episode " + title + " isn't " + str(episode.season) + "x" + str(
|
|
||||||
episode.episode) + ", skipping it", logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
quality = self.getQuality(item)
|
|
||||||
|
|
||||||
if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
|
|
||||||
logger.log(
|
|
||||||
u"Ignoring result " + title + " because we don't want an episode that is " + Quality.qualityStrings[
|
|
||||||
quality], logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.log(u"Found result " + title + " at " + url, logger.DEBUG)
|
|
||||||
|
|
||||||
result = self.getResult([episode])
|
|
||||||
result.url = url
|
|
||||||
result.name = title
|
|
||||||
result.quality = quality
|
|
||||||
result.provider = self
|
|
||||||
result.content = None
|
|
||||||
|
|
||||||
results.append(result)
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
def findSeasonResults(self, show, season):
|
|
||||||
|
|
||||||
itemList = []
|
itemList = []
|
||||||
results = {}
|
results = {}
|
||||||
seasons = {}
|
|
||||||
searchSeason = False
|
|
||||||
|
|
||||||
|
self._checkAuth()
|
||||||
|
|
||||||
# convert wanted seasons and episodes to XEM scene numbering
|
for ep_obj in ep_objs:
|
||||||
seasonEp = show.getAllEpisodes(season)
|
logger.log(u'Searching "%s" for "%s" as "%s"'
|
||||||
wantedEp = [x for x in seasonEp if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL)]
|
% (self.name, ep_obj.prettyName(), ep_obj.scene_prettyName()))
|
||||||
[seasons.setdefault(x.scene_season, []).append(x) for x in wantedEp]
|
|
||||||
|
|
||||||
if wantedEp == seasonEp:
|
self.cache.updateCache()
|
||||||
searchSeason = True
|
results = self.cache.searchCache(ep_obj, manualSearch)
|
||||||
|
logger.log(u"Cache results: " + str(results), logger.DEBUG)
|
||||||
|
logger.log(u"manualSearch: " + str(manualSearch), logger.DEBUG)
|
||||||
|
|
||||||
for season, episodes in seasons.iteritems():
|
# if we got some results then use them no matter what.
|
||||||
for curString in self._get_season_search_strings(show, season, episodes, searchSeason):
|
# OR
|
||||||
itemList += self._doSearch(curString)
|
# return anyway unless we're doing a manual search
|
||||||
|
if results or not manualSearch:
|
||||||
|
return results
|
||||||
|
|
||||||
|
abd = False
|
||||||
|
if show.air_by_date:
|
||||||
|
abd = True
|
||||||
|
|
||||||
|
if seasonSearch:
|
||||||
|
for curString in self._get_season_search_strings(show, ep_obj.scene_season, ep_obj.scene_episode, abd=abd):
|
||||||
|
itemList += self._doSearch(curString)
|
||||||
|
else:
|
||||||
|
for curString in self._get_episode_search_strings(show, ep_obj.scene_season, ep_obj.scene_episode, abd=abd):
|
||||||
|
itemList += self._doSearch(curString, show=show)
|
||||||
|
|
||||||
for item in itemList:
|
for item in itemList:
|
||||||
|
|
||||||
|
@ -373,7 +320,7 @@ class GenericProvider:
|
||||||
# make sure we want the episode
|
# make sure we want the episode
|
||||||
wantEp = True
|
wantEp = True
|
||||||
for epNo in actual_episodes:
|
for epNo in actual_episodes:
|
||||||
if not show.wantEpisode(actual_season, epNo, quality):
|
if not show.wantEpisode(actual_season, epNo, quality, manualSearch=manualSearch):
|
||||||
wantEp = False
|
wantEp = False
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -411,7 +358,7 @@ class GenericProvider:
|
||||||
if epNum in results:
|
if epNum in results:
|
||||||
results[epNum].append(result)
|
results[epNum].append(result)
|
||||||
else:
|
else:
|
||||||
results[epNum] = [result]
|
results = {epNum:[result]}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import generic
|
||||||
import sickbeard
|
import sickbeard
|
||||||
|
|
||||||
from sickbeard import logger, tvcache, exceptions
|
from sickbeard import logger, tvcache, exceptions
|
||||||
from sickbeard.common import Quality
|
from sickbeard.common import Quality, Overview
|
||||||
from sickbeard.exceptions import ex, AuthException
|
from sickbeard.exceptions import ex, AuthException
|
||||||
from sickbeard.name_parser.parser import NameParser, InvalidNameException
|
from sickbeard.name_parser.parser import NameParser, InvalidNameException
|
||||||
|
|
||||||
|
@ -66,72 +66,87 @@ class HDBitsProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def findEpisode(self, episode, manualSearch=False):
|
def searchProviders(self, show, season, episode=None, manualSearch=False):
|
||||||
|
itemList = []
|
||||||
|
results = {}
|
||||||
|
|
||||||
logger.log(u"Searching " + self.name + " for " + episode.prettyName())
|
logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season))
|
||||||
|
|
||||||
self.cache.updateCache()
|
# gather all episodes for season and then pick out the wanted episodes and compare to determin if we want whole season or just a few episodes
|
||||||
results = self.cache.searchCache(episode, manualSearch)
|
if episode is None:
|
||||||
logger.log(u"Cache results: " + str(results), logger.DEBUG)
|
seasonEps = show.getAllEpisodes(season)
|
||||||
|
wantedEps = [x for x in seasonEps if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL)]
|
||||||
|
else:
|
||||||
|
wantedEps = [show.getEpisode(season, episode)]
|
||||||
|
|
||||||
# if we got some results then use them no matter what.
|
for ep_obj in wantedEps:
|
||||||
# OR
|
season = ep_obj.scene_season
|
||||||
# return anyway unless we're doing a manual search
|
episode = ep_obj.scene_episode
|
||||||
if results or not manualSearch:
|
|
||||||
return results
|
|
||||||
|
|
||||||
parsedJSON = self.getURL(self.search_url, post_data=self._make_post_data_JSON(show=episode.show, episode=episode), json=True)
|
self.cache.updateCache()
|
||||||
|
results = self.cache.searchCache(episode, manualSearch)
|
||||||
|
logger.log(u"Cache results: " + str(results), logger.DEBUG)
|
||||||
|
|
||||||
if not parsedJSON:
|
# if we got some results then use them no matter what.
|
||||||
logger.log(u"No data returned from " + self.search_url, logger.ERROR)
|
# OR
|
||||||
return []
|
# return anyway unless we're doing a manual search
|
||||||
|
if results or not manualSearch:
|
||||||
|
return results
|
||||||
|
|
||||||
if self._checkAuthFromData(parsedJSON):
|
itemList += self.getURL(self.search_url, post_data=self._make_post_data_JSON(show=show, season=season, episode=episode), json=True)
|
||||||
results = []
|
|
||||||
|
|
||||||
if parsedJSON and 'data' in parsedJSON:
|
|
||||||
items = parsedJSON['data']
|
|
||||||
else:
|
|
||||||
logger.log(u"Resulting JSON from " + self.name + " isn't correct, not parsing it", logger.ERROR)
|
|
||||||
items = []
|
|
||||||
|
|
||||||
for item in items:
|
for parsedJSON in itemList:
|
||||||
|
if not parsedJSON:
|
||||||
|
logger.log(u"No data returned from " + self.search_url, logger.ERROR)
|
||||||
|
return []
|
||||||
|
|
||||||
(title, url) = self._get_title_and_url(item)
|
if self._checkAuthFromData(parsedJSON):
|
||||||
|
results = []
|
||||||
|
|
||||||
# parse the file name
|
if parsedJSON and 'data' in parsedJSON:
|
||||||
try:
|
items = parsedJSON['data']
|
||||||
myParser = NameParser()
|
else:
|
||||||
parse_result = myParser.parse(title)
|
logger.log(u"Resulting JSON from " + self.name + " isn't correct, not parsing it", logger.ERROR)
|
||||||
except InvalidNameException:
|
items = []
|
||||||
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if episode.show.air_by_date:
|
for item in items:
|
||||||
if parse_result.air_date != episode.airdate:
|
|
||||||
logger.log(u"Episode " + title + " didn't air on " + str(episode.airdate) + ", skipping it",
|
(title, url) = self._get_title_and_url(item)
|
||||||
logger.DEBUG)
|
|
||||||
|
# parse the file name
|
||||||
|
try:
|
||||||
|
myParser = NameParser()
|
||||||
|
parse_result = myParser.parse(title, True)
|
||||||
|
except InvalidNameException:
|
||||||
|
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
|
||||||
continue
|
continue
|
||||||
elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers:
|
|
||||||
logger.log(u"Episode " + title + " isn't " + str(episode.season) + "x" + str(
|
|
||||||
episode.episode) + ", skipping it", logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
quality = self.getQuality(item)
|
if episode.show.air_by_date:
|
||||||
|
if parse_result.air_date != episode.airdate:
|
||||||
|
logger.log(u"Episode " + title + " didn't air on " + str(episode.airdate) + ", skipping it",
|
||||||
|
logger.DEBUG)
|
||||||
|
continue
|
||||||
|
elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers:
|
||||||
|
logger.log(u"Episode " + title + " isn't " + str(episode.season) + "x" + str(
|
||||||
|
episode.episode) + ", skipping it", logger.DEBUG)
|
||||||
|
continue
|
||||||
|
|
||||||
if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
|
quality = self.getQuality(item)
|
||||||
logger.log(u"Ignoring result " + title + " because we don't want an episode that is " +
|
|
||||||
Quality.qualityStrings[quality], logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.log(u"Found result " + title + " at " + url, logger.DEBUG)
|
if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
|
||||||
|
logger.log(u"Ignoring result " + title + " because we don't want an episode that is " +
|
||||||
|
Quality.qualityStrings[quality], logger.DEBUG)
|
||||||
|
continue
|
||||||
|
|
||||||
result = self.getResult([episode])
|
logger.log(u"Found result " + title + " at " + url, logger.DEBUG)
|
||||||
result.url = url
|
|
||||||
result.name = title
|
|
||||||
result.quality = quality
|
|
||||||
|
|
||||||
results.append(result)
|
result = self.getResult([episode])
|
||||||
|
result.url = url
|
||||||
|
result.name = title
|
||||||
|
result.quality = quality
|
||||||
|
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@ -153,8 +168,8 @@ class HDBitsProvider(generic.TorrentProvider):
|
||||||
if episode:
|
if episode:
|
||||||
post_data['tvdb'] = {
|
post_data['tvdb'] = {
|
||||||
'id': show.indexerid,
|
'id': show.indexerid,
|
||||||
'season': episode.scene_season,
|
'season': season,
|
||||||
'episode': episode.scene_episode
|
'episode': episode
|
||||||
}
|
}
|
||||||
|
|
||||||
if season:
|
if season:
|
||||||
|
|
|
@ -111,46 +111,36 @@ class HDTorrentsProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -92,46 +92,37 @@ class IPTorrentsProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + ' %s' % add_string
|
'episodenumber': episode} + ' %s' % add_string
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@ class KATProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed
|
self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed
|
||||||
|
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
def isEnabled(self):
|
def isEnabled(self):
|
||||||
return sickbeard.KAT
|
return sickbeard.KAT
|
||||||
|
|
||||||
|
@ -164,56 +166,40 @@ class KATProvider(generic.TorrentProvider):
|
||||||
logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), logger.ERROR)
|
logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), logger.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) + ' -S%02d' % int(season) + 'E' + ' category:tv' #1) ShowName SXX -SXXE
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' + ' category:tv' #2) ShowName Season X
|
||||||
search_string = {'Season': [], 'Episode': []}
|
search_string['Season'].append(ep_string)
|
||||||
for show_name in set(allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) + ' -S%02d' % int(season) + 'E' + ' category:tv' #1) ShowName SXX -SXXE
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' + ' category:tv' #2) ShowName Season X
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
|
||||||
|
|
||||||
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if abd:
|
||||||
return []
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
|
|
||||||
self.show = ep_obj.show
|
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
|
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + '|' + \
|
'episodenumber': episode} + '|' + \
|
||||||
sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[0] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + '|' + \
|
'episodenumber': episode} + '|' + \
|
||||||
sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[3] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + ' %s category:tv' % add_string
|
'episodenumber': episode} + ' %s category:tv' % add_string
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
@ -308,21 +294,24 @@ class KATProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
def getURL(self, url, post_data=None, headers=None):
|
def getURL(self, url, post_data=None, headers=None):
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Remove double-slashes from url
|
# Remove double-slashes from url
|
||||||
parsed = list(urlparse.urlparse(url))
|
parsed = list(urlparse.urlparse(url))
|
||||||
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
||||||
url = urlparse.urlunparse(parsed)
|
url = urlparse.urlunparse(parsed)
|
||||||
|
|
||||||
if sickbeard.PROXY_SETTING:
|
if sickbeard.PROXY_SETTING:
|
||||||
proxies = {
|
proxies = {
|
||||||
"http": sickbeard.PROXY_SETTING,
|
"http": sickbeard.PROXY_SETTING,
|
||||||
"https": sickbeard.PROXY_SETTING,
|
"https": sickbeard.PROXY_SETTING,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = requests.get(url, proxies=proxies, verify=False)
|
r = self.session.get(url, proxies=proxies, verify=False)
|
||||||
else:
|
else:
|
||||||
r = requests.get(url, verify=False)
|
r = self.session.get(url, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
||||||
return None
|
return None
|
||||||
|
@ -339,6 +328,9 @@ class KATProvider(generic.TorrentProvider):
|
||||||
Save the result to disk.
|
Save the result to disk.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
||||||
|
|
||||||
if not torrent_hash:
|
if not torrent_hash:
|
||||||
|
@ -346,7 +338,7 @@ class KATProvider(generic.TorrentProvider):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
r = self.session.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -251,32 +251,11 @@ class NewzbinProvider(generic.NZBProvider):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
nameList = set(show_name_helpers.allPossibleShowNames(show))
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
|
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
|
||||||
if show.air_by_date:
|
|
||||||
suffix = ''
|
|
||||||
else:
|
|
||||||
suffix = 'x'
|
|
||||||
searchTerms = ['^"' + x + ' - ' + str(season) + suffix + '"' for x in nameList]
|
|
||||||
#searchTerms += ['^"'+x+' - Season '+str(season)+'"' for x in nameList]
|
|
||||||
searchStr = " OR ".join(searchTerms)
|
|
||||||
|
|
||||||
searchStr += " -subpack -extras"
|
|
||||||
|
|
||||||
logger.log("Searching newzbin for string " + searchStr, logger.DEBUG)
|
|
||||||
|
|
||||||
return [searchStr]
|
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
|
||||||
|
|
||||||
nameList = set(show_name_helpers.allPossibleShowNames(ep_obj.show))
|
|
||||||
if not ep_obj.show.air_by_date:
|
|
||||||
searchStr = " OR ".join(['^"' + x + ' - %dx%02d"' % (ep_obj.scene_season, ep_obj.scene_episode) for x in nameList])
|
|
||||||
else:
|
|
||||||
searchStr = " OR ".join(['^"' + x + ' - ' + str(ep_obj.airdate) + '"' for x in nameList])
|
|
||||||
return [searchStr]
|
|
||||||
|
|
||||||
def _doSearch(self, searchStr, show=None, age=None):
|
def _doSearch(self, searchStr, show=None, age=None):
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ class NewznabProvider(generic.NZBProvider):
|
||||||
def isEnabled(self):
|
def isEnabled(self):
|
||||||
return self.enabled
|
return self.enabled
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return [{}]
|
return [{}]
|
||||||
|
@ -94,41 +94,35 @@ class NewznabProvider(generic.NZBProvider):
|
||||||
cur_params = {}
|
cur_params = {}
|
||||||
|
|
||||||
# search
|
# search
|
||||||
|
|
||||||
cur_params['q'] = helpers.sanitizeSceneName(cur_exception)
|
cur_params['q'] = helpers.sanitizeSceneName(cur_exception)
|
||||||
|
|
||||||
# air-by-date means &season=2010&q=2010.03, no other way to do it atm
|
# season
|
||||||
if show.air_by_date:
|
cur_params['season'] = str(season)
|
||||||
cur_params['season'] = str(season).split('-')[0]
|
to_return.append(cur_params)
|
||||||
if 'q' in cur_params:
|
|
||||||
cur_params['q'] += '.' + str(season).replace('-', '.')
|
|
||||||
else:
|
|
||||||
cur_params['q'] = str(season).replace('-', '.')
|
|
||||||
else:
|
|
||||||
cur_params['season'] = str(season)
|
|
||||||
|
|
||||||
to_return.append(cur_params)
|
# episode
|
||||||
|
to_return['episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['ep']
|
||||||
|
|
||||||
return to_return
|
return to_return
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return [params]
|
return [params]
|
||||||
|
|
||||||
# search
|
# search
|
||||||
params['q'] = helpers.sanitizeSceneName(ep_obj.show.name)
|
params['q'] = helpers.sanitizeSceneName(show.name)
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
date_str = str(ep_obj.airdate)
|
date_str = str(episode)
|
||||||
|
|
||||||
params['season'] = date_str.partition('-')[0]
|
params['season'] = date_str.partition('-')[0]
|
||||||
params['ep'] = date_str.partition('-')[2].replace('-', '/')
|
params['ep'] = date_str.partition('-')[2].replace('-', '/')
|
||||||
else:
|
else:
|
||||||
params['season'] = ep_obj.scene_season
|
params['season'] = season
|
||||||
params['ep'] = ep_obj.scene_episode
|
params['ep'] = episode
|
||||||
|
|
||||||
to_return = [params]
|
to_return = [params]
|
||||||
|
|
||||||
|
@ -136,11 +130,11 @@ class NewznabProvider(generic.NZBProvider):
|
||||||
if 'q' in params:
|
if 'q' in params:
|
||||||
|
|
||||||
# add new query strings for exceptions
|
# add new query strings for exceptions
|
||||||
name_exceptions = scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid)
|
name_exceptions = scene_exceptions.get_scene_exceptions(show.indexerid)
|
||||||
for cur_exception in name_exceptions:
|
for cur_exception in name_exceptions:
|
||||||
|
|
||||||
# don't add duplicates
|
# don't add duplicates
|
||||||
if cur_exception == ep_obj.show.name:
|
if cur_exception == show.name:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
cur_return = params.copy()
|
cur_return = params.copy()
|
||||||
|
|
|
@ -129,46 +129,38 @@ class NextGenProvider(generic.TorrentProvider):
|
||||||
logger.log(u'Failed to login:' + str(error), logger.ERROR)
|
logger.log(u'Failed to login:' + str(error), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -54,20 +54,17 @@ class NyaaProvider(generic.TorrentProvider):
|
||||||
quality = Quality.sceneQuality(title)
|
quality = Quality.sceneQuality(title)
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
def findSeasonResults(self, show, season):
|
def getSearchResults(self, show, season, ep_objs, seasonSearch=False, manualSearch=False):
|
||||||
results = {}
|
results = generic.TorrentProvider.getSearchResults(self, show, season, ep_objs, seasonSearch, manualSearch)
|
||||||
|
|
||||||
results = generic.TorrentProvider.findSeasonResults(self, show, season)
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp=None, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
names = []
|
names = []
|
||||||
names.extend(show_name_helpers.makeSceneShowSearchStrings(show))
|
names.extend(show_name_helpers.makeSceneShowSearchStrings(show))
|
||||||
return names
|
return names
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return self._get_season_search_strings(ep_obj.show, ep_obj.scene_season)
|
return self._get_season_search_strings(show, season, episode, abd)
|
||||||
|
|
||||||
def _doSearch(self, search_string, show=None, age=None):
|
def _doSearch(self, search_string, show=None, age=None):
|
||||||
|
|
||||||
|
@ -109,74 +106,6 @@ class NyaaProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return generic.TorrentProvider._get_title_and_url(self, item)
|
return generic.TorrentProvider._get_title_and_url(self, item)
|
||||||
|
|
||||||
def findEpisode(self, episode, manualSearch=False):
|
|
||||||
|
|
||||||
self._checkAuth()
|
|
||||||
|
|
||||||
logger.log(u"Searching " + self.name + " for " + episode.prettyName())
|
|
||||||
|
|
||||||
self.cache.updateCache()
|
|
||||||
results = self.cache.searchCache(episode, manualSearch)
|
|
||||||
logger.log(u"Cache results: " + str(results), logger.DEBUG)
|
|
||||||
|
|
||||||
# if we got some results then use them no matter what.
|
|
||||||
# OR
|
|
||||||
# return anyway unless we're doing a manual search
|
|
||||||
if results or not manualSearch:
|
|
||||||
return results
|
|
||||||
|
|
||||||
itemList = []
|
|
||||||
|
|
||||||
for cur_search_string in self._get_episode_search_strings(episode):
|
|
||||||
itemList += self._doSearch(cur_search_string, show=episode.show)
|
|
||||||
|
|
||||||
for item in itemList:
|
|
||||||
|
|
||||||
(title, url) = self._get_title_and_url(item)
|
|
||||||
|
|
||||||
# parse the file name
|
|
||||||
try:
|
|
||||||
myParser = NameParser(False)
|
|
||||||
parse_result = myParser.parse(title, True)
|
|
||||||
except InvalidNameException:
|
|
||||||
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if episode.show.air_by_date:
|
|
||||||
if parse_result.air_date != episode.airdate:
|
|
||||||
logger.log("Episode " + title + " didn't air on " + str(episode.airdate) + ", skipping it",
|
|
||||||
logger.DEBUG)
|
|
||||||
continue
|
|
||||||
elif episode.show.anime and episode.show.absolute_numbering:
|
|
||||||
if episode.absolute_number not in parse_result.ab_episode_numbers:
|
|
||||||
logger.log("Episode " + title + " isn't " + str(episode.absolute_number) + ", skipping it",
|
|
||||||
logger.DEBUG)
|
|
||||||
continue
|
|
||||||
elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers:
|
|
||||||
logger.log(
|
|
||||||
"Episode " + title + " isn't " + str(episode.season) + "x" + str(episode.episode) + ", skipping it",
|
|
||||||
logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
quality = self.getQuality(item, episode.show.anime)
|
|
||||||
|
|
||||||
if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch):
|
|
||||||
logger.log(
|
|
||||||
u"Ignoring result " + title + " because we don't want an episode that is " + Quality.qualityStrings[
|
|
||||||
quality], logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.log(u"Found result " + title + " at " + url, logger.DEBUG)
|
|
||||||
|
|
||||||
result = self.getResult([episode])
|
|
||||||
result.url = url
|
|
||||||
result.name = title
|
|
||||||
result.quality = quality
|
|
||||||
|
|
||||||
results.append(result)
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
def _extract_name_from_filename(self, filename):
|
def _extract_name_from_filename(self, filename):
|
||||||
name_regex = '(.*?)\.?(\[.*]|\d+\.TPB)\.torrent$'
|
name_regex = '(.*?)\.?(\[.*]|\d+\.TPB)\.torrent$'
|
||||||
logger.log(u"Comparing " + name_regex + " against " + filename, logger.DEBUG)
|
logger.log(u"Comparing " + name_regex + " against " + filename, logger.DEBUG)
|
||||||
|
@ -204,7 +133,7 @@ class NyaaCache(tvcache.TVCache):
|
||||||
|
|
||||||
logger.log(u"NyaaTorrents cache update URL: " + url, logger.DEBUG)
|
logger.log(u"NyaaTorrents cache update URL: " + url, logger.DEBUG)
|
||||||
|
|
||||||
data = self.provider.getURL(url)
|
data = self.provider.getRSSFeed(url)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,11 @@ class NZBsProvider(generic.NZBProvider):
|
||||||
if sickbeard.NZBS_UID in (None, "") or sickbeard.NZBS_HASH in (None, ""):
|
if sickbeard.NZBS_UID in (None, "") or sickbeard.NZBS_HASH in (None, ""):
|
||||||
raise exceptions.AuthException("NZBs.org authentication details are empty, check your config")
|
raise exceptions.AuthException("NZBs.org authentication details are empty, check your config")
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season)]
|
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return ['^' + x for x in show_name_helpers.makeSceneSearchString(ep_obj)]
|
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _doSearch(self, curString, show=None, age=None):
|
def _doSearch(self, curString, show=None, age=None):
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,11 @@ class NZBsRUSProvider(generic.NZBProvider):
|
||||||
if sickbeard.NZBSRUS_UID in (None, "") or sickbeard.NZBSRUS_HASH in (None, ""):
|
if sickbeard.NZBSRUS_UID in (None, "") or sickbeard.NZBSRUS_HASH in (None, ""):
|
||||||
raise exceptions.AuthException("NZBs'R'US authentication details are empty, check your config")
|
raise exceptions.AuthException("NZBs'R'US authentication details are empty, check your config")
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season)]
|
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return ['^' + x for x in show_name_helpers.makeSceneSearchString(ep_obj)]
|
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _doSearch(self, search, show=None, age=None):
|
def _doSearch(self, search, show=None, age=None):
|
||||||
params = {'uid': sickbeard.NZBSRUS_UID,
|
params = {'uid': sickbeard.NZBSRUS_UID,
|
||||||
|
|
|
@ -85,11 +85,11 @@ class OmgwtfnzbsProvider(generic.NZBProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
return [x for x in show_name_helpers.makeSceneSeasonSearchString(show, season)]
|
return [x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj):
|
def _get_episode_search_strings(self, show, season, episode, abd=False):
|
||||||
return [x for x in show_name_helpers.makeSceneSearchString(ep_obj)]
|
return [x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
|
||||||
|
|
||||||
def _get_title_and_url(self, item):
|
def _get_title_and_url(self, item):
|
||||||
return (item['release'], item['getnzb'])
|
return (item['release'], item['getnzb'])
|
||||||
|
|
|
@ -61,6 +61,8 @@ class PublicHDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']}
|
self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']}
|
||||||
|
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
def isEnabled(self):
|
def isEnabled(self):
|
||||||
return sickbeard.PUBLICHD
|
return sickbeard.PUBLICHD
|
||||||
|
|
||||||
|
@ -72,51 +74,41 @@ class PublicHDProvider(generic.TorrentProvider):
|
||||||
quality = Quality.sceneQuality(item[0])
|
quality = Quality.sceneQuality(item[0])
|
||||||
return quality
|
return quality
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX -SXXE
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
ep_string = show_name + ' Season ' + str(season) #2) ShowName Season X
|
||||||
search_string = {'Season': [], 'Episode': []}
|
search_string['Season'].append(ep_string)
|
||||||
for show_name in set(allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX -SXXE
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
ep_string = show_name + ' Season ' + str(season) #2) ShowName Season X
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = ep_obj.show
|
if abd:
|
||||||
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
if ep_obj.show.air_by_date:
|
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
for x in add_string.split('|'):
|
for x in add_string.split('|'):
|
||||||
to_search = re.sub('\s+', ' ', ep_string + ' %s' % x)
|
to_search = re.sub('\s+', ' ', ep_string + ' %s' % x)
|
||||||
|
@ -206,13 +198,16 @@ class PublicHDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
def getURL(self, url, post_data=None, headers=None):
|
def getURL(self, url, post_data=None, headers=None):
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Remove double-slashes from url
|
# Remove double-slashes from url
|
||||||
parsed = list(urlparse.urlparse(url))
|
parsed = list(urlparse.urlparse(url))
|
||||||
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
||||||
url = urlparse.urlunparse(parsed)
|
url = urlparse.urlunparse(parsed)
|
||||||
|
|
||||||
r = requests.get(url, verify=False)
|
r = self.session.get(url, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
||||||
return None
|
return None
|
||||||
|
@ -229,6 +224,9 @@ class PublicHDProvider(generic.TorrentProvider):
|
||||||
Save the result to disk.
|
Save the result to disk.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
||||||
|
|
||||||
if not torrent_hash:
|
if not torrent_hash:
|
||||||
|
@ -236,7 +234,7 @@ class PublicHDProvider(generic.TorrentProvider):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
r = self.session.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -42,6 +42,7 @@ class TorrentRssProvider(generic.TorrentProvider):
|
||||||
self.url = re.sub('\/$', '', url)
|
self.url = re.sub('\/$', '', url)
|
||||||
self.enabled = True
|
self.enabled = True
|
||||||
self.supportsBacklog = False
|
self.supportsBacklog = False
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
def configStr(self):
|
def configStr(self):
|
||||||
return self.name + '|' + self.url + '|' + str(int(self.enabled))
|
return self.name + '|' + self.url + '|' + str(int(self.enabled))
|
||||||
|
@ -114,20 +115,24 @@ class TorrentRssProvider(generic.TorrentProvider):
|
||||||
return (False, 'Error when trying to load RSS: ' + ex(e))
|
return (False, 'Error when trying to load RSS: ' + ex(e))
|
||||||
|
|
||||||
def getURL(self, url, post_data=None, headers=None):
|
def getURL(self, url, post_data=None, headers=None):
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parsed = list(urlparse.urlparse(url))
|
parsed = list(urlparse.urlparse(url))
|
||||||
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
||||||
response = requests.get(url, verify=False)
|
r = self.session.get(url, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u"Error loading " + self.name + " URL: " + ex(e), logger.ERROR)
|
logger.log(u"Error loading " + self.name + " URL: " + ex(e), logger.ERROR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if response.status_code != 200:
|
if r.status_code != 200:
|
||||||
logger.log(self.name + u" page requested with url " + url + " returned status code is " + str(
|
logger.log(self.name + u" page requested with url " + url + " returned status code is " + str(
|
||||||
response.status_code) + ': ' + clients.http_error_code[response.status_code], logger.WARNING)
|
r.status_code) + ': ' + clients.http_error_code[r.status_code], logger.WARNING)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return response.content
|
return r.content
|
||||||
|
|
||||||
def dumpHTML(self, data):
|
def dumpHTML(self, data):
|
||||||
|
|
||||||
|
|
|
@ -100,46 +100,38 @@ class SCCProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import datetime
|
import datetime
|
||||||
|
import urlparse
|
||||||
import sickbeard
|
import sickbeard
|
||||||
import generic
|
import generic
|
||||||
|
|
||||||
from sickbeard.common import Quality
|
from sickbeard.common import Quality
|
||||||
from sickbeard import logger
|
from sickbeard import logger
|
||||||
from sickbeard import tvcache
|
from sickbeard import tvcache
|
||||||
|
@ -32,7 +33,7 @@ from sickbeard.common import Overview
|
||||||
from sickbeard.exceptions import ex
|
from sickbeard.exceptions import ex
|
||||||
from sickbeard import clients
|
from sickbeard import clients
|
||||||
from lib import requests
|
from lib import requests
|
||||||
|
from lib.requests import exceptions
|
||||||
|
|
||||||
class SpeedCDProvider(generic.TorrentProvider):
|
class SpeedCDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
|
@ -55,7 +56,9 @@ class SpeedCDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
self.categories = {'Season': {'c14':1}, 'Episode': {'c2':1, 'c49':1}, 'RSS': {'c14':1, 'c2':1, 'c49':1}}
|
self.categories = {'Season': {'c14':1}, 'Episode': {'c2':1, 'c49':1}, 'RSS': {'c14':1, 'c2':1, 'c49':1}}
|
||||||
|
|
||||||
self.session = None
|
self.session = requests.Session()
|
||||||
|
|
||||||
|
self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'}
|
||||||
|
|
||||||
def isEnabled(self):
|
def isEnabled(self):
|
||||||
return sickbeard.SPEEDCD
|
return sickbeard.SPEEDCD
|
||||||
|
@ -75,10 +78,10 @@ class SpeedCDProvider(generic.TorrentProvider):
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session = requests.Session()
|
self.session = requests.Session()
|
||||||
self.session.headers.update({'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20130519 Firefox/24.0)'})
|
self.session.headers.update(self.headers)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self.session.post(self.urls['login'], data=login_params, timeout=30)
|
response = self.session.post(self.urls['login'], data=login_params, timeout=30, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u'Unable to connect to ' + self.name + ' provider: ' + ex(e), logger.ERROR)
|
logger.log(u'Unable to connect to ' + self.name + ' provider: ' + ex(e), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
|
@ -90,55 +93,43 @@ class SpeedCDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season=None):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
seasonEp = show.getAllEpisodes(season)
|
|
||||||
|
|
||||||
wantedEp = [x for x in seasonEp if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL)]
|
|
||||||
|
|
||||||
#If Every episode in Season is a wanted Episode then search for Season first
|
#If Every episode in Season is a wanted Episode then search for Season first
|
||||||
if wantedEp == seasonEp and not show.air_by_date:
|
search_string = {'Season': [], 'Episode': []}
|
||||||
search_string = {'Season': [], 'Episode': []}
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
ep_string = show_name +' S%02d' % int(season) #1) ShowName SXX
|
||||||
ep_string = show_name +' S%02d' % int(season) #1) ShowName SXX
|
search_string['Season'].append(ep_string)
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
#Building the search string with the episodes we need
|
#Building the search string with the episodes we need
|
||||||
for ep_obj in wantedEp:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
#If no Episode is needed then return an empty list
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ str(ep_obj.airdate)
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ str(episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode}
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season, 'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _doSearch(self, search_params, show=None):
|
def _doSearch(self, search_params, show=None, age=None):
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
items = {'Season': [], 'Episode': [], 'RSS': []}
|
items = {'Season': [], 'Episode': [], 'RSS': []}
|
||||||
|
@ -197,25 +188,34 @@ class SpeedCDProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return (title, url)
|
return (title, url)
|
||||||
|
|
||||||
def getURL(self, url, headers=None):
|
def getURL(self, url, post_data=None, headers=None):
|
||||||
|
|
||||||
if not self.session:
|
if not self.session:
|
||||||
self._doLogin()
|
self._doLogin()
|
||||||
|
|
||||||
if not headers:
|
|
||||||
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self.session.get(url, headers=headers)
|
# Remove double-slashes from url
|
||||||
|
parsed = list(urlparse.urlparse(url))
|
||||||
|
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
|
||||||
|
url = urlparse.urlunparse(parsed)
|
||||||
|
|
||||||
|
if sickbeard.PROXY_SETTING:
|
||||||
|
proxies = {
|
||||||
|
"http": sickbeard.PROXY_SETTING,
|
||||||
|
"https": sickbeard.PROXY_SETTING,
|
||||||
|
}
|
||||||
|
|
||||||
|
r = self.session.get(url, proxies=proxies, verify=False)
|
||||||
|
else:
|
||||||
|
r = self.session.get(url, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u"Error loading "+self.name+" URL: " + ex(e), logger.ERROR)
|
logger.log(u"Error loading "+self.name+" URL: " + ex(e), logger.ERROR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if response.status_code != 200:
|
if r.status_code != 200:
|
||||||
logger.log(self.name + u" page requested with url " + url +" returned status code is " + str(response.status_code) + ': ' + clients.http_error_code[response.status_code], logger.WARNING)
|
logger.log(self.name + u" page requested with url " + url +" returned status code is " + str(r.status_code) + ': ' + clients.http_error_code[r.status_code], logger.WARNING)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return response.content
|
return r.content
|
||||||
|
|
||||||
def findPropers(self, search_date=datetime.datetime.today()):
|
def findPropers(self, search_date=datetime.datetime.today()):
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,8 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
self.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>'
|
self.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>'
|
||||||
|
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
def isEnabled(self):
|
def isEnabled(self):
|
||||||
return sickbeard.THEPIRATEBAY
|
return sickbeard.THEPIRATEBAY
|
||||||
|
|
||||||
|
@ -170,56 +172,45 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return title
|
return title
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' #2) ShowName Season X
|
||||||
search_string = {'Season': [], 'Episode': []}
|
search_string['Season'].append(ep_string)
|
||||||
for show_name in set(allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' #2) ShowName Season X
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = ep_obj.show
|
if abd:
|
||||||
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
if ep_obj.show.air_by_date:
|
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(allPossibleShowNames(ep_obj.show)):
|
for show_name in set(allPossibleShowNames(show)):
|
||||||
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
ep_string = sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + '|' + \
|
'episodenumber': episode} + '|' + \
|
||||||
sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[0] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode} + '|' + \
|
'episodenumber': episode} + '|' + \
|
||||||
sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[3] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
ep_string += ' %s' % add_string
|
ep_string += ' %s' % add_string
|
||||||
|
|
||||||
|
@ -302,6 +293,9 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
if not headers:
|
if not headers:
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
# Glype Proxies does not support Direct Linking.
|
# Glype Proxies does not support Direct Linking.
|
||||||
# We have to fake a search on the proxy site to get data
|
# We have to fake a search on the proxy site to get data
|
||||||
if self.proxy.isEnabled():
|
if self.proxy.isEnabled():
|
||||||
|
@ -314,9 +308,9 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
"https": sickbeard.PROXY_SETTING,
|
"https": sickbeard.PROXY_SETTING,
|
||||||
}
|
}
|
||||||
|
|
||||||
r = requests.get(url, headers=headers, proxies=proxies, verify=False)
|
r = self.session.get(url, headers=headers, proxies=proxies, verify=False)
|
||||||
else:
|
else:
|
||||||
r = requests.get(url, headers=headers, verify=False)
|
r = self.session.get(url, headers=headers, verify=False)
|
||||||
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), e:
|
||||||
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
logger.log(u"Error loading " + self.name + " URL: " + str(sys.exc_info()) + " - " + ex(e), logger.ERROR)
|
||||||
return None
|
return None
|
||||||
|
@ -332,6 +326,8 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
"""
|
"""
|
||||||
Save the result to disk.
|
Save the result to disk.
|
||||||
"""
|
"""
|
||||||
|
if not self.session:
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
torrent_hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0].upper()
|
||||||
|
|
||||||
|
@ -340,7 +336,7 @@ class ThePirateBayProvider(generic.TorrentProvider):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
r = self.session.get('http://torcache.net/torrent/' + torrent_hash + '.torrent', verify=False)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
logger.log("Unable to connect to Torcache: " + ex(e), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -113,47 +113,38 @@ class TorrentDayProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -95,46 +95,38 @@ class TorrentLeechProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_season_search_strings(self, show, season, wantedEp, searchSeason=False):
|
def _get_season_search_strings(self, show, season, episode, abd=False):
|
||||||
search_string = {'Episode': []}
|
|
||||||
|
|
||||||
if not show:
|
if not show:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.show = show
|
search_string = {'Season': [], 'Episode': []}
|
||||||
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
|
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
||||||
|
search_string['Season'].append(ep_string)
|
||||||
|
|
||||||
if searchSeason:
|
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
|
||||||
search_string = {'Season': [], 'Episode': []}
|
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
|
||||||
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
|
|
||||||
search_string['Season'].append(ep_string)
|
|
||||||
|
|
||||||
for ep_obj in wantedEp:
|
|
||||||
search_string['Episode'] += self._get_episode_search_strings(ep_obj)[0]['Episode']
|
|
||||||
|
|
||||||
if not search_string['Episode']:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [search_string]
|
return [search_string]
|
||||||
|
|
||||||
def _get_episode_search_strings(self, ep_obj, add_string=''):
|
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
|
||||||
|
|
||||||
search_string = {'Episode': []}
|
search_string = {'Episode': []}
|
||||||
|
|
||||||
if not ep_obj:
|
if not episode:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if ep_obj.show.air_by_date:
|
if abd:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
str(ep_obj.airdate) + '|' + \
|
str(episode) + '|' + \
|
||||||
helpers.custom_strftime('%Y %b {S}', ep_obj.airdate)
|
helpers.custom_strftime('%Y %b {S}', episode)
|
||||||
search_string['Episode'].append(ep_string)
|
search_string['Episode'].append(ep_string)
|
||||||
else:
|
else:
|
||||||
for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)):
|
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
|
||||||
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
ep_string = show_name_helpers.sanitizeSceneName(show_name) + ' ' + \
|
||||||
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season,
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': season,
|
||||||
'episodenumber': ep_obj.scene_episode}
|
'episodenumber': episode}
|
||||||
|
|
||||||
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
search_string['Episode'].append(re.sub('\s+', ' ', ep_string))
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class TvTorrentsProvider(generic.TorrentProvider):
|
||||||
|
|
||||||
def _checkAuthFromData(self, data):
|
def _checkAuthFromData(self, data):
|
||||||
|
|
||||||
if data is None:
|
if data is None or data.feed is None:
|
||||||
return self._checkAuth()
|
return self._checkAuth()
|
||||||
|
|
||||||
description_text = data.feed.title
|
description_text = data.feed.title
|
||||||
|
@ -84,7 +84,7 @@ class TvTorrentsCache(tvcache.TVCache):
|
||||||
rss_url = self.provider.url + 'RssServlet?digest=' + sickbeard.TVTORRENTS_DIGEST + '&hash=' + sickbeard.TVTORRENTS_HASH + '&fname=true&exclude=(' + ignore_regex + ')'
|
rss_url = self.provider.url + 'RssServlet?digest=' + sickbeard.TVTORRENTS_DIGEST + '&hash=' + sickbeard.TVTORRENTS_HASH + '&fname=true&exclude=(' + ignore_regex + ')'
|
||||||
logger.log(self.provider.name + u" cache update URL: " + rss_url, logger.DEBUG)
|
logger.log(self.provider.name + u" cache update URL: " + rss_url, logger.DEBUG)
|
||||||
|
|
||||||
data = self.provider.getURL(rss_url)
|
data = self.provider.getRSSFeed(rss_url)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
logger.log(u"No data returned from " + rss_url, logger.ERROR)
|
logger.log(u"No data returned from " + rss_url, logger.ERROR)
|
||||||
|
|
|
@ -25,7 +25,7 @@ import datetime
|
||||||
|
|
||||||
import sickbeard
|
import sickbeard
|
||||||
|
|
||||||
from common import SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, Quality, SEASON_RESULT, MULTI_EP_RESULT
|
from common import SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, Quality, SEASON_RESULT, MULTI_EP_RESULT, Overview
|
||||||
|
|
||||||
from sickbeard import logger, db, show_name_helpers, exceptions, helpers
|
from sickbeard import logger, db, show_name_helpers, exceptions, helpers
|
||||||
from sickbeard import sab
|
from sickbeard import sab
|
||||||
|
@ -349,67 +349,23 @@ def isFirstBestMatch(result):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def searchProviders(show, season, episode=None, manualSearch=False):
|
||||||
def findEpisode(episode, manualSearch=False):
|
|
||||||
logger.log(u"Searching for " + episode.prettyName())
|
|
||||||
|
|
||||||
foundResults = []
|
|
||||||
|
|
||||||
didSearch = False
|
|
||||||
|
|
||||||
for curProvider in providers.sortedProviderList():
|
|
||||||
|
|
||||||
if not curProvider.isActive():
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
curFoundResults = curProvider.findEpisode(episode, manualSearch=manualSearch)
|
|
||||||
except exceptions.AuthException, e:
|
|
||||||
logger.log(u"Authentication error: " + ex(e), logger.ERROR)
|
|
||||||
continue
|
|
||||||
except Exception, e:
|
|
||||||
logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR)
|
|
||||||
logger.log(traceback.format_exc(), logger.DEBUG)
|
|
||||||
continue
|
|
||||||
|
|
||||||
didSearch = True
|
|
||||||
|
|
||||||
# skip non-tv crap
|
|
||||||
curFoundResults = filter(
|
|
||||||
lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name,
|
|
||||||
episode.show),
|
|
||||||
curFoundResults)
|
|
||||||
|
|
||||||
# loop all results and see if any of them are good enough that we can stop searching
|
|
||||||
done_searching = False
|
|
||||||
for cur_result in curFoundResults:
|
|
||||||
done_searching = isFinalResult(cur_result)
|
|
||||||
logger.log(u"Should we stop searching after finding " + cur_result.name + ": " + str(done_searching),
|
|
||||||
logger.DEBUG)
|
|
||||||
if done_searching:
|
|
||||||
break
|
|
||||||
|
|
||||||
foundResults += curFoundResults
|
|
||||||
|
|
||||||
# if we did find a result that's good enough to stop then don't continue
|
|
||||||
if done_searching:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not didSearch:
|
|
||||||
logger.log(u"No NZB/Torrent providers found or enabled in the sickbeard config. Please check your settings.",
|
|
||||||
logger.ERROR)
|
|
||||||
|
|
||||||
bestResult = pickBestResult(foundResults, episode.show)
|
|
||||||
|
|
||||||
return bestResult
|
|
||||||
|
|
||||||
|
|
||||||
def findSeason(show, season):
|
|
||||||
logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season))
|
logger.log(u"Searching for stuff we need from " + show.name + " season " + str(season))
|
||||||
|
|
||||||
foundResults = {}
|
foundResults = {}
|
||||||
|
|
||||||
didSearch = False
|
didSearch = False
|
||||||
|
seasonSearch = False
|
||||||
|
|
||||||
|
# gather all episodes for season and then pick out the wanted episodes and compare to determin if we want whole season or just a few episodes
|
||||||
|
if episode is None:
|
||||||
|
seasonEps = show.getAllEpisodes(season)
|
||||||
|
wantedEps = [x for x in seasonEps if show.getOverview(x.status) in (Overview.WANTED, Overview.QUAL)]
|
||||||
|
if len(seasonEps) == len(wantedEps):
|
||||||
|
seasonSearch = True
|
||||||
|
else:
|
||||||
|
ep_obj = show.getEpisode(season, episode)
|
||||||
|
wantedEps = [ep_obj]
|
||||||
|
|
||||||
for curProvider in providers.sortedProviderList():
|
for curProvider in providers.sortedProviderList():
|
||||||
|
|
||||||
|
@ -417,7 +373,7 @@ def findSeason(show, season):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
curResults = curProvider.findSeasonResults(show, season)
|
curResults = curProvider.getSearchResults(show, season, wantedEps, seasonSearch, manualSearch)
|
||||||
|
|
||||||
# make a list of all the results for this provider
|
# make a list of all the results for this provider
|
||||||
for curEp in curResults:
|
for curEp in curResults:
|
||||||
|
|
|
@ -93,28 +93,29 @@ class ManualSearchQueueItem(generic_queue.QueueItem):
|
||||||
|
|
||||||
logger.log("Beginning manual search for " + self.ep_obj.prettyName())
|
logger.log("Beginning manual search for " + self.ep_obj.prettyName())
|
||||||
|
|
||||||
foundEpisode = search.findEpisode(self.ep_obj, manualSearch=True)
|
foundResults = search.searchProviders(self.ep_obj.show, self.ep_obj.season, self.ep_obj.episode, manualSearch=True)
|
||||||
result = False
|
result = False
|
||||||
|
|
||||||
if not foundEpisode:
|
if not foundResults:
|
||||||
ui.notifications.message('No downloads were found',
|
ui.notifications.message('No downloads were found',
|
||||||
"Couldn't find a download for <i>%s</i>" % self.ep_obj.prettyName())
|
"Couldn't find a download for <i>%s</i>" % self.ep_obj.prettyName())
|
||||||
logger.log(u"Unable to find a download for " + self.ep_obj.prettyName())
|
logger.log(u"Unable to find a download for " + self.ep_obj.prettyName())
|
||||||
|
|
||||||
|
self.success = result
|
||||||
else:
|
else:
|
||||||
|
for foundResult in foundResults:
|
||||||
|
# just use the first result for now
|
||||||
|
logger.log(u"Downloading " + foundResult.name + " from " + foundResult.provider.name)
|
||||||
|
|
||||||
# just use the first result for now
|
result = search.snatchEpisode(foundResult)
|
||||||
logger.log(u"Downloading episode from " + foundEpisode.url)
|
|
||||||
|
|
||||||
result = search.snatchEpisode(foundEpisode)
|
providerModule = foundResult.provider
|
||||||
|
if not result:
|
||||||
|
ui.notifications.error('Error while attempting to snatch ' + foundResult.name + ', check your logs')
|
||||||
|
elif providerModule == None:
|
||||||
|
ui.notifications.error('Provider is configured incorrectly, unable to download')
|
||||||
|
|
||||||
providerModule = foundEpisode.provider
|
self.success = result
|
||||||
if not result:
|
|
||||||
ui.notifications.error('Error while attempting to snatch ' + foundEpisode.name + ', check your logs')
|
|
||||||
elif providerModule == None:
|
|
||||||
ui.notifications.error('Provider is configured incorrectly, unable to download')
|
|
||||||
|
|
||||||
self.success = result
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
# don't let this linger if something goes wrong
|
# don't let this linger if something goes wrong
|
||||||
|
@ -195,14 +196,14 @@ class BacklogQueueItem(generic_queue.QueueItem):
|
||||||
statusResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ?",
|
statusResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ?",
|
||||||
[self.show.indexerid, self.segment])
|
[self.show.indexerid, self.segment])
|
||||||
else:
|
else:
|
||||||
segment_year, segment_month = map(int, self.segment.split('-'))
|
season_year, season_month = map(int, self.segment.split('-'))
|
||||||
min_date = datetime.date(segment_year, segment_month, 1)
|
min_date = datetime.date(season_year, season_month, 1)
|
||||||
|
|
||||||
# it's easier to just hard code this than to worry about rolling the year over or making a month length map
|
# it's easier to just hard code this than to worry about rolling the year over or making a month length map
|
||||||
if segment_month == 12:
|
if season_month == 12:
|
||||||
max_date = datetime.date(segment_year, 12, 31)
|
max_date = datetime.date(season_year, 12, 31)
|
||||||
else:
|
else:
|
||||||
max_date = datetime.date(segment_year, segment_month + 1, 1) - datetime.timedelta(days=1)
|
max_date = datetime.date(season_year, season_month + 1, 1) - datetime.timedelta(days=1)
|
||||||
|
|
||||||
statusResults = myDB.select(
|
statusResults = myDB.select(
|
||||||
"SELECT status FROM tv_episodes WHERE showid = ? AND airdate >= ? AND airdate <= ?",
|
"SELECT status FROM tv_episodes WHERE showid = ? AND airdate >= ? AND airdate <= ?",
|
||||||
|
@ -215,7 +216,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
|
||||||
|
|
||||||
generic_queue.QueueItem.execute(self)
|
generic_queue.QueueItem.execute(self)
|
||||||
|
|
||||||
results = search.findSeason(self.show, self.segment)
|
results = search.searchProviders(self.show, self.segment)
|
||||||
|
|
||||||
# download whatever we find
|
# download whatever we find
|
||||||
for curResult in results:
|
for curResult in results:
|
||||||
|
@ -273,13 +274,8 @@ class FailedQueueItem(generic_queue.QueueItem):
|
||||||
|
|
||||||
failed_history.revertEpisode(self.show, season, episode)
|
failed_history.revertEpisode(self.show, season, episode)
|
||||||
|
|
||||||
for season, episode in self.segment.iteritems():
|
# get search results
|
||||||
epObj = self.show.getEpisode(season, episode)
|
results = search.searchProviders(self.show, season, episode)
|
||||||
|
|
||||||
if self.show.air_by_date:
|
|
||||||
results = search.findSeason(self.show, str(epObj.airdate)[:7])
|
|
||||||
else:
|
|
||||||
results = search.findSeason(self.show, season)
|
|
||||||
|
|
||||||
# download whatever we find
|
# download whatever we find
|
||||||
for curResult in results:
|
for curResult in results:
|
||||||
|
|
|
@ -119,14 +119,14 @@ def makeSceneShowSearchStrings(show):
|
||||||
return map(sanitizeSceneName, showNames)
|
return map(sanitizeSceneName, showNames)
|
||||||
|
|
||||||
|
|
||||||
def makeSceneSeasonSearchString(show, segment, extraSearchType=None):
|
def makeSceneSeasonSearchString(show, season, episode, abd=False, extraSearchType=None):
|
||||||
myDB = db.DBConnection()
|
myDB = db.DBConnection()
|
||||||
|
|
||||||
if show.air_by_date:
|
if show.air_by_date:
|
||||||
numseasons = 0
|
numseasons = 0
|
||||||
|
|
||||||
# the search string for air by date shows is just
|
# the search string for air by date shows is just
|
||||||
seasonStrings = [segment]
|
seasonStrings = [season]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
numseasonsSQlResult = myDB.select(
|
numseasonsSQlResult = myDB.select(
|
||||||
|
@ -134,7 +134,7 @@ def makeSceneSeasonSearchString(show, segment, extraSearchType=None):
|
||||||
[show.indexerid])
|
[show.indexerid])
|
||||||
numseasons = int(numseasonsSQlResult[0][0])
|
numseasons = int(numseasonsSQlResult[0][0])
|
||||||
|
|
||||||
seasonStrings = ["S%02d" % int(segment)]
|
seasonStrings = ["S%02d" % int(season)]
|
||||||
|
|
||||||
showNames = set(makeSceneShowSearchStrings(show))
|
showNames = set(makeSceneShowSearchStrings(show))
|
||||||
|
|
||||||
|
@ -152,33 +152,36 @@ def makeSceneSeasonSearchString(show, segment, extraSearchType=None):
|
||||||
for cur_season in seasonStrings:
|
for cur_season in seasonStrings:
|
||||||
toReturn.append(curShow + "." + cur_season)
|
toReturn.append(curShow + "." + cur_season)
|
||||||
|
|
||||||
|
# episode
|
||||||
|
toReturn.extend(makeSceneSearchString(show, season, episode, abd))
|
||||||
|
|
||||||
return toReturn
|
return toReturn
|
||||||
|
|
||||||
|
|
||||||
def makeSceneSearchString(episode):
|
def makeSceneSearchString(show, season, episode, abd=False):
|
||||||
myDB = db.DBConnection()
|
myDB = db.DBConnection()
|
||||||
numseasonsSQlResult = myDB.select(
|
numseasonsSQlResult = myDB.select(
|
||||||
"SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0",
|
"SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0",
|
||||||
[episode.show.indexerid])
|
[show.indexerid])
|
||||||
numseasons = int(numseasonsSQlResult[0][0])
|
numseasons = int(numseasonsSQlResult[0][0])
|
||||||
numepisodesSQlResult = myDB.select(
|
numepisodesSQlResult = myDB.select(
|
||||||
"SELECT COUNT(episode) as numepisodes FROM tv_episodes WHERE showid = ? and season != 0",
|
"SELECT COUNT(episode) as numepisodes FROM tv_episodes WHERE showid = ? and season != 0",
|
||||||
[episode.show.indexerid])
|
[show.indexerid])
|
||||||
numepisodes = int(numepisodesSQlResult[0][0])
|
numepisodes = int(numepisodesSQlResult[0][0])
|
||||||
|
|
||||||
# see if we should use dates instead of episodes
|
# see if we should use dates instead of episodes
|
||||||
if episode.show.air_by_date and episode.airdate != datetime.date.fromordinal(1):
|
if abd and episode != datetime.date.fromordinal(1):
|
||||||
epStrings = [str(episode.airdate)]
|
epStrings = [str(episode.airdate)]
|
||||||
else:
|
else:
|
||||||
epStrings = ["S%02iE%02i" % (int(episode.scene_season), int(episode.scene_episode)),
|
epStrings = ["S%02iE%02i" % (int(season), int(episode)),
|
||||||
"%ix%02i" % (int(episode.scene_season), int(episode.scene_episode))]
|
"%ix%02i" % (int(season), int(episode))]
|
||||||
|
|
||||||
# for single-season shows just search for the show name -- if total ep count (exclude s0) is less than 11
|
# for single-season shows just search for the show name -- if total ep count (exclude s0) is less than 11
|
||||||
# due to the amount of qualities and releases, it is easy to go over the 50 result limit on rss feeds otherwise
|
# due to the amount of qualities and releases, it is easy to go over the 50 result limit on rss feeds otherwise
|
||||||
if numseasons == 1 and numepisodes < 11:
|
if numseasons == 1 and numepisodes < 11:
|
||||||
epStrings = ['']
|
epStrings = ['']
|
||||||
|
|
||||||
showNames = set(makeSceneShowSearchStrings(episode.show))
|
showNames = set(makeSceneShowSearchStrings(show))
|
||||||
|
|
||||||
toReturn = []
|
toReturn = []
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ import datetime
|
||||||
import threading
|
import threading
|
||||||
import re
|
import re
|
||||||
import glob
|
import glob
|
||||||
|
from time import sleep
|
||||||
import traceback
|
import traceback
|
||||||
|
import shutil
|
||||||
|
|
||||||
import sickbeard
|
import sickbeard
|
||||||
|
|
||||||
|
@ -241,6 +243,7 @@ class TVShow(object):
|
||||||
|
|
||||||
last_update_indexer = datetime.date.fromordinal(self.last_update_indexer)
|
last_update_indexer = datetime.date.fromordinal(self.last_update_indexer)
|
||||||
|
|
||||||
|
# in the first year after ended (last airdate), update every 30 days
|
||||||
# in the first year after ended (last airdate), update every 30 days
|
# in the first year after ended (last airdate), update every 30 days
|
||||||
if (update_date - last_airdate) < datetime.timedelta(days=450) and (
|
if (update_date - last_airdate) < datetime.timedelta(days=450) and (
|
||||||
update_date - last_update_indexer) > datetime.timedelta(days=30):
|
update_date - last_update_indexer) > datetime.timedelta(days=30):
|
||||||
|
@ -307,8 +310,49 @@ class TVShow(object):
|
||||||
|
|
||||||
# create TVEpisodes from each media file (if possible)
|
# create TVEpisodes from each media file (if possible)
|
||||||
for mediaFile in mediaFiles:
|
for mediaFile in mediaFiles:
|
||||||
|
sceneConvert = False
|
||||||
|
parse_result = None
|
||||||
curEpisode = None
|
curEpisode = None
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
while i < 2:
|
||||||
|
i+=1
|
||||||
|
|
||||||
|
np = NameParser(False)
|
||||||
|
parse_result = np.parse(mediaFile, sceneConvert)
|
||||||
|
if helpers.validateShow(self, parse_result.season_number, parse_result.episode_numbers[0]):
|
||||||
|
ep = TVEpisode(self, parse_result.season_number, parse_result.episode_numbers[0])
|
||||||
|
proper_path = ep.proper_path()
|
||||||
|
proper_absolute_path = ek.ek(os.path.join, self._location, proper_path)
|
||||||
|
src_path = ek.ek(os.path.dirname, mediaFile)
|
||||||
|
dest_path = ek.ek(os.path.dirname, proper_absolute_path)
|
||||||
|
orig_extension = mediaFile.rpartition('.')[-1]
|
||||||
|
new_base_name = ek.ek(os.path.basename, proper_path)
|
||||||
|
|
||||||
|
new_file_name = new_base_name + '.' + orig_extension
|
||||||
|
old_file_name = ek.ek(os.path.basename, mediaFile)
|
||||||
|
new_mediaFile = os.path.join(dest_path, new_file_name)
|
||||||
|
if old_file_name == new_file_name or os.path.exists(new_mediaFile):break
|
||||||
|
|
||||||
|
if os.path.exists(os.path.join(src_path, old_file_name)):
|
||||||
|
old_mediaFile = os.path.join(src_path, old_file_name)
|
||||||
|
elif os.path.exists(os.path.join(dest_path, old_file_name)):
|
||||||
|
old_mediaFile = os.path.join(dest_path, old_file_name)
|
||||||
|
else:break
|
||||||
|
|
||||||
|
logger.log(u"Scene Converting file %s to %s" % (old_file_name, new_file_name), logger.MESSAGE)
|
||||||
|
if not os.path.exists(dest_path):
|
||||||
|
shutil.move(src_path, dest_path)
|
||||||
|
shutil.move(old_mediaFile, new_mediaFile)
|
||||||
|
mediaFile = new_mediaFile
|
||||||
|
|
||||||
|
# converted
|
||||||
|
break
|
||||||
|
|
||||||
|
sceneConvert = True
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
logger.log(str(self.indexerid) + u": Creating episode from " + mediaFile, logger.DEBUG)
|
logger.log(str(self.indexerid) + u": Creating episode from " + mediaFile, logger.DEBUG)
|
||||||
try:
|
try:
|
||||||
|
@ -326,7 +370,6 @@ class TVShow(object):
|
||||||
ep_file_name = ek.ek(os.path.basename, curEpisode.location)
|
ep_file_name = ek.ek(os.path.basename, curEpisode.location)
|
||||||
ep_file_name = ek.ek(os.path.splitext, ep_file_name)[0]
|
ep_file_name = ek.ek(os.path.splitext, ep_file_name)[0]
|
||||||
|
|
||||||
parse_result = None
|
|
||||||
try:
|
try:
|
||||||
np = NameParser(False)
|
np = NameParser(False)
|
||||||
parse_result = np.parse(ep_file_name)
|
parse_result = np.parse(ep_file_name)
|
||||||
|
@ -2087,8 +2130,7 @@ class TVEpisode(object):
|
||||||
self.location)
|
self.location)
|
||||||
|
|
||||||
if self.show.subtitles and sickbeard.SUBTITLES_DIR != '':
|
if self.show.subtitles and sickbeard.SUBTITLES_DIR != '':
|
||||||
related_subs = postProcessor.PostProcessor(self.location).list_associated_files(
|
related_subs = postProcessor.PostProcessor(self.location).list_associated_files(sickbeard.SUBTITLES_DIR, subtitles_only=True)
|
||||||
sickbeard.SUBTITLES_DIR, subtitles_only=True)
|
|
||||||
absolute_proper_subs_path = ek.ek(os.path.join, sickbeard.SUBTITLES_DIR, self.formatted_filename())
|
absolute_proper_subs_path = ek.ek(os.path.join, sickbeard.SUBTITLES_DIR, self.formatted_filename())
|
||||||
|
|
||||||
logger.log(u"Files associated to " + self.location + ": " + str(related_files), logger.DEBUG)
|
logger.log(u"Files associated to " + self.location + ": " + str(related_files), logger.DEBUG)
|
||||||
|
@ -2104,8 +2146,7 @@ class TVEpisode(object):
|
||||||
logger.log(str(self.indexerid) + u": Unable to rename file " + cur_related_file, logger.ERROR)
|
logger.log(str(self.indexerid) + u": Unable to rename file " + cur_related_file, logger.ERROR)
|
||||||
|
|
||||||
for cur_related_sub in related_subs:
|
for cur_related_sub in related_subs:
|
||||||
cur_result = helpers.rename_ep_file(cur_related_sub, absolute_proper_subs_path,
|
cur_result = helpers.rename_ep_file(cur_related_sub, absolute_proper_subs_path,absolute_current_path_no_ext_length)
|
||||||
absolute_current_path_no_ext_length)
|
|
||||||
if cur_result == False:
|
if cur_result == False:
|
||||||
logger.log(str(self.indexerid) + u": Unable to rename file " + cur_related_sub, logger.ERROR)
|
logger.log(str(self.indexerid) + u": Unable to rename file " + cur_related_sub, logger.ERROR)
|
||||||
|
|
||||||
|
|
|
@ -1397,6 +1397,7 @@ class ConfigProviders:
|
||||||
hdbits_username=None, hdbits_passkey=None,
|
hdbits_username=None, hdbits_passkey=None,
|
||||||
nextgen_username=None, nextgen_password=None,
|
nextgen_username=None, nextgen_password=None,
|
||||||
newzbin_username=None, newzbin_password=None,
|
newzbin_username=None, newzbin_password=None,
|
||||||
|
speedcd_username=None, speedcd_password=None, speedcd_freeleech=None,
|
||||||
provider_order=None):
|
provider_order=None):
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
|
@ -74,13 +74,14 @@ def test_generator(tvdbdid, show_name, curData, forceSearch):
|
||||||
show.quality = curData["q"]
|
show.quality = curData["q"]
|
||||||
show.saveToDB()
|
show.saveToDB()
|
||||||
sickbeard.showList.append(show)
|
sickbeard.showList.append(show)
|
||||||
|
episode = None
|
||||||
|
|
||||||
for epNumber in curData["e"]:
|
for epNumber in curData["e"]:
|
||||||
episode = TVEpisode(show, curData["s"], epNumber)
|
episode = TVEpisode(show, curData["s"], epNumber)
|
||||||
episode.status = c.WANTED
|
episode.status = c.WANTED
|
||||||
episode.saveToDB()
|
episode.saveToDB()
|
||||||
|
|
||||||
bestResult = search.findEpisode(episode, forceSearch)
|
bestResult = search.searchProviders(show, episode.season, episode.episode, forceSearch)
|
||||||
if not bestResult:
|
if not bestResult:
|
||||||
self.assertEqual(curData["b"], bestResult)
|
self.assertEqual(curData["b"], bestResult)
|
||||||
self.assertEqual(curData["b"], bestResult.name) #first is expected, second is choosen one
|
self.assertEqual(curData["b"], bestResult.name) #first is expected, second is choosen one
|
||||||
|
|
|
@ -179,7 +179,7 @@ def tearDown_test_db():
|
||||||
although this seams not to work on my system it leaves me with an zero kb file
|
although this seams not to work on my system it leaves me with an zero kb file
|
||||||
"""
|
"""
|
||||||
# uncomment next line so leave the db intact between test and at the end
|
# uncomment next line so leave the db intact between test and at the end
|
||||||
#return False
|
return False
|
||||||
if os.path.exists(os.path.join(TESTDIR, TESTDBNAME)):
|
if os.path.exists(os.path.join(TESTDIR, TESTDBNAME)):
|
||||||
os.remove(os.path.join(TESTDIR, TESTDBNAME))
|
os.remove(os.path.join(TESTDIR, TESTDBNAME))
|
||||||
if os.path.exists(os.path.join(TESTDIR, TESTCACHEDBNAME)):
|
if os.path.exists(os.path.join(TESTDIR, TESTCACHEDBNAME)):
|
||||||
|
|
|
@ -27,7 +27,9 @@ sys.path.append(os.path.abspath('../lib'))
|
||||||
|
|
||||||
import test_lib as test
|
import test_lib as test
|
||||||
import sickbeard
|
import sickbeard
|
||||||
from sickbeard.tv import TVShow, TVEpisode
|
from sickbeard.helpers import sanitizeSceneName
|
||||||
|
from sickbeard.show_name_helpers import allPossibleShowNames
|
||||||
|
from sickbeard.tv import TVShow
|
||||||
|
|
||||||
class XEMBasicTests(test.SickbeardTestDBCase):
|
class XEMBasicTests(test.SickbeardTestDBCase):
|
||||||
def loadFromDB(self):
|
def loadFromDB(self):
|
||||||
|
@ -50,9 +52,29 @@ class XEMBasicTests(test.SickbeardTestDBCase):
|
||||||
show = sickbeard.helpers.findCertainShow(sickbeard.showList, 111051)
|
show = sickbeard.helpers.findCertainShow(sickbeard.showList, 111051)
|
||||||
ep = show.getEpisode(2014, 34)
|
ep = show.getEpisode(2014, 34)
|
||||||
|
|
||||||
|
scene_ep_string = sanitizeSceneName(show.name) + ' ' + \
|
||||||
|
sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep.scene_season,
|
||||||
|
'episodenumber': ep.scene_episode} + '|' + \
|
||||||
|
sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep.scene_season,
|
||||||
|
'episodenumber': ep.scene_episode} + '|' + \
|
||||||
|
sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep.scene_season,
|
||||||
|
'episodenumber': ep.scene_episode} + ' %s category:tv' % ''
|
||||||
|
|
||||||
|
scene_season_string = show.name + ' S%02d' % int(ep.scene_season) + ' -S%02d' % int(ep.scene_season) + 'E' + ' category:tv' #1) ShowName SXX -SXXE
|
||||||
|
|
||||||
print(
|
print(
|
||||||
u'Searching "%s" for "%s" as "%s"' % (show.name, ep.prettyName(), ep.scene_prettyName()))
|
u'Searching "%s" for "%s" as "%s"' % (show.name, ep.prettyName(), ep.scene_prettyName()))
|
||||||
|
|
||||||
|
print('Scene episode search strings: %s' % (scene_ep_string))
|
||||||
|
|
||||||
|
print('Scene season search strings: %s' % (scene_season_string))
|
||||||
|
|
||||||
|
def test_renaming(self):
|
||||||
|
self.file_name = 'American Pickers - S04E01 - Jurassic Pick.avi'
|
||||||
|
orig_extension = self.file_name.rpartition('.')[-1]
|
||||||
|
new_base_name = os.path.basename(proper_path)
|
||||||
|
new_file_name = new_base_name + '.' + orig_extension
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print "=================="
|
print "=================="
|
||||||
print "STARTING - XEM Scene Numbering TESTS"
|
print "STARTING - XEM Scene Numbering TESTS"
|
||||||
|
|
Loading…
Reference in a new issue