From 33a9e512acafe0419d553660c20659d007a23b85 Mon Sep 17 00:00:00 2001 From: maxwillx Date: Mon, 14 Mar 2022 17:54:36 -0700 Subject: [PATCH] Added languages profile settings to prevent downloaded subtitles from being converted to srt. --- .gitignore | 3 +++ bazarr/api/providers/providers_episodes.py | 4 ++-- bazarr/api/providers/providers_movies.py | 5 ++++- bazarr/api/subtitles/subtitles.py | 3 ++- bazarr/api/system/settings.py | 2 ++ bazarr/database.py | 11 +++++++---- bazarr/get_subtitle/download.py | 4 +++- bazarr/get_subtitle/manual.py | 16 ++++++++++------ bazarr/get_subtitle/upload.py | 2 +- bazarr/utils.py | 7 +++++-- frontend/src/@types/api.d.ts | 2 ++ frontend/src/@types/form.d.ts | 1 + frontend/src/pages/Episodes/table.tsx | 2 ++ frontend/src/pages/Movies/Details/index.tsx | 2 ++ frontend/src/pages/Settings/Languages/modal.tsx | 13 +++++++++++++ frontend/src/pages/Settings/Languages/table.tsx | 1 + libs/subliminal_patch/subtitle.py | 13 +++++++++++-- 17 files changed, 71 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 702d69d74..d70e8a945 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ bazarr.pid .idea .vscode +# LSP +pyrightconfig.json + # Middleware VERSION diff --git a/bazarr/api/providers/providers_episodes.py b/bazarr/api/providers/providers_episodes.py index e4834fb3f..f0cc1ca0b 100644 --- a/bazarr/api/providers/providers_episodes.py +++ b/bazarr/api/providers/providers_episodes.py @@ -66,6 +66,7 @@ class ProviderEpisodes(Resource): hi = request.form.get('hi').capitalize() forced = request.form.get('forced').capitalize() + use_original_format = request.form.get('original_format').capitalize() selected_provider = request.form.get('provider') subtitle = request.form.get('subtitle') @@ -77,8 +78,7 @@ class ProviderEpisodes(Resource): try: result = manual_download_subtitle(episodePath, audio_language, hi, forced, subtitle, selected_provider, - sceneName, title, 'series', - profile_id=get_profile_id(episode_id=sonarrEpisodeId)) + sceneName, title, 'series', use_original_format, profile_id=get_profile_id(episode_id=sonarrEpisodeId)) if result is not None: message = result[0] path = result[1] diff --git a/bazarr/api/providers/providers_movies.py b/bazarr/api/providers/providers_movies.py index 3c5b714a1..2fa6f84a4 100644 --- a/bazarr/api/providers/providers_movies.py +++ b/bazarr/api/providers/providers_movies.py @@ -13,6 +13,7 @@ from notifier import send_notifications_movie from list_subtitles import store_subtitles_movie from ..utils import authenticate +import logging class ProviderMovies(Resource): @@ -64,6 +65,8 @@ class ProviderMovies(Resource): hi = request.form.get('hi').capitalize() forced = request.form.get('forced').capitalize() + use_original_format = request.form.get('original_format').capitalize() + logging.debug(f"use_original_format {use_original_format}") selected_provider = request.form.get('provider') subtitle = request.form.get('subtitle') @@ -75,7 +78,7 @@ class ProviderMovies(Resource): try: result = manual_download_subtitle(moviePath, audio_language, hi, forced, subtitle, selected_provider, - sceneName, title, 'movie', profile_id=get_profile_id(movie_id=radarrId)) + sceneName, title, 'movie', use_original_format, profile_id=get_profile_id(movie_id=radarrId)) if result is not None: message = result[0] path = result[1] diff --git a/bazarr/api/subtitles/subtitles.py b/bazarr/api/subtitles/subtitles.py index b71d5ed7e..571004305 100644 --- a/bazarr/api/subtitles/subtitles.py +++ b/bazarr/api/subtitles/subtitles.py @@ -73,7 +73,8 @@ class Subtitles(Resource): else: return '', 404 else: - subtitles_apply_mods(language, subtitles_path, [action]) + use_original_format = True if request.form.get('original_format') == 'true' else False + subtitles_apply_mods(language, subtitles_path, [action], use_original_format) # apply chmod if required chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( diff --git a/bazarr/api/system/settings.py b/bazarr/api/system/settings.py index 8cdbc90f3..cd09b32a7 100644 --- a/bazarr/api/system/settings.py +++ b/bazarr/api/system/settings.py @@ -59,6 +59,7 @@ class SystemSettings(Resource): TableLanguagesProfiles.items: json.dumps(item['items']), TableLanguagesProfiles.mustContain: item['mustContain'], TableLanguagesProfiles.mustNotContain: item['mustNotContain'], + TableLanguagesProfiles.originalFormat: item['originalFormat'] if item['originalFormat'] != 'null' else None, })\ .where(TableLanguagesProfiles.profileId == item['profileId'])\ .execute() @@ -72,6 +73,7 @@ class SystemSettings(Resource): TableLanguagesProfiles.items: json.dumps(item['items']), TableLanguagesProfiles.mustContain: item['mustContain'], TableLanguagesProfiles.mustNotContain: item['mustNotContain'], + TableLanguagesProfiles.originalFormat: item['originalFormat'] if item['originalFormat'] != 'null' else None, }).execute() for profileId in existing: # Unassign this profileId from series and movies diff --git a/bazarr/database.py b/bazarr/database.py index dd791b174..958ec1a9d 100644 --- a/bazarr/database.py +++ b/bazarr/database.py @@ -131,6 +131,7 @@ class TableHistoryMovie(BaseModel): class TableLanguagesProfiles(BaseModel): cutoff = IntegerField(null=True) + originalFormat = BooleanField(null=True) items = TextField() name = TextField() profileId = AutoField() @@ -332,6 +333,7 @@ def migrate_db(): migrator.add_column('table_history_movie', 'subtitles_path', TextField(null=True)), migrator.add_column('table_languages_profiles', 'mustContain', TextField(null=True)), migrator.add_column('table_languages_profiles', 'mustNotContain', TextField(null=True)), + migrator.add_column('table_languages_profiles', 'originalFormat', BooleanField(null=True)), ) @@ -402,7 +404,8 @@ def update_profile_id_list(): TableLanguagesProfiles.cutoff, TableLanguagesProfiles.items, TableLanguagesProfiles.mustContain, - TableLanguagesProfiles.mustNotContain).dicts() + TableLanguagesProfiles.mustNotContain, + TableLanguagesProfiles.originalFormat).dicts() profile_id_list = list(profile_id_list) for profile in profile_id_list: profile['items'] = json.loads(profile['items']) @@ -434,7 +437,7 @@ def get_desired_languages(profile_id): if profile_id and profile_id != 'null': for profile in profile_id_list: - profileId, name, cutoff, items, mustContain, mustNotContain = profile.values() + profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values() if profileId == int(profile_id): languages = [x['language'] for x in items] break @@ -450,7 +453,7 @@ def get_profile_id_name(profile_id): if profile_id and profile_id != 'null': for profile in profile_id_list: - profileId, name, cutoff, items, mustContain, mustNotContain = profile.values() + profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values() if profileId == int(profile_id): name_from_id = name break @@ -467,7 +470,7 @@ def get_profile_cutoff(profile_id): if profile_id and profile_id != 'null': cutoff_language = [] for profile in profile_id_list: - profileId, name, cutoff, items, mustContain, mustNotContain = profile.values() + profileId, name, cutoff, items, mustContain, mustNotContain, originalFormat = profile.values() if cutoff: if profileId == int(profile_id): for item in items: diff --git a/bazarr/get_subtitle/download.py b/bazarr/get_subtitle/download.py index dce7c012c..f24961de9 100644 --- a/bazarr/get_subtitle/download.py +++ b/bazarr/get_subtitle/download.py @@ -72,8 +72,10 @@ def generate_subtitles(path, languages, audio_language, sceneName, title, media_ if not subtitles: continue + subtitle_formats = set() for s in subtitles: s.mods = subz_mods + subtitle_formats.add(s.format) try: fld = get_target_folder(path) @@ -84,7 +86,7 @@ def generate_subtitles(path, languages, audio_language, sceneName, title, media_ tags=None, # fixme directory=fld, chmod=chmod, - # formats=("srt", "vtt") + formats=tuple(subtitle_formats), path_decoder=force_unicode ) except Exception as e: diff --git a/bazarr/get_subtitle/manual.py b/bazarr/get_subtitle/manual.py index 5fc148e41..6e88af8fa 100644 --- a/bazarr/get_subtitle/manual.py +++ b/bazarr/get_subtitle/manual.py @@ -31,7 +31,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type): pool = _get_pool(media_type, profile_id) - language_set, initial_language_set = _get_language_obj(profile_id=profile_id) + language_set, initial_language_set, original_format = _get_language_obj(profile_id=profile_id) also_forced = any([x.forced for x in initial_language_set]) _set_forced_providers(also_forced=also_forced, pool=pool) @@ -136,6 +136,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type): provider=s.provider_name, subtitle=codecs.encode(pickle.dumps(s.make_picklable()), "base64").decode(), url=s.page_link, + original_format=original_format, matches=list(matches), dont_matches=list(not_matched), release_info=releases, @@ -153,7 +154,7 @@ def manual_search(path, profile_id, providers, sceneName, title, media_type): @update_pools def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provider, sceneName, title, media_type, - profile_id): + use_original_format, profile_id): logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path) if settings.general.getboolean('utf8_encode'): @@ -170,6 +171,8 @@ def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provide subtitle.language.forced = True else: subtitle.language.forced = False + if use_original_format == 'True': + subtitle.use_original_format = use_original_format subtitle.mods = get_array_from(settings.general.subzero_mods) video = get_video(force_unicode(path), title, sceneName, providers={provider}, media_type=media_type) if video: @@ -195,7 +198,7 @@ def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provide tags=None, # fixme directory=get_target_folder(path), chmod=chmod, - # formats=("srt", "vtt") + formats=(subtitle.format,), path_decoder=force_unicode) except Exception: logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) @@ -228,8 +231,9 @@ def _get_language_obj(profile_id): initial_language_set = set() language_set = set() - # where [3] is items list of dict(id, lang, forced, hi) - language_items = get_profiles_list(profile_id=int(profile_id))['items'] + profile = get_profiles_list(profile_id=int(profile_id)) + language_items = profile['items'] + original_format = profile['originalFormat'] for language in language_items: forced = language['forced'] @@ -259,7 +263,7 @@ def _get_language_obj(profile_id): continue language_set.add(lang_obj_hi) - return language_set, initial_language_set + return language_set, initial_language_set, original_format def _set_forced_providers(also_forced, pool): diff --git a/bazarr/get_subtitle/upload.py b/bazarr/get_subtitle/upload.py index 457f0896f..5add35ed7 100644 --- a/bazarr/get_subtitle/upload.py +++ b/bazarr/get_subtitle/upload.py @@ -63,7 +63,7 @@ def manual_upload_subtitle(path, language, forced, hi, title, scene_name, media_ tags=None, # fixme directory=get_target_folder(path), chmod=chmod, - # formats=("srt", "vtt") + formats=(sub.format,), path_decoder=force_unicode) except Exception: logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) diff --git a/bazarr/utils.py b/bazarr/utils.py index def8439e4..96aadfe89 100644 --- a/bazarr/utils.py +++ b/bazarr/utils.py @@ -415,7 +415,7 @@ def delete_subtitles(media_type, language, forced, hi, media_path, subtitles_pat return True -def subtitles_apply_mods(language, subtitle_path, mods): +def subtitles_apply_mods(language, subtitle_path, mods, use_original_format): language = alpha3_from_alpha2(language) custom = CustomLanguage.from_value(language, "alpha3") if custom is None: @@ -423,13 +423,16 @@ def subtitles_apply_mods(language, subtitle_path, mods): else: lang_obj = custom.subzero_language() - sub = Subtitle(lang_obj, mods=mods) + sub = Subtitle(lang_obj, mods=mods, original_format=use_original_format) with open(subtitle_path, 'rb') as f: sub.content = f.read() if not sub.is_valid(): logging.exception('BAZARR Invalid subtitle file: ' + subtitle_path) return + + if use_original_format: + return content = sub.get_modified_content() if content: diff --git a/frontend/src/@types/api.d.ts b/frontend/src/@types/api.d.ts index d7391a9ef..75f7c4dfe 100644 --- a/frontend/src/@types/api.d.ts +++ b/frontend/src/@types/api.d.ts @@ -35,6 +35,7 @@ declare namespace Language { items: ProfileItem[]; mustContain: string[]; mustNotContain: string[]; + originalFormat: boolean | null; } } @@ -252,6 +253,7 @@ interface SearchResultType { subtitle: any; uploader?: string; url?: string; + original_format: PythonBoolean; } interface ReleaseInfo { diff --git a/frontend/src/@types/form.d.ts b/frontend/src/@types/form.d.ts index b681e3a87..44855eafe 100644 --- a/frontend/src/@types/form.d.ts +++ b/frontend/src/@types/form.d.ts @@ -72,5 +72,6 @@ declare namespace FormType { forced: PythonBoolean; provider: string; subtitle: any; + original_format: PythonBoolean; } } diff --git a/frontend/src/pages/Episodes/table.tsx b/frontend/src/pages/Episodes/table.tsx index cfd9c2593..7b5582e6f 100644 --- a/frontend/src/pages/Episodes/table.tsx +++ b/frontend/src/pages/Episodes/table.tsx @@ -52,6 +52,7 @@ const Table: FunctionComponent = ({ forced, provider, subtitle, + original_format, } = result; const { sonarrSeriesId: seriesId, sonarrEpisodeId: episodeId } = item; @@ -64,6 +65,7 @@ const Table: FunctionComponent = ({ forced, provider, subtitle, + original_format: original_format, }, }); }, diff --git a/frontend/src/pages/Movies/Details/index.tsx b/frontend/src/pages/Movies/Details/index.tsx index 2f3570561..82a053111 100644 --- a/frontend/src/pages/Movies/Details/index.tsx +++ b/frontend/src/pages/Movies/Details/index.tsx @@ -60,6 +60,7 @@ const MovieDetailView: FunctionComponent = ({ match }) => { forced, provider, subtitle, + original_format, } = result; const { radarrId } = item; @@ -71,6 +72,7 @@ const MovieDetailView: FunctionComponent = ({ match }) => { forced, provider, subtitle, + original_format, }, }); }, diff --git a/frontend/src/pages/Settings/Languages/modal.tsx b/frontend/src/pages/Settings/Languages/modal.tsx index f7fea93cc..61935b251 100644 --- a/frontend/src/pages/Settings/Languages/modal.tsx +++ b/frontend/src/pages/Settings/Languages/modal.tsx @@ -34,6 +34,7 @@ function createDefaultProfile(): Language.Profile { cutoff: null, mustContain: [], mustNotContain: [], + originalFormat: false, }; } @@ -285,6 +286,18 @@ const LanguagesProfileModal: FunctionComponent = ( will be excluded from search results (regex supported). + + updateProfile("originalFormat", value)} + > + Download subtitle file without format conversion + ); }; diff --git a/frontend/src/pages/Settings/Languages/table.tsx b/frontend/src/pages/Settings/Languages/table.tsx index 7624510f9..13a8ea0b0 100644 --- a/frontend/src/pages/Settings/Languages/table.tsx +++ b/frontend/src/pages/Settings/Languages/table.tsx @@ -166,6 +166,7 @@ const Table: FunctionComponent = () => { cutoff: null, mustContain: [], mustNotContain: [], + originalFormat: false, }; showModal("profile", profile); }} diff --git a/libs/subliminal_patch/subtitle.py b/libs/subliminal_patch/subtitle.py index ee2dc15ce..ab54626cd 100644 --- a/libs/subliminal_patch/subtitle.py +++ b/libs/subliminal_patch/subtitle.py @@ -61,8 +61,10 @@ class Subtitle(Subtitle_): pack_data = None _guessed_encoding = None _is_valid = False + use_original_format = False + format = "srt" # default format is srt - def __init__(self, language, hearing_impaired=False, page_link=None, encoding=None, mods=None): + def __init__(self, language, hearing_impaired=False, page_link=None, encoding=None, mods=None, original_format=False): # set subtitle language to hi if it's hearing_impaired if hearing_impaired: language = Language.rebuild(language, hi=True) @@ -71,6 +73,7 @@ class Subtitle(Subtitle_): encoding=encoding) self.mods = mods self._is_valid = False + self.use_original_format = original_format def __repr__(self): return '<%s %r [%s:%s]>' % ( @@ -257,7 +260,7 @@ class Subtitle(Subtitle_): return encoding def is_valid(self): - """Check if a :attr:`text` is a valid SubRip format. + """Check if a :attr:`text` is a valid SubRip format. Note that orignal format will pypass the checking :return: whether or not the subtitle is valid. :rtype: bool @@ -289,6 +292,12 @@ class Subtitle(Subtitle_): logger.info("Got FPS from MicroDVD subtitle: %s", subs.fps) else: logger.info("Got format: %s", subs.format) + if self.use_original_format: + self.format = subs.format + self._is_valid = True + logger.debug("Using original format") + return True + except pysubs2.UnknownFPSError: # if parsing failed, use frame rate from provider sub_fps = self.get_fps()