mirror of
https://github.com/morpheus65535/bazarr.git
synced 2025-04-24 06:37:16 -04:00
Ongoing development
This commit is contained in:
parent
9b96ec0f99
commit
e236fc7a67
17 changed files with 1381 additions and 368 deletions
206
bazarr.py
206
bazarr.py
|
@ -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>
|
199
views/historymovies.tpl
Normal file
199
views/historymovies.tpl
Normal file
|
@ -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>
|
214
views/historyseries.tpl
Normal file
214
views/historyseries.tpl
Normal file
|
@ -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
|
||||
|
|
181
views/movieseditor.tpl
Normal file
181
views/movieseditor.tpl
Normal file
|
@ -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');
|
||||
}
|
||||
})
|
||||
|
|
173
views/wanted.tpl
173
views/wanted.tpl
|
@ -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>
|
||||
<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="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>
|
||||
|
@ -122,44 +84,43 @@
|
|||
|
||||
|
||||
<script>
|
||||
$('a, button').click(function(){
|
||||
$('.menu .item')
|
||||
.tab()
|
||||
;
|
||||
|
||||
$('#series_tab').click(function() {
|
||||
loadURLseries(1);
|
||||
})
|
||||
|
||||
$('#movies_tab').click(function() {
|
||||
loadURLmovies(1);
|
||||
})
|
||||
|
||||
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');
|
||||
})
|
||||
|
||||
$('.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)}}";
|
||||
})
|
||||
|
||||
$('#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();
|
||||
});
|
||||
})
|
||||
$( "#series_tab" ).trigger( "click" );
|
||||
</script>
|
160
views/wantedmovies.tpl
Normal file
160
views/wantedmovies.tpl
Normal file
|
@ -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>
|
168
views/wantedseries.tpl
Normal file
168
views/wantedseries.tpl
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue