From 6f3a282f2a9b7ca4f921eaf0c1a25b1486a0efa0 Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Sun, 19 Jan 2020 17:49:53 -0500 Subject: [PATCH 01/14] Revert "Feature/provider titrari ro" --- README.md | 1 - bazarr/get_providers.py | 2 +- libs/subliminal_patch/providers/titrari.py | 224 --------------------- libs/subzero/language.py | 1 - views/providers.tpl | 22 -- 5 files changed, 1 insertion(+), 249 deletions(-) delete mode 100644 libs/subliminal_patch/providers/titrari.py diff --git a/README.md b/README.md index 03fe24a62..ef15757bf 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,6 @@ If you need something that is not already part of Bazarr, feel free to create a * SubZ * Supersubtitles * Titlovi -* Titrari.ro * TVSubtitles * XSubs * Zimuku diff --git a/bazarr/get_providers.py b/bazarr/get_providers.py index 3e1507138..c543f930d 100644 --- a/bazarr/get_providers.py +++ b/bazarr/get_providers.py @@ -39,7 +39,7 @@ PROVIDER_THROTTLE_MAP = { } PROVIDERS_FORCED_OFF = ["addic7ed", "tvsubtitles", "legendastv", "napiprojekt", "shooter", "hosszupuska", - "supersubtitles", "titlovi", "titrari", "argenteam", "assrt", "subscene"] + "supersubtitles", "titlovi", "argenteam", "assrt", "subscene"] throttle_count = {} diff --git a/libs/subliminal_patch/providers/titrari.py b/libs/subliminal_patch/providers/titrari.py deleted file mode 100644 index fa02509fc..000000000 --- a/libs/subliminal_patch/providers/titrari.py +++ /dev/null @@ -1,224 +0,0 @@ -# coding=utf-8 - -from __future__ import absolute_import -import io -import logging -import re -from subliminal import __short_version__ -import rarfile - -from zipfile import ZipFile, is_zipfile -from rarfile import RarFile, is_rarfile -from subliminal_patch.providers import Provider -from subliminal_patch.providers.mixins import ProviderSubtitleArchiveMixin -from subliminal_patch.subtitle import Subtitle -from subliminal_patch.utils import sanitize, fix_inconsistent_naming as _fix_inconsistent_naming -from subliminal.exceptions import ProviderError -from subliminal.providers import ParserBeautifulSoup -from subliminal.video import Episode, Movie -from subzero.language import Language - -# parsing regex definitions -title_re = re.compile(r'(?P(?:.+(?= [Aa][Kk][Aa] ))|.+)(?:(?:.+)(?P<altitle>(?<= [Aa][Kk][Aa] ).+))?') - - -def fix_inconsistent_naming(title): - """Fix titles with inconsistent naming using dictionary and sanitize them. - - :param str title: original title. - :return: new title. - :rtype: str - - """ - return _fix_inconsistent_naming(title, {"DC's Legends of Tomorrow": "Legends of Tomorrow", - "Marvel's Jessica Jones": "Jessica Jones"}) - - -logger = logging.getLogger(__name__) - -# Configure :mod:`rarfile` to use the same path separator as :mod:`zipfile` -rarfile.PATH_SEP = '/' - -class TitrariSubtitle(Subtitle): - - provider_name = 'titrari' - - def __init__(self, language, download_link, sid, releases, title, imdb_id, year=None, download_count=None, comments=None): - super(TitrariSubtitle, self).__init__(language) - self.sid = sid - self.title = title - self.imdb_id = imdb_id - self.download_link = download_link - self.year = year - self.download_count = download_count - self.releases = self.release_info = releases - self.comments = comments - - @property - def id(self): - return self.sid - - def __str__(self): - return self.title + "(" + str(self.year) + ")" + " -> " + self.download_link - - def __repr__(self): - return self.title + "(" + str(self.year) + ")" - - def get_matches(self, video): - matches = set() - - if isinstance(video, Movie): - # title - if video.title and sanitize(self.title) == fix_inconsistent_naming(video.title): - matches.add('title') - - if video.year and self.year == video.year: - matches.add('year') - - if video.imdb_id and self.imdb_id == video.imdb_id: - matches.add('imdb_id') - - if video.release_group and video.release_group in self.comments: - matches.add('release_group') - - if video.resolution and video.resolution.lower() in self.comments: - matches.add('resolution') - - self.matches = matches - - return matches - - -class TitrariProvider(Provider, ProviderSubtitleArchiveMixin): - subtitle_class = TitrariSubtitle - languages = {Language(l) for l in ['ron', 'eng']} - languages.update(set(Language.rebuild(l, forced=True) for l in languages)) - api_url = 'https://www.titrari.ro/' - query_advanced_search = 'cautareavansata' - - def __init__(self): - self.session = None - - def initialize(self): - self.session = Session() - self.session.headers['User-Agent'] = 'Subliminal/{}'.format(__short_version__) - - def terminate(self): - self.session.close() - - def query(self, languages=None, title=None, imdb_id=None, video=None): - subtitles = [] - - params = self.getQueryParams(imdb_id, title) - - search_response = self.session.get(self.api_url, params=params, timeout=15) - search_response.raise_for_status() - - if not search_response.content: - logger.debug('[#### Provider: titrari.ro] No data returned from provider') - return [] - - soup = ParserBeautifulSoup(search_response.content.decode('utf-8', 'ignore'), ['lxml', 'html.parser']) - - # loop over subtitle cells - rows = soup.select('td[rowspan=\'5\']') - for index, row in enumerate(rows): - result_anchor_el = row.select_one('a') - - # Download link - href = result_anchor_el.get('href') - download_link = self.api_url + href - - fullTitle = row.parent.find("h1").find("a").text - - #Get title - try: - title = fullTitle.split("(")[0] - except: - logger.error("[#### Provider: titrari.ro] Error parsing title.") - - # Get downloads count - try: - downloads = int(row.parent.parent.select("span")[index].text[12:]) - except: - logger.error("[#### Provider: titrari.ro] Error parsing downloads.") - - # Get year - try: - year = int(fullTitle.split("(")[1].split(")")[0]) - except: - year = None - logger.error("[#### Provider: titrari.ro] Error parsing year.") - - # Get imdbId - sub_imdb_id = self.getImdbIdFromSubtitle(row) - - try: - comments = row.parent.parent.find_all("td", class_=re.compile("comment"))[index*2+1].text - except: - logger.error("Error parsing comments.") - - subtitle = self.subtitle_class(next(iter(languages)), download_link, index, None, title, sub_imdb_id, year, downloads, comments) - logger.debug('[#### Provider: titrari.ro] Found subtitle %r', str(subtitle)) - subtitles.append(subtitle) - - ordered_subs = self.order(subtitles, video) - - return ordered_subs - - def order(self, subtitles, video): - logger.debug("[#### Provider: titrari.ro] Sorting by download count...") - sorted_subs = sorted(subtitles, key=lambda s: s.download_count, reverse=True) - return sorted_subs - - def getImdbIdFromSubtitle(self, row): - try: - imdbId = row.parent.parent.find_all(src=re.compile("imdb"))[0].parent.get('href').split("tt")[-1] - except: - logger.error("[#### Provider: titrari.ro] Error parsing imdbId.") - if imdbId is not None: - return "tt" + imdbId - else: - return None - - - def getQueryParams(self, imdb_id, title): - queryParams = { - 'page': self.query_advanced_search, - 'z8': '1' - } - if imdb_id is not None: - queryParams["z5"] = imdb_id - elif title is not None: - queryParams["z7"] = title - - return queryParams - - def list_subtitles(self, video, languages): - title = fix_inconsistent_naming(video.title) - imdb_id = video.imdb_id[2:] - return [s for s in - self.query(languages, title, imdb_id, video)] - - def download_subtitle(self, subtitle): - r = self.session.get(subtitle.download_link, headers={'Referer': self.api_url}, timeout=10) - r.raise_for_status() - - # open the archive - archive_stream = io.BytesIO(r.content) - if is_rarfile(archive_stream): - logger.debug('[#### Provider: titrari.ro] Archive identified as rar') - archive = RarFile(archive_stream) - elif is_zipfile(archive_stream): - logger.debug('[#### Provider: titrari.ro] Archive identified as zip') - archive = ZipFile(archive_stream) - else: - subtitle.content = r.content - if subtitle.is_valid(): - return - subtitle.content = None - - raise ProviderError('[#### Provider: titrari.ro] Unidentified archive type') - - subtitle.content = self.get_subtitle_from_archive(subtitle, archive) - diff --git a/libs/subzero/language.py b/libs/subzero/language.py index d3be09523..12d41d26e 100644 --- a/libs/subzero/language.py +++ b/libs/subzero/language.py @@ -30,7 +30,6 @@ repl_map = { "rum": "ro", "slo": "sk", "tib": "bo", - "ron": "ro", } ALPHA2_LIST = list(set(filter(lambda x: x, map(lambda x: x.alpha2, LANGUAGE_MATRIX)))) + list(repl_map.values()) diff --git a/views/providers.tpl b/views/providers.tpl index 2eada8f3d..e8c694411 100644 --- a/views/providers.tpl +++ b/views/providers.tpl @@ -699,28 +699,6 @@ </div> </div> - <div class="middle aligned row"> - <div class="right aligned four wide column"> - <label>Titrari.ro</label> - </div> - <div class="one wide column"> - <div id="titrari" class="ui toggle checkbox provider"> - <input type="checkbox"> - <label></label> - </div> - </div> - <div class="collapsed column"> - <div class="collapsed center aligned column"> - <div class="ui basic icon" data-tooltip="Romanian Subtitles Provider." data-inverted=""> - <i class="help circle large icon"></i> - </div> - </div> - </div> - </div> - <div id="titrari_option" class="ui grid container"> - - </div> - <div class="middle aligned row"> <div class="right aligned four wide column"> <label>TVSubtitles</label> From e5ecd17f80fcf7149004dacb689b4e1f72262602 Mon Sep 17 00:00:00 2001 From: JpF4E <joaoprodrigues@ua.pt> Date: Sat, 22 Feb 2020 19:29:04 +0000 Subject: [PATCH 02/14] Added audio language variables to post processing command. Required to use with subsync. --- bazarr/get_subtitle.py | 40 +++++++++++++++++++++++++------------- bazarr/helper.py | 5 ++++- bazarr/main.py | 16 ++++++++++----- views/settings_general.tpl | 12 ++++++++++++ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/bazarr/get_subtitle.py b/bazarr/get_subtitle.py index 8b078f439..ab2afb31c 100644 --- a/bazarr/get_subtitle.py +++ b/bazarr/get_subtitle.py @@ -23,7 +23,8 @@ from subliminal_patch.core import SZAsyncProviderPool, download_best_subtitles, list_all_subtitles, get_subtitle_path from subliminal_patch.score import compute_score from subliminal.refiners.tvdb import series_re -from get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2, language_from_alpha2 +from get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2, language_from_alpha2, \ + alpha2_from_language, alpha3_from_language from config import settings from helper import path_replace, path_replace_movie, path_replace_reverse, \ path_replace_reverse_movie, pp_replace, get_target_folder, force_unicode @@ -106,7 +107,7 @@ def get_scores(video, media_type, min_score_movie_perc=60 * 100 / 120.0, min_sco return min_score, max_score, set(scores) -def download_subtitle(path, language, hi, forced, providers, providers_auth, sceneName, title, media_type, +def download_subtitle(path, language, audio_language, hi, forced, providers, providers_auth, sceneName, title, media_type, forced_minimum_score=None, is_upgrade=False): # fixme: supply all missing languages, not only one, to hit providers only once who support multiple languages in # one query @@ -217,6 +218,8 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce downloaded_language_code3 = subtitle.language.alpha3 downloaded_language = language_from_alpha3(downloaded_language_code3) downloaded_language_code2 = alpha2_from_alpha3(downloaded_language_code3) + audio_language_code2 = alpha2_from_language(audio_language) + audio_language_code3 = alpha3_from_language(audio_language) downloaded_path = subtitle.storage_path is_forced_string = " forced" if subtitle.language.forced else "" logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) @@ -233,8 +236,8 @@ def download_subtitle(path, language, hi, forced, providers, providers_auth, sce if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, - downloaded_language_code2, downloaded_language_code3, - subtitle.language.forced) + downloaded_language_code2, downloaded_language_code3, audio_language, + audio_language_code2, audio_language_code3, subtitle.language.forced) postprocessing(command, path) # fixme: support multiple languages at once @@ -365,7 +368,7 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa return final_subtitles -def manual_download_subtitle(path, language, hi, forced, subtitle, provider, providers_auth, sceneName, title, +def manual_download_subtitle(path, language, audio_language, hi, forced, subtitle, provider, providers_auth, sceneName, title, media_type): logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path) @@ -423,6 +426,8 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro downloaded_language_code3 = subtitle.language.alpha3 downloaded_language = language_from_alpha3(downloaded_language_code3) downloaded_language_code2 = alpha2_from_alpha3(downloaded_language_code3) + audio_language_code2 = alpha2_from_language(audio_language) + audio_language_code3 = alpha3_from_language(audio_language) downloaded_path = saved_subtitle.storage_path logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) is_forced_string = " forced" if subtitle.language.forced else "" @@ -431,8 +436,8 @@ def manual_download_subtitle(path, language, hi, forced, subtitle, provider, pro if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, - downloaded_language_code2, downloaded_language_code3, - subtitle.language.forced) + downloaded_language_code2, downloaded_language_code3, audio_language, + audio_language_code2, audio_language_code3, subtitle.language.forced) postprocessing(command, path) if media_type == 'series': @@ -512,7 +517,7 @@ def series_download_subtitles(no): logging.debug("BAZARR no episode for that sonarrSeriesId can be found in database:", str(no)) return - series_details = database.execute("SELECT hearing_impaired, title, forced FROM table_shows WHERE sonarrSeriesId=?", + series_details = database.execute("SELECT hearing_impaired, audio_language, title, forced FROM table_shows WHERE sonarrSeriesId=?", (no,), only_one=True) if not series_details: logging.debug("BAZARR no series with that sonarrSeriesId can be found in database:", str(no)) @@ -531,6 +536,7 @@ def series_download_subtitles(no): length=count_episodes_details) result = download_subtitle(path_replace(episode['path']), str(alpha3_from_alpha2(language.split(':')[0])), + series_details['audio_language'], series_details['hearing_impaired'], "True" if len(language.split(':')) > 1 else "False", providers_list, @@ -567,7 +573,7 @@ def episode_download_subtitles(no): episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, " "table_episodes.sonarrEpisodeId, table_episodes.scene_name, " "table_shows.hearing_impaired, table_shows.title, table_shows.sonarrSeriesId, " - "table_shows.forced FROM table_episodes LEFT JOIN table_shows on " + "table_shows.forced, table_shows.audio_language FROM table_episodes LEFT JOIN table_shows on " "table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId " "WHERE sonarrEpisodeId=?" + episodes_details_clause, (no,)) @@ -587,6 +593,7 @@ def episode_download_subtitles(no): path_replace(episode['path']), queue='get_subtitle') result = download_subtitle(path_replace(episode['path']), str(alpha3_from_alpha2(language.split(':')[0])), + episode['audio_language'], episode['hearing_impaired'], "True" if len(language.split(':')) > 1 else "False", providers_list, @@ -616,7 +623,7 @@ def movies_download_subtitles(no): else: movie_details_clause = '' - movie = database.execute("SELECT path, missing_subtitles, radarrId, sceneName, hearing_impaired, title, forced " + movie = database.execute("SELECT path, missing_subtitles, audio_language, radarrId, sceneName, hearing_impaired, title, forced " "FROM table_movies WHERE radarrId=?" + movie_details_clause, (no,), only_one=True) if not movie: @@ -638,6 +645,7 @@ def movies_download_subtitles(no): length=count_movie) result = download_subtitle(path_replace_movie(movie['path']), str(alpha3_from_alpha2(language.split(':')[0])), + movie['audio_language'], movie['hearing_impaired'], "True" if len(language.split(':')) > 1 else "False", providers_list, @@ -668,7 +676,7 @@ def movies_download_subtitles(no): def wanted_download_subtitles(path, l, count_episodes): episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, " "table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, " - "table_shows.hearing_impaired, table_episodes.scene_name," + "table_shows.hearing_impaired, table_shows.audio_language, table_episodes.scene_name," "table_episodes.failedAttempts, table_shows.title, table_shows.forced " "FROM table_episodes LEFT JOIN table_shows on " "table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId " @@ -701,6 +709,7 @@ def wanted_download_subtitles(path, l, count_episodes): length=count_episodes) result = download_subtitle(path_replace(episode['path']), str(alpha3_from_alpha2(language.split(':')[0])), + episode['audio_language'], episode['hearing_impaired'], "True" if len(language.split(':')) > 1 else "False", providers_list, @@ -724,7 +733,7 @@ def wanted_download_subtitles(path, l, count_episodes): def wanted_download_subtitles_movie(path, l, count_movies): - movies_details = database.execute("SELECT path, missing_subtitles, radarrId, hearing_impaired, sceneName, " + movies_details = database.execute("SELECT path, missing_subtitles, radarrId, hearing_impaired, audio_language, sceneName, " "failedAttempts, title, forced FROM table_movies WHERE path = ? " "AND missing_subtitles != '[]'", (path_replace_reverse_movie(path),)) @@ -754,6 +763,7 @@ def wanted_download_subtitles_movie(path, l, count_movies): length=count_movies) result = download_subtitle(path_replace_movie(movie['path']), str(alpha3_from_alpha2(language.split(':')[0])), + movie['audio_language'], movie['hearing_impaired'], "True" if len(language.split(':')) > 1 else "False", providers_list, @@ -957,7 +967,7 @@ def upgrade_subtitles(): if settings.general.getboolean('use_sonarr'): upgradable_episodes = database.execute("SELECT table_history.video_path, table_history.language, " - "table_history.score, table_shows.hearing_impaired, " + "table_history.score, table_shows.hearing_impaired, table_shows.audio_language, " "table_episodes.scene_name, table_episodes.title," "table_episodes.sonarrSeriesId, table_episodes.sonarrEpisodeId," "MAX(table_history.timestamp) as timestamp, " @@ -991,7 +1001,7 @@ def upgrade_subtitles(): if settings.general.getboolean('use_radarr'): upgradable_movies = database.execute("SELECT table_history_movie.video_path, table_history_movie.language, " - "table_history_movie.score, table_movies.hearing_impaired, " + "table_history_movie.score, table_movies.hearing_impaired, table_movies.audio_language, " "table_movies.sceneName, table_movies.title, table_movies.radarrId, " "MAX(table_history_movie.timestamp) as timestamp, table_movies.languages, " "table_movies.forced FROM table_history_movie INNER JOIN " @@ -1054,6 +1064,7 @@ def upgrade_subtitles(): result = download_subtitle(path_replace(episode['video_path']), str(alpha3_from_alpha2(language)), + episode['audio_language'], episode['hearing_impaired'], is_forced, providers_list, @@ -1105,6 +1116,7 @@ def upgrade_subtitles(): result = download_subtitle(path_replace_movie(movie['video_path']), str(alpha3_from_alpha2(language)), + movie['audio_language'], movie['hearing_impaired'], is_forced, providers_list, diff --git a/bazarr/helper.py b/bazarr/helper.py index feef91067..5124b2877 100644 --- a/bazarr/helper.py +++ b/bazarr/helper.py @@ -95,7 +95,7 @@ def path_replace_reverse_movie(path): return path -def pp_replace(pp_command, episode, subtitles, language, language_code2, language_code3, forced): +def pp_replace(pp_command, episode, subtitles, language, language_code2, language_code3, episode_language, episode_language_code2, episode_language_code3, forced): is_forced = ":forced" if forced else "" is_forced_string = " forced" if forced else "" pp_command = pp_command.replace('{{directory}}', os.path.dirname(episode)) @@ -105,6 +105,9 @@ def pp_replace(pp_command, episode, subtitles, language, language_code2, languag pp_command = pp_command.replace('{{subtitles_language}}', language + is_forced_string) pp_command = pp_command.replace('{{subtitles_language_code2}}', language_code2 + is_forced) pp_command = pp_command.replace('{{subtitles_language_code3}}', language_code3 + is_forced) + pp_command = pp_command.replace('{{episode_language}}', episode_language) + pp_command = pp_command.replace('{{episode_language_code2}}', episode_language_code2) + pp_command = pp_command.replace('{{episode_language_code3}}', episode_language_code3) return pp_command diff --git a/bazarr/main.py b/bazarr/main.py index cac891428..ec314ecfb 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1797,7 +1797,7 @@ def remove_subtitles_movie(): def get_subtitle(): authorize() ref = request.environ['HTTP_REFERER'] - + episodePath = request.forms.episodePath sceneName = request.forms.sceneName language = request.forms.get('language') @@ -1806,12 +1806,15 @@ def get_subtitle(): sonarrSeriesId = request.forms.get('sonarrSeriesId') sonarrEpisodeId = request.forms.get('sonarrEpisodeId') title = request.forms.title - + + data = database.execute("SELECT audio_language FROM table_shows WHERE sonarrSeriesId=?", (sonarrSeriesId,)) + audio_language = data['audio_language'] + providers_list = get_providers() providers_auth = get_providers_auth() try: - result = download_subtitle(episodePath, language, hi, forced, providers_list, providers_auth, sceneName, title, + result = download_subtitle(episodePath, language, audio_language, hi, forced, providers_list, providers_auth, sceneName, title, 'series') if result is not None: message = result[0] @@ -1942,12 +1945,15 @@ def get_subtitle_movie(): forced = request.forms.get('forced') radarrId = request.forms.get('radarrId') title = request.forms.title - + + data = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,)) + audio_language = data['audio_language'] + providers_list = get_providers() providers_auth = get_providers_auth() try: - result = download_subtitle(moviePath, language, hi, forced, providers_list, providers_auth, sceneName, title, + result = download_subtitle(moviePath, language, audio_language, hi, forced, providers_list, providers_auth, sceneName, title, 'movie') if result is not None: message = result[0] diff --git a/views/settings_general.tpl b/views/settings_general.tpl index 2e4998eb0..40a2af5b4 100644 --- a/views/settings_general.tpl +++ b/views/settings_general.tpl @@ -608,6 +608,18 @@ <div class="header">{{subtitles_language_code3}}</div> The 3-letter ISO-639 language code of the subtitles language. </div> + <div class="item"> + <div class="header">{{episode_language}}</div> + The audio language of the episode file. + </div> + <div class="item"> + <div class="header">{{episode_language_code2}}</div> + The 2-letter ISO-639 language code of the episode audio language. + </div> + <div class="item"> + <div class="header">{{episode_language_code3}}</div> + The 3-letter ISO-639 language code of the episode audio language. + </div> </div> </div> </div> From 1af408f68404f2f8b0343fef5fe6fdc391f943d6 Mon Sep 17 00:00:00 2001 From: JpF4E <joaoprodrigues@ua.pt> Date: Sat, 22 Feb 2020 20:53:33 +0000 Subject: [PATCH 03/14] Added audio language variables to post processing command. Required to use with subsync. --- bazarr/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index ec314ecfb..2f0715a22 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1807,7 +1807,7 @@ def get_subtitle(): sonarrEpisodeId = request.forms.get('sonarrEpisodeId') title = request.forms.title - data = database.execute("SELECT audio_language FROM table_shows WHERE sonarrSeriesId=?", (sonarrSeriesId,)) + data = database.execute("SELECT audio_language FROM table_shows WHERE sonarrSeriesId=?", (sonarrSeriesId,), only_one=True) audio_language = data['audio_language'] providers_list = get_providers() @@ -1946,7 +1946,7 @@ def get_subtitle_movie(): radarrId = request.forms.get('radarrId') title = request.forms.title - data = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,)) + data = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,), only_one=True) audio_language = data['audio_language'] providers_list = get_providers() From 9036a0863cdd6d9607708643077accf1f71a2038 Mon Sep 17 00:00:00 2001 From: German Gutierrez <german.gutierrez@gmail.com> Date: Sun, 23 Feb 2020 17:37:02 +0100 Subject: [PATCH 04/14] bsplayer: adding matches --- libs/subliminal_patch/providers/bsplayer.py | 48 ++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/libs/subliminal_patch/providers/bsplayer.py b/libs/subliminal_patch/providers/bsplayer.py index f6eb20db4..a3bd78182 100644 --- a/libs/subliminal_patch/providers/bsplayer.py +++ b/libs/subliminal_patch/providers/bsplayer.py @@ -2,7 +2,6 @@ from __future__ import absolute_import import logging import io -import os from requests import Session from guessit import guessit @@ -10,6 +9,7 @@ from subliminal_patch.providers import Provider from subliminal_patch.subtitle import Subtitle from subliminal.utils import sanitize_release_group from subliminal.subtitle import guess_matches +from subliminal.video import Episode, Movie from subzero.language import Language import gzip @@ -44,6 +44,52 @@ class BSPlayerSubtitle(Subtitle): def get_matches(self, video): matches = set() matches |= guess_matches(video, guessit(self.filename)) + + subtitle_filename = self.filename + + # episode + if isinstance(video, Episode): + # already matched in search query + matches.update(['title', 'series', 'season', 'episode', 'year']) + + # movie + elif isinstance(video, Movie): + # already matched in search query + matches.update(['title', 'year']) + + # release_group + if video.release_group and video.release_group.lower() in subtitle_filename: + matches.add('release_group') + + # resolution + if video.resolution and video.resolution.lower() in subtitle_filename: + matches.add('resolution') + + # format + formats = [] + if video.format: + formats = [video.format.lower()] + if formats[0] == "web-dl": + formats.append("webdl") + formats.append("webrip") + formats.append("web ") + for frmt in formats: + if frmt.lower() in subtitle_filename: + matches.add('format') + break + + # video_codec + if video.video_codec: + video_codecs = [video.video_codec.lower()] + if video_codecs[0] == "h264": + formats.append("x264") + elif video_codecs[0] == "h265": + formats.append("x265") + for vc in formats: + if vc.lower() in subtitle_filename: + matches.add('video_codec') + break + matches.add('hash') return matches From c72366d8834abfe4e8a320d264947090e3b8d1ca Mon Sep 17 00:00:00 2001 From: German Gutierrez <german.gutierrez@gmail.com> Date: Mon, 24 Feb 2020 11:06:48 +0100 Subject: [PATCH 05/14] legendasdivx: using guessit to pick up the right sub in archive --- libs/subliminal_patch/providers/legendasdivx.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/subliminal_patch/providers/legendasdivx.py b/libs/subliminal_patch/providers/legendasdivx.py index a755fd6e4..36e0b7229 100644 --- a/libs/subliminal_patch/providers/legendasdivx.py +++ b/libs/subliminal_patch/providers/legendasdivx.py @@ -274,7 +274,7 @@ class LegendasdivxProvider(Provider): archive = self._get_archive(res.content) # extract the subtitle - subtitle_content = self._get_subtitle_from_archive(archive) + subtitle_content = self._get_subtitle_from_archive(archive, subtitle) subtitle.content = fix_line_ending(subtitle_content) subtitle.normalize() @@ -297,7 +297,7 @@ class LegendasdivxProvider(Provider): return archive - def _get_subtitle_from_archive(self, archive): + def _get_subtitle_from_archive(self, archive, subtitle): # some files have a non subtitle with .txt extension _tmp = list(SUBTITLE_EXTENSIONS) _tmp.remove('.txt') @@ -312,6 +312,15 @@ class LegendasdivxProvider(Provider): if not name.lower().endswith(_subtitle_extensions): continue + if isinstance(subtitle.video, Episode): + logger.debug ("guessing %s" % name) + guess = guessit(name) + logger.debug("subtitle S{}E{} video S{}E{}".format(guess['season'],guess['episode'],subtitle.video.season,subtitle.video.episode)) + + if subtitle.video.episode != guess['episode'] or subtitle.video.season != guess['season']: + logger.debug('subtitle does not match video, skipping') + continue + logger.debug("returning from archive: %s" % name) return archive.read(name) From 8bdf2db607c18a755bac011cdbd5fb8ed544142e Mon Sep 17 00:00:00 2001 From: JpF4E <joaoprodrigues@ua.pt> Date: Mon, 24 Feb 2020 14:17:34 +0000 Subject: [PATCH 06/14] Fixed manual download. --- bazarr/main.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 2f0715a22..73b2e1386 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1866,11 +1866,14 @@ def manual_get_subtitle(): sonarrSeriesId = request.forms.get('sonarrSeriesId') sonarrEpisodeId = request.forms.get('sonarrEpisodeId') title = request.forms.title - + + data = database.execute("SELECT audio_language FROM table_shows WHERE sonarrSeriesId=?", (sonarrSeriesId,), only_one=True) + audio_language = data['audio_language'] + providers_auth = get_providers_auth() try: - result = manual_download_subtitle(episodePath, language, hi, forced, subtitle, selected_provider, + result = manual_download_subtitle(episodePath, language, audio_language, hi, forced, subtitle, selected_provider, providers_auth, sceneName, title, 'series') if result is not None: @@ -2004,11 +2007,14 @@ def manual_get_subtitle_movie(): subtitle = request.forms.subtitle radarrId = request.forms.get('radarrId') title = request.forms.title - + + data = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,), only_one=True) + audio_language = data['audio_language'] + providers_auth = get_providers_auth() try: - result = manual_download_subtitle(moviePath, language, hi, forced, subtitle, selected_provider, providers_auth, + result = manual_download_subtitle(moviePath, language, audio_language, hi, forced, subtitle, selected_provider, providers_auth, sceneName, title, 'movie') if result is not None: message = result[0] From c2614fc7762fd2de7754c274150b506ab5c6f7d6 Mon Sep 17 00:00:00 2001 From: German Gutierrez <german.gutierrez@gmail.com> Date: Mon, 24 Feb 2020 16:13:30 +0100 Subject: [PATCH 07/14] legendasdivx: adding scores to subtitles to get best match in archive --- .../providers/legendasdivx.py | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/libs/subliminal_patch/providers/legendasdivx.py b/libs/subliminal_patch/providers/legendasdivx.py index 36e0b7229..aa9f2a5f0 100644 --- a/libs/subliminal_patch/providers/legendasdivx.py +++ b/libs/subliminal_patch/providers/legendasdivx.py @@ -15,6 +15,7 @@ from subliminal_patch.subtitle import Subtitle from subliminal.video import Episode, Movie from subliminal.subtitle import SUBTITLE_EXTENSIONS, fix_line_ending,guess_matches from subzero.language import Language +from subliminal_patch.score import get_scores logger = logging.getLogger(__name__) @@ -104,7 +105,8 @@ class LegendasdivxSubtitle(Subtitle): matches.update(['video_codec']) break - matches |= guess_matches(video, guessit(self.description)) + # running guessit on a huge description may break guessit + # matches |= guess_matches(video, guessit(self.description)) return matches @@ -302,6 +304,8 @@ class LegendasdivxProvider(Provider): _tmp = list(SUBTITLE_EXTENSIONS) _tmp.remove('.txt') _subtitle_extensions = tuple(_tmp) + _max_score = 0 + _scores = get_scores (subtitle.video) for name in archive.namelist(): # discard hidden files @@ -312,16 +316,26 @@ class LegendasdivxProvider(Provider): if not name.lower().endswith(_subtitle_extensions): continue + _guess = guessit (name) if isinstance(subtitle.video, Episode): logger.debug ("guessing %s" % name) - guess = guessit(name) - logger.debug("subtitle S{}E{} video S{}E{}".format(guess['season'],guess['episode'],subtitle.video.season,subtitle.video.episode)) + logger.debug("subtitle S{}E{} video S{}E{}".format(_guess['season'],_guess['episode'],subtitle.video.season,subtitle.video.episode)) - if subtitle.video.episode != guess['episode'] or subtitle.video.season != guess['season']: + if subtitle.video.episode != _guess['episode'] or subtitle.video.season != _guess['season']: logger.debug('subtitle does not match video, skipping') continue - logger.debug("returning from archive: %s" % name) - return archive.read(name) + matches = set() + matches |= guess_matches (subtitle.video, _guess) + logger.debug('srt matches: %s' % matches) + _score = sum ((_scores.get (match, 0) for match in matches)) + if _score > _max_score: + _max_name = name + _max_score = _score + logger.debug("new max: {} {}".format(name, _score)) + + if _max_score > 0: + logger.debug("returning from archive: {} scored {}".format(_max_name, _max_score)) + return archive.read(_max_name) raise ParseResponseError('Can not find the subtitle in the compressed file') From fd339b5fffa14e0e92b9d8aa7ad3de91c3e7698b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20V=C3=A9zina?= <5130500+morpheus65535@users.noreply.github.com> Date: Sat, 29 Feb 2020 18:53:13 -0500 Subject: [PATCH 08/14] Fix for release update missing an import --- bazarr/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bazarr/main.py b/bazarr/main.py index e593f4e28..8825154ac 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -62,6 +62,7 @@ from utils import history_log, history_log_movie, get_sonarr_version, get_radarr from helper import path_replace_reverse, path_replace_reverse_movie from scheduler import Scheduler from notifier import send_notifications, send_notifications_movie +from check_update import check_and_apply_update from subliminal_patch.extensions import provider_registry as provider_manager from subliminal_patch.core import SUBTITLE_EXTENSIONS From de1fe680dfc7fda9437e6183f546f573f3da451b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20V=C3=A9zina?= <5130500+morpheus65535@users.noreply.github.com> Date: Sun, 1 Mar 2020 08:51:00 -0500 Subject: [PATCH 09/14] Fix for #843 --- bazarr/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bazarr/main.py b/bazarr/main.py index 8825154ac..3bee90da5 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -2223,6 +2223,8 @@ def api_help(): # Mute DeprecationWarning warnings.simplefilter("ignore", DeprecationWarning) +# Mute Insecure HTTPS requests made to Sonarr and Radarr +warnings.filterwarnings('ignore', message='Unverified HTTPS request') if six.PY3: warnings.simplefilter("ignore", BrokenPipeError) server = CherryPyWSGIServer((str(settings.general.ip), (int(args.port) if args.port else int(settings.general.port))), app) From 30a801b04d8b869406c15bb9d27e69e3c8bbde64 Mon Sep 17 00:00:00 2001 From: Michiel van Baak <michiel@vanbaak.info> Date: Tue, 3 Mar 2020 14:06:25 +0100 Subject: [PATCH 10/14] Move scandir.c header files to the correct directory --- {libs => libs2}/osdefs.h | 0 {libs => libs2}/winreparse.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {libs => libs2}/osdefs.h (100%) rename {libs => libs2}/winreparse.h (100%) diff --git a/libs/osdefs.h b/libs2/osdefs.h similarity index 100% rename from libs/osdefs.h rename to libs2/osdefs.h diff --git a/libs/winreparse.h b/libs2/winreparse.h similarity index 100% rename from libs/winreparse.h rename to libs2/winreparse.h From c12c54a42acb3c29c80ed7e6eb044a68e5a62008 Mon Sep 17 00:00:00 2001 From: morpheus65535 <louis_vezina@hotmail.com> Date: Thu, 5 Mar 2020 12:50:54 -0500 Subject: [PATCH 11/14] Fix for #849 --- bazarr/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/main.py b/bazarr/main.py index 3bee90da5..cae8ff248 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -57,7 +57,7 @@ from get_movies import * from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_subtitles, movies_scan_subtitles, \ list_missing_subtitles, list_missing_subtitles_movies from get_subtitle import download_subtitle, series_download_subtitles, movies_download_subtitles, \ - manual_search, manual_download_subtitle, manual_upload_subtitle + manual_search, manual_download_subtitle, manual_upload_subtitle, wanted_search_missing_subtitles from utils import history_log, history_log_movie, get_sonarr_version, get_radarr_version from helper import path_replace_reverse, path_replace_reverse_movie from scheduler import Scheduler From 9f27b949c026182d3db585164df61275724e9b6a Mon Sep 17 00:00:00 2001 From: morpheus65535 <louis_vezina@hotmail.com> Date: Thu, 5 Mar 2020 12:51:21 -0500 Subject: [PATCH 12/14] Version bump --- bazarr/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/main.py b/bazarr/main.py index cae8ff248..87a27862d 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1,6 +1,6 @@ # coding=utf-8 -bazarr_version = '0.8.4.2' +bazarr_version = '0.8.4.3' import os os.environ["SZ_USER_AGENT"] = "Bazarr/1" From d5feea0b097efe2f7813d9f0fbae4c7542603134 Mon Sep 17 00:00:00 2001 From: panni <panni@fragstore.net> Date: Sun, 8 Mar 2020 05:49:53 +0100 Subject: [PATCH 13/14] fix #731 --- libs/pysubs2/exceptions.py | 3 +++ libs/pysubs2/ssastyle.py | 1 + libs/pysubs2/subrip.py | 7 ++++++- libs/pysubs2/substation.py | 9 ++++++++- libs/subliminal_patch/subtitle.py | 20 ++++++++++++++++---- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/libs/pysubs2/exceptions.py b/libs/pysubs2/exceptions.py index e0c9312fb..b9d528524 100644 --- a/libs/pysubs2/exceptions.py +++ b/libs/pysubs2/exceptions.py @@ -12,3 +12,6 @@ class UnknownFormatIdentifierError(Pysubs2Error): class FormatAutodetectionError(Pysubs2Error): """Subtitle format is ambiguous or unknown.""" + +class ContentNotUsable(Pysubs2Error): + """Current content not usable for specified format""" diff --git a/libs/pysubs2/ssastyle.py b/libs/pysubs2/ssastyle.py index eb59b74b5..b7b4a5ef3 100644 --- a/libs/pysubs2/ssastyle.py +++ b/libs/pysubs2/ssastyle.py @@ -41,6 +41,7 @@ class SSAStyle(object): self.italic = False #: Italic self.underline = False #: Underline (ASS only) self.strikeout = False #: Strikeout (ASS only) + self.drawing = False #: Drawing (ASS only, see http://docs.aegisub.org/3.1/ASS_Tags/#drawing-tags self.scalex = 100.0 #: Horizontal scaling (ASS only) self.scaley = 100.0 #: Vertical scaling (ASS only) self.spacing = 0.0 #: Letter spacing (ASS only) diff --git a/libs/pysubs2/subrip.py b/libs/pysubs2/subrip.py index 70cb96fe5..56055b650 100644 --- a/libs/pysubs2/subrip.py +++ b/libs/pysubs2/subrip.py @@ -5,6 +5,7 @@ from .formatbase import FormatBase from .ssaevent import SSAEvent from .ssastyle import SSAStyle from .substation import parse_tags +from .exceptions import ContentNotUsable from .time import ms_to_times, make_time, TIMESTAMP, timestamp_to_ms #: Largest timestamp allowed in SubRip, ie. 99:59:59,999. @@ -81,6 +82,7 @@ class SubripFormat(FormatBase): if sty.italic: fragment = "<i>%s</i>" % fragment if sty.underline: fragment = "<u>%s</u>" % fragment if sty.strikeout: fragment = "<s>%s</s>" % fragment + if sty.drawing: raise ContentNotUsable body.append(fragment) return re.sub("\n+", "\n", "".join(body).strip()) @@ -90,7 +92,10 @@ class SubripFormat(FormatBase): for i, line in enumerate(visible_lines, 1): start = ms_to_timestamp(line.start) end = ms_to_timestamp(line.end) - text = prepare_text(line.text, subs.styles.get(line.style, SSAStyle.DEFAULT_STYLE)) + try: + text = prepare_text(line.text, subs.styles.get(line.style, SSAStyle.DEFAULT_STYLE)) + except ContentNotUsable: + continue print("%d" % i, file=fp) # Python 2.7 compat print(start, "-->", end, file=fp) diff --git a/libs/pysubs2/substation.py b/libs/pysubs2/substation.py index 8563f8a0d..274075a44 100644 --- a/libs/pysubs2/substation.py +++ b/libs/pysubs2/substation.py @@ -110,7 +110,7 @@ def parse_tags(text, style=SSAStyle.DEFAULT_STYLE, styles={}): def apply_overrides(all_overrides): s = style.copy() - for tag in re.findall(r"\\[ibus][10]|\\r[a-zA-Z_0-9 ]*", all_overrides): + for tag in re.findall(r"\\[ibusp][0-9]|\\r[a-zA-Z_0-9 ]*", all_overrides): if tag == r"\r": s = style.copy() # reset to original line style elif tag.startswith(r"\r"): @@ -122,6 +122,13 @@ def parse_tags(text, style=SSAStyle.DEFAULT_STYLE, styles={}): elif "b" in tag: s.bold = "1" in tag elif "u" in tag: s.underline = "1" in tag elif "s" in tag: s.strikeout = "1" in tag + elif "p" in tag: + try: + scale = int(tag[2:]) + except (ValueError, IndexError): + continue + + s.drawing = scale > 0 return s overrides = SSAEvent.OVERRIDE_SEQUENCE.findall(text) diff --git a/libs/subliminal_patch/subtitle.py b/libs/subliminal_patch/subtitle.py index 43e9a9716..f67417d37 100644 --- a/libs/subliminal_patch/subtitle.py +++ b/libs/subliminal_patch/subtitle.py @@ -279,6 +279,12 @@ class Subtitle(Subtitle_): @classmethod def pysubs2_to_unicode(cls, sub, format="srt"): + """ + this is a modified version of pysubs2.SubripFormat.to_file with special handling for drawing tags in ASS + :param sub: + :param format: + :return: + """ def ms_to_timestamp(ms, mssep=","): """Convert ms to 'HH:MM:SS,mmm'""" # XXX throw on overflow/underflow? @@ -290,9 +296,12 @@ class Subtitle(Subtitle_): def prepare_text(text, style): body = [] for fragment, sty in parse_tags(text, style, sub.styles): - fragment = fragment.replace(r"\h", u" ") - fragment = fragment.replace(r"\n", u"\n") - fragment = fragment.replace(r"\N", u"\n") + fragment = fragment.replace(ur"\h", u" ") + fragment = fragment.replace(ur"\n", u"\n") + fragment = fragment.replace(ur"\N", u"\n") + if sty.drawing: + raise pysubs2.ContentNotUsable + if format == "srt": if sty.italic: fragment = u"<i>%s</i>" % fragment @@ -324,7 +333,10 @@ class Subtitle(Subtitle_): for i, line in enumerate(visible_lines, 1): start = ms_to_timestamp(line.start, mssep=mssep) end = ms_to_timestamp(line.end, mssep=mssep) - text = prepare_text(line.text, sub.styles.get(line.style, SSAStyle.DEFAULT_STYLE)) + try: + text = prepare_text(line.text, sub.styles.get(line.style, SSAStyle.DEFAULT_STYLE)) + except pysubs2.ContentNotUsable: + continue out.append(u"%d\n" % i) out.append(u"%s --> %s\n" % (start, end)) From c7c7a23f58d22edb2d963badaa53887be6c014da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20V=C3=A9zina?= <5130500+morpheus65535@users.noreply.github.com> Date: Sun, 8 Mar 2020 09:50:31 -0400 Subject: [PATCH 14/14] Fix for d5feea0b097efe2f7813d9f0fbae4c7542603134 --- libs/subliminal_patch/subtitle.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/subliminal_patch/subtitle.py b/libs/subliminal_patch/subtitle.py index f67417d37..ad39f031b 100644 --- a/libs/subliminal_patch/subtitle.py +++ b/libs/subliminal_patch/subtitle.py @@ -296,9 +296,9 @@ class Subtitle(Subtitle_): def prepare_text(text, style): body = [] for fragment, sty in parse_tags(text, style, sub.styles): - fragment = fragment.replace(ur"\h", u" ") - fragment = fragment.replace(ur"\n", u"\n") - fragment = fragment.replace(ur"\N", u"\n") + fragment = fragment.replace(r"\h", u" ") + fragment = fragment.replace(r"\n", u"\n") + fragment = fragment.replace(r"\N", u"\n") if sty.drawing: raise pysubs2.ContentNotUsable