# coding=utf-8 # fmt: off import os import sys import logging import subliminal import ast from subzero.language import Language from subliminal_patch.core import save_subtitles from subliminal_patch.core_persistent import download_best_subtitles from subliminal_patch.score import ComputeScore from app.config import settings, get_array_from, get_scores from app.database import TableEpisodes, TableMovies from utilities.path_mappings import path_mappings from utilities.helper import get_target_folder, force_unicode from languages.get_languages import alpha3_from_alpha2 from .pool import update_pools, _get_pool from .utils import get_video, _get_lang_obj, _get_scores, _set_forced_providers from .processing import process_subtitle @update_pools def generate_subtitles(path, languages, audio_language, sceneName, title, media_type, forced_minimum_score=None, is_upgrade=False, profile_id=None, check_if_still_required=False): if not languages: return None logging.debug('BAZARR Searching subtitles for this file: ' + path) if settings.general.getboolean('utf8_encode'): os.environ["SZ_KEEP_ENCODING"] = "" else: os.environ["SZ_KEEP_ENCODING"] = "True" pool = _get_pool(media_type, profile_id) providers = pool.providers language_set = _get_language_obj(languages=languages) hi_required = any([x.hi for x in language_set]) also_forced = any([x.forced for x in language_set]) forced_required = all([x.forced for x in language_set]) _set_forced_providers(pool=pool, also_forced=also_forced, forced_required=forced_required) video = get_video(force_unicode(path), title, sceneName, providers=providers, media_type=media_type) if video: minimum_score = settings.general.minimum_score minimum_score_movie = settings.general.minimum_score_movie min_score, max_score, scores = _get_scores(media_type, minimum_score_movie, minimum_score) subz_mods = get_array_from(settings.general.subzero_mods) saved_any = False if providers: if forced_minimum_score: min_score = int(forced_minimum_score) + 1 for language in language_set: # confirm if language is still missing or if cutoff has been reached if check_if_still_required and language not in check_missing_languages(path, media_type): # cutoff has been reached logging.debug(f"BAZARR this language ({parse_language_object(language)}) is ignored because cutoff " f"has been reached during this search.") continue else: downloaded_subtitles = download_best_subtitles(videos={video}, languages={language}, pool_instance=pool, min_score=int(min_score), hearing_impaired=hi_required, compute_score=ComputeScore(get_scores())) if downloaded_subtitles: for video, subtitles in downloaded_subtitles.items(): 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) chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( 'win') and settings.general.getboolean('chmod_enabled') else None saved_subtitles = save_subtitles(video.original_path, subtitles, single=settings.general.getboolean('single_language'), tags=None, # fixme directory=fld, chmod=chmod, formats=tuple(subtitle_formats), path_decoder=force_unicode ) except Exception as e: logging.exception( 'BAZARR Error saving Subtitles file to disk for this file:' + path + ': ' + repr(e)) pass else: saved_any = True for subtitle in saved_subtitles: processed_subtitle = process_subtitle(subtitle=subtitle, media_type=media_type, audio_language=audio_language, is_upgrade=is_upgrade, is_manual=False, path=path, max_score=max_score) if not processed_subtitle: logging.debug(f"BAZARR unable to process this subtitles: {subtitle}") continue yield processed_subtitle else: logging.info("BAZARR All providers are throttled") return None if not saved_any: logging.debug('BAZARR No Subtitles were found for this file: ' + path) return None subliminal.region.backend.sync() logging.debug('BAZARR Ended searching Subtitles for file: ' + path) def _get_language_obj(languages): language_set = set() if not isinstance(languages, (set, list)): languages = [languages] for language in languages: lang, hi_item, forced_item = language if hi_item == "True": hi = "force HI" else: hi = "force non-HI" # Always use alpha2 in API Request lang = alpha3_from_alpha2(lang) lang_obj = _get_lang_obj(lang) if forced_item == "True": lang_obj = Language.rebuild(lang_obj, forced=True) if hi == "force HI": lang_obj = Language.rebuild(lang_obj, hi=True) language_set.add(lang_obj) return language_set def parse_language_object(language): if isinstance(language, Language): hi = ":hi" if language.hi else "" forced = ":forced" if language.forced else "" return language.basename + hi + forced else: return language def check_missing_languages(path, media_type): # confirm if language is still missing or if cutoff has been reached if media_type == 'series': confirmed_missing_subs = TableEpisodes.select(TableEpisodes.missing_subtitles) \ .where(TableEpisodes.path == path_mappings.path_replace_reverse(path)) \ .dicts() \ .get_or_none() else: confirmed_missing_subs = TableMovies.select(TableMovies.missing_subtitles) \ .where(TableMovies.path == path_mappings.path_replace_reverse_movie(path)) \ .dicts() \ .get_or_none() if not confirmed_missing_subs: reversed_path = path_mappings.path_replace_reverse(path) if media_type == 'series' else \ path_mappings.path_replace_reverse_movie(path) logging.debug(f"BAZARR no media with this path have been found in database: {reversed_path}") return [] languages = [] for language in ast.literal_eval(confirmed_missing_subs['missing_subtitles']): if language is not None: hi_ = "True" if language.endswith(':hi') else "False" forced_ = "True" if language.endswith(':forced') else "False" languages.append((language.split(":")[0], hi_, forced_)) return _get_language_obj(languages=languages)