pull/684/head
Louis Vézina 5 years ago
parent bcded9e45d
commit d4115cb65f

@ -9,18 +9,20 @@ database = Sqlite3Worker(os.path.join(args.config_dir, 'db', 'bazarr.db'), max_q
class SqliteDictConverter: class SqliteDictConverter:
def __init__(self): def __init__(self):
pass
def convert(self, values_dict):
self.keys = str() self.keys = str()
self.values = str() self.values = str()
self.items = str() self.items = str()
def convert(self, values_dict):
if type(values_dict) is dict: if type(values_dict) is dict:
for key, value in values_dict.items(): for key, value in values_dict.items():
self.keys += key + ", " self.keys += key + ", "
if type(value) is not str: if type(value) not in [str, unicode]:
value = str(value) value = str(value)
else: else:
value = "'" + value + "'" value = "\"" + value + "\""
self.values += value + ", " self.values += value + ", "
self.items += key + "=" + value + ", " self.items += key + "=" + value + ", "
self.keys = self.keys.rstrip(", ") self.keys = self.keys.rstrip(", ")
@ -32,3 +34,19 @@ class SqliteDictConverter:
dict_converter = SqliteDictConverter() dict_converter = SqliteDictConverter()
class SqliteDictPathMapper:
def __init__(self):
pass
def path_replace(self, values_dict):
for item in values_dict:
item['path'] = path_replace(item['path'])
def path_replace_movie(self, values_dict):
for item in values_dict:
item['path'] = path_replace_movie(item['path'])
dict_mapper = SqliteDictPathMapper()

@ -49,7 +49,7 @@ def update_series():
# Get current shows in DB # Get current shows in DB
current_shows_db = database.execute("SELECT tvdbId FROM table_shows") current_shows_db = database.execute("SELECT tvdbId FROM table_shows")
current_shows_db_list = [x.tvdb_id for x in current_shows_db] current_shows_db_list = [x['tvdbId'] for x in current_shows_db]
current_shows_sonarr = [] current_shows_sonarr = []
series_to_update = [] series_to_update = []
series_to_add = [] series_to_add = []
@ -83,43 +83,43 @@ def update_series():
if show['tvdbId'] in current_shows_db_list: if show['tvdbId'] in current_shows_db_list:
series_to_update.append({'title': unicode(show["title"]), series_to_update.append({'title': unicode(show["title"]),
'path': unicode(show["path"]), 'path': unicode(show["path"]),
'tvdb_id': int(show["tvdbId"]), 'tvdbId': int(show["tvdbId"]),
'sonarr_series_id': int(show["id"]), 'sonarrSeriesId': int(show["id"]),
'overview': unicode(overview), 'overview': unicode(overview),
'poster': unicode(poster), 'poster': unicode(poster),
'fanart': unicode(fanart), 'fanart': unicode(fanart),
'audio_language': unicode(profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles)), 'audio_language': unicode(profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles)),
'sort_title': unicode(show['sortTitle']), 'sortTitle': unicode(show['sortTitle']),
'year': unicode(show['year']), 'year': unicode(show['year']),
'alternate_titles': unicode(alternateTitles)}) 'alternateTitles': unicode(alternateTitles)})
else: else:
if serie_default_enabled is True: if serie_default_enabled is True:
series_to_add.append({'title': show["title"], series_to_add.append({'title': show["title"],
'path': show["path"], 'path': show["path"],
'tvdb_id': show["tvdbId"], 'tvdbId': show["tvdbId"],
'languages': serie_default_language, 'languages': serie_default_language,
'hearing_impaired': serie_default_hi, 'hearing_impaired': serie_default_hi,
'sonarr_series_id': show["id"], 'sonarrSeriesId': show["id"],
'overview': overview, 'overview': overview,
'poster': poster, 'poster': poster,
'fanart': fanart, 'fanart': fanart,
'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles), 'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles),
'sort_title': show['sortTitle'], 'sortTitle': show['sortTitle'],
'year': show['year'], 'year': show['year'],
'alternate_titles': alternateTitles, 'alternateTitles': alternateTitles,
'forced': serie_default_forced}) 'forced': serie_default_forced})
else: else:
series_to_add.append({'title': show["title"], series_to_add.append({'title': show["title"],
'path': show["path"], 'path': show["path"],
'tvdb_id': show["tvdbId"], 'tvdbId': show["tvdbId"],
'sonarr_series_id': show["id"], 'sonarrSeriesId': show["id"],
'overview': overview, 'overview': overview,
'poster': poster, 'poster': poster,
'fanart': fanart, 'fanart': fanart,
'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles), 'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles),
'sort_title': show['sortTitle'], 'sortTitle': show['sortTitle'],
'year': show['year'], 'year': show['year'],
'alternate_titles': alternateTitles}) 'alternateTitles': alternateTitles})
# Update existing series in DB # Update existing series in DB
series_in_db_list = [] series_in_db_list = []
@ -133,15 +133,14 @@ def update_series():
for updated_series in series_to_update_list: for updated_series in series_to_update_list:
query = dict_converter.convert(updated_series) query = dict_converter.convert(updated_series)
database.execute("UPDATE table_shows SET ? WHERE sonarrSeriesId=?", database.execute("""UPDATE table_shows SET {0} WHERE sonarrSeriesId=?""".format(query.items),
(query.items, updated_series['sonarr_series_id'])) (updated_series['sonarrSeriesId'],))
# Insert new series in DB # Insert new series in DB
for added_series in series_to_add: for added_series in series_to_add:
query = dict_converter.convert(added_series) query = dict_converter.convert(added_series)
database.execute("INSERT OR IGNORE INTO table_shows(?) VALUES(?)", database.execute("""INSERT OR IGNORE INTO table_shows({0}) VALUES({1})""".format(query.keys, query.values))
(query.keys, query.values)) list_missing_subtitles(no=added_series['sonarrSeriesId'])
list_missing_subtitles(no=added_series['sonarr_series_id'])
# Remove old series from DB # Remove old series from DB
removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr)) removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr))

@ -33,7 +33,7 @@ from get_providers import get_providers, get_providers_auth, provider_throttle,
from get_args import args from get_args import args
from queueconfig import notifications from queueconfig import notifications
from pyprobe.pyprobe import VideoFileParser from pyprobe.pyprobe import VideoFileParser
from database import database from database import database, dict_mapper
from analytics import track_event from analytics import track_event
@ -816,9 +816,10 @@ def wanted_search_missing_subtitles():
else: else:
monitored_only_query_string_sonarr = "" monitored_only_query_string_sonarr = ""
# path_replace
episodes = database.execute("SELECT path FROM table_episodes WHERE missing_subtitles != '[]'" + episodes = database.execute("SELECT path FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string_sonarr) monitored_only_query_string_sonarr)
# path_replace
dict_mapper.path_replace(episodes)
count_episodes = len(episodes) count_episodes = len(episodes)
for i, episode in enumerate(episodes, 1): for i, episode in enumerate(episodes, 1):
@ -836,9 +837,10 @@ def wanted_search_missing_subtitles():
else: else:
monitored_only_query_string_radarr = "" monitored_only_query_string_radarr = ""
# path_replace_movie
movies = database.execute("SELECT path FROM table_movies WHERE missing_subtitles != '[]'" + movies = database.execute("SELECT path FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string_radarr) monitored_only_query_string_radarr)
# path_replace
dict_mapper.path_replace_movie(movies)
count_movies = len(movies) count_movies = len(movies)
for i, movie in enumerate(movies, 1): for i, movie in enumerate(movies, 1):
@ -883,17 +885,17 @@ def refine_from_db(path, video):
"table_episodes.video_codec, table_episodes.audio_codec, table_episodes.path " "table_episodes.video_codec, table_episodes.audio_codec, table_episodes.path "
"FROM table_episodes INNER JOIN table_shows on " "FROM table_episodes INNER JOIN table_shows on "
"table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId " "table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
"WHERE table_episodes.path = ?", (unicode(path_replace_reverse(path)),)) "WHERE table_episodes.path = ?", (unicode(path_replace_reverse(path)),))[0]
if data: if data:
video.series, year, country = series_re.match(data['seriesTitle']).groups() video.series, year, country = series_re.match(data['seriesTitle']).groups()
video.season = int(data['season']) video.season = int(data['season'])
video.episode = int(data['episode']) video.episode = int(data['episode'])
video.title = data['episodeTitle'] video.title = data['episodeTitle']
if data.year: if data['year']:
if int(data['year']) > 0: video.year = int(data['year']) if int(data['year']) > 0: video.year = int(data['year'])
video.series_tvdb_id = int(data['tvdb_id']) video.series_tvdb_id = int(data['tvdbId'])
video.alternative_series = ast.literal_eval(data['alternate_titles']) video.alternative_series = ast.literal_eval(data['alternateTitles'])
if not video.format: if not video.format:
video.format = str(data['format']) video.format = str(data['format'])
if not video.resolution: if not video.resolution:
@ -908,7 +910,7 @@ def refine_from_db(path, video):
if data: if data:
video.title = re.sub(r'(\(\d\d\d\d\))', '', data['title']) video.title = re.sub(r'(\(\d\d\d\d\))', '', data['title'])
if data.year: if data['year']:
if int(data['year']) > 0: video.year = int(data['year']) if int(data['year']) > 0: video.year = int(data['year'])
if data['imdb_id']: video.imdb_id = data['imdb_id'] if data['imdb_id']: video.imdb_id = data['imdb_id']
video.alternative_titles = ast.literal_eval(data['alternative_titles']) video.alternative_titles = ast.literal_eval(data['alternative_titles'])

@ -218,9 +218,9 @@ def store_subtitles_movie(file):
def list_missing_subtitles(no=None, epno=None): def list_missing_subtitles(no=None, epno=None):
if no is not None: if no is not None:
episodes_subtitles_clause = " WHERE sonarrSeriesId=no" episodes_subtitles_clause = " WHERE table_episodes.sonarrSeriesId=" + str(no)
elif epno is not None: elif epno is not None:
episodes_subtitles_clause = " WHERE sonarrEpisodeId=no" episodes_subtitles_clause = " WHERE table_episodes.sonarrEpisodeId=" + str(epno)
else: else:
episodes_subtitles_clause = "" episodes_subtitles_clause = ""
episodes_subtitles = database.execute("SELECT table_shows.sonarrSeriesId, table_episodes.sonarrEpisodeId, " episodes_subtitles = database.execute("SELECT table_shows.sonarrSeriesId, table_episodes.sonarrEpisodeId, "
@ -237,27 +237,27 @@ def list_missing_subtitles(no=None, epno=None):
actual_subtitles = [] actual_subtitles = []
desired_subtitles = [] desired_subtitles = []
missing_subtitles = [] missing_subtitles = []
if episode_subtitles.subtitles is not None: if episode_subtitles['subtitles'] is not None:
if use_embedded_subs: if use_embedded_subs:
actual_subtitles = ast.literal_eval(episode_subtitles.subtitles) actual_subtitles = ast.literal_eval(episode_subtitles['subtitles'])
else: else:
actual_subtitles_temp = ast.literal_eval(episode_subtitles.subtitles) actual_subtitles_temp = ast.literal_eval(episode_subtitles['subtitles'])
for subtitle in actual_subtitles_temp: for subtitle in actual_subtitles_temp:
if subtitle[1] is not None: if subtitle[1] is not None:
actual_subtitles.append(subtitle) actual_subtitles.append(subtitle)
if episode_subtitles.languages is not None: if episode_subtitles['languages'] is not None:
desired_subtitles = ast.literal_eval(episode_subtitles.languages) desired_subtitles = ast.literal_eval(episode_subtitles['languages'])
if episode_subtitles.forced == "True" and desired_subtitles is not None: if episode_subtitles['forced'] == "True" and desired_subtitles is not None:
for i, desired_subtitle in enumerate(desired_subtitles): for i, desired_subtitle in enumerate(desired_subtitles):
desired_subtitles[i] = desired_subtitle + ":forced" desired_subtitles[i] = desired_subtitle + ":forced"
elif episode_subtitles.forced == "Both" and desired_subtitles is not None: elif episode_subtitles['forced'] == "Both" and desired_subtitles is not None:
for desired_subtitle in desired_subtitles: for desired_subtitle in desired_subtitles:
desired_subtitles_temp.append(desired_subtitle) desired_subtitles_temp.append(desired_subtitle)
desired_subtitles_temp.append(desired_subtitle + ":forced") desired_subtitles_temp.append(desired_subtitle + ":forced")
desired_subtitles = desired_subtitles_temp desired_subtitles = desired_subtitles_temp
actual_subtitles_list = [] actual_subtitles_list = []
if desired_subtitles is None: if desired_subtitles is None:
missing_subtitles_global.append(tuple(['[]', episode_subtitles.sonarr_episode_id])) missing_subtitles_global.append(tuple(['[]', episode_subtitles['sonarrEpisodeId']]))
else: else:
for item in actual_subtitles: for item in actual_subtitles:
if item[0] == "pt-BR": if item[0] == "pt-BR":
@ -267,7 +267,7 @@ def list_missing_subtitles(no=None, epno=None):
else: else:
actual_subtitles_list.append(item[0]) actual_subtitles_list.append(item[0])
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list)) missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles.sonarr_episode_id])) missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles['sonarrEpisodeId']]))
for missing_subtitles_item in missing_subtitles_global: for missing_subtitles_item in missing_subtitles_global:
database.execute("UPDATE table_episodes SET missing_subtitles=? WHERE sonarrEpisodeId=?", database.execute("UPDATE table_episodes SET missing_subtitles=? WHERE sonarrEpisodeId=?",
@ -291,27 +291,27 @@ def list_missing_subtitles_movies(no=None):
actual_subtitles = [] actual_subtitles = []
desired_subtitles = [] desired_subtitles = []
missing_subtitles = [] missing_subtitles = []
if movie_subtitles.subtitles is not None: if movie_subtitles['subtitles'] is not None:
if use_embedded_subs: if use_embedded_subs:
actual_subtitles = ast.literal_eval(movie_subtitles.subtitles) actual_subtitles = ast.literal_eval(movie_subtitles['subtitles'])
else: else:
actual_subtitles_temp = ast.literal_eval(movie_subtitles.subtitles) actual_subtitles_temp = ast.literal_eval(movie_subtitles['subtitles'])
for subtitle in actual_subtitles_temp: for subtitle in actual_subtitles_temp:
if subtitle[1] is not None: if subtitle[1] is not None:
actual_subtitles.append(subtitle) actual_subtitles.append(subtitle)
if movie_subtitles.languages is not None: if movie_subtitles['languages'] is not None:
desired_subtitles = ast.literal_eval(movie_subtitles.languages) desired_subtitles = ast.literal_eval(movie_subtitles['languages'])
if movie_subtitles.forced == "True" and desired_subtitles is not None: if movie_subtitles['forced'] == "True" and desired_subtitles is not None:
for i, desired_subtitle in enumerate(desired_subtitles): for i, desired_subtitle in enumerate(desired_subtitles):
desired_subtitles[i] = desired_subtitle + ":forced" desired_subtitles[i] = desired_subtitle + ":forced"
elif movie_subtitles.forced == "Both" and desired_subtitles is not None: elif movie_subtitles['forced'] == "Both" and desired_subtitles is not None:
for desired_subtitle in desired_subtitles: for desired_subtitle in desired_subtitles:
desired_subtitles_temp.append(desired_subtitle) desired_subtitles_temp.append(desired_subtitle)
desired_subtitles_temp.append(desired_subtitle + ":forced") desired_subtitles_temp.append(desired_subtitle + ":forced")
desired_subtitles = desired_subtitles_temp desired_subtitles = desired_subtitles_temp
actual_subtitles_list = [] actual_subtitles_list = []
if desired_subtitles is None: if desired_subtitles is None:
missing_subtitles_global.append(tuple(['[]', movie_subtitles.radarr_id])) missing_subtitles_global.append(tuple(['[]', movie_subtitles['radarrId']]))
else: else:
for item in actual_subtitles: for item in actual_subtitles:
if item[0] == "pt-BR": if item[0] == "pt-BR":
@ -321,7 +321,7 @@ def list_missing_subtitles_movies(no=None):
else: else:
actual_subtitles_list.append(item[0]) actual_subtitles_list.append(item[0])
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list)) missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
missing_subtitles_global.append(tuple([str(missing_subtitles), movie_subtitles.radarr_id])) missing_subtitles_global.append(tuple([str(missing_subtitles), movie_subtitles['radarrId']]))
for missing_subtitles_item in missing_subtitles_global: for missing_subtitles_item in missing_subtitles_global:
database.execute("UPDATE table_movies SET missing_subtitles=? WHERE radarrIr=?", database.execute("UPDATE table_movies SET missing_subtitles=? WHERE radarrIr=?",

@ -22,7 +22,7 @@ from calendar import day_name
from get_args import args from get_args import args
from init import * from init import *
from database import database from database import database, dict_mapper
from notifier import update_notifier from notifier import update_notifier
from logger import configure_logging, empty_log from logger import configure_logging, empty_log
@ -517,19 +517,20 @@ def redirect_root():
def series(): def series():
authorize() authorize()
missing_count = database.execute("SELECT COUNT(*) FROM table_shows") series_count = len(database.execute("SELECT COUNT(*) FROM table_shows"))
page = request.GET.page page = request.GET.page
if page == "": if page == "":
page = "1" page = "1"
page_size = int(settings.general.page_size) page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0))) max_page = int(math.ceil(series_count / (page_size + 0.0)))
# Get list of series # Get list of series
# path_replace
data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, " data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, "
"audio_language, forced FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?", "audio_language, forced FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?",
(page_size, offset)) (page_size, offset))
# path_replace
dict_mapper.path_replace(data)
# Get languages list # Get languages list
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1") languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
@ -542,7 +543,7 @@ def series():
# Get missing subtitles count by series # Get missing subtitles count by series
missing_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, " missing_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, "
"COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN " "COUNT(table_episodes.missing_subtitles) as missing_subtitles FROM table_shows LEFT JOIN "
"table_episodes ON table_shows.sonarrSeriesId=" "table_episodes ON table_shows.sonarrSeriesId="
"table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' " "table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' "
"AND table_episodes.missing_subtitles IS NOT '[]'" + "AND table_episodes.missing_subtitles IS NOT '[]'" +
@ -556,13 +557,13 @@ def series():
# Get total subtitles count by series # Get total subtitles count by series
total_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, " total_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, "
"COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN " "COUNT(table_episodes.missing_subtitles) as missing_subtitles FROM table_shows LEFT JOIN "
"table_episodes ON table_shows.sonarrSeriesId=" "table_episodes ON table_shows.sonarrSeriesId="
"table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None'" "table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None'"
+ total_subtitles_clause + " GROUP BY table_shows.sonarrSeriesId") + total_subtitles_clause + " GROUP BY table_shows.sonarrSeriesId")
return template('series', bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list, return template('series', bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list,
total_subtitles_list=total_subtitles_list, languages=languages, missing_count=missing_count, total_subtitles_list=total_subtitles_list, languages=languages, missing_count=series_count,
page=page, max_page=max_page, base_url=base_url, page=page, max_page=max_page, base_url=base_url,
single_language=settings.general.getboolean('single_language'), page_size=page_size, single_language=settings.general.getboolean('single_language'), page_size=page_size,
current_port=settings.general.port) current_port=settings.general.port)
@ -577,9 +578,10 @@ def serieseditor():
missing_count = database.execute("SELECT COUNT(*) FROM table_shows") missing_count = database.execute("SELECT COUNT(*) FROM table_shows")
# Get series list # Get series list
# path_replace
data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, " data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, "
"audio_language, forced FROM table_shows ORDER BY sortTitle ASC") "audio_language, forced FROM table_shows ORDER BY sortTitle ASC")
# path_replace
dict_mapper.path_replace(data)
# Get languages list # Get languages list
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1") languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
@ -690,26 +692,29 @@ def edit_serieseditor():
def episodes(no): def episodes(no):
authorize() authorize()
# path_replace
series_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbId, " series_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbId, "
"audio_language, languages, path, forced FROM table_shows WHERE " "audio_language, languages, path, forced FROM table_shows WHERE "
"sonarrSeriesId=?", (no,)) "sonarrSeriesId=?", (no,))
# path_replace
dict_mapper.path_replace(series_details)
for series in series_details: for series in series_details:
tvdbid = series.tvdb_id tvdbid = series['tvdbId']
series_details = series series_details = series
break break
# path_replace
episodes = database.execute("SELECT title, path, season, episode, subtitles, sonarrSeriesId, missing_subtitles, " episodes = database.execute("SELECT title, path, season, episode, subtitles, sonarrSeriesId, missing_subtitles, "
"sonarrEpisodeId, scene_name, monitored, failedAttempts FROM table_episodes WHERE " "sonarrEpisodeId, scene_name, monitored, failedAttempts FROM table_episodes WHERE "
"sonarrSeriesId=? ORDER BY season DESC, episode DESC", (no,)) "sonarrSeriesId=? ORDER BY season DESC, episode DESC", (no,))
# path_replace
dict_mapper.path_replace(episodes)
number = len(episodes) number = len(episodes)
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1") languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
seasons_list = [] seasons_list = []
for key, season in itertools.groupby(episodes.dicts(), lambda x: x['season']): for key, season in itertools.groupby(episodes, lambda x: x['season']):
seasons_list.append(list(season)) seasons_list.append(list(season))
return template('episodes', bazarr_version=bazarr_version, no=no, details=series_details, return template('episodes', bazarr_version=bazarr_version, no=no, details=series_details,
@ -730,10 +735,11 @@ def movies():
offset = (int(page) - 1) * page_size offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0))) max_page = int(math.ceil(missing_count / (page_size + 0.0)))
# path_replace_movie
data = database.execute("SELECT tmdbId, title, path, languages, hearing_impaired, radarrId, poster, " data = database.execute("SELECT tmdbId, title, path, languages, hearing_impaired, radarrId, poster, "
"audio_language, monitored, scenename, forced FROM table_movies ORDER BY sortTitle ASC " "audio_language, monitored, scenename, forced FROM table_movies ORDER BY sortTitle ASC "
"LIMIT ? OFFSET ?", (page_size, offset)) "LIMIT ? OFFSET ?", (page_size, offset))
# path_replace
dict_mapper.path_replace_movie(data)
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1") languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
@ -750,9 +756,10 @@ def movieseditor():
missing_count = database.execute("SELECT COUNT(*) FORM table_movies") missing_count = database.execute("SELECT COUNT(*) FORM table_movies")
# path_replace_movie
data = database.execute("SELECT tmdbId, title, path, languages, hearing_impaired, radarrId, poster, " data = database.execute("SELECT tmdbId, title, path, languages, hearing_impaired, radarrId, poster, "
"audio_language, forced FROM table_movies ORDER BY sortTitle ASC") "audio_language, forced FROM table_movies ORDER BY sortTitle ASC")
# path_replace
dict_mapper.path_replace_movie(data)
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1") languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
@ -834,11 +841,12 @@ def edit_movie(no):
def movie(no): def movie(no):
authorize() authorize()
# path_replace_movie
movies_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbId, " movies_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbId, "
"audio_language, languages, path, subtitles, radarrId, missing_subtitles, " "audio_language, languages, path, subtitles, radarrId, missing_subtitles, "
"scenename, monitored, failedAttempts, forced FROM table_movies " "scenename, monitored, failedAttempts, forced FROM table_movies "
"WHERE radarrId=?", (no,)) "WHERE radarrId=?", (no,))
# path_replace
dict_mapper.path_replace(movies_details)
for movie_details in movies_details: for movie_details in movies_details:
movies_details = movie_details movies_details = movie_details
@ -1085,7 +1093,6 @@ def wantedseries():
offset = (int(page) - 1) * page_size offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0))) max_page = int(math.ceil(missing_count / (page_size + 0.0)))
# path_replace
data = database.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, " data = database.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, "
"table_episodes.title, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, " "table_episodes.title, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, "
"table_episodes.path, table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, " "table_episodes.path, table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, "
@ -1093,6 +1100,8 @@ def wantedseries():
"INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId " "INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
"WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string + "WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string +
" ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset)) " ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset))
# path_replace
dict_mapper.path_replace(data)
return template('wantedseries', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, return template('wantedseries', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page,
max_page=max_page, base_url=base_url, page_size=page_size, current_port=settings.general.port) max_page=max_page, base_url=base_url, page_size=page_size, current_port=settings.general.port)
@ -1117,11 +1126,12 @@ def wantedmovies():
offset = (int(page) - 1) * page_size offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0))) max_page = int(math.ceil(missing_count / (page_size + 0.0)))
# path_replace_movie
data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, " data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, "
"failedAttempts FROM table_movies WHERE missing_subtitles != '[]'" + "failedAttempts FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?", monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?",
(page_size, offset)) (page_size, offset))
# path_replace
dict_mapper.path_replace_movie(data)
return template('wantedmovies', bazarr_version=bazarr_version, rows=data, return template('wantedmovies', bazarr_version=bazarr_version, rows=data,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size,

@ -58,6 +58,7 @@ class Sqlite3Worker(threading.Thread):
Args: Args:
file_name: The name of the file. file_name: The name of the file.
max_queue_size: The max queries that will be queued. max_queue_size: The max queries that will be queued.
as_dict: Return result as a dictionary.
""" """
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.daemon = True self.daemon = True
@ -89,11 +90,11 @@ class Sqlite3Worker(threading.Thread):
""" """
LOGGER.debug("run: Thread started") LOGGER.debug("run: Thread started")
execute_count = 0 execute_count = 0
for token, query, values in iter(self.sql_queue.get, None): for token, query, values, only_one in iter(self.sql_queue.get, None):
LOGGER.debug("sql_queue: %s", self.sql_queue.qsize()) LOGGER.debug("sql_queue: %s", self.sql_queue.qsize())
if token != self.exit_token: if token != self.exit_token:
LOGGER.debug("run: %s", query) LOGGER.debug("run: %s", query)
self.run_query(token, query, values) self.run_query(token, query, values, only_one)
execute_count += 1 execute_count += 1
# Let the executes build up a little before committing to disk # Let the executes build up a little before committing to disk
# to speed things up. # to speed things up.
@ -111,7 +112,7 @@ class Sqlite3Worker(threading.Thread):
self.thread_running = False self.thread_running = False
return return
def run_query(self, token, query, values): def run_query(self, token, query, values, only_one):
"""Run a query. """Run a query.
Args: Args:
@ -122,6 +123,9 @@ class Sqlite3Worker(threading.Thread):
if query.lower().strip().startswith("select"): if query.lower().strip().startswith("select"):
try: try:
self.sqlite3_cursor.execute(query, values) self.sqlite3_cursor.execute(query, values)
if only_one:
self.results[token] = self.sqlite3_cursor.fetchone()
else:
self.results[token] = self.sqlite3_cursor.fetchall() self.results[token] = self.sqlite3_cursor.fetchall()
except sqlite3.Error as err: except sqlite3.Error as err:
# Put the error into the output queue since a response # Put the error into the output queue since a response
@ -173,7 +177,7 @@ class Sqlite3Worker(threading.Thread):
if delay < 8: if delay < 8:
delay += delay delay += delay
def execute(self, query, values=None): def execute(self, query, values=None, only_one=False):
"""Execute a query. """Execute a query.
Args: Args:
@ -193,10 +197,10 @@ class Sqlite3Worker(threading.Thread):
# If it's a select we queue it up with a token to mark the results # If it's a select we queue it up with a token to mark the results
# into the output queue so we know what results are ours. # into the output queue so we know what results are ours.
if query.lower().strip().startswith("select"): if query.lower().strip().startswith("select"):
self.sql_queue.put((token, query, values), timeout=5) self.sql_queue.put((token, query, values, only_one), timeout=5)
return self.query_results(token) return self.query_results(token)
else: else:
self.sql_queue.put((token, query, values), timeout=5) self.sql_queue.put((token, query, values, only_one), timeout=5)
def dict_factory(cursor, row): def dict_factory(cursor, row):

@ -19,11 +19,11 @@
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml"> <meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<title>{{details.title}} - Bazarr</title> <title>{{details['title']}} - Bazarr</title>
<style> <style>
body { body {
background-color: #1b1c1d; background-color: #1b1c1d;
background-image: url("{{base_url}}image_proxy{{details.fanart}}"); background-image: url("{{base_url}}image_proxy{{details['fanart']}}");
background-repeat: no-repeat; background-repeat: no-repeat;
background-attachment: fixed; background-attachment: fixed;
background-size: cover; background-size: cover;
@ -92,7 +92,7 @@
%from config import settings %from config import settings
%from helper import path_replace %from helper import path_replace
%single_language = settings.general.getboolean('single_language') %single_language = settings.general.getboolean('single_language')
<div style="display: none;"><img src="{{base_url}}image_proxy{{details.fanart}}"></div> <div style="display: none;"><img src="{{base_url}}image_proxy{{details['fanart']}}"></div>
<div id='loader' class="ui page dimmer"> <div id='loader' class="ui page dimmer">
<div id="loader_text" class="ui indeterminate text loader">Loading...</div> <div id="loader_text" class="ui indeterminate text loader">Loading...</div>
</div> </div>
@ -102,14 +102,14 @@
<div id="divdetails" class="ui container"> <div id="divdetails" class="ui container">
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="three wide column"> <div class="three wide column">
<img class="ui image" style="max-height:250px;" src="{{base_url}}image_proxy{{details.poster}}"> <img class="ui image" style="max-height:250px;" src="{{base_url}}image_proxy{{details['poster']}}">
</div> </div>
<div class="thirteen wide column"> <div class="thirteen wide column">
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="ui row"> <div class="ui row">
<div class="twelve wide left aligned column"> <div class="twelve wide left aligned column">
<h2>{{details.title}}</h2> <h2>{{details['title']}}</h2>
</div> </div>
<div class="four wide right aligned column"> <div class="four wide right aligned column">
@ -117,7 +117,7 @@
<button id="scan_disk" class="ui button" data-tooltip="Scan Disk For Subtitles"><i class="ui inverted large compact refresh icon"></i></button> <button id="scan_disk" class="ui button" data-tooltip="Scan Disk For Subtitles"><i class="ui inverted large compact refresh icon"></i></button>
<button id="search_missing_subtitles" class="ui button" data-tooltip="Download Missing Subtitles"><i class="ui inverted huge compact search icon"></i></button> <button id="search_missing_subtitles" class="ui button" data-tooltip="Download Missing Subtitles"><i class="ui inverted huge compact search icon"></i></button>
<% <%
subs_languages = ast.literal_eval(str(details.languages)) subs_languages = ast.literal_eval(str(details['languages']))
subs_languages_list = [] subs_languages_list = []
if subs_languages is not None: if subs_languages is not None:
for subs_language in subs_languages: for subs_language in subs_languages:
@ -125,18 +125,18 @@
end end
end end
%> %>
<button id="config" class="ui button" data-tooltip="Edit series" data-tvdbid="{{details.tvdb_id}}" data-title="{{details.title}}" data-poster="{{details.poster}}" data-audio="{{details.audio_language}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{details.hearing_impaired}}" data-forced="{{details.forced}}"><i class="ui inverted large compact configure icon"></i></button> <button id="config" class="ui button" data-tooltip="Edit series" data-tvdbid="{{details['tvdbId']}}" data-title="{{details['title']}}" data-poster="{{details['poster']}}" data-audio="{{details['audio_language']}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{details['hearing_impaired']}}" data-forced="{{details['forced']}}"><i class="ui inverted large compact configure icon"></i></button>
</div> </div>
</div> </div>
</div> </div>
<div class="ui row"> <div class="ui row">
<p>{{details.overview}}</p> <p>{{details['overview']}}</p>
</div> </div>
<div class="ui row"> <div class="ui row">
<div class="ui tiny inverted label" style='background-color: #777777;'>{{details.audio_language}}</div> <div class="ui tiny inverted label" style='background-color: #777777;'>{{details['audio_language']}}</div>
<div class="ui tiny inverted label" style='background-color: #35c5f4;'>{{details.path}}</div> <div class="ui tiny inverted label" style='background-color: #35c5f4;'>{{details['path']}}</div>
<div class="ui tiny inverted label" style='background-color: #35c5f4;'>{{number}} files</div> <div class="ui tiny inverted label" style='background-color: #35c5f4;'>{{number}} files</div>
</div> </div>
@ -147,8 +147,8 @@
</div> </div>
<div class="ui row" style="padding-top: 0em;"> <div class="ui row" style="padding-top: 0em;">
<div class="ui tiny inverted label" style='background-color: #777777;'>Hearing-impaired: {{details.hearing_impaired}}</div> <div class="ui tiny inverted label" style='background-color: #777777;'>Hearing-impaired: {{details['hearing_impaired']}}</div>
<div class="ui tiny inverted label" style='background-color: #777777;'>Forced: {{details.forced}}</div> <div class="ui tiny inverted label" style='background-color: #777777;'>Forced: {{details['forced']}}</div>
</div> </div>
</div> </div>
</div> </div>
@ -234,7 +234,7 @@
% forced = False % forced = False
%end %end
%if language[1] is not None: %if language[1] is not None:
<a data-episodePath="{{episode['path']}}" data-subtitlesPath="{{path_replace(language[1])}}" data-language="{{alpha3_from_alpha2(str(language[0]))}}" data-sonarrSeriesId={{episode['sonarr_series_id']}} data-sonarrEpisodeId={{episode['sonarr_episode_id']}} class="remove_subtitles ui tiny label"> <a data-episodePath="{{episode['path']}}" data-subtitlesPath="{{path_replace(language[1])}}" data-language="{{alpha3_from_alpha2(str(language[0]))}}" data-sonarrSeriesId={{episode['sonarrSeriesId']}} data-sonarrEpisodeId={{episode['sonarrEpisodeId']}} class="remove_subtitles ui tiny label">
{{!'<span class="ui" data-tooltip="Forced" data-inverted=""><i class="exclamation icon"></i></span>' if forced else ''}}{{language[0].split(':')[0]}} {{!'<span class="ui" data-tooltip="Forced" data-inverted=""><i class="exclamation icon"></i></span>' if forced else ''}}{{language[0].split(':')[0]}}
<i class="delete icon"></i> <i class="delete icon"></i>
</a> </a>
@ -263,12 +263,12 @@
if language in lang: if language in lang:
if search_active(lang[1]): if search_active(lang[1]):
%> %>
<a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarr_series_id']}}" data-sonarrEpisodeId="{{episode['sonarr_episode_id']}}" class="get_subtitle ui tiny label"> <a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details['hearing_impaired']}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarrSeriesId']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="get_subtitle ui tiny label">
{{language}} {{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i> <i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a> </a>
%else: %else:
<a data-tooltip="Automatic searching delayed (adaptive search)" data-position="top right" data-inverted="" data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarr_series_id']}}" data-sonarrEpisodeId="{{episode['sonarr_episode_id']}}" class="get_subtitle ui tiny label"> <a data-tooltip="Automatic searching delayed (adaptive search)" data-position="top right" data-inverted="" data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details['hearing_impaired']}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarrSeriesId']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="get_subtitle ui tiny label">
{{language}} {{language}}
<i style="margin-left:3px; margin-right:0" class="search red icon"></i> <i style="margin-left:3px; margin-right:0" class="search red icon"></i>
</a> </a>
@ -276,7 +276,7 @@
%end %end
%end %end
%else: %else:
<a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarr_series_id']}}" data-sonarrEpisodeId="{{episode['sonarr_episode_id']}}" class="get_subtitle ui tiny label"> <a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{alpha3_from_alpha2(str(language.split(':')[0]))}}" data-hi="{{details['hearing_impaired']}}" data-forced="{{"True" if len(language.split(':')) > 1 else "False"}}" data-sonarrSeriesId="{{episode['sonarrSeriesId']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="get_subtitle ui tiny label">
{{language}} {{language}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i> <i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a> </a>
@ -289,12 +289,12 @@
</td> </td>
<td> <td>
%if subs_languages is not None: %if subs_languages is not None:
<a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{subs_languages_list}}" data-hi="{{details.hearing_impaired}}" data-forced="{{details.forced}}" data-series_title="{{details.title}}" data-season="{{episode['season']}}" data-episode="{{episode['episode']}}" data-episode_title="{{episode['title']}}" data-sonarrSeriesId="{{episode['sonarr_series_id']}}" data-sonarrEpisodeId="{{episode['sonarr_episode_id']}}" class="manual_search ui tiny label"><i class="ui user icon" style="margin-right:0px" ></i></a> <a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{subs_languages_list}}" data-hi="{{details['hearing_impaired']}}" data-forced="{{details['forced']}}" data-series_title="{{details['title']}}" data-season="{{episode['season']}}" data-episode="{{episode['episode']}}" data-episode_title="{{episode['title']}}" data-sonarrSeriesId="{{episode['sonarrSeriesId']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="manual_search ui tiny label"><i class="ui user icon" style="margin-right:0px" ></i></a>
%end %end
</td> </td>
<td> <td>
%if subs_languages is not None: %if subs_languages is not None:
<a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{subs_languages_list}}" data-hi="{{details.hearing_impaired}}" data-series_title="{{details.title}}" data-season="{{episode['season']}}" data-episode="{{episode['episode']}}" data-episode_title="{{episode['title']}}" data-sonarrSeriesId="{{episode['sonarr_series_id']}}" data-sonarrEpisodeId="{{episode['sonarr_episode_id']}}" class="manual_upload ui tiny label"><i class="ui cloud upload icon" style="margin-right:0px" ></i></a> <a data-episodePath="{{episode['path']}}" data-scenename="{{episode['scene_name']}}" data-language="{{subs_languages_list}}" data-hi="{{details['hearing_impaired']}}" data-series_title="{{details['title']}}" data-season="{{episode['season']}}" data-episode="{{episode['episode']}}" data-episode_title="{{episode['title']}}" data-sonarrSeriesId="{{episode['sonarrSeriesId']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="manual_upload ui tiny label"><i class="ui cloud upload icon" style="margin-right:0px" ></i></a>
%end %end
</td> </td>
</tr> </tr>
@ -340,7 +340,7 @@
<option value="None">None</option> <option value="None">None</option>
%end %end
%for language in languages: %for language in languages:
<option value="{{language.code2}}">{{language.name}}</option> <option value="{{language['code2']}}">{{language['name']}}</option>
%end %end
</select> </select>
</div> </div>
@ -512,7 +512,7 @@
forced: $(this).attr("data-forced"), forced: $(this).attr("data-forced"),
sonarrSeriesId: $(this).attr('data-sonarrSeriesId'), sonarrSeriesId: $(this).attr('data-sonarrSeriesId'),
sonarrEpisodeId: $(this).attr('data-sonarrEpisodeId'), sonarrEpisodeId: $(this).attr('data-sonarrEpisodeId'),
title: "{{!str(details.title).replace("'", "\\'")}}" title: "{{!str(details['title']).replace("'", "\\'")}}"
}; };
$('#loader_text').text("Downloading Subtitle..."); $('#loader_text').text("Downloading Subtitle...");
@ -591,7 +591,7 @@
forced: forced, forced: forced,
sonarrSeriesId: sonarrSeriesId, sonarrSeriesId: sonarrSeriesId,
sonarrEpisodeId: sonarrEpisodeId, sonarrEpisodeId: sonarrEpisodeId,
title: "{{!str(details.title).replace("'", "\'")}}" title: "{{!str(details['title']).replace("'", "\'")}}"
}; };
$('#search_result').DataTable( { $('#search_result').DataTable( {
@ -702,7 +702,7 @@
var languages = Array.from({{!subs_languages_list}}); var languages = Array.from({{!subs_languages_list}});
var is_pb = languages.includes('pb'); var is_pb = languages.includes('pb');
var is_pt = languages.includes('pt'); var is_pt = languages.includes('pt');
var title = "{{!details.title.replace("'", "\'")}}"; var title = "{{!details['title'].replace("'", "\'")}}";
$('#language').dropdown(); $('#language').dropdown();
@ -730,7 +730,7 @@
hi: hi, hi: hi,
sonarrSeriesId: sonarrSeriesId, sonarrSeriesId: sonarrSeriesId,
sonarrEpisodeId: sonarrEpisodeId, sonarrEpisodeId: sonarrEpisodeId,
title: "{{!str(details.title).replace("'", "\\'")}}" title: "{{!str(details['title']).replace("'", "\\'")}}"
}; };
$('#loader_text').text("Downloading Subtitle..."); $('#loader_text').text("Downloading Subtitle...");

@ -58,30 +58,24 @@
% import ast % import ast
% import datetime % import datetime
% import os % import os
% from database import TableEpisodes, TableMovies, System % from database import database
% import operator % import operator
% from config import settings % from config import settings
%episodes_missing_subtitles_clause = [
% (TableEpisodes.missing_subtitles != '[]')
%]
%if settings.sonarr.getboolean('only_monitored'): %if settings.sonarr.getboolean('only_monitored'):
% episodes_missing_subtitles_clause.append( % monitored_only_query_string_sonarr = ' AND monitored = "True"'
% (TableEpisodes.monitored == 'True') %else:
% ) % monitored_only_query_string_sonarr = ""
%end %end
%movies_missing_subtitles_clause = [
% (TableMovies.missing_subtitles != '[]')
%]
%if settings.radarr.getboolean('only_monitored'): %if settings.radarr.getboolean('only_monitored'):
% movies_missing_subtitles_clause.append( % monitored_only_query_string_radarr = ' AND monitored = "True"'
% (TableMovies.monitored == 'True') %else:
% ) % monitored_only_query_string_radarr = ""
%end %end
% wanted_series = TableEpisodes.select().where(reduce(operator.and_, episodes_missing_subtitles_clause)).count() % wanted_series = len(database.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string_sonarr))
% wanted_movies = TableMovies.select().where(reduce(operator.and_, movies_missing_subtitles_clause)).count() % wanted_movies = len(database.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string_radarr))
% from get_providers import list_throttled_providers % from get_providers import list_throttled_providers
% throttled_providers_count = len(eval(str(settings.general.throtteled_providers))) % throttled_providers_count = len(eval(str(settings.general.throtteled_providers)))
<div id="divmenu" class="ui container"> <div id="divmenu" class="ui container">
@ -219,17 +213,17 @@
</div> </div>
</div> </div>
% restart_required = System.select(System.configured, System.updated) % restart_required = database.execute("SELECT configured, updated FROM system")
% for item in restart_required: % for item in restart_required:
% restart_required = item % restart_required = item
% break % break
% end % end
% if restart_required.updated == '1' and restart_required.configured == '1': % if restart_required['updated'] == '1' and restart_required['configured'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply The Last Update & Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div> <div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply The Last Update & Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% elif restart_required.updated == '1': % elif restart_required['updated'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To The Last Update. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div> <div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To The Last Update. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% elif restart_required.configured == '1': % elif restart_required['configured'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div> <div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% end % end
</div> </div>

@ -77,26 +77,26 @@
%import os %import os
%for row in rows: %for row in rows:
<tr class="selectable"> <tr class="selectable">
<td><a href="{{base_url}}episodes/{{row.sonarr_series_id}}">{{row.title}}</a></td> <td><a href="{{base_url}}episodes/{{row['sonarrSeriesId']}}">{{row['title']}}</a></td>
<td> <td>
%if os.path.isdir(row.path): %if os.path.isdir(row['path']):
<span data-tooltip="This path seems to be valid." data-inverted="" data-position="top left"><i class="checkmark icon"></i></span> <span data-tooltip="This path seems to be valid." data-inverted="" data-position="top left"><i class="checkmark icon"></i></span>
%else: %else:
<span data-tooltip="This path doesn't seem to be valid." data-inverted="" data-position="top left"><i class="warning sign icon"></i></span> <span data-tooltip="This path doesn't seem to be valid." data-inverted="" data-position="top left"><i class="warning sign icon"></i></span>
%end %end
{{row.path}} {{row['path']}}
</td> </td>
<td>{{row.audio_language}}</td> <td>{{row['audio_language']}}</td>
<td> <td>
%subs_languages = ast.literal_eval(str(row.languages)) %subs_languages = ast.literal_eval(str(row['languages']))
%if subs_languages is not None: %if subs_languages is not None:
%for subs_language in subs_languages: %for subs_language in subs_languages:
<div class="ui tiny label">{{subs_language}}</div> <div class="ui tiny label">{{subs_language}}</div>
%end %end
%end %end
</td> </td>
<td>{{!"" if row.hearing_impaired is None else row.hearing_impaired}}</td> <td>{{!"" if row['hearing_impaired'] is None else row['hearing_impaired']}}</td>
<td>{{row.forced}}</td> <td>{{row['forced']}}</td>
<td> <td>
%total_subs = 0 %total_subs = 0
%missing_subs = 0 %missing_subs = 0
@ -104,13 +104,13 @@
% pass % pass
%else: %else:
% for total_subtitles in total_subtitles_list: % for total_subtitles in total_subtitles_list:
% if total_subtitles.sonarr_series_id == row.sonarr_series_id: % if total_subtitles['sonarrSeriesId'] == row['sonarrSeriesId']:
% total_subs = total_subtitles.missing_subtitles % total_subs = total_subtitles['missing_subtitles']
% end % end
% end % end
% for missing_subtitles in missing_subtitles_list: % for missing_subtitles in missing_subtitles_list:
% if missing_subtitles.sonarr_series_id == row.sonarr_series_id: % if missing_subtitles['sonarrSeriesId'] == row['sonarrSeriesId']:
% missing_subs = missing_subtitles.missing_subtitles % missing_subs = missing_subtitles['missing_subtitles']
% end % end
% end % end
%end %end
@ -120,7 +120,7 @@
</div> </div>
</div> </div>
</td> </td>
<td {{!"style='background-color: #e8e8e8;'" if row.hearing_impaired == None else ""}}> <td {{!"style='background-color: #e8e8e8;'" if row['hearing_impaired'] == None else ""}}>
<% <%
subs_languages_list = [] subs_languages_list = []
if subs_languages is not None: if subs_languages is not None:
@ -129,7 +129,7 @@
end end
end end
%> %>
<div class="config ui inverted basic compact icon" data-tooltip="Edit Series" data-inverted="" data-position="top right" data-no="{{row.sonarr_series_id}}" data-title="{{row.title}}" data-poster="{{row.poster}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{row.hearing_impaired}}" data-forced="{{row.forced}}" data-audio="{{row.audio_language}}"> <div class="config ui inverted basic compact icon" data-tooltip="Edit Series" data-inverted="" data-position="top right" data-no="{{row['sonarrSeriesId']}}" data-title="{{row['title']}}" data-poster="{{row['poster']}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{row['hearing_impaired']}}" data-forced="{{row['forced']}}" data-audio="{{row['audio_language']}}">
<i class="ui black configure icon"></i> <i class="ui black configure icon"></i>
</div> </div>
</td> </td>
@ -205,7 +205,7 @@
<option value="None">None</option> <option value="None">None</option>
%end %end
%for language in languages: %for language in languages:
<option value="{{language.code2}}">{{language.name}}</option> <option value="{{language['code2']}}">{{language['name']}}</option>
%end %end
</select> </select>
</div> </div>

Loading…
Cancel
Save