|
|
@ -96,8 +96,8 @@ def get_scores(video, media_type, min_score_movie_perc=60 * 100 / 120.0, min_sco
|
|
|
|
return min_score, max_score, set(scores)
|
|
|
|
return min_score, max_score, set(scores)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def download_subtitle(path, language, audio_language, hi, forced, providers, providers_auth, sceneName, title, media_type,
|
|
|
|
def download_subtitle(path, language, audio_language, hi, forced, providers, providers_auth, sceneName, title,
|
|
|
|
forced_minimum_score=None, is_upgrade=False):
|
|
|
|
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
|
|
|
|
# fixme: supply all missing languages, not only one, to hit providers only once who support multiple languages in
|
|
|
|
# one query
|
|
|
|
# one query
|
|
|
|
|
|
|
|
|
|
|
@ -194,7 +194,8 @@ def download_subtitle(path, language, audio_language, hi, forced, providers, pro
|
|
|
|
path_decoder=force_unicode
|
|
|
|
path_decoder=force_unicode
|
|
|
|
)
|
|
|
|
)
|
|
|
|
except Exception as e:
|
|
|
|
except Exception as e:
|
|
|
|
logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path + ': ' + repr(e))
|
|
|
|
logging.exception(
|
|
|
|
|
|
|
|
'BAZARR Error saving Subtitles file to disk for this file:' + path + ': ' + repr(e))
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
saved_any = True
|
|
|
|
saved_any = True
|
|
|
@ -216,14 +217,15 @@ def download_subtitle(path, language, audio_language, hi, forced, providers, pro
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
action = "downloaded"
|
|
|
|
action = "downloaded"
|
|
|
|
message = downloaded_language + is_forced_string + " subtitles " + action + " from " + \
|
|
|
|
message = downloaded_language + is_forced_string + " subtitles " + action + " from " + \
|
|
|
|
downloaded_provider + " with a score of " + str(round(subtitle.score * 100 / max_score, 2))\
|
|
|
|
downloaded_provider + " with a score of " + str(
|
|
|
|
+ "%."
|
|
|
|
round(subtitle.score * 100 / max_score, 2)) + "%."
|
|
|
|
|
|
|
|
|
|
|
|
if use_postprocessing is True:
|
|
|
|
if use_postprocessing:
|
|
|
|
percent_score = round(subtitle.score * 100 / max_score, 2)
|
|
|
|
percent_score = round(subtitle.score * 100 / max_score, 2)
|
|
|
|
command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language,
|
|
|
|
command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language,
|
|
|
|
downloaded_language_code2, downloaded_language_code3, audio_language,
|
|
|
|
downloaded_language_code2, downloaded_language_code3, audio_language,
|
|
|
|
audio_language_code2, audio_language_code3, subtitle.language.forced, percent_score)
|
|
|
|
audio_language_code2, audio_language_code3, subtitle.language.forced,
|
|
|
|
|
|
|
|
percent_score)
|
|
|
|
|
|
|
|
|
|
|
|
if media_type == 'series':
|
|
|
|
if media_type == 'series':
|
|
|
|
use_pp_threshold = settings.general.getboolean('use_postprocessing_threshold')
|
|
|
|
use_pp_threshold = settings.general.getboolean('use_postprocessing_threshold')
|
|
|
@ -233,11 +235,11 @@ def download_subtitle(path, language, audio_language, hi, forced, providers, pro
|
|
|
|
pp_threshold = int(settings.general.postprocessing_threshold_movie)
|
|
|
|
pp_threshold = int(settings.general.postprocessing_threshold_movie)
|
|
|
|
|
|
|
|
|
|
|
|
if not use_pp_threshold or (use_pp_threshold and percent_score < pp_threshold):
|
|
|
|
if not use_pp_threshold or (use_pp_threshold and percent_score < pp_threshold):
|
|
|
|
postprocessing(command, path)
|
|
|
|
|
|
|
|
logging.debug("BAZARR Using post-processing command: {}".format(command))
|
|
|
|
logging.debug("BAZARR Using post-processing command: {}".format(command))
|
|
|
|
|
|
|
|
postprocessing(command, path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
logging.debug("BAZARR post-processing skipped because subtitles score isn't below this "
|
|
|
|
logging.debug("BAZARR post-processing skipped because subtitles score isn't below this "
|
|
|
|
"threshold value: " + str(pp_threshold) + "%")
|
|
|
|
"threshold value: " + str(pp_threshold) + "%")
|
|
|
|
|
|
|
|
|
|
|
|
# fixme: support multiple languages at once
|
|
|
|
# fixme: support multiple languages at once
|
|
|
|
if media_type == 'series':
|
|
|
|
if media_type == 'series':
|
|
|
@ -379,8 +381,8 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
|
|
|
|
return final_subtitles
|
|
|
|
return final_subtitles
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def manual_download_subtitle(path, language, audio_language, hi, forced, subtitle, provider, providers_auth, sceneName, title,
|
|
|
|
def manual_download_subtitle(path, language, audio_language, hi, forced, subtitle, provider, providers_auth, sceneName,
|
|
|
|
media_type):
|
|
|
|
title, media_type):
|
|
|
|
logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path)
|
|
|
|
logging.debug('BAZARR Manually downloading Subtitles for this file: ' + path)
|
|
|
|
|
|
|
|
|
|
|
|
if settings.general.getboolean('utf8_encode'):
|
|
|
|
if settings.general.getboolean('utf8_encode'):
|
|
|
@ -444,11 +446,12 @@ def manual_download_subtitle(path, language, audio_language, hi, forced, subtitl
|
|
|
|
message = downloaded_language + is_forced_string + " subtitles downloaded from " + downloaded_provider + " with a score of " + str(
|
|
|
|
message = downloaded_language + is_forced_string + " subtitles downloaded from " + downloaded_provider + " with a score of " + str(
|
|
|
|
score) + "% using manual search."
|
|
|
|
score) + "% using manual search."
|
|
|
|
|
|
|
|
|
|
|
|
if use_postprocessing is True:
|
|
|
|
if use_postprocessing:
|
|
|
|
percent_score = round(subtitle.score * 100 / max_score, 2)
|
|
|
|
percent_score = round(subtitle.score * 100 / max_score, 2)
|
|
|
|
command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language,
|
|
|
|
command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language,
|
|
|
|
downloaded_language_code2, downloaded_language_code3, audio_language,
|
|
|
|
downloaded_language_code2, downloaded_language_code3, audio_language,
|
|
|
|
audio_language_code2, audio_language_code3, subtitle.language.forced, percent_score)
|
|
|
|
audio_language_code2, audio_language_code3, subtitle.language.forced,
|
|
|
|
|
|
|
|
percent_score)
|
|
|
|
|
|
|
|
|
|
|
|
if media_type == 'series':
|
|
|
|
if media_type == 'series':
|
|
|
|
use_pp_threshold = settings.general.getboolean('use_postprocessing_threshold')
|
|
|
|
use_pp_threshold = settings.general.getboolean('use_postprocessing_threshold')
|
|
|
@ -458,17 +461,19 @@ def manual_download_subtitle(path, language, audio_language, hi, forced, subtitl
|
|
|
|
pp_threshold = settings.general.postprocessing_threshold_movie
|
|
|
|
pp_threshold = settings.general.postprocessing_threshold_movie
|
|
|
|
|
|
|
|
|
|
|
|
if not use_pp_threshold or (use_pp_threshold and percent_score < float(pp_threshold)):
|
|
|
|
if not use_pp_threshold or (use_pp_threshold and percent_score < float(pp_threshold)):
|
|
|
|
|
|
|
|
logging.debug("BAZARR Using post-processing command: {}".format(command))
|
|
|
|
postprocessing(command, path)
|
|
|
|
postprocessing(command, path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
logging.debug("BAZARR post-processing skipped because subtitles score isn't below this "
|
|
|
|
logging.debug("BAZARR post-processing skipped because subtitles score isn't below this "
|
|
|
|
"threshold value: " + pp_threshold + "%")
|
|
|
|
"threshold value: " + pp_threshold + "%")
|
|
|
|
|
|
|
|
|
|
|
|
if media_type == 'series':
|
|
|
|
if media_type == 'series':
|
|
|
|
reversed_path = path_mappings.path_replace_reverse(path)
|
|
|
|
reversed_path = path_mappings.path_replace_reverse(path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
reversed_path = path_mappings.path_replace_reverse_movie(path)
|
|
|
|
reversed_path = path_mappings.path_replace_reverse_movie(path)
|
|
|
|
|
|
|
|
|
|
|
|
track_event(category=downloaded_provider, action="manually_downloaded", label=downloaded_language)
|
|
|
|
track_event(category=downloaded_provider, action="manually_downloaded",
|
|
|
|
|
|
|
|
label=downloaded_language)
|
|
|
|
|
|
|
|
|
|
|
|
return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced
|
|
|
|
return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, subtitle.language.forced
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@ -559,14 +564,12 @@ def manual_upload_subtitle(path, language, forced, title, scene_name, media_type
|
|
|
|
audio_language_code2 = alpha2_from_language(audio_language)
|
|
|
|
audio_language_code2 = alpha2_from_language(audio_language)
|
|
|
|
audio_language_code3 = alpha3_from_language(audio_language)
|
|
|
|
audio_language_code3 = alpha3_from_language(audio_language)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if use_postprocessing:
|
|
|
|
if use_postprocessing:
|
|
|
|
command = pp_replace(postprocessing_cmd, path, subtitle_path, uploaded_language,
|
|
|
|
command = pp_replace(postprocessing_cmd, path, subtitle_path, uploaded_language,
|
|
|
|
uploaded_language_code2, uploaded_language_code3, audio_language,
|
|
|
|
uploaded_language_code2, uploaded_language_code3, audio_language,
|
|
|
|
audio_language_code2, audio_language_code3, forced, 100)
|
|
|
|
audio_language_code2, audio_language_code3, forced, 100)
|
|
|
|
postprocessing(command, path)
|
|
|
|
postprocessing(command, path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if media_type == 'series':
|
|
|
|
if media_type == 'series':
|
|
|
|
reversed_path = path_mappings.path_replace_reverse(path)
|
|
|
|
reversed_path = path_mappings.path_replace_reverse(path)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@ -588,8 +591,9 @@ def series_download_subtitles(no):
|
|
|
|
logging.debug("BAZARR no episode for that sonarrSeriesId can be found in database:", str(no))
|
|
|
|
logging.debug("BAZARR no episode for that sonarrSeriesId can be found in database:", str(no))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
series_details = database.execute("SELECT hearing_impaired, audio_language, title, forced FROM table_shows WHERE sonarrSeriesId=?",
|
|
|
|
series_details = database.execute(
|
|
|
|
(no,), only_one=True)
|
|
|
|
"SELECT hearing_impaired, audio_language, title, forced FROM table_shows WHERE sonarrSeriesId=?",
|
|
|
|
|
|
|
|
(no,), only_one=True)
|
|
|
|
if not series_details:
|
|
|
|
if not series_details:
|
|
|
|
logging.debug("BAZARR no series with that sonarrSeriesId can be found in database:", str(no))
|
|
|
|
logging.debug("BAZARR no series with that sonarrSeriesId can be found in database:", str(no))
|
|
|
|
return
|
|
|
|
return
|
|
|
@ -670,7 +674,8 @@ def episode_download_subtitles(no):
|
|
|
|
provider = result[3]
|
|
|
|
provider = result[3]
|
|
|
|
score = result[4]
|
|
|
|
score = result[4]
|
|
|
|
store_subtitles(episode['path'], path_mappings.path_replace(episode['path']))
|
|
|
|
store_subtitles(episode['path'], path_mappings.path_replace(episode['path']))
|
|
|
|
history_log(1, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path, language_code, provider, score)
|
|
|
|
history_log(1, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path,
|
|
|
|
|
|
|
|
language_code, provider, score)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
logging.info("BAZARR All providers are throttled")
|
|
|
|
logging.info("BAZARR All providers are throttled")
|
|
|
@ -683,8 +688,9 @@ def movies_download_subtitles(no):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
movie_details_clause = ''
|
|
|
|
movie_details_clause = ''
|
|
|
|
|
|
|
|
|
|
|
|
movie = database.execute("SELECT path, missing_subtitles, audio_language, radarrId, sceneName, hearing_impaired, title, forced "
|
|
|
|
movie = database.execute(
|
|
|
|
"FROM table_movies WHERE radarrId=?" + movie_details_clause, (no,), only_one=True)
|
|
|
|
"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:
|
|
|
|
if not movie:
|
|
|
|
logging.debug("BAZARR no movie with that radarrId can be found in database:", str(no))
|
|
|
|
logging.debug("BAZARR no movie with that radarrId can be found in database:", str(no))
|
|
|
@ -776,17 +782,20 @@ def wanted_download_subtitles(path, l, count_episodes):
|
|
|
|
provider = result[3]
|
|
|
|
provider = result[3]
|
|
|
|
score = result[4]
|
|
|
|
score = result[4]
|
|
|
|
store_subtitles(episode['path'], path_mappings.path_replace(episode['path']))
|
|
|
|
store_subtitles(episode['path'], path_mappings.path_replace(episode['path']))
|
|
|
|
history_log(1, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path, language_code, provider, score)
|
|
|
|
history_log(1, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path,
|
|
|
|
|
|
|
|
language_code, provider, score)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
logging.debug(
|
|
|
|
logging.debug(
|
|
|
|
'BAZARR Search is not active for episode ' + episode['path'] + ' Language: ' + attempt[i][0])
|
|
|
|
'BAZARR Search is not active for episode ' + episode['path'] + ' Language: ' + attempt[i][
|
|
|
|
|
|
|
|
0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wanted_download_subtitles_movie(path, l, count_movies):
|
|
|
|
def wanted_download_subtitles_movie(path, l, count_movies):
|
|
|
|
movies_details = database.execute("SELECT path, missing_subtitles, radarrId, hearing_impaired, audio_language, sceneName, "
|
|
|
|
movies_details = database.execute(
|
|
|
|
"failedAttempts, title, forced FROM table_movies WHERE path = ? "
|
|
|
|
"SELECT path, missing_subtitles, radarrId, hearing_impaired, audio_language, sceneName, "
|
|
|
|
"AND missing_subtitles != '[]'", (path_mappings.path_replace_reverse_movie(path),))
|
|
|
|
"failedAttempts, title, forced FROM table_movies WHERE path = ? "
|
|
|
|
|
|
|
|
"AND missing_subtitles != '[]'", (path_mappings.path_replace_reverse_movie(path),))
|
|
|
|
|
|
|
|
|
|
|
|
providers_list = get_providers()
|
|
|
|
providers_list = get_providers()
|
|
|
|
providers_auth = get_providers_auth()
|
|
|
|
providers_auth = get_providers_auth()
|
|
|
@ -832,7 +841,8 @@ def wanted_download_subtitles_movie(path, l, count_movies):
|
|
|
|
send_notifications_movie(movie['radarrId'], message)
|
|
|
|
send_notifications_movie(movie['radarrId'], message)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
logging.info(
|
|
|
|
logging.info(
|
|
|
|
'BAZARR Search is not active for this Movie ' + movie['path'] + ' Language: ' + attempt[i][0])
|
|
|
|
'BAZARR Search is not active for this Movie ' + movie['path'] + ' Language: ' + attempt[i][
|
|
|
|
|
|
|
|
0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wanted_search_missing_subtitles_series():
|
|
|
|
def wanted_search_missing_subtitles_series():
|
|
|
@ -902,13 +912,14 @@ def search_active(timestamp):
|
|
|
|
|
|
|
|
|
|
|
|
def refine_from_db(path, video):
|
|
|
|
def refine_from_db(path, video):
|
|
|
|
if isinstance(video, Episode):
|
|
|
|
if isinstance(video, Episode):
|
|
|
|
data = database.execute("SELECT table_shows.title as seriesTitle, table_episodes.season, table_episodes.episode, "
|
|
|
|
data = database.execute(
|
|
|
|
"table_episodes.title as episodeTitle, table_shows.year, table_shows.tvdbId, "
|
|
|
|
"SELECT table_shows.title as seriesTitle, table_episodes.season, table_episodes.episode, "
|
|
|
|
"table_shows.alternateTitles, table_episodes.format, table_episodes.resolution, "
|
|
|
|
"table_episodes.title as episodeTitle, table_shows.year, table_shows.tvdbId, "
|
|
|
|
"table_episodes.video_codec, table_episodes.audio_codec, table_episodes.path "
|
|
|
|
"table_shows.alternateTitles, table_episodes.format, table_episodes.resolution, "
|
|
|
|
"FROM table_episodes INNER JOIN table_shows on "
|
|
|
|
"table_episodes.video_codec, table_episodes.audio_codec, table_episodes.path "
|
|
|
|
"table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
|
|
|
|
"FROM table_episodes INNER JOIN table_shows on "
|
|
|
|
"WHERE table_episodes.path = ?", (path_mappings.path_replace_reverse(path),), only_one=True)
|
|
|
|
"table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
|
|
|
|
|
|
|
|
"WHERE table_episodes.path = ?", (path_mappings.path_replace_reverse(path),), only_one=True)
|
|
|
|
|
|
|
|
|
|
|
|
if data:
|
|
|
|
if data:
|
|
|
|
video.series = data['seriesTitle']
|
|
|
|
video.series = data['seriesTitle']
|
|
|
@ -1019,7 +1030,7 @@ def upgrade_subtitles():
|
|
|
|
"table_episodes on table_episodes.sonarrEpisodeId = "
|
|
|
|
"table_episodes on table_episodes.sonarrEpisodeId = "
|
|
|
|
"table_history.sonarrEpisodeId WHERE action IN "
|
|
|
|
"table_history.sonarrEpisodeId WHERE action IN "
|
|
|
|
"(" + ','.join(map(str, query_actions)) + ") AND timestamp > ? AND "
|
|
|
|
"(" + ','.join(map(str, query_actions)) + ") AND timestamp > ? AND "
|
|
|
|
"score is not null" + series_monitored_only_query_string +
|
|
|
|
"score is not null" + series_monitored_only_query_string +
|
|
|
|
" GROUP BY table_history.video_path, table_history.language",
|
|
|
|
" GROUP BY table_history.video_path, table_history.language",
|
|
|
|
(minimum_timestamp,))
|
|
|
|
(minimum_timestamp,))
|
|
|
|
|
|
|
|
|
|
|
@ -1120,7 +1131,8 @@ def upgrade_subtitles():
|
|
|
|
provider = result[3]
|
|
|
|
provider = result[3]
|
|
|
|
score = result[4]
|
|
|
|
score = result[4]
|
|
|
|
store_subtitles(episode['video_path'], path_mappings.path_replace(episode['video_path']))
|
|
|
|
store_subtitles(episode['video_path'], path_mappings.path_replace(episode['video_path']))
|
|
|
|
history_log(3, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path, language_code, provider, score)
|
|
|
|
history_log(3, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path,
|
|
|
|
|
|
|
|
language_code, provider, score)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
|
|
|
|
|
|
|
|
|
|
if settings.general.getboolean('use_radarr'):
|
|
|
|
if settings.general.getboolean('use_radarr'):
|
|
|
@ -1167,7 +1179,8 @@ def upgrade_subtitles():
|
|
|
|
language_code = result[2] + ":forced" if forced else result[2]
|
|
|
|
language_code = result[2] + ":forced" if forced else result[2]
|
|
|
|
provider = result[3]
|
|
|
|
provider = result[3]
|
|
|
|
score = result[4]
|
|
|
|
score = result[4]
|
|
|
|
store_subtitles_movie(movie['video_path'], path_mappings.path_replace_movie(movie['video_path']))
|
|
|
|
store_subtitles_movie(movie['video_path'],
|
|
|
|
|
|
|
|
path_mappings.path_replace_movie(movie['video_path']))
|
|
|
|
history_log_movie(3, movie['radarrId'], message, path, language_code, provider, score)
|
|
|
|
history_log_movie(3, movie['radarrId'], message, path, language_code, provider, score)
|
|
|
|
send_notifications_movie(movie['radarrId'], message)
|
|
|
|
send_notifications_movie(movie['radarrId'], message)
|
|
|
|
|
|
|
|
|
|
|
|