Continuing development.

pull/543/head
Louis Vézina 5 years ago
parent 13b2637650
commit 93adaea3cb

@ -20,6 +20,11 @@ def path_substitution(path):
return path_replace(path) return path_replace(path)
@database.func('path_substitution_movie')
def path_substitution_movie(path):
return path_replace_movie(path)
class UnknownField(object): class UnknownField(object):
def __init__(self, *_, **__): pass def __init__(self, *_, **__): pass
@ -131,6 +136,7 @@ class TableHistory(BaseModel):
class Meta: class Meta:
table_name = 'table_history' table_name = 'table_history'
primary_key = False
class TableHistoryMovie(BaseModel): class TableHistoryMovie(BaseModel):
@ -145,6 +151,7 @@ class TableHistoryMovie(BaseModel):
class Meta: class Meta:
table_name = 'table_history_movie' table_name = 'table_history_movie'
primary_key = False
class TableSettingsLanguages(BaseModel): class TableSettingsLanguages(BaseModel):

@ -797,7 +797,7 @@ def episodes(no):
series_details = series series_details = series
break break
tvdbid = series.tvdb_id tvdbid = series_details.tvdb_id
episodes = TableEpisodes.select( episodes = TableEpisodes.select(
TableEpisodes.title, TableEpisodes.title,
@ -840,15 +840,8 @@ def episodes(no):
@custom_auth_basic(check_credentials) @custom_auth_basic(check_credentials)
def movies(): def movies():
authorize() authorize()
single_language = settings.general.getboolean('single_language')
db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace_movie)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies") missing_count = TableMovies.select().count()
missing_count = c.fetchone()
missing_count = missing_count[0]
page = request.GET.page page = request.GET.page
if page == "": if page == "":
page = "1" page = "1"
@ -856,16 +849,36 @@ 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)))
c.execute( data = TableMovies.select(
"SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language, monitored, sceneName, forced FROM table_movies ORDER BY sortTitle ASC LIMIT ? OFFSET ?", TableMovies.tmdb_id,
(page_size, offset,)) TableMovies.title,
data = c.fetchall() fn.path_substitution_movie(TableMovies.path).alias('path'),
c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") TableMovies.languages,
languages = c.fetchall() TableMovies.hearing_impaired,
c.close() TableMovies.radarr_id,
TableMovies.poster,
TableMovies.audio_language,
TableMovies.monitored,
TableMovies.scene_name,
TableMovies.forced
).order_by(
TableMovies.sort_title.asc()
).paginate(
int(page),
page_size
)
languages = TableSettingsLanguages.select(
TableSettingsLanguages.code2,
TableSettingsLanguages.name
).where(
TableSettingsLanguages.enabled == 1
)
output = template('movies', bazarr_version=bazarr_version, rows=data, languages=languages, output = template('movies', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url,
single_language=single_language, page_size=page_size, current_port=settings.general.port) single_language=settings.general.getboolean('single_language'), page_size=page_size,
current_port=settings.general.port)
return output return output
@ -873,25 +886,33 @@ def movies():
@custom_auth_basic(check_credentials) @custom_auth_basic(check_credentials)
def movieseditor(): def movieseditor():
authorize() authorize()
single_language = settings.general.getboolean('single_language')
db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) missing_count = TableMovies.select().count()
db.create_function("path_substitution", 1, path_replace_movie)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies") data = TableMovies.select(
missing_count = c.fetchone() TableMovies.tmdb_id,
missing_count = missing_count[0] TableMovies.title,
fn.path_substitution_movie(TableMovies.path).alias('path'),
TableMovies.languages,
TableMovies.hearing_impaired,
TableMovies.radarr_id,
TableMovies.poster,
TableMovies.audio_language,
TableMovies.forced
).order_by(
TableMovies.sort_title.asc()
)
languages = TableSettingsLanguages.select(
TableSettingsLanguages.code2,
TableSettingsLanguages.name
).where(
TableSettingsLanguages.enabled == 1
)
c.execute(
"SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language, forced FROM table_movies ORDER BY title ASC")
data = c.fetchall()
c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1")
languages = c.fetchall()
c.close()
output = template('movieseditor', bazarr_version=bazarr_version, rows=data, languages=languages, output = template('movieseditor', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, base_url=base_url, single_language=single_language, missing_count=missing_count, base_url=base_url,
current_port=settings.general.port) single_language=settings.general.getboolean('single_language'), current_port=settings.general.port)
return output return output
@ -907,23 +928,35 @@ def edit_movieseditor():
hi = request.forms.get('hearing_impaired') hi = request.forms.get('hearing_impaired')
forced = request.forms.get('forced') forced = request.forms.get('forced')
conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30)
c = conn.cursor()
for movie in movies: for movie in movies:
if str(lang) != "[]" and str(lang) != "['']": if str(lang) != "[]" and str(lang) != "['']":
if str(lang) == "['None']": if str(lang) == "['None']":
lang = 'None' lang = 'None'
else: else:
lang = str(lang) lang = str(lang)
c.execute("UPDATE table_movies SET languages = ? WHERE radarrId LIKE ?", (lang, movie)) TableMovies.update(
{
TableMovies.languages: lang
}
).where(
TableMovies.radarr_id % movie
).execute()
if hi != '': if hi != '':
c.execute("UPDATE table_movies SET hearing_impaired = ? WHERE radarrId LIKE ?", (hi, movie)) TableMovies.update(
{
TableMovies.hearing_impaired: hi
}
).where(
TableMovies.radarr_id % movie
).execute()
if forced != '': if forced != '':
c.execute("UPDATE table_movies SET forced = ? WHERE radarrId LIKE ?", (forced, movie)) TableMovies.update(
{
conn.commit() TableMovies.forced: forced
c.close() }
).where(
TableMovies.radarr_id % movie
).execute()
for movie in movies: for movie in movies:
list_missing_subtitles_movies(movie) list_missing_subtitles_movies(movie)
@ -961,12 +994,15 @@ def edit_movie(no):
else: else:
hi = "False" hi = "False"
conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) TableMovies.update(
c = conn.cursor() {
c.execute("UPDATE table_movies SET languages = ?, hearing_impaired = ?, forced = ? WHERE radarrId LIKE ?", TableMovies.languages: str(lang),
(str(lang), hi, forced, no)) TableMovies.hearing_impaired: hi,
conn.commit() TableMovies.forced: forced
c.close() }.where(
TableMovies.radarr_id % no
).execute()
)
list_missing_subtitles_movies(no) list_missing_subtitles_movies(no)
@ -978,18 +1014,39 @@ def edit_movie(no):
def movie(no): def movie(no):
authorize() authorize()
conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) movies_details = TableMovies.select(
conn.create_function("path_substitution", 1, path_replace_movie) TableMovies.title,
c = conn.cursor() TableMovies.overview,
TableMovies.poster,
TableMovies.fanart,
TableMovies.hearing_impaired,
TableMovies.tmdb_id,
TableMovies.audio_language,
TableMovies.languages,
fn.path_substitution_movie(TableMovies.path).alias('path'),
TableMovies.subtitles,
TableMovies.radarr_id,
TableMovies.missing_subtitles,
TableMovies.scene_name,
TableMovies.monitored,
TableMovies.failed_attempts,
TableMovies.forced
).where(
TableMovies.radarr_id % str(no)
)
movies_details = [] for movie_details in movies_details:
movies_details = c.execute( movies_details = movie_details
"SELECT title, overview, poster, fanart, hearing_impaired, tmdbid, audio_language, languages, path_substitution(path), subtitles, radarrId, missing_subtitles, sceneName, monitored, failedAttempts, forced FROM table_movies WHERE radarrId LIKE ?", break
(str(no),)).fetchone()
tmdbid = movies_details[5]
languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall() tmdbid = movies_details.tmdb_id
c.close()
languages = TableSettingsLanguages.select(
TableSettingsLanguages.code2,
TableSettingsLanguages.name
).where(
TableSettingsLanguages.enabled == 1
)
return template('movie', bazarr_version=bazarr_version, no=no, details=movies_details, return template('movie', bazarr_version=bazarr_version, no=no, details=movies_details,
languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid, languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid,
@ -1051,12 +1108,8 @@ def history():
@custom_auth_basic(check_credentials) @custom_auth_basic(check_credentials)
def historyseries(): def historyseries():
authorize() authorize()
db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_history") row_count = TableHistory.select().count()
row_count = c.fetchone()
row_count = row_count[0]
page = request.GET.page page = request.GET.page
if page == "": if page == "":
page = "1" page = "1"
@ -1068,21 +1121,44 @@ def historyseries():
today = [] today = []
thisweek = [] thisweek = []
thisyear = [] thisyear = []
stats = c.execute("SELECT timestamp FROM table_history WHERE action > 0").fetchall() stats = TableHistory.select(
TableHistory.timestamp
).where(
TableHistory.action | 0
)
total = len(stats) total = len(stats)
for stat in stats: for stat in stats:
if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(hours=24) <= datetime.fromtimestamp(stat.timestamp) <= now:
today.append(datetime.fromtimestamp(stat[0]).date()) today.append(datetime.fromtimestamp(stat.timestamp).date())
if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat.timestamp) <= now:
thisweek.append(datetime.fromtimestamp(stat[0]).date()) thisweek.append(datetime.fromtimestamp(stat.timestamp).date())
if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat.timestamp) <= now:
thisyear.append(datetime.fromtimestamp(stat[0]).date()) thisyear.append(datetime.fromtimestamp(stat.timestamp).date())
stats = [len(today), len(thisweek), len(thisyear), total] stats = [len(today), len(thisweek), len(thisyear), total]
c.execute( data = TableHistory.select(
"SELECT table_history.action, table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_history.timestamp, table_history.description, table_history.sonarrSeriesId, table_episodes.path, table_shows.languages, table_history.language, table_history.score, table_shows.forced FROM table_history LEFT JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId LEFT JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId ORDER BY id DESC LIMIT ? OFFSET ?", TableHistory.action,
(page_size, offset,)) TableShows.title.alias('seriesTitle'),
data = c.fetchall() TableEpisodes.season.cast('str').concat('x').concat(TableEpisodes.episode.cast('str')).alias('episode'),
TableEpisodes.title.alias('episodeTitle'),
TableHistory.timestamp,
TableHistory.description,
TableHistory.sonarr_series_id,
fn.path_substitution(TableEpisodes.path).alias('path'),
TableShows.languages,
TableHistory.language,
TableHistory.score,
TableShows.forced
).join(
TableShows
).join(
TableEpisodes
).order_by(
TableHistory.timestamp.desc()
).paginate(
int(page),
page_size
).objects()
upgradable_episodes = [] upgradable_episodes = []
upgradable_episodes_not_perfect = [] upgradable_episodes_not_perfect = []
@ -1096,24 +1172,26 @@ def historyseries():
else: else:
query_actions = [1, 3] query_actions = [1, 3]
upgradable_episodes = c.execute("""SELECT video_path, MAX(timestamp), score upgradable_episodes = TableHistory.select(
FROM table_history fn.path_substitution(TableHistory.video_path).alias('video_path'),
WHERE action IN (""" + ','.join(map(str, query_actions)) + """) AND fn.MAX(TableHistory.timestamp).alias('timestamp'),
timestamp > ? AND score is not null TableHistory.score
GROUP BY table_history.video_path, table_history.language""", ).where(
(minimum_timestamp,)).fetchall() TableHistory.action.in_(query_actions) & TableHistory.score.is_null(False)
for upgradable_episode in upgradable_episodes: ).group_by(
TableHistory.video_path,
TableHistory.language
)
for upgradable_episode in upgradable_episodes.dicts():
if upgradable_episode['timestamp'] > minimum_timestamp:
try: try:
int(upgradable_episode[2]) int(upgradable_episode['score'])
except ValueError: except ValueError:
pass pass
else: else:
if int(upgradable_episode[2]) < 360: if int(upgradable_episode['score']) < 360:
upgradable_episodes_not_perfect.append(upgradable_episode) upgradable_episodes_not_perfect.append(tuple(upgradable_episode.values()))
c.close()
data = reversed(sorted(data, key=operator.itemgetter(4)))
return template('historyseries', bazarr_version=bazarr_version, rows=data, row_count=row_count, return template('historyseries', bazarr_version=bazarr_version, rows=data, row_count=row_count,
page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size,
@ -1124,12 +1202,8 @@ def historyseries():
@custom_auth_basic(check_credentials) @custom_auth_basic(check_credentials)
def historymovies(): def historymovies():
authorize() authorize()
db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_history_movie") row_count = TableHistoryMovie.select().count()
row_count = c.fetchone()
row_count = row_count[0]
page = request.GET.page page = request.GET.page
if page == "": if page == "":
page = "1" page = "1"
@ -1141,21 +1215,40 @@ def historymovies():
today = [] today = []
thisweek = [] thisweek = []
thisyear = [] thisyear = []
stats = c.execute("SELECT timestamp FROM table_history_movie WHERE action > 0").fetchall() stats = TableHistoryMovie.select(
TableHistoryMovie.timestamp
).where(
TableHistoryMovie.action > 0
)
total = len(stats) total = len(stats)
for stat in stats: for stat in stats:
if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(hours=24) <= datetime.fromtimestamp(stat.timestamp) <= now:
today.append(datetime.fromtimestamp(stat[0]).date()) today.append(datetime.fromtimestamp(stat.timestamp).date())
if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat.timestamp) <= now:
thisweek.append(datetime.fromtimestamp(stat[0]).date()) thisweek.append(datetime.fromtimestamp(stat.timestamp).date())
if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat.timestamp) <= now:
thisyear.append(datetime.fromtimestamp(stat[0]).date()) thisyear.append(datetime.fromtimestamp(stat.timestamp).date())
stats = [len(today), len(thisweek), len(thisyear), total] stats = [len(today), len(thisweek), len(thisyear), total]
c.execute( data = TableHistoryMovie.select(
"SELECT table_history_movie.action, table_movies.title, table_history_movie.timestamp, table_history_movie.description, table_history_movie.radarrId, table_history_movie.video_path, table_movies.languages, table_history_movie.language, table_history_movie.score, table_movies.forced FROM table_history_movie LEFT JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId ORDER BY id DESC LIMIT ? OFFSET ?", TableHistoryMovie.action,
(page_size, offset,)) TableMovies.title,
data = c.fetchall() TableHistoryMovie.timestamp,
TableHistoryMovie.description,
TableHistoryMovie.radarr_id,
TableHistoryMovie.video_path,
TableMovies.languages,
TableHistoryMovie.language,
TableHistoryMovie.score,
TableMovies.forced
).join(
TableMovies
).order_by(
TableHistoryMovie.timestamp.desc()
).paginate(
int(page),
page_size
).objects()
upgradable_movies = [] upgradable_movies = []
upgradable_movies_not_perfect = [] upgradable_movies_not_perfect = []
@ -1169,23 +1262,27 @@ def historymovies():
else: else:
query_actions = [1, 3] query_actions = [1, 3]
upgradable_movies = c.execute("""SELECT video_path, MAX(timestamp), score upgradable_movies = TableHistoryMovie.select(
FROM table_history_movie TableHistoryMovie.video_path,
WHERE action IN (""" + ','.join(map(str, query_actions)) + """) AND fn.MAX(TableHistoryMovie.timestamp).alias('timestamp'),
timestamp > ? AND score is not null TableHistoryMovie.score
GROUP BY video_path, language""", ).where(
(minimum_timestamp,)).fetchall() TableHistoryMovie.action.in_(query_actions) & TableHistoryMovie.score.is_null(False)
for upgradable_movie in upgradable_movies: ).group_by(
TableHistoryMovie.video_path,
TableHistoryMovie.language
)
for upgradable_movie in upgradable_movies.dicts():
if upgradable_movie['timestamp'] > minimum_timestamp:
try: try:
int(upgradable_movie[2]) int(upgradable_movie['score'])
except ValueError: except ValueError:
pass pass
else: else:
if int(upgradable_movie[2]) < 120: if int(upgradable_movie['score']) < 120:
upgradable_movies_not_perfect.append(upgradable_movie) upgradable_movies_not_perfect.append(tuple(upgradable_movie.values()))
c.close()
data = reversed(sorted(data, key=operator.itemgetter(2)))
return template('historymovies', bazarr_version=bazarr_version, rows=data, row_count=row_count, return template('historymovies', bazarr_version=bazarr_version, rows=data, row_count=row_count,
page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size,
current_port=settings.general.port, upgradable_movies=upgradable_movies_not_perfect) current_port=settings.general.port, upgradable_movies=upgradable_movies_not_perfect)

@ -58,54 +58,54 @@
%for row in rows: %for row in rows:
<tr class="selectable"> <tr class="selectable">
<td class="collapsing"> <td class="collapsing">
%if row[0] == 0: %if row.action == 0:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been erased." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been erased." data-inverted="" data-position="top left">
<i class="ui trash icon"></i> <i class="ui trash icon"></i>
</div> </div>
%elif row[0] == 1: %elif row.action == 1:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been downloaded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been downloaded." data-inverted="" data-position="top left">
<i class="ui download icon"></i> <i class="ui download icon"></i>
</div> </div>
%elif row[0] == 2: %elif row.action == 2:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been manually downloaded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been manually downloaded." data-inverted="" data-position="top left">
<i class="ui user icon"></i> <i class="ui user icon"></i>
</div> </div>
%elif row[0] == 3: %elif row.action == 3:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been upgraded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been upgraded." data-inverted="" data-position="top left">
<i class="ui recycle icon"></i> <i class="ui recycle icon"></i>
</div> </div>
%end %end
</td> </td>
<td> <td>
<a href="{{base_url}}movie/{{row[4]}}">{{row[1]}}</a> <a href="{{base_url}}movie/{{row.radarr_id.radarr_id}}">{{row.title}}</a>
</td> </td>
<td class="collapsing"> <td class="collapsing">
<div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row[2]))}}" data-inverted="" data-position="top left"> <div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row.timestamp))}}" data-inverted="" data-position="top left">
{{pretty.date(int(row[2]))}} {{pretty.date(int(row.timestamp))}}
</div> </div>
</td> </td>
<td> <td>
% upgradable_criteria = (row[5], row[2], row[8]) % upgradable_criteria = (row.timestamp, row.video_path, row.score)
% if upgradable_criteria in upgradable_movies: % if upgradable_criteria in upgradable_movies:
% if row[6] != "None": % if row.languages != "None":
% desired_languages = ast.literal_eval(str(row[6])) % desired_languages = ast.literal_eval(str(row.languages))
% if row[9] == "True": % if row.forced == "True":
% forced_languages = [l + ":forced" for l in desired_languages] % forced_languages = [l + ":forced" for l in desired_languages]
% elif row[9] == "Both": % elif row.forced == "Both":
% forced_languages = [l + ":forced" for l in desired_languages] + desired_languages % forced_languages = [l + ":forced" for l in desired_languages] + desired_languages
% else: % else:
% forced_languages = desired_languages % forced_languages = desired_languages
% end % end
% if row[6] and row[7] and row[7] in forced_languages: % if row.languages and row.language and row.language in forced_languages:
<div class="ui inverted basic compact icon" data-tooltip="This subtitles is eligible to an upgrade." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="This subtitles is eligible to an upgrade." data-inverted="" data-position="top left">
<i class="ui green recycle icon upgrade"></i>{{row[3]}} <i class="ui green recycle icon upgrade"></i>{{row.description}}
</div> </div>
% else: % else:
{{row[3]}} {{row.description}}
% end % end
% end % end
% else: % else:
{{row[3]}} {{row.description}}
% end % end
</td> </td>
</tr> </tr>

@ -60,67 +60,67 @@
%for row in rows: %for row in rows:
<tr class="selectable"> <tr class="selectable">
<td class="collapsing"> <td class="collapsing">
%if row[0] == 0: %if row.action == 0:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been erased." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been erased." data-inverted="" data-position="top left">
<i class="ui trash icon"></i> <i class="ui trash icon"></i>
</div> </div>
%elif row[0] == 1: %elif row.action == 1:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been downloaded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been downloaded." data-inverted="" data-position="top left">
<i class="ui download icon"></i> <i class="ui download icon"></i>
</div> </div>
%elif row[0] == 2: %elif row.action == 2:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been manually downloaded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been manually downloaded." data-inverted="" data-position="top left">
<i class="ui user icon"></i> <i class="ui user icon"></i>
</div> </div>
%elif row[0] == 3: %elif row.action == 3:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been upgraded." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="Subtitles file has been upgraded." data-inverted="" data-position="top left">
<i class="ui recycle icon"></i> <i class="ui recycle icon"></i>
</div> </div>
%end %end
</td> </td>
<td> <td>
<a href="{{base_url}}episodes/{{row[6]}}">{{row[1]}}</a> <a href="{{base_url}}episodes/{{row.sonarr_series_id.sonarr_series_id}}">{{row.seriesTitle}}</a>
</td> </td>
<td class="collapsing"> <td class="collapsing">
%if row[2] is not None: %if row.episode is not None:
% episode = row[2].split('x') % episode = row.episode.split('x')
{{episode[0] + 'x' + episode[1].zfill(2)}} {{episode[0] + 'x' + episode[1].zfill(2)}}
%end %end
</td> </td>
<td> <td>
%if row[3] is not None: %if row.episodeTitle is not None:
{{row[3]}} {{row.episodeTitle}}
%else: %else:
<em>Deleted episode</em> <em>Deleted episode</em>
%end %end
</td> </td>
<td class="collapsing"> <td class="collapsing">
<div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row[4]))}}" data-inverted="" data-position="top left"> <div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row.timestamp))}}" data-inverted="" data-position="top left">
{{pretty.date(int(row[4]))}} {{pretty.date(int(row.timestamp))}}
</div> </div>
</td> </td>
<td> <td>
% upgradable_criteria = (row[7], row[4], row[10]) % upgradable_criteria = (row.timestamp, row.path, row.score)
% if upgradable_criteria in upgradable_episodes: % if upgradable_criteria in upgradable_episodes:
% if row[8] != "None": % if row.languages != "None":
% desired_languages = ast.literal_eval(str(row[8])) % desired_languages = ast.literal_eval(str(row.languages))
% if row[11] == "True": % if row.forced == "True":
% forced_languages = [l + ":forced" for l in desired_languages] % forced_languages = [l + ":forced" for l in desired_languages]
% elif row[11] == "Both": % elif row.forced == "Both":
% forced_languages = [l + ":forced" for l in desired_languages] + desired_languages % forced_languages = [l + ":forced" for l in desired_languages] + desired_languages
% else: % else:
% forced_languages = desired_languages % forced_languages = desired_languages
% end % end
% if row[9] in forced_languages: % if row.language in forced_languages:
<div class="ui inverted basic compact icon" data-tooltip="This subtitles is eligible to an upgrade." data-inverted="" data-position="top left"> <div class="ui inverted basic compact icon" data-tooltip="This subtitles is eligible to an upgrade." data-inverted="" data-position="top left">
<i class="ui green recycle icon upgrade"></i>{{row[5]}} <i class="ui green recycle icon upgrade"></i>{{row.description}}
</div> </div>
% else: % else:
{{row[5]}} {{row.description}}
% end % end
% end % end
% else: % else:
{{row[5]}} {{row.description}}
% end % end
</td> </td>
</tr> </tr>

@ -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[0]}} - Bazarr</title> <title>{{details.title}} - Bazarr</title>
<style> <style>
body { body {
background-color: #1b1c1d; background-color: #1b1c1d;
background-image: url("{{base_url}}image_proxy_movies{{details[3]}}"); background-image: url("{{base_url}}image_proxy_movies{{details.fanart}}");
background-repeat: no-repeat; background-repeat: no-repeat;
background-attachment: fixed; background-attachment: fixed;
background-size: cover; background-size: cover;
@ -83,7 +83,7 @@
%from config import settings %from config import settings
%from helper import path_replace_movie %from helper import path_replace_movie
%single_language = settings.general.getboolean('single_language') %single_language = settings.general.getboolean('single_language')
<div style="display: none;"><img src="{{base_url}}image_proxy_movies{{details[3]}}"></div> <div style="display: none;"><img src="{{base_url}}image_proxy_movies{{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>
@ -93,7 +93,7 @@
<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="left floated ui image" style="max-height:250px;" src="{{base_url}}image_proxy_movies{{details[2]}}"> <img class="left floated ui image" style="max-height:250px;" src="{{base_url}}image_proxy_movies{{details.poster}}">
</div> </div>
<div class="thirteen wide column"> <div class="thirteen wide column">
@ -101,12 +101,12 @@
<div class="ui row"> <div class="ui row">
<div class="twelve wide left aligned column"> <div class="twelve wide left aligned column">
<h2> <h2>
%if details[13] == 'True': %if details.monitored == 'True':
<span data-tooltip="Movie monitored in Radarr"><i class="bookmark icon"></i></span> <span data-tooltip="Movie monitored in Radarr"><i class="bookmark icon"></i></span>
%else: %else:
<span data-tooltip="Movie unmonitored in Radarr"><i class="bookmark outline icon"></i></span> <span data-tooltip="Movie unmonitored in Radarr"><i class="bookmark outline icon"></i></span>
%end %end
{{details[0]}} {{details.title}}
</h2> </h2>
</div> </div>
@ -115,7 +115,7 @@
<button id="scan_disk" class="ui button" data-tooltip="Scan disk for subtitles" data-inverted=""><i class="ui inverted large compact refresh icon"></i></button> <button id="scan_disk" class="ui button" data-tooltip="Scan disk for subtitles" data-inverted=""><i class="ui inverted large compact refresh icon"></i></button>
<button id="search_missing_subtitles_movie" class="ui button" data-tooltip="Download missing subtitles" data-inverted=""><i class="ui inverted huge compact search icon"></i></button> <button id="search_missing_subtitles_movie" class="ui button" data-tooltip="Download missing subtitles" data-inverted=""><i class="ui inverted huge compact search icon"></i></button>
<% <%
subs_languages = ast.literal_eval(str(details[7])) 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:
@ -124,22 +124,22 @@
end end
%> %>
%if subs_languages is not None: %if subs_languages is not None:
<button class="manual_search ui button" data-tooltip="Manually search for subtitles" data-inverted="" data-moviePath="{{details[8]}}" data-scenename="{{details[12]}}" data-language="{{subs_languages_list}}" data-hi="{{details[4]}}" data-forced="{{details[15]}}" data-movie_title="{{details[0]}}" data-radarrId="{{details[10]}}"><i class="ui inverted large compact user icon"></i></button> <button class="manual_search ui button" data-tooltip="Manually search for subtitles" data-inverted="" data-moviePath="{{details.path}}" data-scenename="{{details.scene_name}}" data-language="{{subs_languages_list}}" data-hi="{{details.hearing_impaired}}" data-forced="{{details.forced}}" data-movie_title="{{details.title}}" data-radarrId="{{details.radarr_id}}"><i class="ui inverted large compact user icon"></i></button>
%end %end
<button id="config" class="ui button" data-tooltip="Edit movie" data-inverted="" data-tmdbid="{{details[5]}}" data-title="{{details[0]}}" data-poster="{{details[2]}}" data-audio="{{details[6]}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{details[4]}}" data-forced="{{details[15]}}"><i class="ui inverted large compact configure icon"></i></button> <button id="config" class="ui button" data-tooltip="Edit movie" data-inverted="" data-tmdbid="{{details.tmdb_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>
</div> </div>
</div> </div>
</div> </div>
<div class="ui row"> <div class="ui row">
{{details[1]}} {{details.overview}}
</div> </div>
<div class="ui row"> <div class="ui row">
<div class="ui tiny inverted label" style='background-color: #777777;'>{{details[6]}}</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[8]}}</div> <div class="ui tiny inverted label" style='background-color: #35c5f4;'>{{details.path}}</div>
% if details[12] is not None: % if details.scene_name is not None:
<div class="ui tiny inverted label" style='background-color: orange;'>{{details[12]}}</div> <div class="ui tiny inverted label" style='background-color: orange;'>{{details.scene_name}}</div>
% end % end
</div> </div>
@ -150,8 +150,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[4]}}</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[15]}}</div> <div class="ui tiny inverted label" style='background-color: #777777;'>Forced: {{details.forced}}</div>
</div> </div>
</div> </div>
</div> </div>
@ -168,7 +168,7 @@
</thead> </thead>
<tbody> <tbody>
<% <%
subtitles_files = ast.literal_eval(str(details[9])) subtitles_files = ast.literal_eval(str(details.subtitles))
subtitles_files.sort() subtitles_files.sort()
if subtitles_files is not None: if subtitles_files is not None:
for subtitles_file in subtitles_files: for subtitles_file in subtitles_files:
@ -183,7 +183,7 @@
<td><div class="ui tiny inverted label" style='background-color: #777777;'>{{language_from_alpha2(subtitles_file[0].split(':')[0])}}{{' forced' if forced else ''}}</div></td> <td><div class="ui tiny inverted label" style='background-color: #777777;'>{{language_from_alpha2(subtitles_file[0].split(':')[0])}}{{' forced' if forced else ''}}</div></td>
<td> <td>
%if subtitles_file[1] is not None: %if subtitles_file[1] is not None:
<a class="remove_subtitles ui inverted basic compact icon" data-tooltip="Delete subtitles file from disk" data-inverted="" data-position="top right" data-moviePath="{{details[8]}}" data-subtitlesPath="{{path_replace_movie(subtitles_file[1])}}" data-language="{{alpha3_from_alpha2(subtitles_file[0].split(':')[0])}}" data-radarrId={{details[10]}}> <a class="remove_subtitles ui inverted basic compact icon" data-tooltip="Delete subtitles file from disk" data-inverted="" data-position="top right" data-moviePath="{{details.path}}" data-subtitlesPath="{{path_replace_movie(subtitles_file[1])}}" data-language="{{alpha3_from_alpha2(subtitles_file[0].split(':')[0])}}" data-radarrId={{details.radarr_id}}>
<i class="ui black delete icon"></i> <i class="ui black delete icon"></i>
</a> </a>
%end %end
@ -201,8 +201,8 @@
</tbody> </tbody>
</table> </table>
<% <%
if details[11] is not None: if details.missing_subtitles is not None:
missing_subs_languages = ast.literal_eval(details[11]) missing_subs_languages = ast.literal_eval(details.missing_subtitles)
else: else:
missing_subs_languages = [] missing_subs_languages = []
end end
@ -224,17 +224,17 @@
forced = False forced = False
end end
if details[14] is not None and settings.general.getboolean('adaptive_searching') and missing_subs_language in details[14]: if details.failed_attempts is not None and settings.general.getboolean('adaptive_searching') and missing_subs_language in details.failed_attempts:
for lang in ast.literal_eval(details[14]): for lang in ast.literal_eval(details.failed_attempts):
if missing_subs_language in lang: if missing_subs_language in lang:
if search_active(lang[1]): if search_active(lang[1]):
%> %>
<a class="get_subtitle ui small blue label" data-moviePath="{{details[8]}}" data-scenename="{{details[12]}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details[4]}}" data-forced="{{details[15]}}" data-radarrId={{details[10]}}> <a class="get_subtitle ui small blue label" data-moviePath="{{details.path}}" data-scenename="{{details.scene_name}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{details.forced}}" data-radarrId={{details.radarr_id}}>
{{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}} {{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}}
<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 left" data-inverted="" class="get_subtitle ui small red label" data-moviePath="{{details[8]}}" data-scenename="{{details[12]}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details[4]}}" data-forced="{{details[15]}}" data-radarrId={{details[10]}}> <a data-tooltip="Automatic searching delayed (adaptive search)" data-position="top left" data-inverted="" class="get_subtitle ui small red label" data-moviePath="{{details.path}}" data-scenename="{{details.scene_name}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{details.forced}}" data-radarrId={{details.radarr_id}}>
{{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}} {{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}}
<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>
@ -244,7 +244,7 @@
end end
else: else:
%> %>
<a class="get_subtitle ui small blue label" data-moviePath="{{details[8]}}" data-scenename="{{details[12]}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details[4]}}" data-forced="{{details[15]}}" data-radarrId={{details[10]}}> <a class="get_subtitle ui small blue label" data-moviePath="{{details.path}}" data-scenename="{{details.scene_name}}" data-language="{{alpha3_from_alpha2(str(missing_subs_language.split(':')[0]))}}" data-hi="{{details.hearing_impaired}}" data-forced="{{details.forced}}" data-radarrId={{details.radarr_id}}>
{{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}} {{language_from_alpha2(str(missing_subs_language.split(':')[0]))}}{{' forced' if forced else ''}}
<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,7 +289,7 @@
<option value="None">None</option> <option value="None">None</option>
%end %end
%for language in languages: %for language in languages:
<option value="{{language[0]}}">{{language[1]}}</option> <option value="{{language.code2}}">{{language.name}}</option>
%end %end
</select> </select>
</div> </div>
@ -404,7 +404,7 @@
forced: $(this).attr("data-forced"), forced: $(this).attr("data-forced"),
radarrId: $(this).attr("data-radarrId"), radarrId: $(this).attr("data-radarrId"),
tmdbid: {{tmdbid}}, tmdbid: {{tmdbid}},
title: "{{!details[0].replace("'", "\\'")}}" title: "{{!details.title.replace("'", "\\'")}}"
}; };
$('#loader_text').text("Downloading subtitle to disk..."); $('#loader_text').text("Downloading subtitle to disk...");
@ -476,7 +476,7 @@
hi: hi, hi: hi,
forced: forced, forced: forced,
radarrId: radarrId, radarrId: radarrId,
title: "{{!details[0].replace("'", "\'")}}" title: "{{!details.title.replace("'", "\'")}}"
}; };
$('#search_result').DataTable( { $('#search_result').DataTable( {
@ -570,7 +570,7 @@
language: $(button).attr("data-language"), language: $(button).attr("data-language"),
hi: hi, hi: hi,
radarrId: radarrId, radarrId: radarrId,
title: "{{!details[0].replace("'", "\\'")}}" title: "{{!details.title.replace("'", "\\'")}}"
}; };
$('#loader_text').text("Downloading subtitle to disk..."); $('#loader_text').text("Downloading subtitle to disk...");

@ -71,38 +71,38 @@
%for row in rows: %for row in rows:
<tr class="selectable"> <tr class="selectable">
<td> <td>
%if row[8] == "True": %if row.monitored == "True":
<span data-tooltip="Movie monitored in Radarr" data-inverted="" data-position="top left"><i class="bookmark icon"></i></span> <span data-tooltip="Movie monitored in Radarr" data-inverted="" data-position="top left"><i class="bookmark icon"></i></span>
%else: %else:
<span data-tooltip="Movie unmonitored in Radarr" data-inverted="" data-position="top left"><i class="bookmark outline icon"></i></span> <span data-tooltip="Movie unmonitored in Radarr" data-inverted="" data-position="top left"><i class="bookmark outline icon"></i></span>
%end %end
</td> </td>
<td> <td>
% if row[9] is not None: % if row.scene_name is not None:
<span data-tooltip="Scenename is: {{row[9]}}" data-inverted='' data-position="top left"><i class="info circle icon"></i></span> <span data-tooltip="Scenename is: {{row.scene_name}}" data-inverted='' data-position="top left"><i class="info circle icon"></i></span>
% end % end
<a href="{{base_url}}movie/{{row[5]}}">{{row[1]}}</a> <a href="{{base_url}}movie/{{row.radarr_id}}">{{row.title}}</a>
</td> </td>
<td> <td>
%if os.path.isfile(row[2]): %if os.path.isfile(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 seems to be valid." data-inverted="" data-position="top left"><i class="warning sign icon"></i></span> <span data-tooltip="This path doesn't seems to be valid." data-inverted="" data-position="top left"><i class="warning sign icon"></i></span>
%end %end
{{row[2]}} {{row.path}}
</td> </td>
<td>{{row[7]}}</td> <td>{{row.audio_language}}</td>
<td> <td>
%subs_languages = ast.literal_eval(str(row[3])) %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[4] is None else row[4]}}</td> <td>{{!"" if row.hearing_impaired is None else row.hearing_impaired}}</td>
<td>{{row[10]}}</td> <td>{{row.forced}}</td>
<td {{!"style='background-color: #e8e8e8;'" if row[4] is None else ""}}> <td {{!"style='background-color: #e8e8e8;'" if row.hearing_impaired is None else ""}}>
<% <%
subs_languages_list = [] subs_languages_list = []
if subs_languages is not None: if subs_languages is not None:
@ -111,7 +111,7 @@
end end
end end
%> %>
<div class="config ui inverted basic compact icon" data-tooltip="Edit movies" data-inverted="" data-position="top right" data-no="{{row[5]}}" data-title="{{row[1]}}" data-poster="{{row[6]}}" data-languages="{{!subs_languages_list}}" data-forced="{{row[10]}}" data-hearing-impaired="{{row[4]}}" data-audio="{{row[7]}}"> <div class="config ui inverted basic compact icon" data-tooltip="Edit movies" data-inverted="" data-position="top right" data-no="{{row.radarr_id}}" data-title="{{row.title}}" data-poster="{{row.poster}}" data-languages="{{!subs_languages_list}}" data-forced="{{row.forced}}" data-hearing-impaired="{{row.hearing_impaired}}" data-audio="{{row.audio_language}}">
<i class="ui black configure icon"></i> <i class="ui black configure icon"></i>
</div> </div>
</td> </td>
@ -187,7 +187,7 @@
<option value="None">None</option> <option value="None">None</option>
%end %end
%for language in languages: %for language in languages:
<option value="{{language[0]}}">{{language[1]}}</option> <option value="{{language.code2}}">{{language.name}}</option>
%end %end
</select> </select>
</div> </div>

@ -74,22 +74,22 @@
<tr class="selectable"> <tr class="selectable">
<td class="collapsing"> <td class="collapsing">
<div class="ui checkbox"> <div class="ui checkbox">
<input id='{{row[5]}}' type="checkbox" class="selected"> <input id='{{row.radarr_id}}' type="checkbox" class="selected">
<label></label> <label></label>
</div> </div>
</td> </td>
<td><a href="{{base_url}}movie/{{row[5]}}">{{row[1]}}</a></td> <td><a href="{{base_url}}movie/{{row.radarr_id}}">{{row.title}}</a></td>
<td>{{row[7]}}</td> <td>{{row.audio_language}}</td>
<td> <td>
%subs_languages = ast.literal_eval(str(row[3])) %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[4] == None else row[4]}}</td> <td>{{!"" if row.hearing_impaired == None else row.hearing_impaired}}</td>
<td>{{!"" if row[8] is None else row[8]}}</td> <td>{{!"" if row.forced is None else row.forced}}</td>
</tr> </tr>
%end %end
</tbody> </tbody>
@ -105,7 +105,7 @@
<option value="">No change</option> <option value="">No change</option>
<option value="None">None</option> <option value="None">None</option>
%for language in languages: %for language in languages:
<option value="{{language[0]}}">{{language[1]}}</option> <option value="{{language.code2}}">{{language.name}}</option>
%end %end
</select> </select>
</div> </div>

Loading…
Cancel
Save