This commit is contained in:
Louis Vézina 2019-10-26 14:52:22 -04:00
parent bcded9e45d
commit d4115cb65f
9 changed files with 158 additions and 131 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,11 +19,11 @@
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>{{details.title}} - Bazarr</title>
<title>{{details['title']}} - Bazarr</title>
<style>
body {
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-attachment: fixed;
background-size: cover;
@ -92,7 +92,7 @@
%from config import settings
%from helper import path_replace
%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_text" class="ui indeterminate text loader">Loading...</div>
</div>
@ -102,14 +102,14 @@
<div id="divdetails" class="ui container">
<div class="ui stackable grid">
<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 class="thirteen wide column">
<div class="ui stackable grid">
<div class="ui row">
<div class="twelve wide left aligned column">
<h2>{{details.title}}</h2>
<h2>{{details['title']}}</h2>
</div>
<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="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 = []
if subs_languages is not None:
for subs_language in subs_languages:
@ -125,18 +125,18 @@
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 class="ui row">
<p>{{details.overview}}</p>
<p>{{details['overview']}}</p>
</div>
<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: #35c5f4;'>{{details.path}}</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;'>{{number}} files</div>
</div>
@ -147,8 +147,8 @@
</div>
<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;'>Forced: {{details.forced}}</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>
</div>
</div>
@ -234,7 +234,7 @@
% forced = False
%end
%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]}}
<i class="delete icon"></i>
</a>
@ -263,12 +263,12 @@
if language in lang:
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}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
%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}}
<i style="margin-left:3px; margin-right:0" class="search red icon"></i>
</a>
@ -276,7 +276,7 @@
%end
%end
%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}}
<i style="margin-left:3px; margin-right:0" class="search icon"></i>
</a>
@ -289,12 +289,12 @@
</td>
<td>
%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
</td>
<td>
%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
</td>
</tr>
@ -340,7 +340,7 @@
<option value="None">None</option>
%end
%for language in languages:
<option value="{{language.code2}}">{{language.name}}</option>
<option value="{{language['code2']}}">{{language['name']}}</option>
%end
</select>
</div>
@ -512,7 +512,7 @@
forced: $(this).attr("data-forced"),
sonarrSeriesId: $(this).attr('data-sonarrSeriesId'),
sonarrEpisodeId: $(this).attr('data-sonarrEpisodeId'),
title: "{{!str(details.title).replace("'", "\\'")}}"
title: "{{!str(details['title']).replace("'", "\\'")}}"
};
$('#loader_text').text("Downloading Subtitle...");
@ -591,7 +591,7 @@
forced: forced,
sonarrSeriesId: sonarrSeriesId,
sonarrEpisodeId: sonarrEpisodeId,
title: "{{!str(details.title).replace("'", "\'")}}"
title: "{{!str(details['title']).replace("'", "\'")}}"
};
$('#search_result').DataTable( {
@ -702,7 +702,7 @@
var languages = Array.from({{!subs_languages_list}});
var is_pb = languages.includes('pb');
var is_pt = languages.includes('pt');
var title = "{{!details.title.replace("'", "\'")}}";
var title = "{{!details['title'].replace("'", "\'")}}";
$('#language').dropdown();
@ -730,7 +730,7 @@
hi: hi,
sonarrSeriesId: sonarrSeriesId,
sonarrEpisodeId: sonarrEpisodeId,
title: "{{!str(details.title).replace("'", "\\'")}}"
title: "{{!str(details['title']).replace("'", "\\'")}}"
};
$('#loader_text').text("Downloading Subtitle...");

View File

@ -58,30 +58,24 @@
% import ast
% import datetime
% import os
% from database import TableEpisodes, TableMovies, System
% from database import database
% import operator
% from config import settings
%episodes_missing_subtitles_clause = [
% (TableEpisodes.missing_subtitles != '[]')
%]
%if settings.sonarr.getboolean('only_monitored'):
% episodes_missing_subtitles_clause.append(
% (TableEpisodes.monitored == 'True')
% )
%if settings.sonarr.getboolean('only_monitored'):
% monitored_only_query_string_sonarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_sonarr = ""
%end
%movies_missing_subtitles_clause = [
% (TableMovies.missing_subtitles != '[]')
%]
%if settings.radarr.getboolean('only_monitored'):
% movies_missing_subtitles_clause.append(
% (TableMovies.monitored == 'True')
% )
%if settings.radarr.getboolean('only_monitored'):
% monitored_only_query_string_radarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_radarr = ""
%end
% wanted_series = TableEpisodes.select().where(reduce(operator.and_, episodes_missing_subtitles_clause)).count()
% wanted_movies = TableMovies.select().where(reduce(operator.and_, movies_missing_subtitles_clause)).count()
% wanted_series = len(database.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string_sonarr))
% 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
% throttled_providers_count = len(eval(str(settings.general.throtteled_providers)))
<div id="divmenu" class="ui container">
@ -219,17 +213,17 @@
</div>
</div>
% restart_required = System.select(System.configured, System.updated)
% restart_required = database.execute("SELECT configured, updated FROM system")
% for item in restart_required:
% restart_required = item
% break
% 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>
% 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>
% 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>
% end
</div>

View File

@ -77,26 +77,26 @@
%import os
%for row in rows:
<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>
%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>
%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>
%end
{{row.path}}
{{row['path']}}
</td>
<td>{{row.audio_language}}</td>
<td>{{row['audio_language']}}</td>
<td>
%subs_languages = ast.literal_eval(str(row.languages))
%subs_languages = ast.literal_eval(str(row['languages']))
%if subs_languages is not None:
%for subs_language in subs_languages:
<div class="ui tiny label">{{subs_language}}</div>
%end
%end
</td>
<td>{{!"" if row.hearing_impaired is None else row.hearing_impaired}}</td>
<td>{{row.forced}}</td>
<td>{{!"" if row['hearing_impaired'] is None else row['hearing_impaired']}}</td>
<td>{{row['forced']}}</td>
<td>
%total_subs = 0
%missing_subs = 0
@ -104,13 +104,13 @@
% pass
%else:
% for total_subtitles in total_subtitles_list:
% if total_subtitles.sonarr_series_id == row.sonarr_series_id:
% total_subs = total_subtitles.missing_subtitles
% if total_subtitles['sonarrSeriesId'] == row['sonarrSeriesId']:
% total_subs = total_subtitles['missing_subtitles']
% end
% end
% for missing_subtitles in missing_subtitles_list:
% if missing_subtitles.sonarr_series_id == row.sonarr_series_id:
% missing_subs = missing_subtitles.missing_subtitles
% if missing_subtitles['sonarrSeriesId'] == row['sonarrSeriesId']:
% missing_subs = missing_subtitles['missing_subtitles']
% end
% end
%end
@ -120,7 +120,7 @@
</div>
</div>
</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 = []
if subs_languages is not None:
@ -129,7 +129,7 @@
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>
</div>
</td>
@ -205,7 +205,7 @@
<option value="None">None</option>
%end
%for language in languages:
<option value="{{language.code2}}">{{language.name}}</option>
<option value="{{language['code2']}}">{{language['name']}}</option>
%end
</select>
</div>