bazarr/bazarr/get_subtitle/manual.py

273 lines
11 KiB
Python

# coding=utf-8
# fmt: off
import os
import sys
import logging
import pickle
import codecs
import subliminal
from subzero.language import Language
from subliminal_patch.core import save_subtitles
from subliminal_patch.core_persistent import list_all_subtitles, download_subtitles
from subliminal_patch.score import compute_score
from get_languages import alpha3_from_alpha2
from config import settings, get_array_from
from helper import get_target_folder, force_unicode
from database import get_profiles_list
from score import movie_score, series_score
from .pool import update_pools, _get_pool, _init_pool
from .utils import get_video, _get_lang_obj, _get_scores
from .processing import process_subtitle
@update_pools
def manual_search(path, profile_id, providers, sceneName, title, media_type):
logging.debug('BAZARR Manually searching subtitles for this file: ' + path)
final_subtitles = []
pool = _get_pool(media_type, 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)
if providers:
video = get_video(force_unicode(path), title, sceneName, providers=providers, media_type=media_type)
else:
logging.info("BAZARR All providers are throttled")
return None
if video:
handler = series_score if media_type == "series" else movie_score
try:
if providers:
subtitles = list_all_subtitles([video], language_set, pool)
if 'subscene' in providers:
s_pool = _init_pool("movie", profile_id, {"subscene"})
subscene_language_set = set()
for language in language_set:
if language.forced:
subscene_language_set.add(language)
if len(subscene_language_set):
s_pool.provider_configs['subscene'] = {}
s_pool.provider_configs['subscene']['only_foreign'] = True
subtitles_subscene = list_all_subtitles([video], subscene_language_set, s_pool)
s_pool.provider_configs['subscene']['only_foreign'] = False
subtitles[video] += subtitles_subscene[video]
else:
subtitles = []
logging.info("BAZARR All providers are throttled")
return None
except Exception:
logging.exception("BAZARR Error trying to get Subtitle list from provider for this file: " + path)
else:
subtitles_list = []
minimum_score = settings.general.minimum_score
minimum_score_movie = settings.general.minimum_score_movie
for s in subtitles[video]:
try:
matches = s.get_matches(video)
except AttributeError:
continue
# skip wrong season/episodes
if media_type == "series":
can_verify_series = True
if not s.hash_verifiable and "hash" in matches:
can_verify_series = False
if can_verify_series and not {"series", "season", "episode"}.issubset(matches):
logging.debug(f"BAZARR Skipping {s}, because it doesn't match our series/episode")
continue
initial_hi = None
initial_hi_match = False
for language in initial_language_set:
if s.language.basename == language.basename and \
s.language.forced == language.forced and \
s.language.hi == language.hi:
initial_hi = language.hi
initial_hi_match = True
break
if not initial_hi_match:
initial_hi = None
_, max_score, scores = _get_scores(media_type, minimum_score_movie, minimum_score)
score, score_without_hash = compute_score(matches, s, video, hearing_impaired=initial_hi,
score_obj=handler)
if 'hash' not in matches:
not_matched = scores - matches
s.score = score_without_hash
else:
s.score = score
not_matched = set()
if s.hearing_impaired == initial_hi:
matches.add('hearing_impaired')
else:
not_matched.add('hearing_impaired')
releases = []
if hasattr(s, 'release_info'):
if s.release_info is not None:
for s_item in s.release_info.split(','):
if s_item.strip():
releases.append(s_item)
if s.uploader and s.uploader.strip():
s_uploader = s.uploader.strip()
else:
s_uploader = None
subtitles_list.append(
dict(score=round((score / max_score * 100), 2),
orig_score=score,
score_without_hash=score_without_hash,
forced=str(s.language.forced),
language=str(s.language.basename),
hearing_impaired=str(s.hearing_impaired),
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,
uploader=s_uploader))
final_subtitles = sorted(subtitles_list, key=lambda x: (x['orig_score'], x['score_without_hash']),
reverse=True)
logging.debug('BAZARR ' + str(len(final_subtitles)) + " Subtitles have been found for this file: " + path)
logging.debug('BAZARR Ended searching Subtitles for this file: ' + path)
subliminal.region.backend.sync()
return final_subtitles
@update_pools
def manual_download_subtitle(path, audio_language, hi, forced, subtitle, provider, sceneName, title, media_type,
use_original_format, profile_id):
logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path)
if settings.general.getboolean('utf8_encode'):
os.environ["SZ_KEEP_ENCODING"] = ""
else:
os.environ["SZ_KEEP_ENCODING"] = "True"
subtitle = pickle.loads(codecs.decode(subtitle.encode(), "base64"))
if hi == 'True':
subtitle.language.hi = True
else:
subtitle.language.hi = False
if forced == 'True':
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:
try:
if provider:
download_subtitles([subtitle], _get_pool(media_type, profile_id))
logging.debug('BAZARR Subtitles file downloaded for this file:' + path)
else:
logging.info("BAZARR All providers are throttled")
return None
except Exception:
logging.exception('BAZARR Error downloading Subtitles for this file ' + path)
return None
else:
if not subtitle.is_valid():
logging.exception('BAZARR No valid Subtitles file found for this file: ' + path)
return
try:
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, [subtitle],
single=settings.general.getboolean('single_language'),
tags=None, # fixme
directory=get_target_folder(path),
chmod=chmod,
formats=(subtitle.format,),
path_decoder=force_unicode)
except Exception:
logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path)
return
else:
if saved_subtitles:
_, max_score, _ = _get_scores(media_type)
for saved_subtitle in saved_subtitles:
processed_subtitle = process_subtitle(subtitle=saved_subtitle, media_type=media_type,
audio_language=audio_language, is_upgrade=False,
is_manual=True, path=path, max_score=max_score)
if processed_subtitle:
return processed_subtitle
else:
logging.debug(f"BAZARR unable to process this subtitles: {subtitle}")
continue
else:
logging.error(
"BAZARR Tried to manually download a Subtitles for file: " + path
+ " but we weren't able to do (probably throttled by " + str(subtitle.provider_name)
+ ". Please retry later or select a Subtitles from another provider.")
return None
subliminal.region.backend.sync()
logging.debug('BAZARR Ended manually downloading Subtitles for file: ' + path)
def _get_language_obj(profile_id):
initial_language_set = set()
language_set = set()
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']
hi = language['hi']
language = language['language']
lang = alpha3_from_alpha2(language)
lang_obj = _get_lang_obj(lang)
if forced == "True":
lang_obj = Language.rebuild(lang_obj, forced=True)
if hi == "True":
lang_obj = Language.rebuild(lang_obj, hi=True)
initial_language_set.add(lang_obj)
language_set = initial_language_set.copy()
for language in language_set.copy():
lang_obj_for_hi = language
if not language.forced and not language.hi:
lang_obj_hi = Language.rebuild(lang_obj_for_hi, hi=True)
elif not language.forced and language.hi:
lang_obj_hi = Language.rebuild(lang_obj_for_hi, hi=False)
else:
continue
language_set.add(lang_obj_hi)
return language_set, initial_language_set, original_format
def _set_forced_providers(also_forced, pool):
if also_forced:
pool.provider_configs['podnapisi']['also_foreign'] = True
pool.provider_configs['opensubtitles']['also_foreign'] = True