diff --git a/gui/slick/images/network/el rey network.png b/gui/slick/images/network/el rey network.png new file mode 100644 index 0000000000000000000000000000000000000000..d256f84832b689f2fadfc84b0ec8f3d2ed784c74 Binary files /dev/null and b/gui/slick/images/network/el rey network.png differ diff --git a/gui/slick/interfaces/default/config_subtitles.tmpl b/gui/slick/interfaces/default/config_subtitles.tmpl index 420d3e54abe81dc1ad74a8fc6076d49b1f098fdd..90d18bc3834235ebbb84c73daaf4eafea656b813 100644 --- a/gui/slick/interfaces/default/config_subtitles.tmpl +++ b/gui/slick/interfaces/default/config_subtitles.tmpl @@ -106,6 +106,13 @@ <span class="component-desc">Log downloaded Subtitle on History page?</span> </label> </div> + <div class="field-pair"> + <input type="checkbox" name="subtitles_multi" id="subtitles_multi" #if $sickbeard.SUBTITLES_MULTI then " checked=\"checked\"" else ""#/> + <label class="clearfix" for="subtitles_multi"> + <span class="component-title">Subtitles Multi-Language</span> + <span class="component-desc">Append language codes to subtitle filenames?</span> + </label> + </div> <br/><input type="submit" class="btn config_submitter" value="Save Changes" /><br/> </div> </fieldset> diff --git a/lib/imdb/__init__.py b/lib/imdb/__init__.py index 0cdc9650f61526e4b6c9be30cc9853e79d7ce8bb..5114dd22db58eb836b7e3d147f6e1a66549ba0dc 100644 --- a/lib/imdb/__init__.py +++ b/lib/imdb/__init__.py @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA __all__ = ['IMDb', 'IMDbError', 'Movie', 'Person', 'Character', 'Company', 'available_access_systems'] -__version__ = VERSION = '5.0' +__version__ = VERSION = '5.1dev20141116' # Import compatibility module (importing it is enough). import _compat diff --git a/lib/imdb/imdbpy.cfg b/lib/imdb/imdbpy.cfg deleted file mode 100644 index 68b305386518020c110d81e30adaea4bcbbc9f2c..0000000000000000000000000000000000000000 --- a/lib/imdb/imdbpy.cfg +++ /dev/null @@ -1,78 +0,0 @@ -# -# IMDbPY configuration file. -# -# This file can be placed in many locations; the first file found is -# used, _ignoring_ the content of the others. -# -# Place it in one of the following directories (in order of precedence): -# -# - imdbpy.cfg in the current directory. -# - .imdbpy.cfg in the current directory. -# - imdbpy.cfg in the user's home directory. -# - .imdbpy.cfg in the user's home directory. -# - /etc/imdbpy.cfg Unix-like systems only. -# - /etc/conf.d/imdbpy.cfg Unix-like systems only. -# - sys.prefix + imdbpy.cfg for non-Unix (e.g.: C:\Python\etc\imdbpy.cfg) -# -# If this file is not found, 'http' access system is used by default. -# -# Lines starting with #, ; and // are considered comments and ignored. -# -# Some special values are replaced with Python equivalents (case insensitive): -# -# 0, off, false, no -> False -# 1, on, true, yes -> True -# none -> None -# -# Other options, like defaultModFunct, must be passed by the code. -# - -[imdbpy] -## Default. -accessSystem = httpThin - -## Optional (options common to every data access system): -# Activate adult searches (on, by default). -#adultSearch = on -# Number of results for searches (20 by default). -#results = 20 -# Re-raise all caught exceptions (off, by default). -#reraiseExceptions = off - -## Optional (options common to http and mobile data access systems): -# Proxy used to access the network. If it requires authentication, -# try with: http://username:password@server_address:port/ -#proxy = http://localhost:8080/ -# Cookies of the IMDb.com account -#cookie_id = string_representing_the_cookie_id -#cookie_uu = string_representing_the_cookie_uu -## Timeout for the connection to IMDb (30 seconds, by default). -#timeout = 30 -# Base url to access pages on the IMDb.com web server. -#imdbURL_base = http://akas.imdb.com/ - -## Parameters for the 'http' data access system. -# Parser to use; can be a single value or a list of value separated by -# a comma, to express order preference. Valid values: "lxml", "beautifulsoup" -#useModule = lxml,beautifulsoup - -## Parameters for the 'mobile' data access system. -#accessSystem = mobile - -## Parameters for the 'sql' data access system. -#accessSystem = sql -#uri = mysql://user:password@localhost/imdb -# ORM to use; can be a single value or a list of value separated by -# a comma, to express order preference. Valid values: "sqlobject", "sqlalchemy" -#useORM = sqlobject,sqlalchemy - -## Set the threshold for logging messages. -# Can be one of "debug", "info", "warning", "error", "critical" (default: -# "warning"). -loggingLevel = debug - -## Path to a configuration file for the logging facility; -# see: http://docs.python.org/library/logging.html#configuring-logging -#loggingConfig = ~/.imdbpy-logger.cfg - - diff --git a/lib/imdb/utils.py b/lib/imdb/utils.py index f468efd4dd7fc0290902b3502301070fea6ae53e..c43cb627a460c06a01e6431d6a01ae275f481d23 100644 --- a/lib/imdb/utils.py +++ b/lib/imdb/utils.py @@ -639,11 +639,14 @@ def analyze_company_name(name, stripNotes=False): o_name = name name = name.strip() country = None - if name.endswith(']'): - idx = name.rfind('[') - if idx != -1: - country = name[idx:] - name = name[:idx].rstrip() + if name.startswith('['): + name = re.sub('[!@#$\(\)\[\]]', '', name) + else: + if name.endswith(']'): + idx = name.rfind('[') + if idx != -1: + country = name[idx:] + name = name[:idx].rstrip() if not name: raise IMDbParserError('invalid name: "%s"' % o_name) result = {'name': name} diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 5c94c8712576b78a80e6408c1d49e7b7f4dc94ee..115c31ec732586f4a9481905f411d34a644875e8 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -571,9 +571,9 @@ class Tvdb: "https": self.config['proxy'], } - resp = session.get(url, cache_auto=True, params=params) + resp = session.get(url.strip(), cache_auto=True, params=params) else: - resp = requests.get(url, params=params) + resp = requests.get(url.strip(), params=params) resp.raise_for_status() except requests.exceptions.HTTPError, e: @@ -619,7 +619,7 @@ class Tvdb: raise tvdb_error("Bad zip file received from thetvdb.com, could not read it") else: try: - return xmltodict.parse(resp.content.strip(), postprocessor=process) + return xmltodict.parse(resp.text.rstrip("\r"), postprocessor=process) except: return dict([(u'data', None)]) diff --git a/lib/tvrage_api/tvrage_api.py b/lib/tvrage_api/tvrage_api.py index f5aff5ab8b39520baa0be3095d10b50b530f3f00..832b82ae24eefa88132d009796c79021c74dce1c 100644 --- a/lib/tvrage_api/tvrage_api.py +++ b/lib/tvrage_api/tvrage_api.py @@ -392,7 +392,7 @@ class TVRage: return os.path.join(tempfile.gettempdir(), "tvrage_api-%s" % (uid)) - #@retry(tvrage_error) + @retry(tvrage_error) def _loadUrl(self, url, params=None): try: log().debug("Retrieving URL %s" % url) @@ -471,11 +471,10 @@ class TVRage: return (key, value) - if resp.ok: - try: - return xmltodict.parse(resp.content.strip(), postprocessor=remap_keys) - except: - return dict([(u'data', None)]) + try: + return xmltodict.parse(resp.text.rstrip("\r"), postprocessor=remap_keys) + except: + return dict([(u'data', None)]) def _getetsrc(self, url, params=None): """Loads a URL using caching, returns an ElementTree of the source @@ -524,7 +523,7 @@ class TVRage: - Trailing whitespace """ - if not isinstance(data, dict or list): + if isinstance(data, basestring): data = data.replace(u"&", u"&") data = data.strip() diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index fc3fc87730f5fd76cd37417a571c51a72a311955..75bbbd4c7bd7f7353449da7b9b068490f5e42681 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -451,6 +451,7 @@ SUBTITLES_SERVICES_LIST = [] SUBTITLES_SERVICES_ENABLED = [] SUBTITLES_HISTORY = False SUBTITLES_FINDER_FREQUENCY = 1 +SUBTITLES_MULTI = False USE_FAILED_DOWNLOADS = False DELETE_FAILED = False @@ -515,7 +516,7 @@ def initialize(consoleLogging=True): GUI_NAME, HOME_LAYOUT, HISTORY_LAYOUT, DISPLAY_SHOW_SPECIALS, COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, COMING_EPS_MISSED_RANGE, FUZZY_DATING, TRIM_ZERO, DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, THEME_NAME, \ POSTER_SORTBY, POSTER_SORTDIR, \ METADATA_WDTV, METADATA_TIVO, METADATA_MEDE8ER, IGNORE_WORDS, REQUIRE_WORDS, CALENDAR_UNPROTECTED, CREATE_MISSING_SHOW_DIRS, \ - ADD_SHOWS_WO_DIR, USE_SUBTITLES, SUBTITLES_LANGUAGES, SUBTITLES_DIR, SUBTITLES_SERVICES_LIST, SUBTITLES_SERVICES_ENABLED, SUBTITLES_HISTORY, SUBTITLES_FINDER_FREQUENCY, subtitlesFinderScheduler, \ + ADD_SHOWS_WO_DIR, USE_SUBTITLES, SUBTITLES_LANGUAGES, SUBTITLES_DIR, SUBTITLES_SERVICES_LIST, SUBTITLES_SERVICES_ENABLED, SUBTITLES_HISTORY, SUBTITLES_FINDER_FREQUENCY, SUBTITLES_MULTI, subtitlesFinderScheduler, \ USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, PROXY_INDEXERS, \ AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \ ANIME_DEFAULT, NAMING_ANIME, ANIMESUPPORT, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \ @@ -934,6 +935,7 @@ def initialize(consoleLogging=True): SUBTITLES_DEFAULT = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_default', 0)) SUBTITLES_HISTORY = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_history', 0)) SUBTITLES_FINDER_FREQUENCY = check_setting_int(CFG, 'Subtitles', 'subtitles_finder_frequency', 1) + SUBTITLES_MULTI = bool(check_setting_int(CFG, 'Subtitles', 'subtitles_multi', 1)) USE_FAILED_DOWNLOADS = bool(check_setting_int(CFG, 'FailedDownloads', 'use_failed_downloads', 0)) DELETE_FAILED = bool(check_setting_int(CFG, 'FailedDownloads', 'delete_failed', 0)) @@ -1815,6 +1817,7 @@ def save_config(): new_config['Subtitles']['subtitles_default'] = int(SUBTITLES_DEFAULT) new_config['Subtitles']['subtitles_history'] = int(SUBTITLES_HISTORY) new_config['Subtitles']['subtitles_finder_frequency'] = int(SUBTITLES_FINDER_FREQUENCY) + new_config['Subtitles']['subtitles_multi'] = int(SUBTITLES_MULTI) new_config['FailedDownloads'] = {} new_config['FailedDownloads']['use_failed_downloads'] = int(USE_FAILED_DOWNLOADS) diff --git a/sickbeard/traktChecker.py b/sickbeard/traktChecker.py index 8ef1e0a57961f436fb35f5ac67b7eb47852f3d6d..7ca6f14d9384634fd1c30e73bc54d1a00336e2ea 100644 --- a/sickbeard/traktChecker.py +++ b/sickbeard/traktChecker.py @@ -119,6 +119,7 @@ class TraktChecker(): self.trakt_api.traktRequest("show/library/%APIKEY%", data) except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % e.message, logger.WARNING) + return def updateShows(self): logger.log(u"Starting trakt show watchlist check", logger.DEBUG) diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 27431ec1b5efd91633b82a77e6f8ec701dfc0c57..c64adfce47ea45a1333a4b6e86e511d40a081587 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -910,10 +910,13 @@ class TVShow(object): 'last_update': '' } + i = imdb.IMDb() + if not self.imdbid: + self.imdbid = i.title2imdbID(self.name, kind='tv series') + if self.imdbid: logger.log(str(self.indexerid) + u": Loading show info from IMDb") - i = imdb.IMDb() imdbTv = i.get_movie(str(re.sub("[^0-9]", "", self.imdbid))) for key in filter(lambda x: x.replace('_', ' ') in imdbTv.keys(), imdb_info.keys()): @@ -1110,30 +1113,28 @@ class TVShow(object): myDB.mass_action(sql_l) def downloadSubtitles(self, force=False): - # TODO: Add support for force option if not ek.ek(os.path.isdir, self._location): logger.log(str(self.indexerid) + ": Show dir doesn't exist, can't download subtitles", logger.DEBUG) return + logger.log(str(self.indexerid) + ": Downloading subtitles", logger.DEBUG) try: - myDB = db.DBConnection() - episodes = myDB.select( - "SELECT location FROM tv_episodes WHERE showid = ? AND location NOT LIKE '' ORDER BY season DESC, episode DESC", - [self.indexerid]) + episodes = self.getAllEpisodes(has_location=True) + if not len(episodes) > 0: + logger.log(str(self.indexerid) + ": No episodes to download subtitles for " + self.name, logger.DEBUG) + return - for episodeLoc in episodes: - episode = self.makeEpFromFile(episodeLoc['location']) - subtitles = episode.downloadSubtitles(force=force) - except Exception as e: - logger.log("Error occurred when downloading subtitles: " + traceback.format_exc(), logger.DEBUG) - return + for episode in episodes: + episode.downloadSubtitles(force=force) + except Exception: + logger.log("Error occurred when downloading subtitles: " + traceback.format_exc(), logger.DEBUG) def saveToDB(self, forceSave=False): if not self.dirty and not forceSave: - logger.log(str(self.indexerid) + u": Not saving show to db - record is not dirty", logger.DEBUG) + logger.log(str(self.indexerid) + ": Not saving show to db - record is not dirty", logger.DEBUG) return logger.log(str(self.indexerid) + u": Saving show info to database", logger.DEBUG) @@ -1405,7 +1406,7 @@ class TVEpisode(object): need_languages = set(sickbeard.SUBTITLES_LANGUAGES) - set(self.subtitles) subtitles = subliminal.download_subtitles([self.location], languages=need_languages, services=sickbeard.subtitles.getEnabledServiceList(), force=force, - multi=True, cache_dir=sickbeard.CACHE_DIR) + multi=sickbeard.SUBTITLES_MULTI, cache_dir=sickbeard.CACHE_DIR) if sickbeard.SUBTITLES_DIR: for video in subtitles: diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index c5740025abeba77d4ef5ea5f7d71d6e00cdcfaac..a89b80e44a0aa3ba8f10e2aea1be4b10674b5950 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2608,7 +2608,9 @@ class ConfigSubtitles(MainHandler): def saveSubtitles(self, use_subtitles=None, subtitles_plugins=None, subtitles_languages=None, subtitles_dir=None, - service_order=None, subtitles_history=None, subtitles_finder_frequency=None): + service_order=None, subtitles_history=None, subtitles_finder_frequency=None, + subtitles_multi=None): + results = [] if subtitles_finder_frequency == '' or subtitles_finder_frequency is None: @@ -2634,6 +2636,7 @@ class ConfigSubtitles(MainHandler): sickbeard.SUBTITLES_DIR = subtitles_dir sickbeard.SUBTITLES_HISTORY = config.checkbox_to_value(subtitles_history) sickbeard.SUBTITLES_FINDER_FREQUENCY = config.to_int(subtitles_finder_frequency, default=1) + sickbeard.SUBTITLES_MULTI = config.checkbox_to_value(subtitles_multi) # Subtitles services services_str_list = service_order.split()