Ongoing development

pull/72/head
morpheus65535 7 years ago
parent 9b96ec0f99
commit e236fc7a67

@ -1,4 +1,4 @@
bazarr_version = '0.4.5 dev'
bazarr_version = '0.5.0 dev'
import gc
gc.enable()
@ -339,24 +339,55 @@ def movies():
output = template('movies', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, single_language=single_language)
return output
@route(base_url + 'movie/<no:int>', method='GET')
def movie(no):
from get_radarr_settings import get_radarr_settings
@route(base_url + 'movieseditor')
def movieseditor():
single_language = get_general_settings()[7]
url_radarr_short = get_radarr_settings()[1]
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies")
missing_count = c.fetchone()
missing_count = missing_count[0]
c.execute("SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language 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', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, base_url=base_url, single_language=single_language)
return output
@route(base_url + 'edit_movieseditor', method='POST')
def edit_movieseditor():
ref = request.environ['HTTP_REFERER']
movies = request.forms.get('movies')
movies = ast.literal_eval(str('[' + movies + ']'))
lang = request.forms.getall('languages')
hi = request.forms.get('hearing_impaired')
conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
conn.create_function("path_substitution", 1, path_replace)
c = conn.cursor()
movies_details = []
movies_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbid, audio_language, languages, path_substitution(path), subtitles FROM table_movies WHERE radarrId LIKE ?", (str(no),)).fetchone()
tmdbid = movies_details[5]
for movie in movies:
if str(lang) != "[]" and str(lang) != "['']":
if str(lang) == "['None']":
lang = 'None'
else:
lang = str(lang)
c.execute("UPDATE table_movies SET languages = ? WHERE radarrId LIKE ?", (lang, movie))
if hi != '':
c.execute("UPDATE table_movies SET hearing_impaired = ? WHERE radarrId LIKE ?", (hi, movie))
languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall()
conn.commit()
c.close()
return template('movie', __file__=__file__, bazarr_version=bazarr_version, no=no, details=movies_details, languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid)
for movie in movies:
list_missing_subtitles_movies(movie)
redirect(ref)
@route(base_url + 'edit_movie/<no:int>', method='POST')
def edit_movie(no):
@ -388,6 +419,25 @@ def edit_movie(no):
redirect(ref)
@route(base_url + 'movie/<no:int>', method='GET')
def movie(no):
from get_radarr_settings import get_radarr_settings
single_language = get_general_settings()[7]
url_radarr_short = get_radarr_settings()[1]
conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
conn.create_function("path_substitution", 1, path_replace)
c = conn.cursor()
movies_details = []
movies_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbid, audio_language, languages, path_substitution(path), subtitles, radarrId, missing_subtitles, sceneName FROM table_movies WHERE radarrId LIKE ?", (str(no),)).fetchone()
tmdbid = movies_details[5]
languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall()
c.close()
return template('movie', __file__=__file__, bazarr_version=bazarr_version, no=no, details=movies_details, languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid)
@route(base_url + 'scan_disk/<no:int>', method='GET')
def scan_disk(no):
ref = request.environ['HTTP_REFERER']
@ -422,6 +472,10 @@ def search_missing_subtitles_movie(no):
@route(base_url + 'history')
def history():
return template('history', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url)
@route(base_url + 'historyseries')
def historyseries():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c = db.cursor()
@ -453,10 +507,49 @@ def history():
data = c.fetchall()
c.close()
data = reversed(sorted(data, key=operator.itemgetter(4)))
return template('history', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url)
return template('historyseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url)
@route(base_url + 'historymovies')
def historymovies():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_history_movie")
row_count = c.fetchone()
row_count = row_count[0]
page = request.GET.page
if page == "":
page = "1"
offset = (int(page) - 1) * 15
max_page = int(math.ceil(row_count / 15.0))
now = datetime.now()
today = []
thisweek = []
thisyear = []
stats = c.execute("SELECT timestamp FROM table_history_movie WHERE action LIKE '1'").fetchall()
total = len(stats)
for stat in stats:
if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now:
today.append(datetime.fromtimestamp(stat[0]).date())
if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now:
thisweek.append(datetime.fromtimestamp(stat[0]).date())
if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now:
thisyear.append(datetime.fromtimestamp(stat[0]).date())
stats = [len(today), len(thisweek), len(thisyear), total]
c.execute("SELECT table_history_movie.action, table_movies.title, table_history_movie.timestamp, table_history_movie.description, table_history_movie.radarrId FROM table_history_movie LEFT JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId ORDER BY id DESC LIMIT 15 OFFSET ?", (offset,))
data = c.fetchall()
c.close()
data = reversed(sorted(data, key=operator.itemgetter(2)))
return template('historymovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url)
@route(base_url + 'wanted')
def wanted():
return template('wanted', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url)
@route(base_url + 'wantedseries')
def wantedseries():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
c = db.cursor()
@ -473,7 +566,27 @@ def wanted():
c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, path_substitution(table_episodes.path), table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, table_episodes.scene_name FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]' ORDER BY table_episodes._rowid_ DESC LIMIT 15 OFFSET ?", (offset,))
data = c.fetchall()
c.close()
return template('wanted', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url)
return template('wantedseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url)
@route(base_url + 'wantedmovies')
def wantedmovies():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'")
missing_count = c.fetchone()
missing_count = missing_count[0]
page = request.GET.page
if page == "":
page = "1"
offset = (int(page) - 1) * 15
max_page = int(math.ceil(missing_count / 15.0))
c.execute("SELECT title, missing_subtitles, radarrId, path_substitution(path), hearing_impaired, sceneName FROM table_movies WHERE missing_subtitles != '[]' ORDER BY _rowid_ DESC LIMIT 15 OFFSET ?", (offset,))
data = c.fetchall()
c.close()
return template('wantedmovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url)
@route(base_url + 'wanted_search_missing_subtitles')
def wanted_search_missing_subtitles_list():
@ -864,6 +977,7 @@ def execute_task(taskid):
redirect(ref)
@route(base_url + 'remove_subtitles', method='POST')
def remove_subtitles():
episodePath = request.forms.get('episodePath')
@ -871,7 +985,6 @@ def remove_subtitles():
subtitlesPath = request.forms.get('subtitlesPath')
sonarrSeriesId = request.forms.get('sonarrSeriesId')
sonarrEpisodeId = request.forms.get('sonarrEpisodeId')
tvdbid = request.forms.get('tvdbid')
try:
os.remove(subtitlesPath)
@ -882,6 +995,24 @@ def remove_subtitles():
store_subtitles(unicode(episodePath))
list_missing_subtitles(sonarrSeriesId)
@route(base_url + 'remove_subtitles_movie', method='POST')
def remove_subtitles_movie():
moviePath = request.forms.get('moviePath')
language = request.forms.get('language')
subtitlesPath = request.forms.get('subtitlesPath')
radarrId = request.forms.get('radarrId')
try:
os.remove(subtitlesPath)
result = pycountry.languages.lookup(language).name + " subtitles deleted from disk."
history_log_movie(0, radarrId, result)
except OSError:
pass
store_subtitles_movie(unicode(moviePath))
list_missing_subtitles_movies(radarrId)
@route(base_url + 'get_subtitle', method='POST')
def get_subtitle():
ref = request.environ['HTTP_REFERER']
@ -918,7 +1049,7 @@ def get_subtitle():
providers_auth = None
try:
result = download_subtitle(episodePath, language, hi, providers_list, providers_auth, sceneName)
result = download_subtitle(episodePath, language, hi, providers_list, providers_auth, sceneName, 'series')
if result is not None:
history_log(1, sonarrSeriesId, sonarrEpisodeId, result)
send_notifications(sonarrSeriesId, sonarrEpisodeId, result)
@ -928,6 +1059,51 @@ def get_subtitle():
except OSError:
pass
@route(base_url + 'get_subtitle_movie', method='POST')
def get_subtitle_movie():
ref = request.environ['HTTP_REFERER']
moviePath = request.forms.get('moviePath')
sceneName = request.forms.get('sceneName')
language = request.forms.get('language')
hi = request.forms.get('hi')
radarrId = request.forms.get('radarrId')
tmdbid = request.forms.get('tmdbid')
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c = db.cursor()
c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1")
enabled_providers = c.fetchall()
c.close()
providers_list = []
providers_auth = {}
if len(enabled_providers) > 0:
for provider in enabled_providers:
providers_list.append(provider[0])
try:
if provider[2] is not '' and provider[3] is not '':
provider_auth = providers_auth.append(provider[0])
provider_auth.update({'username':providers[2], 'password':providers[3]})
else:
providers_auth = None
except:
providers_auth = None
else:
providers_list = None
providers_auth = None
try:
result = download_subtitle(moviePath, language, hi, providers_list, providers_auth, sceneName, 'movies')
if result is not None:
history_log_movie(1, radarrId, result)
send_notifications_movie(radarrId, result)
store_subtitles_movie(unicode(moviePath))
list_missing_subtitles_movies(radarrId)
redirect(ref)
except OSError:
pass
def configured():
conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c = conn.cursor()

@ -6,7 +6,7 @@ import logging
from get_general_settings import *
from list_subtitles import *
def update_all_episodes():
def update_all_episodes_and_movies():
full_scan_subtitles()
logging.info('All existing subtitles indexed from disk.')
list_missing_subtitles()

@ -36,7 +36,7 @@ def update_movies():
overview = ""
try:
poster_big = movie['images'][0]['url']
poster = os.path.splitext(poster_big)[0] + '-250' + os.path.splitext(poster_big)[1]
poster = os.path.splitext(poster_big)[0] + '-500' + os.path.splitext(poster_big)[1]
except:
poster = ""
try:

@ -15,8 +15,12 @@ from notifier import send_notifications, send_notifications_movie
# configure the cache
region.configure('dogpile.cache.memory')
def download_subtitle(path, language, hi, providers, providers_auth, sceneName):
minimum_score = float(get_general_settings()[8]) / 100 * 359
def download_subtitle(path, language, hi, providers, providers_auth, sceneName, type):
if type == 'series':
type_of_score = 359
elif type == 'movies':
type_of_score = 119
minimum_score = float(get_general_settings()[8]) / 100 * type_of_score
use_scenename = get_general_settings()[9]
use_postprocessing = get_general_settings()[10]
postprocessing_cmd = get_general_settings()[11]
@ -45,7 +49,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName):
else:
single = get_general_settings()[7]
try:
score = round(float(compute_score(best_subtitle, video)) / 359 * 100, 2)
score = round(float(compute_score(best_subtitle, video)) / type_of_score * 100, 2)
if used_sceneName == True:
video = scan_video(path)
if single == 'True':
@ -122,7 +126,7 @@ def series_download_subtitles(no):
for episode in episodes_details:
for language in ast.literal_eval(episode[1]):
message = download_subtitle(path_replace(episode[0]), str(pycountry.languages.lookup(language).alpha_3), series_details[0], providers_list, providers_auth, episode[3])
message = download_subtitle(path_replace(episode[0]), str(pycountry.languages.lookup(language).alpha_3), series_details[0], providers_list, providers_auth, episode[3], 'series')
if message is not None:
store_subtitles(path_replace(episode[0]))
history_log(1, no, episode[2], message)
@ -155,7 +159,7 @@ def movies_download_subtitles(no):
providers_auth = None
for language in ast.literal_eval(movie[1]):
message = download_subtitle(path_replace(movie[0]), str(pycountry.languages.lookup(language).alpha_3), movie[4], providers_list, providers_auth, movie[3])
message = download_subtitle(path_replace(movie[0]), str(pycountry.languages.lookup(language).alpha_3), movie[4], providers_list, providers_auth, movie[3], 'movies')
if message is not None:
store_subtitles_movie(path_replace(movie[0]))
history_log_movie(1, no, message)
@ -189,7 +193,7 @@ def wanted_download_subtitles(path):
for episode in episodes_details:
for language in ast.literal_eval(episode[1]):
message = download_subtitle(path_replace(episode[0]), str(pycountry.languages.lookup(language).alpha_3), episode[4], providers_list, providers_auth, episode[5])
message = download_subtitle(path_replace(episode[0]), str(pycountry.languages.lookup(language).alpha_3), episode[4], providers_list, providers_auth, episode[5], 'series')
if message is not None:
store_subtitles(path_replace(episode[0]))
list_missing_subtitles(episode[3])
@ -201,11 +205,15 @@ def wanted_search_missing_subtitles():
db.create_function("path_substitution", 1, path_replace)
c = db.cursor()
c.execute("SELECT path_substitution(path) FROM table_episodes WHERE table_episodes.missing_subtitles != '[]'")
data = c.fetchall()
c.execute("SELECT path_substitution(path) FROM table_episodes WHERE missing_subtitles != '[]'")
episodes = c.fetchall()
c.execute("SELECT path_substitution(path) FROM table_movies WHERE missing_subtitles != '[]'")
movies = c.fetchall()
c.close()
for episode in data:
for episode in episodes:
wanted_download_subtitles(episode[0])
logging.info('Finished searching for missing subtitles. Check history for more information.')
logging.info('Finished searching for missing subtitles. Check histories for more information.')

@ -2,6 +2,7 @@ from get_general_settings import *
from get_sonarr_settings import get_sonarr_settings
from get_series import *
from get_episodes import *
from get_movies import *
from list_subtitles import *
from get_subtitle import *
from check_update import *
@ -15,11 +16,11 @@ from tzlocal import get_localzone
def sonarr_full_update():
full_update = get_sonarr_settings()[3]
if full_update == "Daily":
scheduler.add_job(update_all_episodes, 'cron', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', name='Update all episodes from Sonarr', replace_existing=True)
scheduler.add_job(update_all_episodes_and_movies, 'cron', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes_and_movies', name='Update all subtitles from disk', replace_existing=True)
elif full_update == "Weekly":
scheduler.add_job(update_all_episodes, 'cron', day_of_week='sun', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', name='Update all episodes from Sonarr', replace_existing=True)
scheduler.add_job(update_all_episodes_and_movies, 'cron', day_of_week='sun', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes_and_movies', name='Update all subtitles from disk', replace_existing=True)
elif full_update == "Manually":
scheduler.add_job(update_all_episodes, 'cron', year='2100', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', name='Update all episodes from Sonarr', replace_existing=True)
scheduler.add_job(update_all_episodes_and_movies, 'cron', year='2100', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes_and_movies', name='Update all subtitles from disk', replace_existing=True)
def execute_now(taskid):
scheduler.modify_job(taskid, jobstore=None, next_run_time=datetime.now())
@ -36,6 +37,7 @@ else:
scheduler.add_job(check_and_apply_update, 'cron', year='2100', hour=4, id='update_bazarr', name='Update bazarr from source on Github')
scheduler.add_job(update_series, 'interval', minutes=1, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_series', name='Update series list from Sonarr')
scheduler.add_job(sync_episodes, 'interval', minutes=5, max_instances=1, coalesce=True, misfire_grace_time=15, id='sync_episodes', name='Sync episodes with Sonarr')
scheduler.add_job(update_movies, 'interval', minutes=1, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_movies', name='Update movies list from Radarr')
scheduler.add_job(wanted_search_missing_subtitles, 'interval', hours=3, max_instances=1, coalesce=True, misfire_grace_time=15, id='wanted_search_missing_subtitles', name='Search for wanted subtitles')
sonarr_full_update()
scheduler.start()

@ -107,7 +107,7 @@ if os.path.exists(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
pass
else:
from scheduler import execute_now
execute_now('update_all_episodes')
execute_now('update_all_episodes_and_movies')
# Close database connection
db.close()

@ -1,214 +1,109 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>History - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 3em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
#bottommenu {
background-color: #333333;
box-shadow: 0 0 10px 1px #333;
padding: 10px;
margin-bottom: -2em !important;
}
.label, .value {
color: white !important;
}
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
% include('menu.tpl')
<div id="fondblanc" class="ui container">
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th></th>
<th>Series</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Date</th>
<th>Description</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%for row in rows:
<tr class="selectable">
<td class="collapsing">
%if row[0] == 0:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been erased." data-inverted="">
<i class="ui trash icon"></i>
</div>
%elif row[0] == 1:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been downloaded." data-inverted="">
<i class="ui download icon"></i>
</div>
%end
</td>
<td>
<a href="{{base_url}}episodes/{{row[6]}}">{{row[1]}}</a>
</td>
<td class="collapsing">
%if row[2] is not None:
% episode = row[2].split('x')
{{episode[0] + 'x' + episode[1].zfill(2)}}
%end
</td>
<td>
%if row[3] is not None:
{{row[3]}}
%else:
<em>Deleted episode</em>
%end
</td>
<td class="collapsing">
<div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row[4]))}}" data-inverted="">
{{pretty.date(int(row[4]))}}
</div>
</td>
<td>{{row[5]}}</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == '1':
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == '1':
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{row_count}}</div>
</div>
</div>
</div>
<div id='bottommenu' class="ui fluid inverted bottom fixed five item menu">
<div class="ui statistics">
<div class="statistic">
<div class="text value">
<br>
Statistics
</div>
<div class="label">
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[0]}}
</div>
<div class="label">
Since 24 hours
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[1]}}
</div>
<div class="label">
Since one week
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[2]}}
</div>
<div class="label">
Since one year
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[3]}}
</div>
<div class="label">
Total
</div>
</div>
</div>
</div>
% include('footer.tpl')
<br><br><br><br>
</body>
</html>
<script>
if (sessionStorage.scrolly) {
$(window).scrollTop(sessionStorage.scrolly);
sessionStorage.clear();
}
$('a, i').click(function(){
sessionStorage.scrolly=$(window).scrollTop();
$('#loader').addClass('active');
})
$('.backward').click(function(){
location.href="?page={{int(page)-1}}";
})
$('.fast.backward').click(function(){
location.href="?page=1";
})
$('.forward').click(function(){
location.href="?page={{int(page)+1}}";
})
$('.fast.forward').click(function(){
location.href="?page={{int(max_page)}}";
})
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>History - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 1em;
}
#logs {
margin-top: 4em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
% include('menu.tpl')
<div id="fondblanc" class="ui container">
<div class="ui top attached tabular menu">
<a id="series_tab" class="tabs item active" data-tab="series">Series</a>
<a id="movies_tab" class="tabs item" data-tab="movies">Movies</a>
</div>
<div class="ui bottom attached tab segment" data-tab="series">
<div class="content">
<div id="content_series"></div>
</div>
</div>
<div class="ui bottom attached tab segment" data-tab="movies">
<div class="content">
<div id="content_movies"></div>
</div>
</div>
</div>
% include('footer.tpl')
</body>
</html>
<script>
$('.menu .item')
.tab()
;
$('#series_tab').click(function() {
loadURLseries(1);
})
$('#movies_tab').click(function() {
loadURLmovies(1);
})
function loadURLseries(page) {
$.ajax({
url: "{{base_url}}historyseries?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_series").html(data);
});
}
function loadURLmovies(page) {
$.ajax({
url: "{{base_url}}historymovies?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_movies").html(data);
});
}
$('a:not(.tabs), button:not(.cancel, #download_log)').click(function(){
$('#loader').addClass('active');
})
$( "#series_tab" ).trigger( "click" );
</script>

@ -0,0 +1,199 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>History - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 3em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
#bottommenu {
background-color: #333333;
box-shadow: 0 0 10px 1px #333;
padding: 10px;
margin-bottom: -2em !important;
}
.label, .value {
color: white !important;
}
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
<div class="ui container">
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Date</th>
<th>Description</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%for row in rows:
<tr class="selectable">
<td class="collapsing">
%if row[0] == 0:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been erased." data-inverted="">
<i class="ui trash icon"></i>
</div>
%elif row[0] == 1:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been downloaded." data-inverted="">
<i class="ui download icon"></i>
</div>
%end
</td>
<td>
<a href="{{base_url}}movie/{{row[4]}}">{{row[1]}}</a>
</td>
<td class="collapsing">
<div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row[2]))}}" data-inverted="">
{{pretty.date(int(row[2]))}}
</div>
</td>
<td>{{row[3]}}</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == '1':
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == '1':
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{row_count}}</div>
</div>
</div>
</div>
<div id='bottommenu' class="ui fluid inverted bottom fixed five item menu">
<div class="ui small statistics">
<div class="statistic">
<div class="text value">
<br>
Movies
<br>
statistics
</div>
<div class="label">
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[0]}}
</div>
<div class="label">
Since 24 hours
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[1]}}
</div>
<div class="label">
Since one week
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[2]}}
</div>
<div class="label">
Since one year
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[3]}}
</div>
<div class="label">
Total
</div>
</div>
</div>
</div>
<br><br><br><br>
</body>
</html>
<script>
if (sessionStorage.scrolly) {
$(window).scrollTop(sessionStorage.scrolly);
sessionStorage.clear();
}
$('a, i').click(function(){
sessionStorage.scrolly=$(window).scrollTop();
$('#loader').addClass('active');
})
$('.fast.backward').click(function(){
loadURLseries(1);
})
$('.backward:not(.fast)').click(function(){
loadURLseries({{int(page)-1}});
})
$('.forward:not(.fast)').click(function(){
loadURLseries({{int(page)+1}});
})
$('.fast.forward').click(function(){
loadURLseries({{int(max_page)}});
})
</script>

@ -0,0 +1,214 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>History - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 3em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
#bottommenu {
background-color: #333333;
box-shadow: 0 0 10px 1px #333;
padding: 10px;
margin-bottom: -2em !important;
}
.label, .value {
color: white !important;
}
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
<div class="ui container">
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Date</th>
<th>Description</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%for row in rows:
<tr class="selectable">
<td class="collapsing">
%if row[0] == 0:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been erased." data-inverted="">
<i class="ui trash icon"></i>
</div>
%elif row[0] == 1:
<div class="ui inverted basic compact icon" data-tooltip="Subtitles file have been downloaded." data-inverted="">
<i class="ui download icon"></i>
</div>
%end
</td>
<td>
<a href="{{base_url}}episodes/{{row[6]}}">{{row[1]}}</a>
</td>
<td class="collapsing">
%if row[2] is not None:
% episode = row[2].split('x')
{{episode[0] + 'x' + episode[1].zfill(2)}}
%end
</td>
<td>
%if row[3] is not None:
{{row[3]}}
%else:
<em>Deleted episode</em>
%end
</td>
<td class="collapsing">
<div class="ui inverted" data-tooltip="{{time.strftime('%Y/%m/%d %H:%M', time.localtime(row[4]))}}" data-inverted="">
{{pretty.date(int(row[4]))}}
</div>
</td>
<td>{{row[5]}}</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == '1':
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == '1':
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{row_count}}</div>
</div>
</div>
</div>
<div id='bottommenu' class="ui fluid inverted bottom fixed five item menu">
<div class="ui small statistics">
<div class="statistic">
<div class="text value">
<br>
Series
<br>
statistics
</div>
<div class="label">
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[0]}}
</div>
<div class="label">
Since 24 hours
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[1]}}
</div>
<div class="label">
Since one week
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[2]}}
</div>
<div class="label">
Since one year
</div>
</div>
<div class="statistic">
<div class="value">
{{stats[3]}}
</div>
<div class="label">
Total
</div>
</div>
</div>
</div>
<br><br><br><br>
</body>
</html>
<script>
if (sessionStorage.scrolly) {
$(window).scrollTop(sessionStorage.scrolly);
sessionStorage.clear();
}
$('a, i').click(function(){
sessionStorage.scrolly=$(window).scrollTop();
$('#loader').addClass('active');
})
$('.fast.backward').click(function(){
loadURLseries(1);
})
$('.backward:not(.fast)').click(function(){
loadURLseries({{int(page)-1}});
})
$('.forward:not(.fast)').click(function(){
loadURLseries({{int(page)+1}});
})
$('.fast.forward').click(function(){
loadURLseries({{int(max_page)}});
})
</script>

@ -26,7 +26,8 @@
% conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
% c = conn.cursor()
% wanted = c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'").fetchone()
% wanted_series = c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'").fetchone()
% wanted_movies = c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'").fetchone()
<div id="divmenu" class="ui container">
<div class="ui grid">
@ -55,11 +56,12 @@
</a>
<a class="item" href="{{base_url}}wanted">
<i class="warning sign icon">
% if wanted[0] > 0:
<div class="floating ui tiny yellow label">
{{wanted[0]}}
<div class="floating ui tiny yellow label" style="left:90% !important;top:0.5em !important;">
{{wanted_series[0]}}
</div>
<div class="floating ui tiny green label" style="left:90% !important;top:3em !important;">
{{wanted_movies[0]}}
</div>
% end
</i>
Wanted
</a>

@ -47,6 +47,7 @@
padding-left: 2em;
padding-right: 2em;
padding-bottom: 1em;
text-color: black;
}
.ui.basic.button:hover, .ui.basic.buttons .button:hover {
background: transparent !important;
@ -75,7 +76,7 @@
<div style='padding-left: 2em; padding-right: 2em;' class='ui container'>
<div id="divdetails" class="ui container">
<img class="left floated ui image" 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[2]}}">
<div class="ui right floated basic icon buttons">
<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" class="ui button" data-tooltip="Download missing subtitles" data-inverted=""><i class="ui inverted huge compact search icon"></i></button>
@ -104,19 +105,65 @@
<div style='clear:both;'></div>
<div id="fondblanc" class="ui container">
<h1 class="ui header">Subtitles</h1>
<table class="ui very basic single line selectable table">
<thead>
<tr>
<th>Existing subtitles</th>
<th>Subtitles path</th>
<th>Language</th>
<th></th>
</tr>
</thead>
<tbody>
<%
subtitles_files = ast.literal_eval(str(details[9]))
if subtitles_files is not None:
for subtitles_file in subtitles_files:
%>
<tr>
<td>{{details[9]}}</td>
<td>{{path_replace(subtitles_file[1]) if subtitles_file[1] is not None else 'Video file subtitles track'}}</td>
<td><div class="ui tiny inverted label" style='background-color: #777777;'>{{pycountry.languages.lookup(str(subtitles_file[0])).name}}</div></td>
<td>
%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-moviePath="{{details[8]}}" data-subtitlesPath="{{path_replace(subtitles_file[1])}}" data-language="{{pycountry.languages.lookup(str(subtitles_file[0])).alpha_3}}" data-radarrId={{details[10]}}>
<i class="ui black delete icon"></i>
</a>
%end
</td>
</tr>
<%
end
if len(subtitles_files) == 0:
%>
<tr><td colspan="3">No subtitles detected for this movie.</td></tr>
<%
end
end
%>
</tbody>
</table>
<%
missing_subs_languages = ast.literal_eval(str(details[11]))
missing_subs_languages_list = []
if missing_subs_languages is not None:
%>
<table class="ui very basic single line selectable table">
<thead>
<tr>
<th>Missing subtitles</th>
</tr>
</thead>
</table>
<%
for missing_subs_language in missing_subs_languages:
%>
<a class="get_subtitle ui small blue label" data-moviePath="{{details[8]}}" data-scenename="{{details[12]}}" data-language="{{pycountry.languages.lookup(str(missing_subs_language)).alpha_3}}" data-hi="{{details[4]}}" data-radarrId={{details[10]}}>
{{pycountry.languages.lookup(str(missing_subs_language)).name}}
<i style="margin-left:3px; margin-right:0px" class="search icon"></i>
</a>
<%
end
end
%>
</div>
</div>
</div>
@ -192,15 +239,14 @@
$('.remove_subtitles').click(function(){
var values = {
episodePath: $(this).attr("data-episodePath"),
moviePath: $(this).attr("data-moviePath"),
language: $(this).attr("data-language"),
subtitlesPath: $(this).attr("data-subtitlesPath"),
sonarrmovieId: $(this).attr("data-sonarrmovieId"),
sonarrEpisodeId: $(this).attr("data-sonarrEpisodeId"),
radarrId: $(this).attr("data-radarrId"),
tmdbid: {{tmdbid}}
};
$.ajax({
url: "{{base_url}}remove_subtitles",
url: "{{base_url}}remove_subtitles_movie",
type: "POST",
dataType: "json",
data: values
@ -215,16 +261,15 @@
$('.get_subtitle').click(function(){
var values = {
episodePath: $(this).attr("data-episodePath"),
moviePath: $(this).attr("data-moviePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
sonarrmovieId: $(this).attr("data-sonarrmovieId"),
sonarrEpisodeId: $(this).attr("data-sonarrEpisodeId"),
radarrId: $(this).attr("data-radarrId"),
tmdbid: {{tmdbid}}
};
$.ajax({
url: "{{base_url}}get_subtitle",
url: "{{base_url}}get_subtitle_movie",
type: "POST",
dataType: "json",
data: values

@ -0,0 +1,181 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Movies Editor - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 2em 3em 2em 3em;
}
#tablemovies {
padding-top: 1em;
}
#divdetails {
min-height: 250px;
}
#bottommenu {
background-color: #333333;
box-shadow: 0 0 10px 1px #333;
padding: 10px;
}
#bottomform {
width: 100%;
padding-left: 8em;
margin-bottom: -1em !important;
}
</style>
</head>
<body>
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
% include('menu.tpl')
<div id="fondblanc" class="ui container">
<table id="tablemovies" class="ui very basic selectable sortable table">
<thead>
<tr>
<th class="no-sort collapsing">
<div class="ui checkbox">
<input id='selectall' type="checkbox">
<label></label>
</div>
</th>
<th class="sorted ascending">Name</th>
<th>Audio language</th>
<th>Subtitles languages</th>
<th>Hearing-impaired</th>
</tr>
</thead>
<tbody>
%import ast
%import os
%for row in rows:
<tr class="selectable">
<td class="collapsing">
<div class="ui checkbox">
<input id='{{row[5]}}' type="checkbox" class="selected">
<label></label>
</div>
</td>
<td><a href="{{base_url}}episodes/{{row[5]}}">{{row[1]}}</a></td>
<td>{{row[7]}}</td>
<td>
%subs_languages = ast.literal_eval(str(row[3]))
%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[4] == None else row[4]}}</td>
</tr>
%end
</tbody>
</table>
</div>
<div id='bottommenu' class="ui inverted bottom fixed menu">
<form id='bottomform' action="{{base_url}}edit_movieseditor" method="POST" class="ui form">
<input type="hidden" name="movies" id="checked" />
<div class="fields">
<div class="eight wide field">
<label style='color: white;'>Subtitles languages</label>
<select name="languages" {{!'multiple="" ' if single_language == 'False' else ''}}class="select ui disabled selection dropdown">
<option value="">No change</option>
<option value="None">None</option>
%for language in languages:
<option value="{{language[0]}}">{{language[1]}}</option>
%end
</select>
</div>
<div class="field">
<label style='color: white;'>Hearing-impaired</label>
<select name="hearing_impaired" class="select ui disabled selection dropdown">
<option value="">No change</option>
<option value="True">True</option>
<option value="False">False</option>
</select>
</div>
<div class='field'>
<label style='color: white;'><span id='count'>0</span> movies selected</label>
<button type="submit" id="save" name="save" value="save" class="ui disabled blue approve button">Save</button>
</div>
</div>
</form>
</div>
% include('footer.tpl')
<br><br><br><br>
</body>
</html>
<script>
if (sessionStorage.scrolly) {
$(window).scrollTop(sessionStorage.scrolly);
sessionStorage.clear();
}
$('table').tablesort();
$('a, button').click(function(){
$('#loader').addClass('active');
})
$('.modal')
.modal({
autofocus: false
})
;
$('.selected').change(function() {
$("#count").text($('.selected:checked').length);
if ( $('.selected:checked').length > 0 ) {
$('.select').removeClass('disabled');
$('#save').removeClass('disabled');
}
else {
$('.select').addClass('disabled');
$('#save').addClass('disabled');
}
var result = [];
$('.selected:checked').each(function(i){
result.push($(this).attr('id'));
});
$("#checked").val(result);
});
$('#selectall').change(function() {
if ( $('#selectall').is(":checked") ) {
$('.selected').prop('checked', true).change();
}
else {
$('.selected').prop('checked', false).change();
}
});
$('.select').dropdown();
</script>

@ -14,7 +14,7 @@
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Bazarr</title>
<title>Series - Bazarr</title>
<style>
body {

@ -822,9 +822,11 @@
$('.submit').addClass('disabled');
},
onFailure: function(){
$('.submit').addClass('disabled');
return false;
},
onSuccess: function(){
$('.submit').removeClass('disabled');
$('#loader').addClass('active');
}
})

@ -27,10 +27,10 @@
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 2em 3em 2em 3em;
padding: 1em;
}
#tablehistory {
padding-top: 2em;
#logs {
margin-top: 4em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
@ -40,79 +40,41 @@
</style>
</head>
<body>
%import ast
%import pycountry
% import os
% import sqlite3
% conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
% c = conn.cursor()
% wanted_series = c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'").fetchone()
% wanted_movies = c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'").fetchone()
% c.close()
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
% include('menu.tpl')
<div id="fondblanc" class="ui container">
<div class="ui right floated basic buttons">
<button id="wanted_search_missing_subtitles" class="ui button"><i class="download icon"></i>Download wanted subtitles</button>
<div class="ui top attached tabular menu">
<a id="series_tab" class="tabs item active" data-tab="series">Series
<div class="ui tiny yellow label">
{{wanted_series[0]}}
</div>
</a>
<a id="movies_tab" class="tabs item" data-tab="movies">Movies
<div class="ui tiny green label">
{{wanted_movies[0]}}
</div>
</a>
</div>
<div class="ui bottom attached tab segment" data-tab="series">
<div class="content">
<div id="content_series"></div>
</div>
</div>
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th>Series</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Missing subtitles</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%for row in rows:
<tr class="selectable">
<td><a href="{{base_url}}episodes/{{row[4]}}">{{row[0]}}</a></td>
<td class="collapsing">
<%episode = row[1].split('x')%>
{{episode[0] + 'x' + episode[1].zfill(2)}}
</td>
<td>{{row[2]}}</td>
<td>
%missing_languages = ast.literal_eval(row[3])
%if missing_languages is not None:
%for language in missing_languages:
<a data-episodePath="{{row[5]}}" data-sceneName="{{row[8]}}" data-language="{{pycountry.languages.lookup(str(language)).alpha_3}}" data-hi="{{row[6]}}" data-sonarrSeriesId={{row[4]}} data-sonarrEpisodeId={{row[7]}} class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0px" class="search icon"></i>
</a>
%end
%end
</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == "1":
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == "1":
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{missing_count}}</div>
<div class="ui bottom attached tab segment" data-tab="movies">
<div class="content">
<div id="content_movies"></div>
</div>
</div>
</div>
@ -122,44 +84,43 @@
<script>
$('a, button').click(function(){
$('#loader').addClass('active');
})
$('.menu .item')
.tab()
;
$('.fast.backward').click(function(){
location.href="?page=1";
})
$('.backward:not(.fast)').click(function(){
location.href="?page={{int(page)-1}}";
})
$('.forward:not(.fast)').click(function(){
location.href="?page={{int(page)+1}}";
})
$('.fast.forward').click(function(){
location.href="?page={{int(max_page)}}";
$('#series_tab').click(function() {
loadURLseries(1);
})
$('#wanted_search_missing_subtitles').click(function(){
window.location = '{{base_url}}wanted_search_missing_subtitles';
$('#movies_tab').click(function() {
loadURLmovies(1);
})
$('.get_subtitle').click(function(){
var values = {
episodePath: $(this).attr("data-episodePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
sonarrSeriesId: $(this).attr("data-sonarrSeriesId"),
sonarrEpisodeId: $(this).attr("data-sonarrEpisodeId")
};
$('#loader').addClass('active');
$.ajax({
url: "{{base_url}}get_subtitle",
type: "POST",
dataType: "json",
data: values
}).always(function () {
window.location.reload();
});
function loadURLseries(page) {
$.ajax({
url: "{{base_url}}wantedseries?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_series").html(data);
});
}
function loadURLmovies(page) {
$.ajax({
url: "{{base_url}}wantedmovies?page=" + page,
beforeSend: function() { $('#loader').addClass('active'); },
complete: function() { $('#loader').removeClass('active'); },
cache: false
}).done(function(data) {
$("#content_movies").html(data);
});
}
$('a:not(.tabs), button:not(.cancel, #download_log)').click(function(){
$('#loader').addClass('active');
})
$( "#series_tab" ).trigger( "click" );
</script>

@ -0,0 +1,160 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Wanted - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 2em 3em 2em 3em;
}
#tablehistory {
padding-top: 2em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
</style>
</head>
<body>
%import ast
%import pycountry
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
<div class="ui container">
<div class="ui right floated basic buttons">
<button id="wanted_search_missing_subtitles" class="ui button"><i class="download icon"></i>Download wanted movies subtitles</button>
</div>
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th>Movies</th>
<th>Missing subtitles</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%if len(rows) == 0:
<tr>
<td colspan="2">No missing movie subtitles.</td>
</tr>
%end
%for row in rows:
<tr class="selectable">
<td><a href="{{base_url}}movie/{{row[2]}}">{{row[0]}}</a></td>
<td>
%missing_languages = ast.literal_eval(row[1])
%if missing_languages is not None:
%for language in missing_languages:
<a data-moviePath="{{row[3]}}" data-sceneName="{{row[5]}}" data-language="{{pycountry.languages.lookup(str(language)).alpha_3}}" data-hi="{{row[4]}}" data-radarrId={{row[2]}} class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0px" class="search icon"></i>
</a>
%end
%end
</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == "1":
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == "1":
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{missing_count}}</div>
</div>
</div>
</div>
</body>
</html>
<script>
$('a, button').click(function(){
$('#loader').addClass('active');
})
$('.fast.backward').click(function(){
loadURLmovies(1);
})
$('.backward:not(.fast)').click(function(){
loadURLmovies({{int(page)-1}});
})
$('.forward:not(.fast)').click(function(){
loadURLmovies({{int(page)+1}});
})
$('.fast.forward').click(function(){
loadURLmovies({{int(max_page)}});
})
$('#wanted_search_missing_subtitles').click(function(){
window.location = '{{base_url}}wanted_search_missing_subtitles_movies';
})
$('.get_subtitle').click(function(){
var values = {
moviePath: $(this).attr("data-moviePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
radarrId: $(this).attr("data-radarrId")
};
$('#loader').addClass('active');
$.ajax({
url: "{{base_url}}get_subtitle_movie",
type: "POST",
dataType: "json",
data: values
}).always(function () {
window.location.reload();
});
})
</script>

@ -0,0 +1,168 @@
<html>
<head>
<!DOCTYPE html>
<script src="{{base_url}}static/jquery/jquery-latest.min.js"></script>
<script src="{{base_url}}static/semantic/semantic.min.js"></script>
<script src="{{base_url}}static/jquery/tablesort.js"></script>
<link rel="stylesheet" href="{{base_url}}static/semantic/semantic.min.css">
<link rel="apple-touch-icon" sizes="120x120" href="{{base_url}}static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{base_url}}static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{base_url}}static/favicon-16x16.png">
<link rel="manifest" href="{{base_url}}static/manifest.json">
<link rel="mask-icon" href="{{base_url}}static/safari-pinned-tab.svg" color="#5bbad5">
<link rel="shortcut icon" href="{{base_url}}static/favicon.ico">
<meta name="msapplication-config" content="{{base_url}}static/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<title>Wanted - Bazarr</title>
<style>
body {
background-color: #272727;
}
#fondblanc {
background-color: #ffffff;
border-radius: 0px;
box-shadow: 0px 0px 5px 5px #ffffff;
margin-top: 32px;
margin-bottom: 3em;
padding: 2em 3em 2em 3em;
}
#tablehistory {
padding-top: 2em;
}
.fast.backward, .backward, .forward, .fast.forward {
cursor: pointer;
}
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
</style>
</head>
<body>
%import ast
%import pycountry
<div id='loader' class="ui page dimmer">
<div class="ui indeterminate text loader">Loading...</div>
</div>
<div class="ui container">
<div class="ui right floated basic buttons">
<button id="wanted_search_missing_subtitles" class="ui button"><i class="download icon"></i>Download wanted series subtitles</button>
</div>
<table id="tablehistory" class="ui very basic selectable table">
<thead>
<tr>
<th>Series</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Missing subtitles</th>
</tr>
</thead>
<tbody>
%import time
%import pretty
%if len(rows) == 0:
<tr>
<td colspan="4">No missing episode subtitles.</td>
</tr>
%end
%for row in rows:
<tr class="selectable">
<td><a href="{{base_url}}episodes/{{row[4]}}">{{row[0]}}</a></td>
<td class="collapsing">
<%episode = row[1].split('x')%>
{{episode[0] + 'x' + episode[1].zfill(2)}}
</td>
<td>{{row[2]}}</td>
<td>
%missing_languages = ast.literal_eval(row[3])
%if missing_languages is not None:
%for language in missing_languages:
<a data-episodePath="{{row[5]}}" data-sceneName="{{row[8]}}" data-language="{{pycountry.languages.lookup(str(language)).alpha_3}}" data-hi="{{row[6]}}" data-sonarrSeriesId={{row[4]}} data-sonarrEpisodeId={{row[7]}} class="get_subtitle ui tiny label">
{{language}}
<i style="margin-left:3px; margin-right:0px" class="search icon"></i>
</a>
%end
%end
</td>
</tr>
%end
</tbody>
</table>
<div class="ui grid">
<div class="three column row">
<div class="column"></div>
<div class="center aligned column">
<i class="\\
%if page == "1":
disabled\\
%end
fast backward icon"></i>
<i class="\\
%if page == "1":
disabled\\
%end
backward icon"></i>
{{page}} / {{max_page}}
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
forward icon"></i>
<i class="\\
%if int(page) == int(max_page):
disabled\\
%end
fast forward icon"></i>
</div>
<div class="right floated right aligned column">Total records: {{missing_count}}</div>
</div>
</div>
</div>
</body>
</html>
<script>
$('a, button').click(function(){
$('#loader').addClass('active');
})
$('.fast.backward').click(function(){
loadURLseries(1);
})
$('.backward:not(.fast)').click(function(){
loadURLseries({{int(page)-1}});
})
$('.forward:not(.fast)').click(function(){
loadURLseries({{int(page)+1}});
})
$('.fast.forward').click(function(){
loadURLseries({{int(max_page)}});
})
$('#wanted_search_missing_subtitles').click(function(){
window.location = '{{base_url}}wanted_search_missing_subtitles';
})
$('.get_subtitle').click(function(){
var values = {
episodePath: $(this).attr("data-episodePath"),
sceneName: $(this).attr("data-sceneName"),
language: $(this).attr("data-language"),
hi: $(this).attr("data-hi"),
sonarrSeriesId: $(this).attr("data-sonarrSeriesId"),
sonarrEpisodeId: $(this).attr("data-sonarrEpisodeId")
};
$('#loader').addClass('active');
$.ajax({
url: "{{base_url}}get_subtitle",
type: "POST",
dataType: "json",
data: values
}).always(function () {
window.location.reload();
});
})
</script>
Loading…
Cancel
Save