mirror of https://github.com/morpheus65535/bazarr
Continuing development
This commit is contained in:
parent
1568d0e363
commit
546c3ac066
127
bazarr.py
127
bazarr.py
|
@ -17,6 +17,8 @@ from init_db import *
|
|||
from get_languages import *
|
||||
from get_providers import *
|
||||
|
||||
from get_series import *
|
||||
from get_episodes import *
|
||||
from get_general_settings import *
|
||||
from get_sonarr_settings import *
|
||||
from list_subtitles import *
|
||||
|
@ -74,18 +76,28 @@ def edit_series(no):
|
|||
|
||||
redirect('/')
|
||||
|
||||
@route('/update_series')
|
||||
def update_series_list():
|
||||
update_series()
|
||||
|
||||
redirect('/')
|
||||
|
||||
@route('/update_all_episodes')
|
||||
def update_all_episodes_list():
|
||||
update_all_episodes()
|
||||
|
||||
redirect('/')
|
||||
|
||||
@route('/episodes/<no:int>', method='GET')
|
||||
def episodes(no):
|
||||
conn = sqlite3.connect('bazarr.db')
|
||||
conn.create_function("path_substitution", 1, path_replace)
|
||||
conn.create_function("missing_subtitles", 1, list_missing_subtitles)
|
||||
c = conn.cursor()
|
||||
|
||||
series_details = []
|
||||
series_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired FROM table_shows WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchone()
|
||||
|
||||
sqlite3.enable_callback_tracebacks(True)
|
||||
episodes = c.execute("SELECT title, path_substitution(path), season, episode, subtitles, sonarrSeriesId, missing_subtitles(path), sonarrEpisodeId FROM table_episodes WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchall()
|
||||
episodes = c.execute("SELECT title, path_substitution(path), season, episode, subtitles, sonarrSeriesId, missing_subtitles, sonarrEpisodeId FROM table_episodes WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchall()
|
||||
episodes = reversed(sorted(episodes, key=operator.itemgetter(2)))
|
||||
seasons_list = []
|
||||
for key,season in itertools.groupby(episodes,operator.itemgetter(2)):
|
||||
|
@ -98,11 +110,41 @@ def episodes(no):
|
|||
def history():
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
c.execute("SELECT table_history.action, table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_history.timestamp, table_history.description, table_history.sonarrSeriesId FROM table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId ORDER BY id DESC LIMIT 15")
|
||||
|
||||
c.execute("SELECT COUNT(*) FROM table_history")
|
||||
row_count = c.fetchone()
|
||||
row_count = row_count[0]
|
||||
page = request.GET.page
|
||||
if page == "":
|
||||
page = "1"
|
||||
offset = (int(page) - 1) * 15
|
||||
max_page = (row_count / 15) + 1
|
||||
|
||||
c.execute("SELECT table_history.action, table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_history.timestamp, table_history.description, table_history.sonarrSeriesId FROM table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId ORDER BY id DESC LIMIT 15 OFFSET ?", (offset,))
|
||||
data = c.fetchall()
|
||||
data = reversed(sorted(data, key=operator.itemgetter(4)))
|
||||
c.close()
|
||||
return template('history', rows=data)
|
||||
return template('history', rows=data, row_count=row_count, page=page, max_page=max_page)
|
||||
|
||||
@route('/wanted')
|
||||
def wanted():
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
db.create_function("path_substitution", 1, path_replace)
|
||||
c = db.cursor()
|
||||
|
||||
c.execute("SELECT COUNT(*) FROM table_episodes 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 = (missing_count / 15) + 1
|
||||
|
||||
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 FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]' LIMIT 15 OFFSET ?", (offset,))
|
||||
data = c.fetchall()
|
||||
c.close()
|
||||
return template('wanted', rows=data, missing_count=missing_count, page=page, max_page=max_page)
|
||||
|
||||
@route('/settings')
|
||||
def settings():
|
||||
|
@ -121,27 +163,41 @@ def settings():
|
|||
|
||||
@route('/save_settings', method='POST')
|
||||
def save_settings():
|
||||
lang = request.forms.getall('languages')
|
||||
if len(lang) > 0:
|
||||
if lang[0] == '':
|
||||
lang = None
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
lang = None
|
||||
hi = request.forms.get('hearing_impaired')
|
||||
|
||||
if hi == "on":
|
||||
hi = "True"
|
||||
else:
|
||||
hi = "False"
|
||||
|
||||
conn = sqlite3.connect('bazarr.db')
|
||||
c = conn.cursor()
|
||||
c.execute("UPDATE table_shows SET languages = ?, hearing_impaired = ? WHERE tvdbId LIKE ?", (str(lang), hi, no))
|
||||
c = conn.cursor()
|
||||
|
||||
settings_general_ip = request.forms.get('settings_general_ip')
|
||||
settings_general_port = request.forms.get('settings_general_port')
|
||||
settings_general_baseurl = request.forms.get('settings_general_baseurl')
|
||||
settings_general_sourcepath = request.forms.getall('settings_general_sourcepath')
|
||||
settings_general_destpath = request.forms.getall('settings_general_destpath')
|
||||
settings_general_pathmapping = []
|
||||
settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)])
|
||||
c.execute("UPDATE table_settings_general SET ip = ?, port = ?, base_url = ?, path_mapping = ?", (settings_general_ip, settings_general_port, settings_general_baseurl, str(settings_general_pathmapping)))
|
||||
|
||||
settings_sonarr_ip = request.forms.get('settings_sonarr_ip')
|
||||
settings_sonarr_port = request.forms.get('settings_sonarr_port')
|
||||
settings_sonarr_baseurl = request.forms.get('settings_sonarr_baseurl')
|
||||
settings_sonarr_ssl = request.forms.get('settings_sonarr_ssl')
|
||||
if settings_sonarr_ssl is None:
|
||||
settings_sonarr_ssl = 'False'
|
||||
else:
|
||||
settings_sonarr_ssl = 'True'
|
||||
settings_sonarr_apikey = request.forms.get('settings_sonarr_apikey')
|
||||
c.execute("UPDATE table_settings_sonarr SET ip = ?, port = ?, base_url = ?, ssl = ?, apikey = ?", (settings_sonarr_ip, settings_sonarr_port, settings_sonarr_baseurl, settings_sonarr_ssl, settings_sonarr_apikey))
|
||||
|
||||
settings_subliminal_providers = request.forms.getall('settings_subliminal_providers')
|
||||
c.execute("UPDATE table_settings_providers SET enabled = 0")
|
||||
for item in settings_subliminal_providers:
|
||||
c.execute("UPDATE table_settings_providers SET enabled = '1' WHERE name = ?", (item,))
|
||||
settings_subliminal_languages = request.forms.getall('settings_subliminal_languages')
|
||||
c.execute("UPDATE table_settings_languages SET enabled = 0")
|
||||
for item in settings_subliminal_languages:
|
||||
c.execute("UPDATE table_settings_languages SET enabled = '1' WHERE code2 = ?", (item,))
|
||||
|
||||
conn.commit()
|
||||
c.close()
|
||||
|
||||
|
||||
redirect('/settings')
|
||||
|
||||
@route('/system')
|
||||
|
@ -168,22 +224,37 @@ def remove_subtitles():
|
|||
except OSError:
|
||||
pass
|
||||
store_subtitles(episodePath)
|
||||
list_missing_subtitles()
|
||||
redirect('/episodes/' + sonarrSeriesId)
|
||||
|
||||
@route('/get_subtitle', method='GET')
|
||||
def get_subtitle():
|
||||
ref = request.environ['HTTP_REFERER']
|
||||
|
||||
episodePath = request.GET.episodePath
|
||||
language = request.GET.language
|
||||
hi = request.GET.hi
|
||||
sonarrSeriesId = request.GET.sonarrSeriesId
|
||||
sonarrEpisodeId = request.GET.sonarrEpisodeId
|
||||
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
c.execute("SELECT name FROM table_settings_providers WHERE enabled = 1")
|
||||
providers = c.fetchall()
|
||||
c.close()
|
||||
|
||||
providers_list = []
|
||||
for provider in providers:
|
||||
providers_list.append(provider[0])
|
||||
|
||||
try:
|
||||
result = download_subtitle(episodePath, language, hi, None)
|
||||
history_log(1, sonarrSeriesId, sonarrEpisodeId, result)
|
||||
store_subtitles(episodePath)
|
||||
redirect('/episodes/' + sonarrSeriesId)
|
||||
result = download_subtitle(episodePath, language, hi, providers_list)
|
||||
if result is not None:
|
||||
history_log(1, sonarrSeriesId, sonarrEpisodeId, result)
|
||||
store_subtitles(episodePath)
|
||||
list_missing_subtitles()
|
||||
redirect(ref)
|
||||
except OSError:
|
||||
redirect('/episodes/' + sonarrSeriesId + '?error=2')
|
||||
redirect(ref + '?error=2')
|
||||
|
||||
run(host=ip, port=port, server='waitress')
|
||||
|
|
|
@ -3,44 +3,46 @@ import requests
|
|||
|
||||
from list_subtitles import *
|
||||
|
||||
# Open database connection
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
def update_all_episodes():
|
||||
# Open database connection
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
|
||||
# Get Sonarr API URL from database config table
|
||||
c.execute('''SELECT * FROM table_settings_sonarr''')
|
||||
config_sonarr = c.fetchone()
|
||||
if config_sonarr[3] == 1:
|
||||
protocol_sonarr = "https"
|
||||
else:
|
||||
protocol_sonarr = "http"
|
||||
if config_sonarr[2] == "":
|
||||
base_url_sonarr = ""
|
||||
else:
|
||||
base_url_sonarr = "/" + config_sonarr[2].strip("/")
|
||||
# Get Sonarr API URL from database config table
|
||||
c.execute('''SELECT * FROM table_settings_sonarr''')
|
||||
config_sonarr = c.fetchone()
|
||||
if config_sonarr[3] == 1:
|
||||
protocol_sonarr = "https"
|
||||
else:
|
||||
protocol_sonarr = "http"
|
||||
if config_sonarr[2] == "":
|
||||
base_url_sonarr = ""
|
||||
else:
|
||||
base_url_sonarr = "/" + config_sonarr[2].strip("/")
|
||||
|
||||
# Get sonarrId for each series from database
|
||||
c.execute("SELECT sonarrSeriesId FROM table_shows")
|
||||
seriesIdList = c.fetchall()
|
||||
for seriesId in seriesIdList:
|
||||
# Get episodes data for a series from Sonarr
|
||||
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + config_sonarr[4]
|
||||
r = requests.get(url_sonarr_api_episode)
|
||||
for episode in r.json():
|
||||
if episode['hasFile']:
|
||||
try:
|
||||
c.execute('''INSERT INTO table_episodes(sonarrSeriesId, sonarrEpisodeId, title, path, season, episode) VALUES (?, ?, ?, ?, ?, ?)''', (episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber']))
|
||||
except sqlite3.Error:
|
||||
test = c.execute('''UPDATE table_episodes SET sonarrSeriesId = ?, sonarrEpisodeId = ?, title = ?, path = ?, season = ?, episode = ? WHERE path = ?''', (episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], episode['episodeFile']['path']))
|
||||
else:
|
||||
continue
|
||||
continue
|
||||
# Get sonarrId for each series from database
|
||||
c.execute("SELECT sonarrSeriesId FROM table_shows")
|
||||
seriesIdList = c.fetchall()
|
||||
for seriesId in seriesIdList:
|
||||
# Get episodes data for a series from Sonarr
|
||||
url_sonarr_api_episode = protocol_sonarr + "://" + config_sonarr[0] + ":" + str(config_sonarr[1]) + base_url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + config_sonarr[4]
|
||||
r = requests.get(url_sonarr_api_episode)
|
||||
for episode in r.json():
|
||||
if episode['hasFile']:
|
||||
try:
|
||||
c.execute('''INSERT INTO table_episodes(sonarrSeriesId, sonarrEpisodeId, title, path, season, episode) VALUES (?, ?, ?, ?, ?, ?)''', (episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber']))
|
||||
except sqlite3.Error:
|
||||
test = c.execute('''UPDATE table_episodes SET sonarrSeriesId = ?, sonarrEpisodeId = ?, title = ?, path = ?, season = ?, episode = ? WHERE path = ?''', (episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], episode['episodeFile']['path']))
|
||||
else:
|
||||
continue
|
||||
continue
|
||||
|
||||
# Commit changes to database table
|
||||
db.commit()
|
||||
# Commit changes to database table
|
||||
db.commit()
|
||||
|
||||
# Close database connection
|
||||
c.close()
|
||||
|
||||
# Store substitles from episodes we've just added
|
||||
new_scan_subtitles()
|
||||
# Close database connection
|
||||
c.close()
|
||||
|
||||
# Store substitles from episodes we've just added
|
||||
new_scan_subtitles()
|
||||
list_missing_subtitles()
|
||||
|
|
|
@ -4,56 +4,57 @@ import requests
|
|||
|
||||
from get_sonarr_settings import *
|
||||
|
||||
# Open database connection
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
def update_series():
|
||||
# Open database connection
|
||||
db = sqlite3.connect('bazarr.db')
|
||||
c = db.cursor()
|
||||
|
||||
# Get shows data from Sonarr
|
||||
url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr
|
||||
# Get shows data from Sonarr
|
||||
url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr
|
||||
|
||||
r = requests.get(url_sonarr_api_series)
|
||||
shows_list = []
|
||||
r = requests.get(url_sonarr_api_series)
|
||||
shows_list = []
|
||||
|
||||
# Get current shows in DB
|
||||
current_shows_db = c.execute('SELECT tvdbId FROM table_shows').fetchall()
|
||||
current_shows_db_list = [x[0] for x in current_shows_db]
|
||||
current_shows_sonarr = []
|
||||
# Get current shows in DB
|
||||
current_shows_db = c.execute('SELECT tvdbId FROM table_shows').fetchall()
|
||||
current_shows_db_list = [x[0] for x in current_shows_db]
|
||||
current_shows_sonarr = []
|
||||
|
||||
# Parsing data returned from Sonarr
|
||||
for show in r.json():
|
||||
try:
|
||||
overview = unicode(show['overview'])
|
||||
except:
|
||||
overview = ""
|
||||
try:
|
||||
poster_big = show['images'][2]['url'].split('?')[0]
|
||||
poster = os.path.splitext(poster_big)[0] + '-250' + os.path.splitext(poster_big)[1]
|
||||
except:
|
||||
poster = ""
|
||||
try:
|
||||
fanart = show['images'][0]['url'].split('?')[0]
|
||||
except:
|
||||
fanart = ""
|
||||
# Parsing data returned from Sonarr
|
||||
for show in r.json():
|
||||
try:
|
||||
overview = unicode(show['overview'])
|
||||
except:
|
||||
overview = ""
|
||||
try:
|
||||
poster_big = show['images'][2]['url'].split('?')[0]
|
||||
poster = os.path.splitext(poster_big)[0] + '-250' + os.path.splitext(poster_big)[1]
|
||||
except:
|
||||
poster = ""
|
||||
try:
|
||||
fanart = show['images'][0]['url'].split('?')[0]
|
||||
except:
|
||||
fanart = ""
|
||||
|
||||
# Add shows in Sonarr to current shows list
|
||||
current_shows_sonarr.append(show['tvdbId'])
|
||||
# Add shows in Sonarr to current shows list
|
||||
current_shows_sonarr.append(show['tvdbId'])
|
||||
|
||||
# Update or insert shows list in database table
|
||||
try:
|
||||
c.execute('''UPDATE table_shows SET title = ?, path = ?, tvdbId = ?, sonarrSeriesId = ?, overview = ?, poster = ?, fanart = ? WHERE tvdbid = ?''', (show["title"],show["path"],show["tvdbId"],show["id"],overview,poster,fanart,show["tvdbId"]))
|
||||
except:
|
||||
print show["title"]
|
||||
c.execute('''INSERT INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart) VALUES (?,?,?,(SELECT languages FROM table_shows WHERE tvdbId = ?),(SELECT `hearing_impaired` FROM table_shows WHERE tvdbId = ?), ?, ?, ?, ?)''', (show["title"],show["path"],show["tvdbId"],show["tvdbId"],show["tvdbId"],show["id"],overview,poster,fanart))
|
||||
# Update or insert shows list in database table
|
||||
try:
|
||||
c.execute('''UPDATE table_shows SET title = ?, path = ?, tvdbId = ?, sonarrSeriesId = ?, overview = ?, poster = ?, fanart = ? WHERE tvdbid = ?''', (show["title"],show["path"],show["tvdbId"],show["id"],overview,poster,fanart,show["tvdbId"]))
|
||||
except:
|
||||
print show["title"]
|
||||
c.execute('''INSERT INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart) VALUES (?,?,?,(SELECT languages FROM table_shows WHERE tvdbId = ?),(SELECT `hearing_impaired` FROM table_shows WHERE tvdbId = ?), ?, ?, ?, ?)''', (show["title"],show["path"],show["tvdbId"],show["tvdbId"],show["tvdbId"],show["id"],overview,poster,fanart))
|
||||
|
||||
# Delete shows not in Sonarr anymore
|
||||
deleted_items = []
|
||||
for item in current_shows_db_list:
|
||||
if item not in current_shows_sonarr:
|
||||
deleted_items.append(tuple([item]))
|
||||
c.executemany('DELETE FROM table_shows WHERE tvdbId = ?',deleted_items)
|
||||
# Delete shows not in Sonarr anymore
|
||||
deleted_items = []
|
||||
for item in current_shows_db_list:
|
||||
if item not in current_shows_sonarr:
|
||||
deleted_items.append(tuple([item]))
|
||||
c.executemany('DELETE FROM table_shows WHERE tvdbId = ?',deleted_items)
|
||||
|
||||
# Commit changes to database table
|
||||
db.commit()
|
||||
# Commit changes to database table
|
||||
db.commit()
|
||||
|
||||
# Close database connection
|
||||
db.close()
|
||||
# Close database connection
|
||||
db.close()
|
||||
|
|
|
@ -9,11 +9,14 @@ region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'})
|
|||
def download_subtitle(path, language, hi, providers):
|
||||
video = scan_video(path)
|
||||
best_subtitles = download_best_subtitles([video], {Language(language)}, providers=providers, hearing_impaired=hi)
|
||||
best_subtitle = best_subtitles[video][0]
|
||||
try:
|
||||
best_subtitle = best_subtitles[video][0]
|
||||
|
||||
result = save_subtitles(video, [best_subtitle])
|
||||
downloaded_provider = str(result[0]).strip('<>').split(' ')[0][:-8]
|
||||
downloaded_language = pycountry.languages.lookup(str(str(result[0]).strip('<>').split(' ')[2].strip('[]'))).name
|
||||
message = downloaded_language + " subtitles downloaded from " + downloaded_provider + "."
|
||||
result = save_subtitles(video, [best_subtitle])
|
||||
downloaded_provider = str(result[0]).strip('<>').split(' ')[0][:-8]
|
||||
downloaded_language = pycountry.languages.lookup(str(str(result[0]).strip('<>').split(' ')[2].strip('[]'))).name
|
||||
message = downloaded_language + " subtitles downloaded from " + downloaded_provider + "."
|
||||
|
||||
return message
|
||||
return message
|
||||
except:
|
||||
return None
|
||||
|
|
|
@ -65,37 +65,52 @@ def store_subtitles(file):
|
|||
|
||||
return actual_subtitles
|
||||
|
||||
def list_missing_subtitles(file):
|
||||
def list_missing_subtitles():
|
||||
conn_db = sqlite3.connect('bazarr.db')
|
||||
c_db = conn_db.cursor()
|
||||
actual_subtitles_long = c_db.execute("SELECT sonarrSeriesId, subtitles FROM table_episodes WHERE path = ?", (file,)).fetchone()
|
||||
desired_subtitles = c_db.execute("SELECT languages FROM table_shows WHERE sonarrSeriesId = ?", (actual_subtitles_long[0],)).fetchone()
|
||||
c_db.close()
|
||||
missing_subtitles = []
|
||||
actual_subtitles = []
|
||||
if desired_subtitles[0] == "None":
|
||||
pass
|
||||
else:
|
||||
actual_subtitles_long = ast.literal_eval(actual_subtitles_long[1])
|
||||
for actual_subtitle in actual_subtitles_long:
|
||||
actual_subtitles.append(actual_subtitle[0])
|
||||
episodes_subtitles = c_db.execute("SELECT table_episodes.sonarrEpisodeId, table_episodes.subtitles, table_shows.languages FROM table_episodes INNER JOIN table_shows on table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId").fetchall()
|
||||
|
||||
desired_subtitles = ast.literal_eval(desired_subtitles[0])
|
||||
|
||||
missing_subtitles = (list(set(desired_subtitles) - set(actual_subtitles)))
|
||||
return str(missing_subtitles)
|
||||
missing_subtitles_global = []
|
||||
|
||||
for episode_subtitles in episodes_subtitles:
|
||||
actual_subtitles = []
|
||||
desired_subtitles = []
|
||||
missing_subtitles = []
|
||||
actual_subtitles = ast.literal_eval(episode_subtitles[1])
|
||||
desired_subtitles = ast.literal_eval(episode_subtitles[2])
|
||||
actual_subtitles_list = []
|
||||
if desired_subtitles == None:
|
||||
pass
|
||||
else:
|
||||
actual_subtitles_list = []
|
||||
for item in actual_subtitles:
|
||||
actual_subtitles_list.append(item[0])
|
||||
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
|
||||
missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles[0]]))
|
||||
|
||||
c_db.executemany("UPDATE table_episodes SET missing_subtitles = ? WHERE sonarrEpisodeId = ?", (missing_subtitles_global))
|
||||
conn_db.commit()
|
||||
|
||||
c_db.close()
|
||||
|
||||
def full_scan_subtitles():
|
||||
conn_db = sqlite3.connect('bazarr.db')
|
||||
c_db = conn_db.cursor()
|
||||
c_db.execute("SELECT path FROM table_episodes").fetchall()
|
||||
episodes = c_db.execute("SELECT path FROM table_episodes").fetchall()
|
||||
c_db.close()
|
||||
|
||||
for episode in episodes:
|
||||
store_subtitles(path_replace(episode[0]))
|
||||
|
||||
def new_scan_subtitles():
|
||||
conn_db = sqlite3.connect('bazarr.db')
|
||||
c_db = conn_db.cursor()
|
||||
c_db.execute("SELECT path FROM table_episodes WHERE subtitles is null").fetchall()
|
||||
episodes = c_db.execute("SELECT path FROM table_episodes WHERE subtitles is null").fetchall()
|
||||
c_db.close()
|
||||
|
||||
for episode in episodes:
|
||||
store_subtitles(path_replace(episode[0]))
|
||||
|
||||
#full_scan_subtitles()
|
||||
#new_scan_subtitles()
|
||||
#list_missing_subtitles()
|
||||
|
|
Binary file not shown.
|
@ -26,9 +26,8 @@
|
|||
background-position:center center;
|
||||
}
|
||||
#divmenu {
|
||||
background-color: #1b1c1d;
|
||||
background-color: #272727;
|
||||
opacity: 0.9;
|
||||
border-radius: 5px;
|
||||
padding-top: 2em;
|
||||
padding-bottom: 1em;
|
||||
padding-left: 1em;
|
||||
|
@ -82,8 +81,8 @@
|
|||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div id="menu" class="ui inverted borderless labeled icon huge menu four item">
|
||||
<a href="/"><img class="logo" src="/static/logo128.png"></a>
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="item" href="/">
|
||||
<i class="play icon"></i>
|
||||
|
@ -93,6 +92,10 @@
|
|||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
|
@ -106,17 +109,12 @@
|
|||
</div>
|
||||
|
||||
<div style='padding-left: 2em; padding-right: 2em;' class='ui container'>
|
||||
<br>
|
||||
<div class="ui hidden negative message">
|
||||
<i class="close icon"></i>
|
||||
<div class="header">
|
||||
An error occured while trying to delete subtitles file from disk.
|
||||
</div>
|
||||
<p>Please try again.</p>
|
||||
</div>
|
||||
|
||||
<div id="divdetails" class="ui container">
|
||||
<img class="left floated ui image" src="/image_proxy{{details[2]}}">
|
||||
<div class="ui right floated inverted basic buttons">
|
||||
<button id="scan_disk" class="ui button"><i class="refresh icon"></i>Scan disk for subtitles</button>
|
||||
<button id="search_missing_subtitles" class="ui button"><i class="download icon"></i>Download missing subtitles</button>
|
||||
</div>
|
||||
<h2>{{details[0]}}</h2>
|
||||
<p>{{details[1]}}</p>
|
||||
</div>
|
||||
|
|
|
@ -35,10 +35,11 @@
|
|||
box-shadow: 0px 0px 5px 5px #ffffff;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
#tablehistory {
|
||||
padding: 3em;
|
||||
}
|
||||
.fast.backward, .backward, .forward, .fast.forward {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -46,7 +47,7 @@
|
|||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu four item">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="item" href="/">
|
||||
|
@ -57,6 +58,10 @@
|
|||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
|
@ -113,6 +118,35 @@
|
|||
%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>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -122,4 +156,17 @@
|
|||
$('a').click(function(){
|
||||
$('#loader').addClass('active');
|
||||
})
|
||||
|
||||
$('.fast.backward').click(function(){
|
||||
location.href="?page=1";
|
||||
})
|
||||
$('.backward').click(function(){
|
||||
location.href="?page={{int(page)-1}}";
|
||||
})
|
||||
$('.forward').click(function(){
|
||||
location.href="?page={{int(page)+1}}";
|
||||
})
|
||||
$('.fast.forward').click(function(){
|
||||
location.href="?page={{int(max_page)}}";
|
||||
})
|
||||
</script>
|
|
@ -35,9 +35,10 @@
|
|||
box-shadow: 0px 0px 5px 5px #ffffff;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 3em;
|
||||
padding: 2em 3em 2em 3em;
|
||||
}
|
||||
#tableseries {
|
||||
padding: 3em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
#divdetails {
|
||||
min-height: 250px;
|
||||
|
@ -49,7 +50,7 @@
|
|||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu four item">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="item" href="/">
|
||||
|
@ -60,6 +61,10 @@
|
|||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
|
@ -73,6 +78,11 @@
|
|||
</div>
|
||||
|
||||
<div id="fondblanc" class="ui container">
|
||||
<div class="ui basic buttons">
|
||||
<button id="update_series" class="ui button"><i class="refresh icon"></i>Update Series</button>
|
||||
<button id="update_all_episodes" class="ui button"><i class="refresh icon"></i>Update All Episodes</button>
|
||||
</div>
|
||||
|
||||
<table id="tableseries" class="ui very basic selectable sortable table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -110,7 +120,7 @@
|
|||
end
|
||||
end
|
||||
%>
|
||||
<div class="config ui inverted basic compact icon" data-tooltip="Edit series" data-inverted="" data-tvdbid="{{row[0]}}" data-title="{{row[1]}}" data-poster="{{row[6]}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{row[4]}}">
|
||||
<div class="ui inverted basic compact icon" data-tooltip="Edit series" data-inverted="" data-tvdbid="{{row[0]}}" data-title="{{row[1]}}" data-poster="{{row[6]}}" data-languages="{{!subs_languages_list}}" data-hearing-impaired="{{row[4]}}">
|
||||
<i class="ui black configure icon"></i>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -178,7 +188,7 @@
|
|||
|
||||
$('table').tablesort();
|
||||
|
||||
$('a').click(function(){
|
||||
$('a, button').click(function(){
|
||||
$('#loader').addClass('active');
|
||||
})
|
||||
|
||||
|
@ -188,6 +198,14 @@
|
|||
})
|
||||
;
|
||||
|
||||
$('#update_series').click(function(){
|
||||
window.location = '/update_series';
|
||||
})
|
||||
|
||||
$('#update_all_episodes').click(function(){
|
||||
window.location = '/update_all_episodes';
|
||||
})
|
||||
|
||||
$('.config').click(function(){
|
||||
sessionStorage.scrolly=$(window).scrollTop();
|
||||
|
||||
|
|
|
@ -44,22 +44,26 @@
|
|||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu four item">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="menu item" href="/">
|
||||
<a class="item" href="/">
|
||||
<i class="play icon"></i>
|
||||
Series
|
||||
</a>
|
||||
<a class="menu item" href="/history">
|
||||
<a class="item" href="/history">
|
||||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="menu item" href="/settings">
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
</a>
|
||||
<a class="menu item" href="/system">
|
||||
<a class="item" href="/system">
|
||||
<i class="laptop icon"></i>
|
||||
System
|
||||
</a>
|
||||
|
@ -68,206 +72,209 @@
|
|||
</div>
|
||||
|
||||
<div id="fondblanc" class="ui container">
|
||||
<form name="settings_form" id="settings_form" action="/save_settings" method="post" class="ui form">
|
||||
<div class="ui top attached tabular menu">
|
||||
<a class="item active" data-tab="general">General</a>
|
||||
<a class="item" data-tab="sonarr">Sonarr</a>
|
||||
<a class="item" data-tab="subliminal">Subliminal</a>
|
||||
</div>
|
||||
<form>
|
||||
<div class="ui bottom attached tab segment active" data-tab="general">
|
||||
<div class="ui container"><button class="ui blue right floated button">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Bazarr settings</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening IP address</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input type="text" value="{{settings_general[0]}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment active" data-tab="general">
|
||||
<div class="ui container"><button class="ui blue right floated button" type="submit" value="Submit" form="settings_form">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Bazarr settings</div>
|
||||
<div class="ui negative message">
|
||||
<p>These changes require that you restart Bazarr.</p>
|
||||
</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening IP address</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input name="settings_general_ip" type="text" value="{{settings_general[0]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening port</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input type="text" value="{{settings_general[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening port</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input name="settings_general_port" type="text" value="{{settings_general[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Base URL</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
%if settings_general[2] == None:
|
||||
% base_url = "/"
|
||||
%else:
|
||||
% base_url = settings_general[2]
|
||||
%end
|
||||
<input type="text" value="{{base_url}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Base URL</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
%if settings_general[2] == None:
|
||||
% base_url = "/"
|
||||
%else:
|
||||
% base_url = settings_general[2]
|
||||
%end
|
||||
<input name="settings_general_baseurl" type="text" value="{{base_url}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui dividing header">Remote Path Mappings</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
%import ast
|
||||
%path_substitutions = ast.literal_eval(settings_general[3])
|
||||
%for x in range(0, 5):
|
||||
% path = []
|
||||
% try:
|
||||
% path = path_substitutions[x]
|
||||
% except IndexError:
|
||||
% path = ["", ""]
|
||||
% end
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
|
||||
</div>
|
||||
<div class="four wide column">
|
||||
<div class="ui fluid input">
|
||||
<input type="text" value="{{path[0]}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="center aligned column">
|
||||
<i class="arrow circle right icon"></i>
|
||||
</div>
|
||||
<div class="four wide column">
|
||||
<div class="ui fluid input">
|
||||
<input type="text" value="{{path[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
%end
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment" data-tab="sonarr">
|
||||
<div class="ui container"><button class="ui blue right floated button">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Sonarr settings</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening IP address</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input type="text" value="{{settings_sonarr[0]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening port</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input type="text" value="{{settings_sonarr[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui dividing header">Remote Path Mappings</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
%import ast
|
||||
%path_substitutions = ast.literal_eval(settings_general[3])
|
||||
%for x in range(0, 5):
|
||||
% path = []
|
||||
% try:
|
||||
% path = path_substitutions[x]
|
||||
% except IndexError:
|
||||
% path = ["", ""]
|
||||
% end
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
|
||||
</div>
|
||||
<div class="four wide column">
|
||||
<div class="ui fluid input">
|
||||
<input name="settings_general_sourcepath" type="text" value="{{path[0]}}">
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Base URL</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input type="text" value="{{settings_sonarr[2]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>SSL enabled</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div id="sonarr_ssl_div" class="ui toggle checkbox" data-ssl={{settings_sonarr[3]}}>
|
||||
<input type="checkbox">
|
||||
<label></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>API key</label>
|
||||
</div>
|
||||
<div class="five wide column">
|
||||
<div class="ui fluid input">
|
||||
<input type="text" value="{{settings_sonarr[4]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center aligned column">
|
||||
<i class="arrow circle right icon"></i>
|
||||
</div>
|
||||
<div class="four wide column">
|
||||
<div class="ui fluid input">
|
||||
<input name="settings_general_destpath" type="text" value="{{path[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
%end
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment" data-tab="subliminal">
|
||||
<div class="ui container"><button class="ui blue right floated button">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Subtitles providers</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Enabled providers</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<select name="settings_providers" id="settings_providers" multiple="" class="ui fluid selection dropdown">
|
||||
<option value="">Providers</option>
|
||||
%enabled_providers = []
|
||||
%for provider in settings_providers:
|
||||
<option value="{{provider[0]}}">{{provider[0]}}</option>
|
||||
%if provider[1] == True:
|
||||
% enabled_providers.append(str(provider[0]))
|
||||
%end
|
||||
%end
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment" data-tab="sonarr">
|
||||
<div class="ui container"><button class="ui blue right floated button">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Sonarr settings</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening IP address</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input name="settings_sonarr_ip" type="text" value="{{settings_sonarr[0]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui dividing header">Subtitles languages</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Enabled languages</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<select name="settings_languages" id="settings_languages" multiple="" class="ui fluid selection dropdown">
|
||||
<option value="">Languages</option>
|
||||
%enabled_languages = []
|
||||
%for language in settings_languages:
|
||||
<option value="{{language[1]}}">{{language[2]}}</option>
|
||||
%if language[3] == True:
|
||||
% enabled_languages.append(str(language[1]))
|
||||
%end
|
||||
%end
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Listening port</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input name="settings_sonarr_port" type="text" value="{{settings_sonarr[1]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Base URL</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div class="ui input">
|
||||
<input name="settings_sonarr_baseurl" type="text" value="{{settings_sonarr[2]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>SSL enabled</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<div id="sonarr_ssl_div" class="ui toggle checkbox" data-ssl={{settings_sonarr[3]}}>
|
||||
<input name="settings_sonarr_ssl" type="checkbox">
|
||||
<label></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>API key</label>
|
||||
</div>
|
||||
<div class="five wide column">
|
||||
<div class="ui fluid input">
|
||||
<input name="settings_sonarr_apikey" type="text" value="{{settings_sonarr[4]}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment" data-tab="subliminal">
|
||||
<div class="ui container"><button class="ui blue right floated button">Save</button></div>
|
||||
<br>
|
||||
<div class="ui dividing header">Subtitles providers</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Enabled providers</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<select name="settings_subliminal_providers" id="settings_providers" multiple="" class="ui fluid selection dropdown">
|
||||
<option value="">Providers</option>
|
||||
%enabled_providers = []
|
||||
%for provider in settings_providers:
|
||||
<option value="{{provider[0]}}">{{provider[0]}}</option>
|
||||
%if provider[1] == True:
|
||||
% enabled_providers.append(str(provider[0]))
|
||||
%end
|
||||
%end
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui dividing header">Subtitles languages</div>
|
||||
<div class="twelve wide column">
|
||||
<div class="ui grid">
|
||||
<div class="middle aligned row">
|
||||
<div class="right aligned four wide column">
|
||||
<label>Enabled languages</label>
|
||||
</div>
|
||||
<div class="eleven wide column">
|
||||
<select name="settings_subliminal_languages" id="settings_languages" multiple="" class="ui fluid selection dropdown">
|
||||
<option value="">Languages</option>
|
||||
%enabled_languages = []
|
||||
%for language in settings_languages:
|
||||
<option value="{{language[1]}}">{{language[2]}}</option>
|
||||
%if language[3] == True:
|
||||
% enabled_languages.append(str(language[1]))
|
||||
%end
|
||||
%end
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -43,22 +43,26 @@
|
|||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu four item">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="menu item" href="/">
|
||||
<a class="item" href="/">
|
||||
<i class="play icon"></i>
|
||||
Series
|
||||
</a>
|
||||
<a class="menu item" href="/history">
|
||||
<a class="item" href="/history">
|
||||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="menu item" href="/settings">
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
</a>
|
||||
<a class="menu item" href="/system">
|
||||
<a class="item" href="/system">
|
||||
<i class="laptop icon"></i>
|
||||
System
|
||||
</a>
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
<html>
|
||||
<head>
|
||||
<!DOCTYPE html>
|
||||
<script src="/static/jquery/jquery-latest.min.js"></script>
|
||||
<script src="/static/semantic/semantic.min.js"></script>
|
||||
<script src="/static/jquery/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="/static/semantic/semantic.min.css">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
|
||||
<link rel="manifest" href="/static/manifest.json">
|
||||
<link rel="mask-icon" href="/static/safari-pinned-tab.svg" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<meta name="msapplication-config" content="/static/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<title>Wanted - Bazarr</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: #272727;
|
||||
}
|
||||
#divmenu {
|
||||
background-color: #272727;
|
||||
opacity: 0.9;
|
||||
padding-top: 2em;
|
||||
padding-bottom: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 128px;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
%import ast
|
||||
%import pycountry
|
||||
<div id='loader' class="ui page dimmer">
|
||||
<div class="ui indeterminate text loader">Loading...</div>
|
||||
</div>
|
||||
<div id="divmenu" class="ui container">
|
||||
<div style="background-color:#272727;" class="ui inverted borderless labeled icon huge menu five item">
|
||||
<a href="/"><img style="margin-right:32px;" class="logo" src="/static/logo128.png"></a>
|
||||
<div style="height:80px;" class="ui container">
|
||||
<a class="item" href="/">
|
||||
<i class="play icon"></i>
|
||||
Series
|
||||
</a>
|
||||
<a class="item" href="/history">
|
||||
<i class="wait icon"></i>
|
||||
History
|
||||
</a>
|
||||
<a class="item" href="/wanted">
|
||||
<i class="warning sign icon"></i>
|
||||
Wanted
|
||||
</a>
|
||||
<a class="item" href="/settings">
|
||||
<i class="settings icon"></i>
|
||||
Settings
|
||||
</a>
|
||||
<a class="item" href="/system">
|
||||
<i class="laptop icon"></i>
|
||||
System
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fondblanc" class="ui container">
|
||||
<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="/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 href="/get_subtitle?episodePath={{row[5]}}&language={{pycountry.languages.lookup(str(language)).alpha_3}}&hi={{row[6]}}&sonarrSeriesId={{row[4]}}&sonarrEpisodeId={{row[7]}}" class="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').click(function(){
|
||||
$('#loader').addClass('active');
|
||||
})
|
||||
|
||||
$('.fast.backward').click(function(){
|
||||
location.href="?page=1";
|
||||
})
|
||||
$('.backward').click(function(){
|
||||
location.href="?page={{int(page)-1}}";
|
||||
})
|
||||
$('.forward').click(function(){
|
||||
location.href="?page={{int(page)+1}}";
|
||||
})
|
||||
$('.fast.forward').click(function(){
|
||||
location.href="?page={{int(max_page)}}";
|
||||
})
|
||||
</script>
|
Loading…
Reference in New Issue