mirror of https://github.com/morpheus65535/bazarr
Languages profiles (#1232)
Implementing the languages profiles functionality.
This commit is contained in:
parent
240a3759cf
commit
22cd45bc41
304
bazarr/api.py
304
bazarr/api.py
|
@ -1,15 +1,12 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import os
|
|
||||||
import ast
|
import ast
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import datetime
|
|
||||||
from dateutil import rrule
|
from dateutil import rrule
|
||||||
import pretty
|
import pretty
|
||||||
import time
|
import time
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
import platform
|
import platform
|
||||||
import io
|
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -18,13 +15,13 @@ from config import settings, base_url, save_settings
|
||||||
|
|
||||||
from init import *
|
from init import *
|
||||||
import logging
|
import logging
|
||||||
from database import database, get_exclusion_clause
|
from database import database, get_exclusion_clause, get_profiles_list, get_desired_languages, get_profile_id_name, \
|
||||||
|
get_audio_profile_languages, update_profile_id_list
|
||||||
from helper import path_mappings
|
from helper import path_mappings
|
||||||
from get_languages import language_from_alpha3, language_from_alpha2, alpha2_from_alpha3, alpha2_from_language, \
|
from get_languages import language_from_alpha2, alpha3_from_alpha2
|
||||||
alpha3_from_language, alpha3_from_alpha2
|
from get_subtitle import download_subtitle, series_download_subtitles, manual_search, manual_download_subtitle, \
|
||||||
from get_subtitle import download_subtitle, series_download_subtitles, movies_download_subtitles, \
|
manual_upload_subtitle, wanted_search_missing_subtitles_series, wanted_search_missing_subtitles_movies, \
|
||||||
manual_search, manual_download_subtitle, manual_upload_subtitle, wanted_search_missing_subtitles_series, \
|
episode_download_subtitles, movies_download_subtitles
|
||||||
wanted_search_missing_subtitles_movies, episode_download_subtitles, movies_download_subtitles
|
|
||||||
from notifier import send_notifications, send_notifications_movie
|
from notifier import send_notifications, send_notifications_movie
|
||||||
from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_subtitles, movies_scan_subtitles, \
|
from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_subtitles, movies_scan_subtitles, \
|
||||||
list_missing_subtitles, list_missing_subtitles_movies
|
list_missing_subtitles, list_missing_subtitles_movies
|
||||||
|
@ -128,6 +125,12 @@ class Languages(Resource):
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
|
class LanguagesProfiles(Resource):
|
||||||
|
@authenticate
|
||||||
|
def get(self):
|
||||||
|
return jsonify(data=get_profiles_list())
|
||||||
|
|
||||||
|
|
||||||
class Notifications(Resource):
|
class Notifications(Resource):
|
||||||
@authenticate
|
@authenticate
|
||||||
def get(self):
|
def get(self):
|
||||||
|
@ -182,6 +185,40 @@ class ResetProviders(Resource):
|
||||||
class SaveSettings(Resource):
|
class SaveSettings(Resource):
|
||||||
@authenticate
|
@authenticate
|
||||||
def post(self):
|
def post(self):
|
||||||
|
languages_profiles = request.form.get('languages_profiles')
|
||||||
|
if languages_profiles:
|
||||||
|
existing_ids = database.execute('SELECT profileId FROM table_languages_profiles')
|
||||||
|
existing = [x['profileId'] for x in existing_ids]
|
||||||
|
for item in json.loads(languages_profiles):
|
||||||
|
if item['profileId'] in existing:
|
||||||
|
# Update existing profiles
|
||||||
|
database.execute('UPDATE table_languages_profiles SET name = ?, cutoff = ?, items = ? '
|
||||||
|
'WHERE profileId = ?', (item['name'],
|
||||||
|
item['cutoff'] if item['cutoff'] != '' else None,
|
||||||
|
item['items'],
|
||||||
|
item['profileId']))
|
||||||
|
existing.remove(item['profileId'])
|
||||||
|
else:
|
||||||
|
# Add new profiles
|
||||||
|
database.execute('INSERT INTO table_languages_profiles (profileId, name, cutoff, items) '
|
||||||
|
'VALUES (?, ?, ?, ?)', (item['profileId'],
|
||||||
|
item['name'],
|
||||||
|
item['cutoff'] if item['cutoff'] != '' else None,
|
||||||
|
item['items']))
|
||||||
|
for profileId in existing:
|
||||||
|
# Unassign this profileId from series and movies
|
||||||
|
database.execute('UPDATE table_shows SET profileId = null WHERE profileId = ?', (profileId,))
|
||||||
|
database.execute('UPDATE table_movies SET profileId = null WHERE profileId = ?', (profileId,))
|
||||||
|
# Remove deleted profiles
|
||||||
|
database.execute('DELETE FROM table_languages_profiles WHERE profileId = ?', (profileId,))
|
||||||
|
|
||||||
|
update_profile_id_list()
|
||||||
|
|
||||||
|
if settings.general.getboolean('use_sonarr'):
|
||||||
|
scheduler.add_job(list_missing_subtitles, kwargs={'send_event': False})
|
||||||
|
if settings.general.getboolean('use_radarr'):
|
||||||
|
scheduler.add_job(list_missing_subtitles_movies, kwargs={'send_event': False})
|
||||||
|
|
||||||
save_settings(zip(request.form.keys(), request.form.listvalues()))
|
save_settings(zip(request.form.keys(), request.form.listvalues()))
|
||||||
|
|
||||||
return '', 200
|
return '', 200
|
||||||
|
@ -283,10 +320,6 @@ class Series(Resource):
|
||||||
if seriesId:
|
if seriesId:
|
||||||
result = database.execute("SELECT * FROM table_shows WHERE sonarrSeriesId=? ORDER BY sortTitle ASC LIMIT ? "
|
result = database.execute("SELECT * FROM table_shows WHERE sonarrSeriesId=? ORDER BY sortTitle ASC LIMIT ? "
|
||||||
"OFFSET ?", (seriesId, length, start))
|
"OFFSET ?", (seriesId, length, start))
|
||||||
desired_languages = database.execute("SELECT languages FROM table_shows WHERE sonarrSeriesId=?",
|
|
||||||
(seriesId,), only_one=True)['languages']
|
|
||||||
if desired_languages == "None":
|
|
||||||
desired_languages = '[]'
|
|
||||||
else:
|
else:
|
||||||
result = database.execute("SELECT * FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?", (length, start))
|
result = database.execute("SELECT * FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?", (length, start))
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -294,11 +327,10 @@ class Series(Resource):
|
||||||
item.update({"DT_RowId": 'row_' + str(item['sonarrSeriesId'])})
|
item.update({"DT_RowId": 'row_' + str(item['sonarrSeriesId'])})
|
||||||
|
|
||||||
# Parse audio language
|
# Parse audio language
|
||||||
item.update({"audio_language": {"name": item['audio_language'],
|
item.update({"audio_language": get_audio_profile_languages(series_id=item['sonarrSeriesId'])})
|
||||||
"code2": alpha2_from_language(item['audio_language']) or None,
|
|
||||||
"code3": alpha3_from_language(item['audio_language']) or None}})
|
|
||||||
|
|
||||||
# Parse desired languages
|
# Parse desired languages
|
||||||
|
item['languages'] = str(get_desired_languages(item['profileId']))
|
||||||
if item['languages'] and item['languages'] != 'None':
|
if item['languages'] and item['languages'] != 'None':
|
||||||
item.update({"languages": ast.literal_eval(item['languages'])})
|
item.update({"languages": ast.literal_eval(item['languages'])})
|
||||||
for i, subs in enumerate(item['languages']):
|
for i, subs in enumerate(item['languages']):
|
||||||
|
@ -306,6 +338,9 @@ class Series(Resource):
|
||||||
"code2": subs,
|
"code2": subs,
|
||||||
"code3": alpha3_from_alpha2(subs)}
|
"code3": alpha3_from_alpha2(subs)}
|
||||||
|
|
||||||
|
# Parse profileId
|
||||||
|
item['profileId'] = {"id": item['profileId'], "name": get_profile_id_name(item['profileId'])}
|
||||||
|
|
||||||
# Parse alternate titles
|
# Parse alternate titles
|
||||||
if item['alternateTitles']:
|
if item['alternateTitles']:
|
||||||
item.update({"alternateTitles": ast.literal_eval(item['alternateTitles'])})
|
item.update({"alternateTitles": ast.literal_eval(item['alternateTitles'])})
|
||||||
|
@ -343,42 +378,20 @@ class Series(Resource):
|
||||||
item.update({"episodeFileCount": episodeFileCount})
|
item.update({"episodeFileCount": episodeFileCount})
|
||||||
|
|
||||||
# Add the series desired subtitles language code2
|
# Add the series desired subtitles language code2
|
||||||
try:
|
item.update({"desired_languages": get_desired_languages(item['profileId']['id'])})
|
||||||
item.update({"desired_languages": desired_languages})
|
|
||||||
except NameError:
|
|
||||||
pass
|
|
||||||
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
||||||
|
|
||||||
@authenticate
|
@authenticate
|
||||||
def post(self):
|
def post(self):
|
||||||
seriesId = request.args.get('seriesid')
|
seriesId = request.args.get('seriesid')
|
||||||
|
|
||||||
lang = request.form.getlist('languages')
|
languages_profile = request.form.get('languages')
|
||||||
if len(lang) > 0:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
lang = 'None'
|
|
||||||
|
|
||||||
single_language = settings.general.getboolean('single_language')
|
if languages_profile == 'None':
|
||||||
if single_language:
|
languages_profile = None
|
||||||
if str(lang) == "['None']":
|
|
||||||
lang = 'None'
|
|
||||||
else:
|
|
||||||
lang = str(lang)
|
|
||||||
else:
|
|
||||||
if str(lang) == "['']":
|
|
||||||
lang = '[]'
|
|
||||||
|
|
||||||
hi = request.form.get('hi')
|
database.execute("UPDATE table_shows SET profileId=? WHERE sonarrSeriesId=?", (languages_profile, seriesId))
|
||||||
forced = request.form.get('forced')
|
|
||||||
|
|
||||||
if hi == "on":
|
|
||||||
hi = "True"
|
|
||||||
else:
|
|
||||||
hi = "False"
|
|
||||||
|
|
||||||
result = database.execute("UPDATE table_shows SET languages=?, hearing_impaired=?, forced=? WHERE "
|
|
||||||
"sonarrSeriesId=?", (str(lang), hi, forced, seriesId))
|
|
||||||
|
|
||||||
list_missing_subtitles(no=seriesId)
|
list_missing_subtitles(no=seriesId)
|
||||||
|
|
||||||
|
@ -392,7 +405,7 @@ class SeriesEditor(Resource):
|
||||||
def get(self, **kwargs):
|
def get(self, **kwargs):
|
||||||
draw = request.args.get('draw')
|
draw = request.args.get('draw')
|
||||||
|
|
||||||
result = database.execute("SELECT sonarrSeriesId, title, languages, hearing_impaired, forced, audio_language "
|
result = database.execute("SELECT sonarrSeriesId, title, audio_language, profileId "
|
||||||
"FROM table_shows ORDER BY sortTitle")
|
"FROM table_shows ORDER BY sortTitle")
|
||||||
|
|
||||||
row_count = len(result)
|
row_count = len(result)
|
||||||
|
@ -402,11 +415,10 @@ class SeriesEditor(Resource):
|
||||||
item.update({"DT_RowId": 'row_' + str(item['sonarrSeriesId'])})
|
item.update({"DT_RowId": 'row_' + str(item['sonarrSeriesId'])})
|
||||||
|
|
||||||
# Parse audio language
|
# Parse audio language
|
||||||
item.update({"audio_language": {"name": item['audio_language'],
|
item.update({"audio_language": get_audio_profile_languages(series_id=item['sonarrSeriesId'])})
|
||||||
"code2": alpha2_from_language(item['audio_language']) or None,
|
|
||||||
"code3": alpha3_from_language(item['audio_language']) or None}})
|
|
||||||
|
|
||||||
# Parse desired languages
|
# Parse desired languages
|
||||||
|
item['languages'] = str(get_desired_languages(item['profileId']))
|
||||||
if item['languages'] and item['languages'] != 'None':
|
if item['languages'] and item['languages'] != 'None':
|
||||||
item.update({"languages": ast.literal_eval(item['languages'])})
|
item.update({"languages": ast.literal_eval(item['languages'])})
|
||||||
for i, subs in enumerate(item['languages']):
|
for i, subs in enumerate(item['languages']):
|
||||||
|
@ -414,43 +426,30 @@ class SeriesEditor(Resource):
|
||||||
"code2": subs,
|
"code2": subs,
|
||||||
"code3": alpha3_from_alpha2(subs)}
|
"code3": alpha3_from_alpha2(subs)}
|
||||||
|
|
||||||
|
# Parse profileId
|
||||||
|
item['profileId'] = {"id": item['profileId'], "name": get_profile_id_name(item['profileId'])}
|
||||||
|
|
||||||
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
||||||
|
|
||||||
|
|
||||||
class SeriesEditSave(Resource):
|
class SeriesEditSave(Resource):
|
||||||
@authenticate
|
@authenticate
|
||||||
def post(self):
|
def post(self):
|
||||||
lang = request.form.getlist('languages[]')
|
lang = request.form.get('languages')
|
||||||
hi = request.form.getlist('hi[]')
|
|
||||||
forced = request.form.getlist('forced[]')
|
|
||||||
|
|
||||||
if lang == ['None']:
|
if lang == 'None':
|
||||||
lang = 'None'
|
lang = None
|
||||||
|
|
||||||
seriesIdList = []
|
seriesIdList = []
|
||||||
seriesidLangList = []
|
seriesidLangList = []
|
||||||
seriesidHiList = []
|
|
||||||
seriesidForcedList = []
|
|
||||||
for item in request.form.getlist('seriesid[]'):
|
for item in request.form.getlist('seriesid[]'):
|
||||||
seriesid = item.lstrip('row_')
|
seriesid = item.lstrip('row_')
|
||||||
seriesIdList.append(seriesid)
|
seriesIdList.append(seriesid)
|
||||||
if len(lang):
|
seriesidLangList.append([lang, seriesid])
|
||||||
seriesidLangList.append([str(lang), seriesid])
|
|
||||||
if len(hi):
|
|
||||||
seriesidHiList.append([hi[0], seriesid])
|
|
||||||
if len(forced):
|
|
||||||
seriesidForcedList.append([forced[0], seriesid])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(lang):
|
database.execute("UPDATE table_shows SET profileId=? WHERE sonarrSeriesId=?", seriesidLangList,
|
||||||
database.execute("UPDATE table_shows SET languages=? WHERE sonarrSeriesId=?", seriesidLangList,
|
execute_many=True)
|
||||||
execute_many=True)
|
|
||||||
if len(hi):
|
|
||||||
database.execute("UPDATE table_shows SET hearing_impaired=? WHERE sonarrSeriesId=?", seriesidHiList,
|
|
||||||
execute_many=True)
|
|
||||||
if len(forced):
|
|
||||||
database.execute("UPDATE table_shows SET forced=? WHERE sonarrSeriesId=?", seriesidForcedList,
|
|
||||||
execute_many=True)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -476,27 +475,22 @@ class Episodes(Resource):
|
||||||
(seriesId,), only_one=True)['count']
|
(seriesId,), only_one=True)['count']
|
||||||
if episodeId:
|
if episodeId:
|
||||||
result = database.execute("SELECT * FROM table_episodes WHERE sonarrEpisodeId=?", (episodeId,))
|
result = database.execute("SELECT * FROM table_episodes WHERE sonarrEpisodeId=?", (episodeId,))
|
||||||
desired_languages = database.execute("SELECT languages FROM table_shows WHERE sonarrSeriesId=?",
|
|
||||||
(seriesId,), only_one=True)['languages']
|
|
||||||
if desired_languages == "None":
|
|
||||||
desired_languages = '[]'
|
|
||||||
elif seriesId:
|
elif seriesId:
|
||||||
result = database.execute("SELECT * FROM table_episodes WHERE sonarrSeriesId=? ORDER BY season DESC, "
|
result = database.execute("SELECT * FROM table_episodes WHERE sonarrSeriesId=? ORDER BY season DESC, "
|
||||||
"episode DESC", (seriesId,))
|
"episode DESC", (seriesId,))
|
||||||
desired_languages = database.execute("SELECT languages FROM table_shows WHERE sonarrSeriesId=?",
|
|
||||||
(seriesId,), only_one=True)['languages']
|
|
||||||
if desired_languages == "None":
|
|
||||||
desired_languages = '[]'
|
|
||||||
else:
|
else:
|
||||||
return "Series ID not provided", 400
|
return "Series ID not provided", 400
|
||||||
|
|
||||||
|
profileId = database.execute("SELECT profileId FROM table_shows WHERE sonarrSeriesId = ?", (seriesId,),
|
||||||
|
only_one=True)['profileId']
|
||||||
|
desired_languages = str(get_desired_languages(profileId))
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
# Add Datatables rowId
|
# Add Datatables rowId
|
||||||
item.update({"DT_RowId": 'row_' + str(item['sonarrEpisodeId'])})
|
item.update({"DT_RowId": 'row_' + str(item['sonarrEpisodeId'])})
|
||||||
|
|
||||||
# Parse audio language
|
# Parse audio language
|
||||||
item.update({"audio_language": {"name": item['audio_language'],
|
item.update({"audio_language": get_audio_profile_languages(episode_id=item['sonarrEpisodeId'])})
|
||||||
"code2": alpha2_from_language(item['audio_language']) or None,
|
|
||||||
"code3": alpha3_from_language(item['audio_language']) or None}})
|
|
||||||
|
|
||||||
# Parse subtitles
|
# Parse subtitles
|
||||||
if item['subtitles']:
|
if item['subtitles']:
|
||||||
|
@ -616,8 +610,12 @@ class EpisodesSubtitlesDownload(Resource):
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
audio_language = database.execute("SELECT audio_language FROM table_episodes WHERE sonarrEpisodeId=?",
|
|
||||||
(sonarrEpisodeId,), only_one=True)['audio_language']
|
audio_language_list = get_audio_profile_languages(episode_id=sonarrEpisodeId)
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = download_subtitle(episodePath, language, audio_language, hi, forced, providers_list, providers_auth, sceneName,
|
result = download_subtitle(episodePath, language, audio_language, hi, forced, providers_list, providers_auth, sceneName,
|
||||||
|
@ -659,14 +657,12 @@ class EpisodesSubtitlesManualSearch(Resource):
|
||||||
sceneName = request.form.get('sceneName')
|
sceneName = request.form.get('sceneName')
|
||||||
if sceneName == "null":
|
if sceneName == "null":
|
||||||
sceneName = "None"
|
sceneName = "None"
|
||||||
language = request.form.get('language')
|
profileId = request.form.get('profileId')
|
||||||
hi = request.form.get('hi').capitalize()
|
|
||||||
forced = request.form.get('forced').capitalize()
|
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
|
|
||||||
data = manual_search(episodePath, language, hi, forced, providers_list, providers_auth, sceneName, title,
|
data = manual_search(episodePath, profileId, providers_list, providers_auth, sceneName, title,
|
||||||
'series')
|
'series')
|
||||||
if not data:
|
if not data:
|
||||||
data = []
|
data = []
|
||||||
|
@ -690,8 +686,12 @@ class EpisodesSubtitlesManualDownload(Resource):
|
||||||
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
|
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
audio_language = database.execute("SELECT audio_language FROM table_episodes WHERE sonarrEpisodeId=?",
|
|
||||||
(sonarrEpisodeId,), only_one=True)['audio_language']
|
audio_language_list = get_audio_profile_languages(episode_id=sonarrEpisodeId)
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = manual_download_subtitle(episodePath, language, audio_language, hi, forced, subtitle,
|
result = manual_download_subtitle(episodePath, language, audio_language, hi, forced, subtitle,
|
||||||
|
@ -887,10 +887,6 @@ class Movies(Resource):
|
||||||
if moviesId:
|
if moviesId:
|
||||||
result = database.execute("SELECT * FROM table_movies WHERE radarrId=? ORDER BY sortTitle ASC LIMIT ? "
|
result = database.execute("SELECT * FROM table_movies WHERE radarrId=? ORDER BY sortTitle ASC LIMIT ? "
|
||||||
"OFFSET ?", (moviesId, length, start))
|
"OFFSET ?", (moviesId, length, start))
|
||||||
desired_languages = database.execute("SELECT languages FROM table_movies WHERE radarrId=?",
|
|
||||||
(moviesId,), only_one=True)['languages']
|
|
||||||
if desired_languages == "None":
|
|
||||||
desired_languages = '[]'
|
|
||||||
else:
|
else:
|
||||||
result = database.execute("SELECT * FROM table_movies ORDER BY sortTitle ASC LIMIT ? OFFSET ?",
|
result = database.execute("SELECT * FROM table_movies ORDER BY sortTitle ASC LIMIT ? OFFSET ?",
|
||||||
(length, start))
|
(length, start))
|
||||||
|
@ -899,11 +895,10 @@ class Movies(Resource):
|
||||||
item.update({"DT_RowId": 'row_' + str(item['radarrId'])})
|
item.update({"DT_RowId": 'row_' + str(item['radarrId'])})
|
||||||
|
|
||||||
# Parse audio language
|
# Parse audio language
|
||||||
item.update({"audio_language": {"name": item['audio_language'],
|
item.update({"audio_language": get_audio_profile_languages(movie_id=item['radarrId'])})
|
||||||
"code2": alpha2_from_language(item['audio_language']) or None,
|
|
||||||
"code3": alpha3_from_language(item['audio_language']) or None}})
|
|
||||||
|
|
||||||
# Parse desired languages
|
# Parse desired languages
|
||||||
|
item['languages'] = str(get_desired_languages(item['profileId']))
|
||||||
if item['languages'] and item['languages'] != 'None':
|
if item['languages'] and item['languages'] != 'None':
|
||||||
item.update({"languages": ast.literal_eval(item['languages'])})
|
item.update({"languages": ast.literal_eval(item['languages'])})
|
||||||
for i, subs in enumerate(item['languages']):
|
for i, subs in enumerate(item['languages']):
|
||||||
|
@ -911,6 +906,9 @@ class Movies(Resource):
|
||||||
"code2": subs,
|
"code2": subs,
|
||||||
"code3": alpha3_from_alpha2(subs)}
|
"code3": alpha3_from_alpha2(subs)}
|
||||||
|
|
||||||
|
# Parse profileId
|
||||||
|
item['profileId'] = {"id": item['profileId'], "name": get_profile_id_name(item['profileId'])}
|
||||||
|
|
||||||
# Parse alternate titles
|
# Parse alternate titles
|
||||||
if item['alternativeTitles']:
|
if item['alternativeTitles']:
|
||||||
item.update({"alternativeTitles": ast.literal_eval(item['alternativeTitles'])})
|
item.update({"alternativeTitles": ast.literal_eval(item['alternativeTitles'])})
|
||||||
|
@ -975,42 +973,20 @@ class Movies(Resource):
|
||||||
item.update({"exist": os.path.isfile(mapped_path)})
|
item.update({"exist": os.path.isfile(mapped_path)})
|
||||||
|
|
||||||
# Add the movie desired subtitles language code2
|
# Add the movie desired subtitles language code2
|
||||||
try:
|
item.update({"desired_languages": get_desired_languages(item['profileId']['id'])})
|
||||||
item.update({"desired_languages": desired_languages})
|
|
||||||
except NameError:
|
|
||||||
pass
|
|
||||||
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
||||||
|
|
||||||
@authenticate
|
@authenticate
|
||||||
def post(self):
|
def post(self):
|
||||||
radarrId = request.args.get('radarrid')
|
radarrId = request.args.get('radarrid')
|
||||||
|
|
||||||
lang = request.form.getlist('languages')
|
languages_profile = request.form.get('languages')
|
||||||
if len(lang) > 0:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
lang = 'None'
|
|
||||||
|
|
||||||
single_language = settings.general.getboolean('single_language')
|
if languages_profile == 'None':
|
||||||
if single_language:
|
languages_profile = None
|
||||||
if str(lang) == "['None']":
|
|
||||||
lang = 'None'
|
|
||||||
else:
|
|
||||||
lang = str(lang)
|
|
||||||
else:
|
|
||||||
if str(lang) == "['']":
|
|
||||||
lang = '[]'
|
|
||||||
|
|
||||||
hi = request.form.get('hi')
|
database.execute("UPDATE table_movies SET profileId=? WHERE radarrId=?", (languages_profile, radarrId))
|
||||||
forced = request.form.get('forced')
|
|
||||||
|
|
||||||
if hi == "on":
|
|
||||||
hi = "True"
|
|
||||||
else:
|
|
||||||
hi = "False"
|
|
||||||
|
|
||||||
result = database.execute("UPDATE table_movies SET languages=?, hearing_impaired=?, forced=? WHERE "
|
|
||||||
"radarrId=?", (str(lang), hi, forced, radarrId))
|
|
||||||
|
|
||||||
list_missing_subtitles_movies(no=radarrId)
|
list_missing_subtitles_movies(no=radarrId)
|
||||||
|
|
||||||
|
@ -1024,7 +1000,7 @@ class MoviesEditor(Resource):
|
||||||
def get(self):
|
def get(self):
|
||||||
draw = request.args.get('draw')
|
draw = request.args.get('draw')
|
||||||
|
|
||||||
result = database.execute("SELECT radarrId, title, languages, hearing_impaired, forced, audio_language "
|
result = database.execute("SELECT radarrId, title, audio_language, profileId "
|
||||||
"FROM table_movies ORDER BY sortTitle")
|
"FROM table_movies ORDER BY sortTitle")
|
||||||
|
|
||||||
row_count = len(result)
|
row_count = len(result)
|
||||||
|
@ -1034,11 +1010,10 @@ class MoviesEditor(Resource):
|
||||||
item.update({"DT_RowId": 'row_' + str(item['radarrId'])})
|
item.update({"DT_RowId": 'row_' + str(item['radarrId'])})
|
||||||
|
|
||||||
# Parse audio language
|
# Parse audio language
|
||||||
item.update({"audio_language": {"name": item['audio_language'],
|
item.update({"audio_language": get_audio_profile_languages(movie_id=item['radarrId'])})
|
||||||
"code2": alpha2_from_language(item['audio_language']) or None,
|
|
||||||
"code3": alpha3_from_language(item['audio_language']) or None}})
|
|
||||||
|
|
||||||
# Parse desired languages
|
# Parse desired languages
|
||||||
|
item['languages'] = str(get_desired_languages(item['profileId']))
|
||||||
if item['languages'] and item['languages'] != 'None':
|
if item['languages'] and item['languages'] != 'None':
|
||||||
item.update({"languages": ast.literal_eval(item['languages'])})
|
item.update({"languages": ast.literal_eval(item['languages'])})
|
||||||
for i, subs in enumerate(item['languages']):
|
for i, subs in enumerate(item['languages']):
|
||||||
|
@ -1046,42 +1021,29 @@ class MoviesEditor(Resource):
|
||||||
"code2": subs,
|
"code2": subs,
|
||||||
"code3": alpha3_from_alpha2(subs)}
|
"code3": alpha3_from_alpha2(subs)}
|
||||||
|
|
||||||
|
# Parse profileId
|
||||||
|
item['profileId'] = {"id": item['profileId'], "name": get_profile_id_name(item['profileId'])}
|
||||||
|
|
||||||
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
return jsonify(draw=draw, recordsTotal=row_count, recordsFiltered=row_count, data=result)
|
||||||
|
|
||||||
|
|
||||||
class MoviesEditSave(Resource):
|
class MoviesEditSave(Resource):
|
||||||
@authenticate
|
@authenticate
|
||||||
def post(self):
|
def post(self):
|
||||||
lang = request.form.getlist('languages[]')
|
lang = request.form.get('languages')
|
||||||
hi = request.form.getlist('hi[]')
|
|
||||||
forced = request.form.getlist('forced[]')
|
|
||||||
|
|
||||||
if lang == ['None']:
|
if lang == 'None':
|
||||||
lang = 'None'
|
lang = None
|
||||||
|
|
||||||
radarrIdList = []
|
radarrIdList = []
|
||||||
radarrIdLangList = []
|
radarrIdLangList = []
|
||||||
radarrIdHiList = []
|
|
||||||
radarrIdForcedList = []
|
|
||||||
for item in request.form.getlist('radarrid[]'):
|
for item in request.form.getlist('radarrid[]'):
|
||||||
radarrid = item.lstrip('row_')
|
radarrid = item.lstrip('row_')
|
||||||
radarrIdList.append(radarrid)
|
radarrIdList.append(radarrid)
|
||||||
if len(lang):
|
radarrIdLangList.append([lang, radarrid])
|
||||||
radarrIdLangList.append([str(lang), radarrid])
|
|
||||||
if len(hi):
|
|
||||||
radarrIdHiList.append([hi[0], radarrid])
|
|
||||||
if len(forced):
|
|
||||||
radarrIdForcedList.append([forced[0], radarrid])
|
|
||||||
try:
|
try:
|
||||||
if len(lang):
|
database.execute("UPDATE table_movies SET profileId=? WHERE radarrId=?", radarrIdLangList,
|
||||||
database.execute("UPDATE table_movies SET languages=? WHERE radarrId=?", radarrIdLangList,
|
execute_many=True)
|
||||||
execute_many=True)
|
|
||||||
if len(hi):
|
|
||||||
database.execute("UPDATE table_movies SET hearing_impaired=? WHERE radarrId=?", radarrIdHiList,
|
|
||||||
execute_many=True)
|
|
||||||
if len(forced):
|
|
||||||
database.execute("UPDATE table_movies SET forced=? WHERE radarrId=?", radarrIdForcedList,
|
|
||||||
execute_many=True)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -1131,8 +1093,12 @@ class MovieSubtitlesDownload(Resource):
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
audio_language = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,),
|
|
||||||
only_one=True)['audio_language']
|
audio_language_list = get_audio_profile_languages(movie_id=radarrId)
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = download_subtitle(moviePath, language, audio_language, hi, forced, providers_list,
|
result = download_subtitle(moviePath, language, audio_language, hi, forced, providers_list,
|
||||||
|
@ -1174,14 +1140,12 @@ class MovieSubtitlesManualSearch(Resource):
|
||||||
sceneName = request.form.get('sceneName')
|
sceneName = request.form.get('sceneName')
|
||||||
if sceneName == "null":
|
if sceneName == "null":
|
||||||
sceneName = "None"
|
sceneName = "None"
|
||||||
language = request.form.get('language')
|
profileId = request.form.get('profileId')
|
||||||
hi = request.form.get('hi').capitalize()
|
|
||||||
forced = request.form.get('forced').capitalize()
|
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
|
|
||||||
data = manual_search(moviePath, language, hi, forced, providers_list, providers_auth, sceneName, title,
|
data = manual_search(moviePath, profileId, providers_list, providers_auth, sceneName, title,
|
||||||
'movie')
|
'movie')
|
||||||
if not data:
|
if not data:
|
||||||
data = []
|
data = []
|
||||||
|
@ -1204,8 +1168,12 @@ class MovieSubtitlesManualDownload(Resource):
|
||||||
radarrId = request.form.get('radarrId')
|
radarrId = request.form.get('radarrId')
|
||||||
title = request.form.get('title')
|
title = request.form.get('title')
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
audio_language = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?", (radarrId,),
|
|
||||||
only_one=True)['audio_language']
|
audio_language_list = get_audio_profile_languages(movie_id=radarrId)
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = manual_download_subtitle(moviePath, language, audio_language, hi, forced, subtitle,
|
result = manual_download_subtitle(moviePath, language, audio_language, hi, forced, subtitle,
|
||||||
|
@ -1412,8 +1380,7 @@ class HistorySeries(Resource):
|
||||||
"table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId INNER JOIN table_shows on "
|
"table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId INNER JOIN table_shows on "
|
||||||
"table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE action IN (" +
|
"table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE action IN (" +
|
||||||
','.join(map(str, query_actions)) + ") AND timestamp > ? AND score is not null" +
|
','.join(map(str, query_actions)) + ") AND timestamp > ? AND score is not null" +
|
||||||
get_exclusion_clause('series') + " GROUP BY table_history.video_path, table_history.language",
|
get_exclusion_clause('series') + " GROUP BY table_history.video_path", (minimum_timestamp,))
|
||||||
(minimum_timestamp,))
|
|
||||||
|
|
||||||
for upgradable_episode in upgradable_episodes:
|
for upgradable_episode in upgradable_episodes:
|
||||||
if upgradable_episode['timestamp'] > minimum_timestamp:
|
if upgradable_episode['timestamp'] > minimum_timestamp:
|
||||||
|
@ -1433,16 +1400,16 @@ class HistorySeries(Resource):
|
||||||
"table_episodes.title as episodeTitle, table_history.timestamp, table_history.subs_id, "
|
"table_episodes.title as episodeTitle, table_history.timestamp, table_history.subs_id, "
|
||||||
"table_history.description, table_history.sonarrSeriesId, table_episodes.path, "
|
"table_history.description, table_history.sonarrSeriesId, table_episodes.path, "
|
||||||
"table_history.language, table_history.score, table_shows.tags, table_history.action, "
|
"table_history.language, table_history.score, table_shows.tags, table_history.action, "
|
||||||
"table_history.subtitles_path, table_history.sonarrEpisodeId, table_history.provider "
|
"table_history.subtitles_path, table_history.sonarrEpisodeId, table_history.provider, "
|
||||||
"FROM table_history LEFT JOIN table_shows on table_shows.sonarrSeriesId = "
|
"table_shows.seriesType FROM table_history LEFT JOIN table_shows on "
|
||||||
"table_history.sonarrSeriesId LEFT JOIN table_episodes on "
|
"table_shows.sonarrSeriesId = table_history.sonarrSeriesId LEFT JOIN table_episodes on "
|
||||||
"table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE "
|
"table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE "
|
||||||
"table_episodes.title is not NULL ORDER BY timestamp DESC LIMIT ? OFFSET ?",
|
"table_episodes.title is not NULL ORDER BY timestamp DESC LIMIT ? OFFSET ?",
|
||||||
(length, start))
|
(length, start))
|
||||||
|
|
||||||
for item in data:
|
for item in data:
|
||||||
# Mark episode as upgradable or not
|
# Mark episode as upgradable or not
|
||||||
if {"video_path": str(item['path']), "timestamp": float(item['timestamp']), "score": str(item['score']), "tags": str(item['tags']), "monitored": str(item['monitored'])} in upgradable_episodes_not_perfect:
|
if {"video_path": str(item['path']), "timestamp": float(item['timestamp']), "score": str(item['score']), "tags": str(item['tags']), "monitored": str(item['monitored']), "seriesType": str(item['seriesType'])} in upgradable_episodes_not_perfect:
|
||||||
item.update({"upgradable": True})
|
item.update({"upgradable": True})
|
||||||
else:
|
else:
|
||||||
item.update({"upgradable": False})
|
item.update({"upgradable": False})
|
||||||
|
@ -1516,8 +1483,8 @@ class HistoryMovies(Resource):
|
||||||
upgradable_movies = database.execute(
|
upgradable_movies = database.execute(
|
||||||
"SELECT video_path, MAX(timestamp) as timestamp, score, tags, monitored FROM table_history_movie "
|
"SELECT video_path, MAX(timestamp) as timestamp, score, tags, monitored FROM table_history_movie "
|
||||||
"INNER JOIN table_movies on table_movies.radarrId=table_history_movie.radarrId WHERE action IN (" +
|
"INNER JOIN table_movies on table_movies.radarrId=table_history_movie.radarrId WHERE action IN (" +
|
||||||
','.join(map(str, query_actions)) + ") AND timestamp > ? AND score is not NULL" +
|
','.join(map(str, query_actions)) + ") AND timestamp > ? AND score is not NULL" +
|
||||||
get_exclusion_clause('movie') + " GROUP BY video_path, language", (minimum_timestamp,))
|
get_exclusion_clause('movie') + " GROUP BY video_path", (minimum_timestamp,))
|
||||||
|
|
||||||
for upgradable_movie in upgradable_movies:
|
for upgradable_movie in upgradable_movies:
|
||||||
if upgradable_movie['timestamp'] > minimum_timestamp:
|
if upgradable_movie['timestamp'] > minimum_timestamp:
|
||||||
|
@ -1661,7 +1628,7 @@ class WantedSeries(Resource):
|
||||||
data = database.execute("SELECT table_shows.title as seriesTitle, table_episodes.monitored, "
|
data = database.execute("SELECT table_shows.title as seriesTitle, table_episodes.monitored, "
|
||||||
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
|
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
|
||||||
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles, "
|
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles, "
|
||||||
"table_episodes.sonarrSeriesId, table_episodes.path, table_shows.hearing_impaired, "
|
"table_episodes.sonarrSeriesId, table_episodes.path, "
|
||||||
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
||||||
"table_episodes.failedAttempts, table_shows.seriesType FROM table_episodes INNER JOIN "
|
"table_episodes.failedAttempts, table_shows.seriesType FROM table_episodes INNER JOIN "
|
||||||
"table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE "
|
"table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE "
|
||||||
|
@ -1707,7 +1674,7 @@ class WantedMovies(Resource):
|
||||||
data_count = database.execute("SELECT tags, monitored FROM table_movies WHERE missing_subtitles != '[]'" +
|
data_count = database.execute("SELECT tags, monitored FROM table_movies WHERE missing_subtitles != '[]'" +
|
||||||
get_exclusion_clause('movie'))
|
get_exclusion_clause('movie'))
|
||||||
row_count = len(data_count)
|
row_count = len(data_count)
|
||||||
data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, "
|
data = database.execute("SELECT title, missing_subtitles, radarrId, path, sceneName, "
|
||||||
"failedAttempts, tags, monitored FROM table_movies WHERE missing_subtitles != '[]'" +
|
"failedAttempts, tags, monitored FROM table_movies WHERE missing_subtitles != '[]'" +
|
||||||
get_exclusion_clause('movie') + " ORDER BY _rowid_ DESC LIMIT " + length + " OFFSET " +
|
get_exclusion_clause('movie') + " ORDER BY _rowid_ DESC LIMIT " + length + " OFFSET " +
|
||||||
start)
|
start)
|
||||||
|
@ -2002,6 +1969,7 @@ api.add_resource(BadgesSeries, '/badges_series')
|
||||||
api.add_resource(BadgesMovies, '/badges_movies')
|
api.add_resource(BadgesMovies, '/badges_movies')
|
||||||
api.add_resource(BadgesProviders, '/badges_providers')
|
api.add_resource(BadgesProviders, '/badges_providers')
|
||||||
api.add_resource(Languages, '/languages')
|
api.add_resource(Languages, '/languages')
|
||||||
|
api.add_resource(LanguagesProfiles, '/languages_profiles')
|
||||||
api.add_resource(Notifications, '/notifications')
|
api.add_resource(Notifications, '/notifications')
|
||||||
|
|
||||||
api.add_resource(Search, '/search_json')
|
api.add_resource(Search, '/search_json')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/env python
|
# coding=utf-8
|
||||||
|
|
||||||
from flask import Flask, redirect, render_template, request, url_for
|
from flask import Flask, redirect, render_template, request, url_for
|
||||||
from flask_debugtoolbar import DebugToolbarExtension
|
from flask_debugtoolbar import DebugToolbarExtension
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -30,13 +31,9 @@ defaults = {
|
||||||
'use_radarr': 'False',
|
'use_radarr': 'False',
|
||||||
'path_mappings_movie': '[]',
|
'path_mappings_movie': '[]',
|
||||||
'serie_default_enabled': 'False',
|
'serie_default_enabled': 'False',
|
||||||
'serie_default_language': '[]',
|
'serie_default_profile': '',
|
||||||
'serie_default_hi': 'False',
|
|
||||||
'serie_default_forced': 'False',
|
|
||||||
'movie_default_enabled': 'False',
|
'movie_default_enabled': 'False',
|
||||||
'movie_default_language': '[]',
|
'movie_default_profile': '',
|
||||||
'movie_default_hi': 'False',
|
|
||||||
'movie_default_forced': 'False',
|
|
||||||
'page_size': '25',
|
'page_size': '25',
|
||||||
'page_size_manual_search': '10',
|
'page_size_manual_search': '10',
|
||||||
'minimum_score_movie': '70',
|
'minimum_score_movie': '70',
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import ast
|
import ast
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
from sqlite3worker import Sqlite3Worker
|
from sqlite3worker import Sqlite3Worker
|
||||||
|
|
||||||
|
@ -9,6 +12,9 @@ from get_args import args
|
||||||
from helper import path_mappings
|
from helper import path_mappings
|
||||||
from config import settings
|
from config import settings
|
||||||
|
|
||||||
|
global profile_id_list
|
||||||
|
profile_id_list = []
|
||||||
|
|
||||||
|
|
||||||
def db_init():
|
def db_init():
|
||||||
if not os.path.exists(os.path.join(args.config_dir, 'db', 'bazarr.db')):
|
if not os.path.exists(os.path.join(args.config_dir, 'db', 'bazarr.db')):
|
||||||
|
@ -95,6 +101,7 @@ def db_upgrade():
|
||||||
['table_shows', 'tags', 'text', '[]'],
|
['table_shows', 'tags', 'text', '[]'],
|
||||||
['table_shows', 'seriesType', 'text', ''],
|
['table_shows', 'seriesType', 'text', ''],
|
||||||
['table_shows', 'imdbId', 'text', ''],
|
['table_shows', 'imdbId', 'text', ''],
|
||||||
|
['table_shows', 'profileId', 'integer'],
|
||||||
['table_episodes', 'format', 'text'],
|
['table_episodes', 'format', 'text'],
|
||||||
['table_episodes', 'resolution', 'text'],
|
['table_episodes', 'resolution', 'text'],
|
||||||
['table_episodes', 'video_codec', 'text'],
|
['table_episodes', 'video_codec', 'text'],
|
||||||
|
@ -112,6 +119,7 @@ def db_upgrade():
|
||||||
['table_movies', 'forced', 'text', 'False'],
|
['table_movies', 'forced', 'text', 'False'],
|
||||||
['table_movies', 'movie_file_id', 'integer'],
|
['table_movies', 'movie_file_id', 'integer'],
|
||||||
['table_movies', 'tags', 'text', '[]'],
|
['table_movies', 'tags', 'text', '[]'],
|
||||||
|
['table_movies', 'profileId', 'integer'],
|
||||||
['table_history', 'video_path', 'text'],
|
['table_history', 'video_path', 'text'],
|
||||||
['table_history', 'language', 'text'],
|
['table_history', 'language', 'text'],
|
||||||
['table_history', 'provider', 'text'],
|
['table_history', 'provider', 'text'],
|
||||||
|
@ -143,20 +151,61 @@ def db_upgrade():
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Fix null languages, hearing-impaired and forced for series and movies.
|
|
||||||
database.execute("UPDATE table_shows SET languages = '[]' WHERE languages is null")
|
|
||||||
database.execute("UPDATE table_shows SET hearing_impaired = 'False' WHERE hearing_impaired is null")
|
|
||||||
database.execute("UPDATE table_shows SET forced = 'False' WHERE forced is null")
|
|
||||||
database.execute("UPDATE table_movies SET languages = '[]' WHERE languages is null")
|
|
||||||
database.execute("UPDATE table_movies SET hearing_impaired = 'False' WHERE hearing_impaired is null")
|
|
||||||
database.execute("UPDATE table_movies SET forced = 'False' WHERE forced is null")
|
|
||||||
|
|
||||||
# Create blacklist tables
|
# Create blacklist tables
|
||||||
database.execute("CREATE TABLE IF NOT EXISTS table_blacklist (sonarr_series_id integer, sonarr_episode_id integer, "
|
database.execute("CREATE TABLE IF NOT EXISTS table_blacklist (sonarr_series_id integer, sonarr_episode_id integer, "
|
||||||
"timestamp integer, provider text, subs_id text, language text)")
|
"timestamp integer, provider text, subs_id text, language text)")
|
||||||
database.execute("CREATE TABLE IF NOT EXISTS table_blacklist_movie (radarr_id integer, timestamp integer, "
|
database.execute("CREATE TABLE IF NOT EXISTS table_blacklist_movie (radarr_id integer, timestamp integer, "
|
||||||
"provider text, subs_id text, language text)")
|
"provider text, subs_id text, language text)")
|
||||||
|
|
||||||
|
# Create languages profiles table and populate it
|
||||||
|
lang_table_content = database.execute("SELECT * FROM table_languages_profiles")
|
||||||
|
if isinstance(lang_table_content, list):
|
||||||
|
lang_table_exist = True
|
||||||
|
else:
|
||||||
|
lang_table_exist = False
|
||||||
|
database.execute("CREATE TABLE IF NOT EXISTS table_languages_profiles ("
|
||||||
|
"profileId INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, "
|
||||||
|
"cutoff INTEGER, items TEXT NOT NULL)")
|
||||||
|
|
||||||
|
if not lang_table_exist:
|
||||||
|
profiles_to_create = database.execute("SELECT DISTINCT languages, hearing_impaired, forced "
|
||||||
|
"FROM (SELECT languages, hearing_impaired, forced FROM table_shows "
|
||||||
|
"UNION ALL SELECT languages, hearing_impaired, forced FROM table_movies) "
|
||||||
|
"a WHERE languages NOT null and languages NOT IN ('None', '[]')")
|
||||||
|
for profile in profiles_to_create:
|
||||||
|
profile_items = []
|
||||||
|
languages_list = ast.literal_eval(profile['languages'])
|
||||||
|
for i, language in enumerate(languages_list, 1):
|
||||||
|
if profile['forced'] == 'Both':
|
||||||
|
profile_items.append({'id': i, 'language': language, 'forced': 'True',
|
||||||
|
'hi': profile['hearing_impaired'], 'audio_exclude': 'False'})
|
||||||
|
profile_items.append({'id': i, 'language': language, 'forced': 'False',
|
||||||
|
'hi': profile['hearing_impaired'], 'audio_exclude': 'False'})
|
||||||
|
else:
|
||||||
|
profile_items.append({'id': i, 'language': language, 'forced': profile['forced'],
|
||||||
|
'hi': profile['hearing_impaired'], 'audio_exclude': 'False'})
|
||||||
|
# Create profiles
|
||||||
|
new_profile_name = profile['languages'] + ' (' + profile['hearing_impaired'] + '/' + profile['forced'] + ')'
|
||||||
|
database.execute("INSERT INTO table_languages_profiles (name, cutoff, items) VALUES("
|
||||||
|
"?,null,?)", (new_profile_name, json.dumps(profile_items),))
|
||||||
|
created_profile_id = database.execute("SELECT profileId FROM table_languages_profiles WHERE name = ?",
|
||||||
|
(new_profile_name,), only_one=True)['profileId']
|
||||||
|
# Assign profiles to series and movies
|
||||||
|
database.execute("UPDATE table_shows SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND "
|
||||||
|
"forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'],
|
||||||
|
profile['forced']))
|
||||||
|
database.execute("UPDATE table_movies SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND "
|
||||||
|
"forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'],
|
||||||
|
profile['forced']))
|
||||||
|
|
||||||
|
# null languages, forced and hearing_impaired for all series and movies
|
||||||
|
database.execute("UPDATE table_shows SET languages = null, forced = null, hearing_impaired = null")
|
||||||
|
database.execute("UPDATE table_movies SET languages = null, forced = null, hearing_impaired = null")
|
||||||
|
|
||||||
|
# Force series, episodes and movies sync with Sonarr to get all the audio track from video files
|
||||||
|
# Set environment variable that is going to be use during the init process to run sync once Bazarr is ready.
|
||||||
|
os.environ['BAZARR_AUDIO_PROFILES_MIGRATION'] = '1'
|
||||||
|
|
||||||
|
|
||||||
def get_exclusion_clause(type):
|
def get_exclusion_clause(type):
|
||||||
where_clause = ''
|
where_clause = ''
|
||||||
|
@ -184,3 +233,115 @@ def get_exclusion_clause(type):
|
||||||
where_clause += ' AND table_shows.seriesType != "' + type + '"'
|
where_clause += ' AND table_shows.seriesType != "' + type + '"'
|
||||||
|
|
||||||
return where_clause
|
return where_clause
|
||||||
|
|
||||||
|
|
||||||
|
def update_profile_id_list():
|
||||||
|
global profile_id_list
|
||||||
|
profile_id_list = database.execute("SELECT profileId, name, cutoff, items FROM table_languages_profiles")
|
||||||
|
|
||||||
|
|
||||||
|
def get_profiles_list(profile_id=None):
|
||||||
|
if not len(profile_id_list):
|
||||||
|
update_profile_id_list()
|
||||||
|
|
||||||
|
if profile_id:
|
||||||
|
for profile in profile_id_list:
|
||||||
|
if profile['profileId'] == profile_id:
|
||||||
|
return profile
|
||||||
|
else:
|
||||||
|
return profile_id_list
|
||||||
|
|
||||||
|
|
||||||
|
def get_desired_languages(profile_id):
|
||||||
|
languages = []
|
||||||
|
|
||||||
|
if not len(profile_id_list):
|
||||||
|
update_profile_id_list()
|
||||||
|
|
||||||
|
if profile_id:
|
||||||
|
for profile in profile_id_list:
|
||||||
|
profileId, name, cutoff, items = profile.values()
|
||||||
|
if profileId == int(profile_id):
|
||||||
|
items_list = ast.literal_eval(items)
|
||||||
|
languages = [x['language'] for x in items_list]
|
||||||
|
break
|
||||||
|
|
||||||
|
return languages
|
||||||
|
|
||||||
|
|
||||||
|
def get_profile_id_name(profile_id):
|
||||||
|
name_from_id = None
|
||||||
|
|
||||||
|
if not len(profile_id_list):
|
||||||
|
update_profile_id_list()
|
||||||
|
|
||||||
|
if profile_id:
|
||||||
|
for profile in profile_id_list:
|
||||||
|
profileId, name, cutoff, items = profile.values()
|
||||||
|
if profileId == int(profile_id):
|
||||||
|
name_from_id = name
|
||||||
|
break
|
||||||
|
|
||||||
|
return name_from_id
|
||||||
|
|
||||||
|
|
||||||
|
def get_profile_cutoff(profile_id):
|
||||||
|
cutoff_language = None
|
||||||
|
|
||||||
|
if not len(profile_id_list):
|
||||||
|
update_profile_id_list()
|
||||||
|
|
||||||
|
if profile_id:
|
||||||
|
cutoff_language = []
|
||||||
|
for profile in profile_id_list:
|
||||||
|
profileId, name, cutoff, items = profile.values()
|
||||||
|
if cutoff:
|
||||||
|
if profileId == int(profile_id):
|
||||||
|
for item in ast.literal_eval(items):
|
||||||
|
if item['id'] == cutoff:
|
||||||
|
return [item]
|
||||||
|
elif cutoff == 65535:
|
||||||
|
cutoff_language.append(item)
|
||||||
|
|
||||||
|
if not len(cutoff_language):
|
||||||
|
cutoff_language = None
|
||||||
|
|
||||||
|
return cutoff_language
|
||||||
|
|
||||||
|
|
||||||
|
def get_audio_profile_languages(series_id=None, episode_id=None, movie_id=None):
|
||||||
|
from get_languages import alpha2_from_language, alpha3_from_language
|
||||||
|
audio_languages = []
|
||||||
|
|
||||||
|
if series_id:
|
||||||
|
audio_languages_list_str = database.execute("SELECT audio_language FROM table_shows WHERE sonarrSeriesId=?",
|
||||||
|
(series_id,), only_one=True)['audio_language']
|
||||||
|
audio_languages_list = ast.literal_eval(audio_languages_list_str)
|
||||||
|
for language in audio_languages_list:
|
||||||
|
audio_languages.append(
|
||||||
|
{"name": language,
|
||||||
|
"code2": alpha2_from_language(language) or None,
|
||||||
|
"code3": alpha3_from_language(language) or None}
|
||||||
|
)
|
||||||
|
elif episode_id:
|
||||||
|
audio_languages_list_str = database.execute("SELECT audio_language FROM table_episodes WHERE sonarrEpisodeId=?",
|
||||||
|
(episode_id,), only_one=True)['audio_language']
|
||||||
|
audio_languages_list = ast.literal_eval(audio_languages_list_str)
|
||||||
|
for language in audio_languages_list:
|
||||||
|
audio_languages.append(
|
||||||
|
{"name": language,
|
||||||
|
"code2": alpha2_from_language(language) or None,
|
||||||
|
"code3": alpha3_from_language(language) or None}
|
||||||
|
)
|
||||||
|
elif movie_id:
|
||||||
|
audio_languages_list_str = database.execute("SELECT audio_language FROM table_movies WHERE radarrId=?",
|
||||||
|
(movie_id,), only_one=True)['audio_language']
|
||||||
|
audio_languages_list = ast.literal_eval(audio_languages_list_str)
|
||||||
|
for language in audio_languages_list:
|
||||||
|
audio_languages.append(
|
||||||
|
{"name": language,
|
||||||
|
"code2": alpha2_from_language(language) or None,
|
||||||
|
"code3": alpha3_from_language(language) or None}
|
||||||
|
)
|
||||||
|
|
||||||
|
return audio_languages
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import enzyme
|
import enzyme
|
||||||
from enzyme.exceptions import MalformedMKVError
|
from enzyme.exceptions import MalformedMKVError
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from app import socketio
|
from app import socketio
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
from database import database, dict_converter, get_exclusion_clause
|
from database import database, dict_converter, get_exclusion_clause
|
||||||
|
|
||||||
from config import settings, url_sonarr
|
from config import settings, url_sonarr
|
||||||
from helper import path_mappings
|
from helper import path_mappings
|
||||||
from list_subtitles import list_missing_subtitles, store_subtitles, series_full_scan_subtitles
|
from list_subtitles import store_subtitles, series_full_scan_subtitles
|
||||||
from get_subtitle import episode_download_subtitles
|
from get_subtitle import episode_download_subtitles
|
||||||
from event_handler import event_stream
|
from event_handler import event_stream
|
||||||
|
|
||||||
|
@ -85,12 +86,12 @@ def sync_episodes():
|
||||||
videoCodec = None
|
videoCodec = None
|
||||||
audioCodec = None
|
audioCodec = None
|
||||||
|
|
||||||
audio_language = None
|
audio_language = []
|
||||||
if 'language' in episode['episodeFile'] and len(episode['episodeFile']['language']):
|
if 'language' in episode['episodeFile'] and len(episode['episodeFile']['language']):
|
||||||
item = episode['episodeFile']['language']
|
item = episode['episodeFile']['language']
|
||||||
if isinstance(item, dict):
|
if isinstance(item, dict):
|
||||||
if 'name' in item:
|
if 'name' in item:
|
||||||
audio_language = item['name']
|
audio_language.append(item['name'])
|
||||||
else:
|
else:
|
||||||
audio_language = database.execute("SELECT audio_language FROM table_shows WHERE "
|
audio_language = database.execute("SELECT audio_language FROM table_shows WHERE "
|
||||||
"sonarrSeriesId=?", (episode['seriesId'],),
|
"sonarrSeriesId=?", (episode['seriesId'],),
|
||||||
|
@ -113,7 +114,7 @@ def sync_episodes():
|
||||||
'video_codec': videoCodec,
|
'video_codec': videoCodec,
|
||||||
'audio_codec': audioCodec,
|
'audio_codec': audioCodec,
|
||||||
'episode_file_id': episode['episodeFile']['id'],
|
'episode_file_id': episode['episodeFile']['id'],
|
||||||
'audio_language': audio_language})
|
'audio_language': str(audio_language)})
|
||||||
else:
|
else:
|
||||||
episodes_to_add.append({'sonarrSeriesId': episode['seriesId'],
|
episodes_to_add.append({'sonarrSeriesId': episode['seriesId'],
|
||||||
'sonarrEpisodeId': episode['id'],
|
'sonarrEpisodeId': episode['id'],
|
||||||
|
@ -128,7 +129,7 @@ def sync_episodes():
|
||||||
'video_codec': videoCodec,
|
'video_codec': videoCodec,
|
||||||
'audio_codec': audioCodec,
|
'audio_codec': audioCodec,
|
||||||
'episode_file_id': episode['episodeFile']['id'],
|
'episode_file_id': episode['episodeFile']['id'],
|
||||||
'audio_language': audio_language})
|
'audio_language': str(audio_language)})
|
||||||
|
|
||||||
# Remove old episodes from DB
|
# Remove old episodes from DB
|
||||||
removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr))
|
removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import pycountry
|
import pycountry
|
||||||
import ast
|
|
||||||
|
|
||||||
from subzero.language import Language
|
from subzero.language import Language
|
||||||
from database import database
|
from database import database
|
||||||
|
@ -76,48 +75,5 @@ def get_language_set():
|
||||||
return language_set
|
return language_set
|
||||||
|
|
||||||
|
|
||||||
def clean_desired_languages():
|
|
||||||
from list_subtitles import list_missing_subtitles, list_missing_subtitles_movies
|
|
||||||
enabled_languages = []
|
|
||||||
enabled_languages_temp = database.execute("SELECT code2 FROM table_settings_languages WHERE enabled=1")
|
|
||||||
for language in enabled_languages_temp:
|
|
||||||
enabled_languages.append(language['code2'])
|
|
||||||
|
|
||||||
series_languages = database.execute("SELECT sonarrSeriesId, languages FROM table_shows")
|
|
||||||
movies_languages = database.execute("SELECT radarrId, languages FROM table_movies")
|
|
||||||
|
|
||||||
for item in series_languages:
|
|
||||||
if item['languages'] != 'None':
|
|
||||||
try:
|
|
||||||
languages_list = ast.literal_eval(item['languages'])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
cleaned_languages_list = []
|
|
||||||
for language in languages_list:
|
|
||||||
if language in enabled_languages:
|
|
||||||
cleaned_languages_list.append(language)
|
|
||||||
if cleaned_languages_list != languages_list:
|
|
||||||
database.execute("UPDATE table_shows SET languages=? WHERE sonarrSeriesId=?",
|
|
||||||
(str(cleaned_languages_list), item['sonarrSeriesId']))
|
|
||||||
list_missing_subtitles(no=item['sonarrSeriesId'])
|
|
||||||
|
|
||||||
for item in movies_languages:
|
|
||||||
if item['languages'] != 'None':
|
|
||||||
try:
|
|
||||||
languages_list = ast.literal_eval(item['languages'])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
cleaned_languages_list = []
|
|
||||||
for language in languages_list:
|
|
||||||
if language in enabled_languages:
|
|
||||||
cleaned_languages_list.append(language)
|
|
||||||
if cleaned_languages_list != languages_list:
|
|
||||||
database.execute("UPDATE table_movies SET languages=? WHERE radarrId=?",
|
|
||||||
(str(cleaned_languages_list), item['radarrId']))
|
|
||||||
list_missing_subtitles_movies(no=item['radarrId'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
load_language_in_db()
|
load_language_in_db()
|
||||||
|
|
|
@ -7,7 +7,7 @@ import logging
|
||||||
from config import settings, url_radarr
|
from config import settings, url_radarr
|
||||||
from helper import path_mappings
|
from helper import path_mappings
|
||||||
from utils import get_radarr_version
|
from utils import get_radarr_version
|
||||||
from list_subtitles import store_subtitles_movie, list_missing_subtitles_movies, movies_full_scan_subtitles
|
from list_subtitles import store_subtitles_movie, movies_full_scan_subtitles
|
||||||
|
|
||||||
from get_subtitle import movies_download_subtitles
|
from get_subtitle import movies_download_subtitles
|
||||||
from database import database, dict_converter, get_exclusion_clause
|
from database import database, dict_converter, get_exclusion_clause
|
||||||
|
@ -26,13 +26,11 @@ def update_movies():
|
||||||
movie_default_enabled = settings.general.getboolean('movie_default_enabled')
|
movie_default_enabled = settings.general.getboolean('movie_default_enabled')
|
||||||
|
|
||||||
if movie_default_enabled is True:
|
if movie_default_enabled is True:
|
||||||
movie_default_language = settings.general.movie_default_language
|
movie_default_profile = settings.general.movie_default_profile
|
||||||
movie_default_hi = settings.general.movie_default_hi
|
if movie_default_profile == '':
|
||||||
movie_default_forced = settings.general.movie_default_forced
|
movie_default_profile = None
|
||||||
else:
|
else:
|
||||||
movie_default_language = '[]'
|
movie_default_profile = None
|
||||||
movie_default_hi = 'False'
|
|
||||||
movie_default_forced = 'False'
|
|
||||||
|
|
||||||
if apikey_radarr is None:
|
if apikey_radarr is None:
|
||||||
pass
|
pass
|
||||||
|
@ -146,13 +144,14 @@ def update_movies():
|
||||||
videoCodec = None
|
videoCodec = None
|
||||||
audioCodec = None
|
audioCodec = None
|
||||||
|
|
||||||
audio_language = None
|
audio_language = []
|
||||||
if radarr_version.startswith('0'):
|
if radarr_version.startswith('0'):
|
||||||
if 'mediaInfo' in movie['movieFile']:
|
if 'mediaInfo' in movie['movieFile']:
|
||||||
if 'audioLanguages' in movie['movieFile']['mediaInfo']:
|
if 'audioLanguages' in movie['movieFile']['mediaInfo']:
|
||||||
audio_language_list = movie['movieFile']['mediaInfo']['audioLanguages'].split('/')
|
audio_languages_list = movie['movieFile']['mediaInfo']['audioLanguages'].split('/')
|
||||||
if len(audio_language_list):
|
if len(audio_languages_list):
|
||||||
audio_language = audio_language_list[0].strip()
|
for audio_language_list in audio_languages_list:
|
||||||
|
audio_language.append(audio_language_list.strip())
|
||||||
if not audio_language:
|
if not audio_language:
|
||||||
audio_language = profile_id_to_language(movie['qualityProfileId'], audio_profiles)
|
audio_language = profile_id_to_language(movie['qualityProfileId'], audio_profiles)
|
||||||
else:
|
else:
|
||||||
|
@ -160,8 +159,7 @@ def update_movies():
|
||||||
for item in movie['movieFile']['languages']:
|
for item in movie['movieFile']['languages']:
|
||||||
if isinstance(item, dict):
|
if isinstance(item, dict):
|
||||||
if 'name' in item:
|
if 'name' in item:
|
||||||
audio_language = item['name']
|
audio_language.append(item['name'])
|
||||||
break
|
|
||||||
|
|
||||||
tags = [d['label'] for d in tagsDict if d['id'] in movie['tags']]
|
tags = [d['label'] for d in tagsDict if d['id'] in movie['tags']]
|
||||||
|
|
||||||
|
@ -175,7 +173,7 @@ def update_movies():
|
||||||
'tmdbId': str(movie["tmdbId"]),
|
'tmdbId': str(movie["tmdbId"]),
|
||||||
'poster': poster,
|
'poster': poster,
|
||||||
'fanart': fanart,
|
'fanart': fanart,
|
||||||
'audio_language': audio_language,
|
'audio_language': str(audio_language),
|
||||||
'sceneName': sceneName,
|
'sceneName': sceneName,
|
||||||
'monitored': str(bool(movie['monitored'])),
|
'monitored': str(bool(movie['monitored'])),
|
||||||
'year': str(movie['year']),
|
'year': str(movie['year']),
|
||||||
|
@ -194,13 +192,11 @@ def update_movies():
|
||||||
'title': movie["title"],
|
'title': movie["title"],
|
||||||
'path': movie["path"] + separator + movie['movieFile']['relativePath'],
|
'path': movie["path"] + separator + movie['movieFile']['relativePath'],
|
||||||
'tmdbId': str(movie["tmdbId"]),
|
'tmdbId': str(movie["tmdbId"]),
|
||||||
'languages': movie_default_language,
|
|
||||||
'subtitles': '[]',
|
'subtitles': '[]',
|
||||||
'hearing_impaired': movie_default_hi,
|
|
||||||
'overview': overview,
|
'overview': overview,
|
||||||
'poster': poster,
|
'poster': poster,
|
||||||
'fanart': fanart,
|
'fanart': fanart,
|
||||||
'audio_language': audio_language,
|
'audio_language': str(audio_language),
|
||||||
'sceneName': sceneName,
|
'sceneName': sceneName,
|
||||||
'monitored': str(bool(movie['monitored'])),
|
'monitored': str(bool(movie['monitored'])),
|
||||||
'sortTitle': movie['sortTitle'],
|
'sortTitle': movie['sortTitle'],
|
||||||
|
@ -211,9 +207,9 @@ def update_movies():
|
||||||
'video_codec': videoCodec,
|
'video_codec': videoCodec,
|
||||||
'audio_codec': audioCodec,
|
'audio_codec': audioCodec,
|
||||||
'imdbId': imdbId,
|
'imdbId': imdbId,
|
||||||
'forced': movie_default_forced,
|
|
||||||
'movie_file_id': int(movie['movieFile']['id']),
|
'movie_file_id': int(movie['movieFile']['id']),
|
||||||
'tags': str(tags)})
|
'tags': str(tags),
|
||||||
|
'profileId': movie_default_profile})
|
||||||
else:
|
else:
|
||||||
logging.error(
|
logging.error(
|
||||||
'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator +
|
'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator +
|
||||||
|
@ -315,8 +311,10 @@ def get_profile_list():
|
||||||
|
|
||||||
def profile_id_to_language(id, profiles):
|
def profile_id_to_language(id, profiles):
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
|
profiles_to_return = []
|
||||||
if id == profile[0]:
|
if id == profile[0]:
|
||||||
return profile[1]
|
profiles_to_return.append(profile[1])
|
||||||
|
return profiles_to_return
|
||||||
|
|
||||||
|
|
||||||
def RadarrFormatAudioCodec(audioFormat, audioCodecID, audioProfile, audioAdditionalFeatures):
|
def RadarrFormatAudioCodec(audioFormat, audioCodecID, audioProfile, audioAdditionalFeatures):
|
||||||
|
|
|
@ -22,13 +22,11 @@ def update_series():
|
||||||
serie_default_enabled = settings.general.getboolean('serie_default_enabled')
|
serie_default_enabled = settings.general.getboolean('serie_default_enabled')
|
||||||
|
|
||||||
if serie_default_enabled is True:
|
if serie_default_enabled is True:
|
||||||
serie_default_language = settings.general.serie_default_language
|
serie_default_profile = settings.general.serie_default_profile
|
||||||
serie_default_hi = settings.general.serie_default_hi
|
if serie_default_profile == '':
|
||||||
serie_default_forced = settings.general.serie_default_forced
|
serie_default_profile = None
|
||||||
else:
|
else:
|
||||||
serie_default_language = '[]'
|
serie_default_profile = None
|
||||||
serie_default_hi = 'False'
|
|
||||||
serie_default_forced = 'False'
|
|
||||||
|
|
||||||
audio_profiles = get_profile_list()
|
audio_profiles = get_profile_list()
|
||||||
tagsDict = get_tags()
|
tagsDict = get_tags()
|
||||||
|
@ -76,6 +74,7 @@ def update_series():
|
||||||
if show['alternateTitles'] is not None:
|
if show['alternateTitles'] is not None:
|
||||||
alternate_titles = str([item['title'] for item in show['alternateTitles']])
|
alternate_titles = str([item['title'] for item in show['alternateTitles']])
|
||||||
|
|
||||||
|
audio_language = []
|
||||||
if sonarr_version.startswith('2'):
|
if sonarr_version.startswith('2'):
|
||||||
audio_language = profile_id_to_language(show['qualityProfileId'], audio_profiles)
|
audio_language = profile_id_to_language(show['qualityProfileId'], audio_profiles)
|
||||||
else:
|
else:
|
||||||
|
@ -96,7 +95,7 @@ def update_series():
|
||||||
'overview': overview,
|
'overview': overview,
|
||||||
'poster': poster,
|
'poster': poster,
|
||||||
'fanart': fanart,
|
'fanart': fanart,
|
||||||
'audio_language': audio_language,
|
'audio_language': str(audio_language),
|
||||||
'sortTitle': show['sortTitle'],
|
'sortTitle': show['sortTitle'],
|
||||||
'year': str(show['year']),
|
'year': str(show['year']),
|
||||||
'alternateTitles': alternate_titles,
|
'alternateTitles': alternate_titles,
|
||||||
|
@ -107,20 +106,18 @@ def update_series():
|
||||||
series_to_add.append({'title': show["title"],
|
series_to_add.append({'title': show["title"],
|
||||||
'path': show["path"],
|
'path': show["path"],
|
||||||
'tvdbId': show["tvdbId"],
|
'tvdbId': show["tvdbId"],
|
||||||
'languages': serie_default_language,
|
|
||||||
'hearing_impaired': serie_default_hi,
|
|
||||||
'sonarrSeriesId': show["id"],
|
'sonarrSeriesId': show["id"],
|
||||||
'overview': overview,
|
'overview': overview,
|
||||||
'poster': poster,
|
'poster': poster,
|
||||||
'fanart': fanart,
|
'fanart': fanart,
|
||||||
'audio_language': audio_language,
|
'audio_language': str(audio_language),
|
||||||
'sortTitle': show['sortTitle'],
|
'sortTitle': show['sortTitle'],
|
||||||
'year': str(show['year']),
|
'year': str(show['year']),
|
||||||
'alternateTitles': alternate_titles,
|
'alternateTitles': alternate_titles,
|
||||||
'forced': serie_default_forced,
|
|
||||||
'tags': str(tags),
|
'tags': str(tags),
|
||||||
'seriesType': show['seriesType'],
|
'seriesType': show['seriesType'],
|
||||||
'imdbId': imdbId})
|
'imdbId': imdbId,
|
||||||
|
'profileId': serie_default_profile})
|
||||||
|
|
||||||
# Remove old series from DB
|
# Remove old series from DB
|
||||||
removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr))
|
removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr))
|
||||||
|
@ -197,9 +194,11 @@ def get_profile_list():
|
||||||
|
|
||||||
|
|
||||||
def profile_id_to_language(id_, profiles):
|
def profile_id_to_language(id_, profiles):
|
||||||
|
profiles_to_return = []
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
if id_ == profile[0]:
|
if id_ == profile[0]:
|
||||||
return profile[1]
|
profiles_to_return.append(profile[1])
|
||||||
|
return profiles_to_return
|
||||||
|
|
||||||
|
|
||||||
def get_tags():
|
def get_tags():
|
||||||
|
|
|
@ -30,7 +30,8 @@ from get_providers import get_providers, get_providers_auth, provider_throttle,
|
||||||
from knowit import api
|
from knowit import api
|
||||||
from subsyncer import subsync
|
from subsyncer import subsync
|
||||||
from guessit import guessit
|
from guessit import guessit
|
||||||
from database import database, dict_mapper, get_exclusion_clause
|
from database import database, dict_mapper, get_exclusion_clause, get_profiles_list, get_audio_profile_languages, \
|
||||||
|
get_desired_languages
|
||||||
|
|
||||||
from analytics import track_event
|
from analytics import track_event
|
||||||
from locale import getpreferredencoding
|
from locale import getpreferredencoding
|
||||||
|
@ -304,44 +305,48 @@ def download_subtitle(path, language, audio_language, hi, forced, providers, pro
|
||||||
logging.debug('BAZARR Ended searching Subtitles for file: ' + path)
|
logging.debug('BAZARR Ended searching Subtitles for file: ' + path)
|
||||||
|
|
||||||
|
|
||||||
def manual_search(path, language, hi, forced, providers, providers_auth, sceneName, title, media_type):
|
def manual_search(path, profileId, providers, providers_auth, sceneName, title, media_type):
|
||||||
logging.debug('BAZARR Manually searching subtitles for this file: ' + path)
|
logging.debug('BAZARR Manually searching subtitles for this file: ' + path)
|
||||||
|
|
||||||
final_subtitles = []
|
final_subtitles = []
|
||||||
|
|
||||||
initial_hi = True if hi == "True" else False
|
initial_language_set = set()
|
||||||
if hi == "True":
|
|
||||||
hi = "force HI"
|
|
||||||
else:
|
|
||||||
hi = "force non-HI"
|
|
||||||
language_set = set()
|
language_set = set()
|
||||||
|
|
||||||
if forced == "True":
|
# where [3] is items list of dict(id, lang, forced, hi)
|
||||||
providers_auth['podnapisi']['only_foreign'] = True
|
language_items = ast.literal_eval(get_profiles_list(profile_id=int(profileId))['items'])
|
||||||
providers_auth['subscene']['only_foreign'] = True
|
|
||||||
providers_auth['opensubtitles']['only_foreign'] = True
|
for language in language_items:
|
||||||
else:
|
lang_id, lang, forced, hi, audio_exclude = language.values()
|
||||||
providers_auth['podnapisi']['only_foreign'] = False
|
|
||||||
providers_auth['subscene']['only_foreign'] = False
|
|
||||||
providers_auth['opensubtitles']['only_foreign'] = False
|
|
||||||
|
|
||||||
for lang in ast.literal_eval(language):
|
|
||||||
lang = alpha3_from_alpha2(lang)
|
lang = alpha3_from_alpha2(lang)
|
||||||
|
|
||||||
if lang == 'pob':
|
if lang == 'pob':
|
||||||
lang_obj = Language('por', 'BR')
|
lang_obj = Language('por', 'BR')
|
||||||
if forced == "True":
|
|
||||||
lang_obj = Language.rebuild(lang_obj, forced=True)
|
|
||||||
else:
|
else:
|
||||||
lang_obj = Language(lang)
|
lang_obj = Language(lang)
|
||||||
if forced == "True":
|
|
||||||
lang_obj = Language.rebuild(lang_obj, forced=True)
|
|
||||||
|
|
||||||
language_set.add(lang_obj)
|
if forced == "True":
|
||||||
|
lang_obj = Language.rebuild(lang_obj, forced=True)
|
||||||
|
|
||||||
if forced != "True":
|
providers_auth['podnapisi']['also_foreign'] = True
|
||||||
lang_obj_hi = Language.rebuild(lang_obj, hi=True)
|
providers_auth['opensubtitles']['also_foreign'] = True
|
||||||
language_set.add(lang_obj_hi)
|
|
||||||
|
if hi == "True":
|
||||||
|
lang_obj = Language.rebuild(lang_obj, hi=True)
|
||||||
|
|
||||||
|
initial_language_set.add(lang_obj)
|
||||||
|
|
||||||
|
language_set = initial_language_set.copy()
|
||||||
|
for language in language_set.copy():
|
||||||
|
lang_obj_for_hi = language
|
||||||
|
if not language.forced and not language.hi:
|
||||||
|
lang_obj_hi = Language.rebuild(lang_obj_for_hi, hi=True)
|
||||||
|
elif not language.forced and language.hi:
|
||||||
|
lang_obj_hi = Language.rebuild(lang_obj_for_hi, hi=False)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
language_set.add(lang_obj_hi)
|
||||||
|
|
||||||
minimum_score = settings.general.minimum_score
|
minimum_score = settings.general.minimum_score
|
||||||
minimum_score_movie = settings.general.minimum_score_movie
|
minimum_score_movie = settings.general.minimum_score_movie
|
||||||
|
@ -365,6 +370,22 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
|
||||||
blacklist=get_blacklist(media_type=media_type),
|
blacklist=get_blacklist(media_type=media_type),
|
||||||
throttle_callback=provider_throttle,
|
throttle_callback=provider_throttle,
|
||||||
language_hook=None) # fixme
|
language_hook=None) # fixme
|
||||||
|
|
||||||
|
if 'subscene' in providers:
|
||||||
|
subscene_language_set = set()
|
||||||
|
for language in language_set:
|
||||||
|
if language.forced:
|
||||||
|
subscene_language_set.add(language)
|
||||||
|
if len(subscene_language_set):
|
||||||
|
providers_auth['subscene']['only_foreign'] = True
|
||||||
|
subtitles_subscene = list_all_subtitles([video], subscene_language_set,
|
||||||
|
providers=['subscene'],
|
||||||
|
provider_configs=providers_auth,
|
||||||
|
blacklist=get_blacklist(media_type=media_type),
|
||||||
|
throttle_callback=provider_throttle,
|
||||||
|
language_hook=None) # fixme
|
||||||
|
providers_auth['subscene']['only_foreign'] = False
|
||||||
|
subtitles[video] += subtitles_subscene[video]
|
||||||
else:
|
else:
|
||||||
subtitles = []
|
subtitles = []
|
||||||
logging.info("BAZARR All providers are throttled")
|
logging.info("BAZARR All providers are throttled")
|
||||||
|
@ -390,6 +411,20 @@ def manual_search(path, language, hi, forced, providers, providers_auth, sceneNa
|
||||||
logging.debug(u"BAZARR Skipping %s, because it doesn't match our series/episode", s)
|
logging.debug(u"BAZARR Skipping %s, because it doesn't match our series/episode", s)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
initial_hi_match = False
|
||||||
|
for language in initial_language_set:
|
||||||
|
if s.language.basename == language.basename and \
|
||||||
|
s.language.forced == language.forced and \
|
||||||
|
s.language.hi == language.hi:
|
||||||
|
initial_hi = language.hi
|
||||||
|
initial_hi_match = True
|
||||||
|
break
|
||||||
|
if not initial_hi_match:
|
||||||
|
initial_hi = None
|
||||||
|
|
||||||
|
if initial_hi_match:
|
||||||
|
matches.add('hearing_impaired')
|
||||||
|
|
||||||
score, score_without_hash = compute_score(matches, s, video, hearing_impaired=initial_hi)
|
score, score_without_hash = compute_score(matches, s, video, hearing_impaired=initial_hi)
|
||||||
if 'hash' not in matches:
|
if 'hash' not in matches:
|
||||||
not_matched = scores - matches
|
not_matched = scores - matches
|
||||||
|
@ -680,21 +715,14 @@ def manual_upload_subtitle(path, language, forced, title, scene_name, media_type
|
||||||
def series_download_subtitles(no):
|
def series_download_subtitles(no):
|
||||||
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, monitored, "
|
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, monitored, "
|
||||||
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
||||||
"table_shows.seriesType, table_episodes.audio_language FROM table_episodes "
|
"table_shows.seriesType, table_episodes.audio_language, table_shows.title "
|
||||||
"INNER JOIN table_shows on table_shows.sonarrSeriesId = "
|
"FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = "
|
||||||
"table_episodes.sonarrSeriesId WHERE table_episodes.sonarrSeriesId=? and "
|
"table_episodes.sonarrSeriesId WHERE table_episodes.sonarrSeriesId=? and "
|
||||||
"missing_subtitles!='[]'" + get_exclusion_clause('series'), (no,))
|
"missing_subtitles!='[]'" + get_exclusion_clause('series'), (no,))
|
||||||
if not episodes_details:
|
if not episodes_details:
|
||||||
logging.debug("BAZARR no episode for that sonarrSeriesId can be found in database:", str(no))
|
logging.debug("BAZARR no episode for that sonarrSeriesId can be found in database:", str(no))
|
||||||
return
|
return
|
||||||
|
|
||||||
series_details = database.execute(
|
|
||||||
"SELECT hearing_impaired, title, forced FROM table_shows WHERE sonarrSeriesId=?",
|
|
||||||
(no,), only_one=True)
|
|
||||||
if not series_details:
|
|
||||||
logging.debug("BAZARR no series with that sonarrSeriesId can be found in database:", str(no))
|
|
||||||
return
|
|
||||||
|
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
providers_auth = get_providers_auth()
|
providers_auth = get_providers_auth()
|
||||||
|
|
||||||
|
@ -704,15 +732,21 @@ def series_download_subtitles(no):
|
||||||
if providers_list:
|
if providers_list:
|
||||||
for language in ast.literal_eval(episode['missing_subtitles']):
|
for language in ast.literal_eval(episode['missing_subtitles']):
|
||||||
if language is not None:
|
if language is not None:
|
||||||
|
audio_language_list = get_audio_profile_languages(episode_id=episode['sonarrEpisodeId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
||||||
str(alpha3_from_alpha2(language.split(':')[0])),
|
str(alpha3_from_alpha2(language.split(':')[0])),
|
||||||
episode['audio_language'],
|
audio_language,
|
||||||
series_details['hearing_impaired'],
|
"True" if language.endswith(':hi') else "False",
|
||||||
"True" if language.endswith(':forced') else "False",
|
"True" if language.endswith(':forced') else "False",
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
str(episode['scene_name']),
|
str(episode['scene_name']),
|
||||||
series_details['title'],
|
episode['title'],
|
||||||
'series')
|
'series')
|
||||||
if result is not None:
|
if result is not None:
|
||||||
message = result[0]
|
message = result[0]
|
||||||
|
@ -740,10 +774,9 @@ def series_download_subtitles(no):
|
||||||
def episode_download_subtitles(no):
|
def episode_download_subtitles(no):
|
||||||
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, monitored, "
|
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, monitored, "
|
||||||
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
"table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.tags, "
|
||||||
"table_shows.hearing_impaired, table_shows.title, table_shows.sonarrSeriesId, "
|
"table_shows.title, table_shows.sonarrSeriesId, table_episodes.audio_language, "
|
||||||
"table_shows.forced, table_episodes.audio_language, table_shows.seriesType FROM "
|
"table_shows.seriesType FROM table_episodes LEFT JOIN table_shows on "
|
||||||
"table_episodes LEFT JOIN table_shows on table_episodes.sonarrSeriesId = "
|
"table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId WHERE sonarrEpisodeId=?" +
|
||||||
"table_shows.sonarrSeriesId WHERE sonarrEpisodeId=?" +
|
|
||||||
get_exclusion_clause('series'), (no,))
|
get_exclusion_clause('series'), (no,))
|
||||||
if not episodes_details:
|
if not episodes_details:
|
||||||
logging.debug("BAZARR no episode with that sonarrEpisodeId can be found in database:", str(no))
|
logging.debug("BAZARR no episode with that sonarrEpisodeId can be found in database:", str(no))
|
||||||
|
@ -756,10 +789,16 @@ def episode_download_subtitles(no):
|
||||||
if providers_list:
|
if providers_list:
|
||||||
for language in ast.literal_eval(episode['missing_subtitles']):
|
for language in ast.literal_eval(episode['missing_subtitles']):
|
||||||
if language is not None:
|
if language is not None:
|
||||||
|
audio_language_list = get_audio_profile_languages(episode_id=episode['sonarrEpisodeId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
||||||
str(alpha3_from_alpha2(language.split(':')[0])),
|
str(alpha3_from_alpha2(language.split(':')[0])),
|
||||||
episode['audio_language'],
|
audio_language,
|
||||||
episode['hearing_impaired'],
|
"True" if language.endswith(':hi') else "False",
|
||||||
"True" if language.endswith(':forced') else "False",
|
"True" if language.endswith(':forced') else "False",
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
|
@ -791,7 +830,7 @@ def episode_download_subtitles(no):
|
||||||
|
|
||||||
def movies_download_subtitles(no):
|
def movies_download_subtitles(no):
|
||||||
movies = database.execute(
|
movies = database.execute(
|
||||||
"SELECT path, missing_subtitles, audio_language, radarrId, sceneName, hearing_impaired, title, forced, tags, "
|
"SELECT path, missing_subtitles, audio_language, radarrId, sceneName, title, tags, "
|
||||||
"monitored FROM table_movies WHERE radarrId=?" + get_exclusion_clause('movie'), (no,))
|
"monitored FROM table_movies WHERE radarrId=?" + get_exclusion_clause('movie'), (no,))
|
||||||
if not len(movies):
|
if not len(movies):
|
||||||
logging.debug("BAZARR no movie with that radarrId can be found in database:", str(no))
|
logging.debug("BAZARR no movie with that radarrId can be found in database:", str(no))
|
||||||
|
@ -810,10 +849,16 @@ def movies_download_subtitles(no):
|
||||||
for i, language in enumerate(ast.literal_eval(movie['missing_subtitles']), 1):
|
for i, language in enumerate(ast.literal_eval(movie['missing_subtitles']), 1):
|
||||||
if providers_list:
|
if providers_list:
|
||||||
if language is not None:
|
if language is not None:
|
||||||
|
audio_language_list = get_audio_profile_languages(movie_id=movie['radarrId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace_movie(movie['path']),
|
result = download_subtitle(path_mappings.path_replace_movie(movie['path']),
|
||||||
str(alpha3_from_alpha2(language.split(':')[0])),
|
str(alpha3_from_alpha2(language.split(':')[0])),
|
||||||
movie['audio_language'],
|
audio_language,
|
||||||
movie['hearing_impaired'],
|
"True" if language.endswith(':hi') else "False",
|
||||||
"True" if language.endswith(':forced') else "False",
|
"True" if language.endswith(':forced') else "False",
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
|
@ -845,8 +890,8 @@ def movies_download_subtitles(no):
|
||||||
def wanted_download_subtitles(path, l, count_episodes):
|
def wanted_download_subtitles(path, l, count_episodes):
|
||||||
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, "
|
episodes_details = database.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, "
|
||||||
"table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, "
|
"table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, "
|
||||||
"table_shows.hearing_impaired, table_episodes.audio_language, table_episodes.scene_name,"
|
"table_episodes.audio_language, table_episodes.scene_name,"
|
||||||
"table_episodes.failedAttempts, table_shows.title, table_shows.forced "
|
"table_episodes.failedAttempts, table_shows.title "
|
||||||
"FROM table_episodes LEFT JOIN table_shows on "
|
"FROM table_episodes LEFT JOIN table_shows on "
|
||||||
"table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId "
|
"table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId "
|
||||||
"WHERE table_episodes.path=? and table_episodes.missing_subtitles!='[]'",
|
"WHERE table_episodes.path=? and table_episodes.missing_subtitles!='[]'",
|
||||||
|
@ -874,10 +919,16 @@ def wanted_download_subtitles(path, l, count_episodes):
|
||||||
for i in range(len(attempt)):
|
for i in range(len(attempt)):
|
||||||
if attempt[i][0] == language:
|
if attempt[i][0] == language:
|
||||||
if search_active(attempt[i][1]):
|
if search_active(attempt[i][1]):
|
||||||
|
audio_language_list = get_audio_profile_languages(episode_id=episode['sonarrEpisodeId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
result = download_subtitle(path_mappings.path_replace(episode['path']),
|
||||||
str(alpha3_from_alpha2(language.split(':')[0])),
|
str(alpha3_from_alpha2(language.split(':')[0])),
|
||||||
episode['audio_language'],
|
audio_language,
|
||||||
episode['hearing_impaired'],
|
"True" if language.endswith(':hi') else "False",
|
||||||
"True" if language.endswith(':forced') else "False",
|
"True" if language.endswith(':forced') else "False",
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
|
@ -910,8 +961,8 @@ def wanted_download_subtitles(path, l, count_episodes):
|
||||||
|
|
||||||
def wanted_download_subtitles_movie(path, l, count_movies):
|
def wanted_download_subtitles_movie(path, l, count_movies):
|
||||||
movies_details = database.execute(
|
movies_details = database.execute(
|
||||||
"SELECT path, missing_subtitles, radarrId, hearing_impaired, audio_language, sceneName, "
|
"SELECT path, missing_subtitles, radarrId, audio_language, sceneName, "
|
||||||
"failedAttempts, title, forced FROM table_movies WHERE path = ? "
|
"failedAttempts, title FROM table_movies WHERE path = ? "
|
||||||
"AND missing_subtitles != '[]'", (path_mappings.path_replace_reverse_movie(path),))
|
"AND missing_subtitles != '[]'", (path_mappings.path_replace_reverse_movie(path),))
|
||||||
|
|
||||||
providers_list = get_providers()
|
providers_list = get_providers()
|
||||||
|
@ -936,10 +987,16 @@ def wanted_download_subtitles_movie(path, l, count_movies):
|
||||||
for i in range(len(attempt)):
|
for i in range(len(attempt)):
|
||||||
if attempt[i][0] == language:
|
if attempt[i][0] == language:
|
||||||
if search_active(attempt[i][1]) is True:
|
if search_active(attempt[i][1]) is True:
|
||||||
|
audio_language_list = get_audio_profile_languages(movie_id=movie['radarrId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace_movie(movie['path']),
|
result = download_subtitle(path_mappings.path_replace_movie(movie['path']),
|
||||||
str(alpha3_from_alpha2(language.split(':')[0])),
|
str(alpha3_from_alpha2(language.split(':')[0])),
|
||||||
movie['audio_language'],
|
audio_language,
|
||||||
movie['hearing_impaired'],
|
"True" if language.endswith(':hi') else "False",
|
||||||
"True" if language.endswith(':forced') else "False",
|
"True" if language.endswith(':forced') else "False",
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
|
@ -1144,17 +1201,17 @@ def upgrade_subtitles():
|
||||||
|
|
||||||
if settings.general.getboolean('use_sonarr'):
|
if settings.general.getboolean('use_sonarr'):
|
||||||
upgradable_episodes = database.execute("SELECT table_history.video_path, table_history.language, "
|
upgradable_episodes = database.execute("SELECT table_history.video_path, table_history.language, "
|
||||||
"table_history.score, table_shows.hearing_impaired, "
|
"table_history.score, table_shows.tags, table_shows.profileId, "
|
||||||
"table_episodes.audio_language, table_episodes.scene_name, table_episodes.title,"
|
"table_episodes.audio_language, table_episodes.scene_name, "
|
||||||
"table_episodes.sonarrSeriesId, table_episodes.sonarrEpisodeId,"
|
"table_episodes.title, table_episodes.sonarrSeriesId, "
|
||||||
"MAX(table_history.timestamp) as timestamp, table_episodes.monitored, "
|
"table_episodes.sonarrEpisodeId, MAX(table_history.timestamp) "
|
||||||
"table_shows.languages, table_shows.forced, table_shows.tags, "
|
"as timestamp, table_episodes.monitored, table_shows.seriesType FROM "
|
||||||
"table_shows.seriesType FROM table_history INNER JOIN table_shows on "
|
"table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = "
|
||||||
"table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN "
|
"table_history.sonarrSeriesId INNER JOIN table_episodes on "
|
||||||
"table_episodes on table_episodes.sonarrEpisodeId = "
|
"table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE "
|
||||||
"table_history.sonarrEpisodeId WHERE action IN "
|
"action IN (" + ','.join(map(str, query_actions)) +
|
||||||
"(" + ','.join(map(str, query_actions)) + ") AND timestamp > ? AND score"
|
") AND timestamp > ? AND score is not null" +
|
||||||
" is not null" + get_exclusion_clause('series') + " GROUP BY "
|
get_exclusion_clause('series') + " GROUP BY "
|
||||||
"table_history.video_path, table_history.language",
|
"table_history.video_path, table_history.language",
|
||||||
(minimum_timestamp,))
|
(minimum_timestamp,))
|
||||||
upgradable_episodes_not_perfect = []
|
upgradable_episodes_not_perfect = []
|
||||||
|
@ -1177,13 +1234,13 @@ def upgrade_subtitles():
|
||||||
|
|
||||||
if settings.general.getboolean('use_radarr'):
|
if settings.general.getboolean('use_radarr'):
|
||||||
upgradable_movies = database.execute("SELECT table_history_movie.video_path, table_history_movie.language, "
|
upgradable_movies = database.execute("SELECT table_history_movie.video_path, table_history_movie.language, "
|
||||||
"table_history_movie.score, table_movies.hearing_impaired, "
|
"table_history_movie.score, table_movies.profileId, "
|
||||||
"table_movies.audio_language, table_movies.sceneName, table_movies.title, "
|
"table_movies.audio_language, table_movies.sceneName, table_movies.title, "
|
||||||
"table_movies.radarrId, MAX(table_history_movie.timestamp) as timestamp, "
|
"table_movies.radarrId, MAX(table_history_movie.timestamp) as timestamp, "
|
||||||
"table_movies.languages, table_movies.forced, table_movies.tags, "
|
"table_movies.tags, table_movies.monitored FROM table_history_movie INNER "
|
||||||
"table_movies.monitored FROM table_history_movie INNER JOIN table_movies "
|
"JOIN table_movies on table_movies.radarrId = "
|
||||||
"on table_movies.radarrId = table_history_movie.radarrId WHERE action IN "
|
"table_history_movie.radarrId WHERE action IN (" +
|
||||||
"(" + ','.join(map(str, query_actions)) + ") AND timestamp > ? AND score "
|
','.join(map(str, query_actions)) + ") AND timestamp > ? AND score "
|
||||||
"is not null" + get_exclusion_clause('movie') + " GROUP BY "
|
"is not null" + get_exclusion_clause('movie') + " GROUP BY "
|
||||||
"table_history_movie.video_path, table_history_movie.language",
|
"table_history_movie.video_path, table_history_movie.language",
|
||||||
(minimum_timestamp,))
|
(minimum_timestamp,))
|
||||||
|
@ -1210,110 +1267,113 @@ def upgrade_subtitles():
|
||||||
|
|
||||||
if settings.general.getboolean('use_sonarr'):
|
if settings.general.getboolean('use_sonarr'):
|
||||||
for i, episode in enumerate(episodes_to_upgrade, 1):
|
for i, episode in enumerate(episodes_to_upgrade, 1):
|
||||||
if episode['languages'] in [None, 'None', '[]']:
|
|
||||||
continue
|
|
||||||
providers = get_providers()
|
providers = get_providers()
|
||||||
if not providers:
|
if not providers:
|
||||||
logging.info("BAZARR All providers are throttled")
|
logging.info("BAZARR All providers are throttled")
|
||||||
return
|
return
|
||||||
if episode['languages']:
|
if episode['language'].endswith('forced'):
|
||||||
desired_languages = ast.literal_eval(str(episode['languages']))
|
language = episode['language'].split(':')[0]
|
||||||
if episode['forced'] == "True":
|
is_forced = True
|
||||||
forced_languages = [l + ":forced" for l in desired_languages]
|
is_hi = False
|
||||||
elif episode['forced'] == "Both":
|
elif episode['language'].endswith('hi'):
|
||||||
forced_languages = [l + ":forced" for l in desired_languages] + desired_languages
|
language = episode['language'].split(':')[0]
|
||||||
|
is_forced = False
|
||||||
|
is_hi = True
|
||||||
|
else:
|
||||||
|
language = episode['language'].split(':')[0]
|
||||||
|
is_forced = False
|
||||||
|
is_hi = False
|
||||||
|
|
||||||
|
audio_language_list = get_audio_profile_languages(episode_id=episode['sonarrEpisodeId'])
|
||||||
|
if len(audio_language_list) > 0:
|
||||||
|
audio_language = audio_language_list[0]['name']
|
||||||
|
else:
|
||||||
|
audio_language = 'None'
|
||||||
|
|
||||||
|
result = download_subtitle(path_mappings.path_replace(episode['video_path']),
|
||||||
|
str(alpha3_from_alpha2(language)),
|
||||||
|
audio_language,
|
||||||
|
is_hi,
|
||||||
|
is_forced,
|
||||||
|
providers_list,
|
||||||
|
providers_auth,
|
||||||
|
str(episode['scene_name']),
|
||||||
|
episode['title'],
|
||||||
|
'series',
|
||||||
|
forced_minimum_score=int(episode['score']),
|
||||||
|
is_upgrade=True)
|
||||||
|
if result is not None:
|
||||||
|
message = result[0]
|
||||||
|
path = result[1]
|
||||||
|
forced = result[5]
|
||||||
|
if result[8]:
|
||||||
|
language_code = result[2] + ":hi"
|
||||||
|
elif forced:
|
||||||
|
language_code = result[2] + ":forced"
|
||||||
else:
|
else:
|
||||||
forced_languages = desired_languages
|
language_code = result[2]
|
||||||
|
provider = result[3]
|
||||||
if episode['language'] in forced_languages:
|
score = result[4]
|
||||||
if episode['language'].endswith('forced'):
|
subs_id = result[6]
|
||||||
language = episode['language'].split(':')[0]
|
subs_path = result[7]
|
||||||
is_forced = "True"
|
store_subtitles(episode['video_path'], path_mappings.path_replace(episode['video_path']))
|
||||||
else:
|
history_log(3, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path,
|
||||||
language = episode['language']
|
language_code, provider, score, subs_id, subs_path)
|
||||||
is_forced = "False"
|
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace(episode['video_path']),
|
|
||||||
str(alpha3_from_alpha2(language)),
|
|
||||||
episode['audio_language'],
|
|
||||||
episode['hearing_impaired'],
|
|
||||||
is_forced,
|
|
||||||
providers_list,
|
|
||||||
providers_auth,
|
|
||||||
str(episode['scene_name']),
|
|
||||||
episode['title'],
|
|
||||||
'series',
|
|
||||||
forced_minimum_score=int(episode['score']),
|
|
||||||
is_upgrade=True)
|
|
||||||
if result is not None:
|
|
||||||
message = result[0]
|
|
||||||
path = result[1]
|
|
||||||
forced = result[5]
|
|
||||||
if result[8]:
|
|
||||||
language_code = result[2] + ":hi"
|
|
||||||
elif forced:
|
|
||||||
language_code = result[2] + ":forced"
|
|
||||||
else:
|
|
||||||
language_code = result[2]
|
|
||||||
provider = result[3]
|
|
||||||
score = result[4]
|
|
||||||
subs_id = result[6]
|
|
||||||
subs_path = result[7]
|
|
||||||
store_subtitles(episode['video_path'], path_mappings.path_replace(episode['video_path']))
|
|
||||||
history_log(3, episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message, path,
|
|
||||||
language_code, provider, score, subs_id, subs_path)
|
|
||||||
send_notifications(episode['sonarrSeriesId'], episode['sonarrEpisodeId'], message)
|
|
||||||
|
|
||||||
if settings.general.getboolean('use_radarr'):
|
if settings.general.getboolean('use_radarr'):
|
||||||
for i, movie in enumerate(movies_to_upgrade, 1):
|
for i, movie in enumerate(movies_to_upgrade, 1):
|
||||||
if movie['languages'] in [None, 'None', '[]']:
|
|
||||||
continue
|
|
||||||
providers = get_providers()
|
providers = get_providers()
|
||||||
if not providers:
|
if not providers:
|
||||||
logging.info("BAZARR All providers are throttled")
|
logging.info("BAZARR All providers are throttled")
|
||||||
return
|
return
|
||||||
if movie['languages']:
|
if not providers:
|
||||||
desired_languages = ast.literal_eval(str(movie['languages']))
|
logging.info("BAZARR All providers are throttled")
|
||||||
if movie['forced'] == "True":
|
return
|
||||||
forced_languages = [l + ":forced" for l in desired_languages]
|
if episode['language'].endswith('forced'):
|
||||||
elif movie['forced'] == "Both":
|
language = episode['language'].split(':')[0]
|
||||||
forced_languages = [l + ":forced" for l in desired_languages] + desired_languages
|
is_forced = True
|
||||||
else:
|
is_hi = False
|
||||||
forced_languages = desired_languages
|
elif episode['language'].endswith('hi'):
|
||||||
|
language = episode['language'].split(':')[0]
|
||||||
|
is_forced = False
|
||||||
|
is_hi = True
|
||||||
|
else:
|
||||||
|
language = episode['language'].split(':')[0]
|
||||||
|
is_forced = False
|
||||||
|
is_hi = False
|
||||||
|
|
||||||
if movie['language'] in forced_languages:
|
audio_language_list = get_audio_profile_languages(movie_id=movie['radarrId'])
|
||||||
if movie['language'].endswith('forced'):
|
if len(audio_language_list) > 0:
|
||||||
language = movie['language'].split(':')[0]
|
audio_language = audio_language_list[0]['name']
|
||||||
is_forced = "True"
|
else:
|
||||||
else:
|
audio_language = 'None'
|
||||||
language = movie['language']
|
|
||||||
is_forced = "False"
|
|
||||||
|
|
||||||
result = download_subtitle(path_mappings.path_replace_movie(movie['video_path']),
|
result = download_subtitle(path_mappings.path_replace_movie(movie['video_path']),
|
||||||
str(alpha3_from_alpha2(language)),
|
str(alpha3_from_alpha2(language)),
|
||||||
movie['audio_language'],
|
audio_language,
|
||||||
movie['hearing_impaired'],
|
is_hi,
|
||||||
is_forced,
|
is_forced,
|
||||||
providers_list,
|
providers_list,
|
||||||
providers_auth,
|
providers_auth,
|
||||||
str(movie['sceneName']),
|
str(movie['sceneName']),
|
||||||
movie['title'],
|
movie['title'],
|
||||||
'movie',
|
'movie',
|
||||||
forced_minimum_score=int(movie['score']),
|
forced_minimum_score=int(movie['score']),
|
||||||
is_upgrade=True)
|
is_upgrade=True)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
message = result[0]
|
message = result[0]
|
||||||
path = result[1]
|
path = result[1]
|
||||||
forced = result[5]
|
forced = result[5]
|
||||||
language_code = result[2] + ":forced" if forced else result[2]
|
language_code = result[2] + ":forced" if forced else result[2]
|
||||||
provider = result[3]
|
provider = result[3]
|
||||||
score = result[4]
|
score = result[4]
|
||||||
subs_id = result[6]
|
subs_id = result[6]
|
||||||
subs_path = result[7]
|
subs_path = result[7]
|
||||||
store_subtitles_movie(movie['video_path'],
|
store_subtitles_movie(movie['video_path'],
|
||||||
path_mappings.path_replace_movie(movie['video_path']))
|
path_mappings.path_replace_movie(movie['video_path']))
|
||||||
history_log_movie(3, movie['radarrId'], message, path, language_code, provider, score, subs_id, subs_path)
|
history_log_movie(3, movie['radarrId'], message, path, language_code, provider, score, subs_id, subs_path)
|
||||||
send_notifications_movie(movie['radarrId'], message)
|
send_notifications_movie(movie['radarrId'], message)
|
||||||
|
|
||||||
|
|
||||||
def postprocessing(command, path):
|
def postprocessing(command, path):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
import rarfile
|
import rarfile
|
||||||
import json
|
|
||||||
import hashlib
|
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ from guess_language import guess_language
|
||||||
from subliminal_patch import core, search_external_subtitles
|
from subliminal_patch import core, search_external_subtitles
|
||||||
from subzero.language import Language
|
from subzero.language import Language
|
||||||
|
|
||||||
from database import database
|
from database import database, get_profiles_list, get_profile_cutoff
|
||||||
from get_languages import alpha2_from_alpha3, get_language_set
|
from get_languages import alpha2_from_alpha3, language_from_alpha2, get_language_set
|
||||||
from config import settings
|
from config import settings
|
||||||
from helper import path_mappings, get_subtitle_destination_folder
|
from helper import path_mappings, get_subtitle_destination_folder
|
||||||
|
|
||||||
|
@ -203,157 +203,212 @@ def store_subtitles_movie(original_path, reversed_path):
|
||||||
|
|
||||||
|
|
||||||
def list_missing_subtitles(no=None, epno=None, send_event=True):
|
def list_missing_subtitles(no=None, epno=None, send_event=True):
|
||||||
if no is not None:
|
if epno is not None:
|
||||||
episodes_subtitles_clause = " WHERE table_episodes.sonarrSeriesId=" + str(no)
|
|
||||||
elif epno is not None:
|
|
||||||
episodes_subtitles_clause = " WHERE table_episodes.sonarrEpisodeId=" + str(epno)
|
episodes_subtitles_clause = " WHERE table_episodes.sonarrEpisodeId=" + str(epno)
|
||||||
|
elif no is not None:
|
||||||
|
episodes_subtitles_clause = " WHERE table_episodes.sonarrSeriesId=" + str(no)
|
||||||
else:
|
else:
|
||||||
episodes_subtitles_clause = ""
|
episodes_subtitles_clause = ""
|
||||||
episodes_subtitles = database.execute("SELECT table_shows.sonarrSeriesId, table_episodes.sonarrEpisodeId, "
|
episodes_subtitles = database.execute("SELECT table_shows.sonarrSeriesId, table_episodes.sonarrEpisodeId, "
|
||||||
"table_episodes.subtitles, table_shows.languages, table_shows.forced, "
|
"table_episodes.subtitles, table_shows.profileId, "
|
||||||
"table_shows.hearing_impaired FROM table_episodes LEFT JOIN table_shows "
|
"table_episodes.audio_language FROM table_episodes "
|
||||||
"on table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId" +
|
"LEFT JOIN table_shows on table_episodes.sonarrSeriesId = "
|
||||||
episodes_subtitles_clause)
|
"table_shows.sonarrSeriesId" + episodes_subtitles_clause)
|
||||||
if isinstance(episodes_subtitles, str):
|
if isinstance(episodes_subtitles, str):
|
||||||
logging.error("BAZARR list missing subtitles query to DB returned this instead of rows: " + episodes_subtitles)
|
logging.error("BAZARR list missing subtitles query to DB returned this instead of rows: " + episodes_subtitles)
|
||||||
return
|
return
|
||||||
|
|
||||||
missing_subtitles_global = []
|
|
||||||
use_embedded_subs = settings.general.getboolean('use_embedded_subs')
|
use_embedded_subs = settings.general.getboolean('use_embedded_subs')
|
||||||
|
|
||||||
for episode_subtitles in episodes_subtitles:
|
for episode_subtitles in episodes_subtitles:
|
||||||
actual_subtitles_temp = []
|
missing_subtitles_text = '[]'
|
||||||
desired_subtitles_temp = []
|
if episode_subtitles['profileId']:
|
||||||
actual_subtitles = []
|
# get desired subtitles
|
||||||
desired_subtitles = []
|
desired_subtitles_temp = get_profiles_list(profile_id=episode_subtitles['profileId'])
|
||||||
missing_subtitles = []
|
desired_subtitles_list = []
|
||||||
if episode_subtitles['subtitles'] is not None:
|
if desired_subtitles_temp:
|
||||||
if use_embedded_subs:
|
for language in ast.literal_eval(desired_subtitles_temp['items']):
|
||||||
actual_subtitles = ast.literal_eval(episode_subtitles['subtitles'])
|
if language['audio_exclude'] == "True":
|
||||||
else:
|
if language_from_alpha2(language['language']) in ast.literal_eval(episode_subtitles['audio_language']):
|
||||||
actual_subtitles_temp = ast.literal_eval(episode_subtitles['subtitles'])
|
continue
|
||||||
for subtitle in actual_subtitles_temp:
|
desired_subtitles_list.append([language['language'], language['forced'], language['hi']])
|
||||||
if subtitle[1] is not None:
|
|
||||||
actual_subtitles.append(subtitle)
|
|
||||||
if episode_subtitles['languages'] is not None:
|
|
||||||
desired_subtitles = ast.literal_eval(episode_subtitles['languages'])
|
|
||||||
if desired_subtitles:
|
|
||||||
desired_subtitles_enum = enumerate(desired_subtitles)
|
|
||||||
else:
|
|
||||||
desired_subtitles_enum = None
|
|
||||||
|
|
||||||
if episode_subtitles['hearing_impaired'] == "True" and desired_subtitles is not None:
|
# get existing subtitles
|
||||||
for i, desired_subtitle in desired_subtitles_enum:
|
actual_subtitles_list = []
|
||||||
desired_subtitles[i] = desired_subtitle + ":hi"
|
if episode_subtitles['subtitles'] is not None:
|
||||||
elif episode_subtitles['forced'] == "True" and desired_subtitles is not None:
|
if use_embedded_subs:
|
||||||
for i, desired_subtitle in desired_subtitles_enum:
|
actual_subtitles_temp = ast.literal_eval(episode_subtitles['subtitles'])
|
||||||
desired_subtitles[i] = desired_subtitle + ":forced"
|
|
||||||
elif episode_subtitles['forced'] == "Both" and desired_subtitles is not None:
|
|
||||||
for desired_subtitle in desired_subtitles:
|
|
||||||
desired_subtitles_temp.append(desired_subtitle)
|
|
||||||
desired_subtitles_temp.append(desired_subtitle + ":forced")
|
|
||||||
desired_subtitles = desired_subtitles_temp
|
|
||||||
actual_subtitles_list = []
|
|
||||||
if desired_subtitles is None:
|
|
||||||
missing_subtitles_global.append(tuple(['[]', episode_subtitles['sonarrEpisodeId'],
|
|
||||||
episode_subtitles['sonarrSeriesId']]))
|
|
||||||
else:
|
|
||||||
for item in actual_subtitles:
|
|
||||||
if item[0] == "pt-BR":
|
|
||||||
actual_subtitles_list.append("pb")
|
|
||||||
elif item[0] == "pt-BR:forced":
|
|
||||||
actual_subtitles_list.append("pb:forced")
|
|
||||||
else:
|
else:
|
||||||
actual_subtitles_list.append(item[0])
|
actual_subtitles_temp = [x for x in ast.literal_eval(episode_subtitles['subtitles']) if x[1]]
|
||||||
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
|
|
||||||
hi_subs_to_remove = []
|
for subtitles in actual_subtitles_temp:
|
||||||
for item in missing_subtitles:
|
subtitles = subtitles[0].split(':')
|
||||||
if item + ':hi' in actual_subtitles_list:
|
lang = subtitles[0]
|
||||||
hi_subs_to_remove.append(item)
|
forced = False
|
||||||
missing_subtitles = list(set(missing_subtitles) - set(hi_subs_to_remove))
|
hi = False
|
||||||
missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles['sonarrEpisodeId'],
|
if len(subtitles) > 1:
|
||||||
episode_subtitles['sonarrSeriesId']]))
|
if subtitles[1] == 'forced':
|
||||||
|
forced = True
|
||||||
|
hi = False
|
||||||
|
elif subtitles[1] == 'hi':
|
||||||
|
forced = False
|
||||||
|
hi = True
|
||||||
|
actual_subtitles_list.append([lang, str(forced), str(hi)])
|
||||||
|
|
||||||
|
# check if cutoff is reached and skip any further check
|
||||||
|
cutoff_met = False
|
||||||
|
cutoff_temp_list = get_profile_cutoff(profile_id=episode_subtitles['profileId'])
|
||||||
|
|
||||||
|
if cutoff_temp_list:
|
||||||
|
for cutoff_temp in cutoff_temp_list:
|
||||||
|
cutoff_language = [cutoff_temp['language'], cutoff_temp['forced'], cutoff_temp['hi']]
|
||||||
|
if cutoff_language in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
elif cutoff_language and [cutoff_language[0], 'True', 'False'] in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
elif cutoff_language and [cutoff_language[0], 'False', 'True'] in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
|
||||||
|
if not cutoff_met:
|
||||||
|
# if cutoff isn't met or None, we continue
|
||||||
|
|
||||||
|
# get difference between desired and existing subtitles
|
||||||
|
missing_subtitles_list = []
|
||||||
|
for item in desired_subtitles_list:
|
||||||
|
if item not in actual_subtitles_list:
|
||||||
|
missing_subtitles_list.append(item)
|
||||||
|
|
||||||
|
# remove missing that have forced or hi subtitles for this language in existing
|
||||||
|
for item in actual_subtitles_list:
|
||||||
|
if item[1] == 'True' or item[2] == 'True':
|
||||||
|
try:
|
||||||
|
missing_subtitles_list.remove([item[0], 'False', 'False'])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# make the missing languages list looks like expected
|
||||||
|
missing_subtitles_output_list = []
|
||||||
|
for item in missing_subtitles_list:
|
||||||
|
lang = item[0]
|
||||||
|
if item[1] == 'True':
|
||||||
|
lang += ':forced'
|
||||||
|
elif item[2] == 'True':
|
||||||
|
lang += ':hi'
|
||||||
|
missing_subtitles_output_list.append(lang)
|
||||||
|
|
||||||
|
missing_subtitles_text = str(missing_subtitles_output_list)
|
||||||
|
|
||||||
for missing_subtitles_item in missing_subtitles_global:
|
|
||||||
database.execute("UPDATE table_episodes SET missing_subtitles=? WHERE sonarrEpisodeId=?",
|
database.execute("UPDATE table_episodes SET missing_subtitles=? WHERE sonarrEpisodeId=?",
|
||||||
(missing_subtitles_item[0], missing_subtitles_item[1]))
|
(missing_subtitles_text, episode_subtitles['sonarrEpisodeId']))
|
||||||
|
|
||||||
if send_event:
|
if send_event:
|
||||||
event_stream(type='episode', action='update', series=missing_subtitles_item[2],
|
event_stream(type='episode', action='update', series=episode_subtitles['sonarrSeriesId'],
|
||||||
episode=missing_subtitles_item[1])
|
episode=episode_subtitles['sonarrEpisodeId'])
|
||||||
event_stream(type='badges_series')
|
event_stream(type='badges_series')
|
||||||
|
|
||||||
|
|
||||||
def list_missing_subtitles_movies(no=None, send_event=True):
|
def list_missing_subtitles_movies(no=None, epno=None, send_event=True):
|
||||||
if no is not None:
|
if no is not None:
|
||||||
movies_subtitles_clause = " WHERE radarrId=" + str(no)
|
movies_subtitles_clause = " WHERE radarrId=" + str(no)
|
||||||
else:
|
else:
|
||||||
movies_subtitles_clause = ""
|
movies_subtitles_clause = ""
|
||||||
|
|
||||||
movies_subtitles = database.execute("SELECT radarrId, subtitles, languages, forced, hearing_impaired FROM "
|
movies_subtitles = database.execute("SELECT radarrId, subtitles, profileId, audio_language FROM table_movies" +
|
||||||
"table_movies" + movies_subtitles_clause)
|
movies_subtitles_clause)
|
||||||
if isinstance(movies_subtitles, str):
|
if isinstance(movies_subtitles, str):
|
||||||
logging.error("BAZARR list missing subtitles query to DB returned this instead of rows: " + movies_subtitles)
|
logging.error("BAZARR list missing subtitles query to DB returned this instead of rows: " + movies_subtitles)
|
||||||
return
|
return
|
||||||
|
|
||||||
missing_subtitles_global = []
|
|
||||||
use_embedded_subs = settings.general.getboolean('use_embedded_subs')
|
|
||||||
for movie_subtitles in movies_subtitles:
|
|
||||||
actual_subtitles_temp = []
|
|
||||||
desired_subtitles_temp = []
|
|
||||||
actual_subtitles = []
|
|
||||||
desired_subtitles = []
|
|
||||||
missing_subtitles = []
|
|
||||||
if movie_subtitles['subtitles'] is not None:
|
|
||||||
if use_embedded_subs:
|
|
||||||
actual_subtitles = ast.literal_eval(movie_subtitles['subtitles'])
|
|
||||||
else:
|
|
||||||
actual_subtitles_temp = ast.literal_eval(movie_subtitles['subtitles'])
|
|
||||||
for subtitle in actual_subtitles_temp:
|
|
||||||
if subtitle[1] is not None:
|
|
||||||
actual_subtitles.append(subtitle)
|
|
||||||
if movie_subtitles['languages'] is not None:
|
|
||||||
desired_subtitles = ast.literal_eval(movie_subtitles['languages'])
|
|
||||||
if desired_subtitles:
|
|
||||||
desired_subtitles_enum = enumerate(desired_subtitles)
|
|
||||||
else:
|
|
||||||
desired_subtitles_enum = None
|
|
||||||
|
|
||||||
if movie_subtitles['hearing_impaired'] == "True" and desired_subtitles is not None:
|
|
||||||
for i, desired_subtitle in desired_subtitles_enum:
|
use_embedded_subs = settings.general.getboolean('use_embedded_subs')
|
||||||
desired_subtitles[i] = desired_subtitle + ":hi"
|
|
||||||
elif movie_subtitles['forced'] == "True" and desired_subtitles is not None:
|
for movie_subtitles in movies_subtitles:
|
||||||
for i, desired_subtitle in desired_subtitles_enum:
|
missing_subtitles_text = '[]'
|
||||||
desired_subtitles[i] = desired_subtitle + ":forced"
|
if movie_subtitles['profileId']:
|
||||||
elif movie_subtitles['forced'] == "Both" and desired_subtitles is not None:
|
# get desired subtitles
|
||||||
for desired_subtitle in desired_subtitles:
|
desired_subtitles_temp = get_profiles_list(profile_id=movie_subtitles['profileId'])
|
||||||
desired_subtitles_temp.append(desired_subtitle)
|
desired_subtitles_list = []
|
||||||
desired_subtitles_temp.append(desired_subtitle + ":forced")
|
if desired_subtitles_temp:
|
||||||
desired_subtitles = desired_subtitles_temp
|
for language in ast.literal_eval(desired_subtitles_temp['items']):
|
||||||
actual_subtitles_list = []
|
if language['audio_exclude'] == "True":
|
||||||
if desired_subtitles is None:
|
if language_from_alpha2(language['language']) in ast.literal_eval(movie_subtitles['audio_language']):
|
||||||
missing_subtitles_global.append(tuple(['[]', movie_subtitles['radarrId']]))
|
continue
|
||||||
else:
|
desired_subtitles_list.append([language['language'], language['forced'], language['hi']])
|
||||||
for item in actual_subtitles:
|
|
||||||
if item[0] == "pt-BR":
|
# get existing subtitles
|
||||||
actual_subtitles_list.append("pb")
|
actual_subtitles_list = []
|
||||||
elif item[0] == "pt-BR:forced":
|
if movie_subtitles['subtitles'] is not None:
|
||||||
actual_subtitles_list.append("pb:forced")
|
if use_embedded_subs:
|
||||||
|
actual_subtitles_temp = ast.literal_eval(movie_subtitles['subtitles'])
|
||||||
else:
|
else:
|
||||||
actual_subtitles_list.append(item[0])
|
actual_subtitles_temp = [x for x in ast.literal_eval(movie_subtitles['subtitles']) if x[1]]
|
||||||
missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list))
|
|
||||||
hi_subs_to_remove = []
|
for subtitles in actual_subtitles_temp:
|
||||||
for item in missing_subtitles:
|
subtitles = subtitles[0].split(':')
|
||||||
if item + ':hi' in actual_subtitles_list:
|
lang = subtitles[0]
|
||||||
hi_subs_to_remove.append(item)
|
forced = False
|
||||||
missing_subtitles = list(set(missing_subtitles) - set(hi_subs_to_remove))
|
hi = False
|
||||||
missing_subtitles_global.append(tuple([str(missing_subtitles), movie_subtitles['radarrId']]))
|
if len(subtitles) > 1:
|
||||||
|
if subtitles[1] == 'forced':
|
||||||
for missing_subtitles_item in missing_subtitles_global:
|
forced = True
|
||||||
|
hi = False
|
||||||
|
elif subtitles[1] == 'hi':
|
||||||
|
forced = False
|
||||||
|
hi = True
|
||||||
|
actual_subtitles_list.append([lang, str(forced), str(hi)])
|
||||||
|
|
||||||
|
# check if cutoff is reached and skip any further check
|
||||||
|
cutoff_met = False
|
||||||
|
cutoff_temp_list = get_profile_cutoff(profile_id=movie_subtitles['profileId'])
|
||||||
|
|
||||||
|
if cutoff_temp_list:
|
||||||
|
for cutoff_temp in cutoff_temp_list:
|
||||||
|
cutoff_language = [cutoff_temp['language'], cutoff_temp['forced'], cutoff_temp['hi']]
|
||||||
|
if cutoff_language in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
elif cutoff_language and [cutoff_language[0], 'True', 'False'] in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
elif cutoff_language and [cutoff_language[0], 'False', 'True'] in actual_subtitles_list:
|
||||||
|
cutoff_met = True
|
||||||
|
missing_subtitles_text = str([])
|
||||||
|
|
||||||
|
if not cutoff_met:
|
||||||
|
# get difference between desired and existing subtitles
|
||||||
|
missing_subtitles_list = []
|
||||||
|
for item in desired_subtitles_list:
|
||||||
|
if item not in actual_subtitles_list:
|
||||||
|
missing_subtitles_list.append(item)
|
||||||
|
|
||||||
|
# remove missing that have forced or hi subtitles for this language in existing
|
||||||
|
for item in actual_subtitles_list:
|
||||||
|
if item[1] == 'True' or item[2] == 'True':
|
||||||
|
try:
|
||||||
|
missing_subtitles_list.remove([item[0], 'False', 'False'])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# make the missing languages list looks like expected
|
||||||
|
missing_subtitles_output_list = []
|
||||||
|
for item in missing_subtitles_list:
|
||||||
|
lang = item[0]
|
||||||
|
if item[1] == 'True':
|
||||||
|
lang += ':forced'
|
||||||
|
elif item[2] == 'True':
|
||||||
|
lang += ':hi'
|
||||||
|
missing_subtitles_output_list.append(lang)
|
||||||
|
|
||||||
|
missing_subtitles_text = str(missing_subtitles_output_list)
|
||||||
|
|
||||||
database.execute("UPDATE table_movies SET missing_subtitles=? WHERE radarrId=?",
|
database.execute("UPDATE table_movies SET missing_subtitles=? WHERE radarrId=?",
|
||||||
(missing_subtitles_item[0], missing_subtitles_item[1]))
|
(missing_subtitles_text, movie_subtitles['radarrId']))
|
||||||
|
|
||||||
if send_event:
|
if send_event:
|
||||||
event_stream(type='movie', action='update', movie=missing_subtitles_item[1])
|
event_stream(type='movie', action='update', movie=movie_subtitles['radarrId'])
|
||||||
event_stream(type='badges_movies')
|
event_stream(type='badges_movies')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,29 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
bazarr_version = '0.9.0.8'
|
bazarr_version = '0.9.1'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
os.environ["BAZARR_VERSION"] = bazarr_version
|
os.environ["BAZARR_VERSION"] = bazarr_version
|
||||||
|
|
||||||
import gc
|
import gc
|
||||||
import sys
|
|
||||||
import libs
|
import libs
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import apprise
|
import apprise
|
||||||
import requests
|
|
||||||
import calendar
|
import calendar
|
||||||
|
|
||||||
from get_args import args
|
from get_args import args
|
||||||
from logger import empty_log
|
from logger import empty_log
|
||||||
from config import settings, url_sonarr, url_radarr, url_radarr_short, url_sonarr_short, base_url, configure_proxy_func
|
from config import settings, url_sonarr, url_radarr, configure_proxy_func
|
||||||
|
|
||||||
from init import *
|
from init import *
|
||||||
from database import database, dict_mapper
|
from database import database
|
||||||
|
|
||||||
from notifier import update_notifier
|
from notifier import update_notifier
|
||||||
|
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
from get_languages import load_language_in_db, language_from_alpha3, language_from_alpha2, alpha2_from_alpha3, \
|
from get_languages import load_language_in_db, language_from_alpha2, alpha3_from_alpha2
|
||||||
alpha3_from_alpha2
|
|
||||||
from flask import make_response, request, redirect, abort, render_template, Response, session, flash, url_for, \
|
from flask import make_response, request, redirect, abort, render_template, Response, session, flash, url_for, \
|
||||||
send_file, stream_with_context
|
send_file, stream_with_context
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ from get_episodes import sync_episodes, update_all_episodes
|
||||||
from get_movies import update_movies, update_all_movies
|
from get_movies import update_movies, update_all_movies
|
||||||
from get_series import update_series
|
from get_series import update_series
|
||||||
from config import settings
|
from config import settings
|
||||||
from get_subtitle import wanted_search_missing_subtitles_series, wanted_search_missing_subtitles_movies, upgrade_subtitles
|
from get_subtitle import wanted_search_missing_subtitles_series, wanted_search_missing_subtitles_movies, \
|
||||||
|
upgrade_subtitles
|
||||||
from utils import cache_maintenance
|
from utils import cache_maintenance
|
||||||
from get_args import args
|
from get_args import args
|
||||||
if not args.no_update:
|
if not args.no_update:
|
||||||
|
@ -21,6 +22,7 @@ from calendar import day_name
|
||||||
import pretty
|
import pretty
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from event_handler import event_stream
|
from event_handler import event_stream
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class Scheduler:
|
class Scheduler:
|
||||||
|
@ -62,10 +64,10 @@ class Scheduler:
|
||||||
if args.no_tasks:
|
if args.no_tasks:
|
||||||
self.__no_task()
|
self.__no_task()
|
||||||
|
|
||||||
def add_job(self, job, name=None, max_instances=1, coalesce=True, args=None):
|
def add_job(self, job, name=None, max_instances=1, coalesce=True, args=None, kwargs=None):
|
||||||
self.aps_scheduler.add_job(
|
self.aps_scheduler.add_job(
|
||||||
job, DateTrigger(run_date=datetime.now()), name=name, id=name, max_instances=max_instances,
|
job, DateTrigger(run_date=datetime.now()), name=name, id=name, max_instances=max_instances,
|
||||||
coalesce=coalesce, args=args)
|
coalesce=coalesce, args=args, kwargs=kwargs)
|
||||||
|
|
||||||
def execute_job_now(self, taskid):
|
def execute_job_now(self, taskid):
|
||||||
self.aps_scheduler.modify_job(taskid, next_run_time=datetime.now())
|
self.aps_scheduler.modify_job(taskid, next_run_time=datetime.now())
|
||||||
|
@ -252,3 +254,12 @@ class Scheduler:
|
||||||
|
|
||||||
|
|
||||||
scheduler = Scheduler()
|
scheduler = Scheduler()
|
||||||
|
|
||||||
|
# Force the execution of the sync process with Sonarr and Radarr after migration to v0.9.1
|
||||||
|
if 'BAZARR_AUDIO_PROFILES_MIGRATION' in os.environ:
|
||||||
|
if settings.general.getboolean('use_sonarr'):
|
||||||
|
scheduler.aps_scheduler.modify_job('update_series', next_run_time=datetime.now())
|
||||||
|
scheduler.aps_scheduler.modify_job('sync_episodes', next_run_time=datetime.now())
|
||||||
|
if settings.general.getboolean('use_radarr'):
|
||||||
|
scheduler.aps_scheduler.modify_job('update_movies', next_run_time=datetime.now())
|
||||||
|
del os.environ['BAZARR_AUDIO_PROFILES_MIGRATION']
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# coding=utf-8
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
|
@ -823,9 +823,8 @@ def get_subtitle_path(video_path, language=None, extension='.srt', forced_tag=Fa
|
||||||
if forced_tag:
|
if forced_tag:
|
||||||
tags.append("forced")
|
tags.append("forced")
|
||||||
|
|
||||||
# fixme when we'll be ready to add .hi to filename when saving a subtitles
|
elif hi_tag:
|
||||||
# elif hi_tag:
|
tags.append("hi")
|
||||||
# tags.append("hi")
|
|
||||||
|
|
||||||
if language:
|
if language:
|
||||||
subtitle_root += '.' + str(language.basename)
|
subtitle_root += '.' + str(language.basename)
|
||||||
|
|
|
@ -269,11 +269,11 @@
|
||||||
class="fas fa-cogs"></i><span class="hide-menu"> Settings</span></a>
|
class="fas fa-cogs"></i><span class="hide-menu"> Settings</span></a>
|
||||||
<ul aria-expanded="false" class="collapse">
|
<ul aria-expanded="false" class="collapse">
|
||||||
<li><a href="{{ url_for('settingsgeneral') }}"> General</a></li>
|
<li><a href="{{ url_for('settingsgeneral') }}"> General</a></li>
|
||||||
<li><a href="{{ url_for('settingssonarr') }}"> Sonarr</a></li>
|
|
||||||
<li><a href="{{ url_for('settingsradarr') }}"> Radarr</a></li>
|
|
||||||
<li><a href="{{ url_for('settingssubtitles') }}"> Subtitles</a></li>
|
|
||||||
<li><a href="{{ url_for('settingslanguages') }}"> Languages</a></li>
|
<li><a href="{{ url_for('settingslanguages') }}"> Languages</a></li>
|
||||||
<li><a href="{{ url_for('settingsproviders') }}"> Providers</a></li>
|
<li><a href="{{ url_for('settingsproviders') }}"> Providers</a></li>
|
||||||
|
<li><a href="{{ url_for('settingssubtitles') }}"> Subtitles</a></li>
|
||||||
|
<li><a href="{{ url_for('settingssonarr') }}"> Sonarr</a></li>
|
||||||
|
<li><a href="{{ url_for('settingsradarr') }}"> Radarr</a></li>
|
||||||
<li><a href="{{ url_for('settingsnotifications') }}"> Notifications</a></li>
|
<li><a href="{{ url_for('settingsnotifications') }}"> Notifications</a></li>
|
||||||
<li><a href="{{ url_for('settingsscheduler') }}"> Scheduler</a></li>
|
<li><a href="{{ url_for('settingsscheduler') }}"> Scheduler</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -87,7 +87,9 @@
|
||||||
title="None" data-html="true"></i>
|
title="None" data-html="true"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5><span id="seriesAudioLanguage" class="badge badge-secondary"></span></h5>
|
<h5><span id="seriesAudioLanguage"></span></h5>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<h5><span id="seriesMappedPath" class="badge badge-secondary"></span></h5>
|
<h5><span id="seriesMappedPath" class="badge badge-secondary"></span></h5>
|
||||||
<h5><span id="seriesFileCount" class="badge badge-secondary"></span></h5>
|
<h5><span id="seriesFileCount" class="badge badge-secondary"></span></h5>
|
||||||
<h5><span id="seriesType" class="badge badge-secondary"></span></h5>
|
<h5><span id="seriesType" class="badge badge-secondary"></span></h5>
|
||||||
|
@ -95,7 +97,7 @@
|
||||||
title="None" data-html="true">Tags</span></h5>
|
title="None" data-html="true">Tags</span></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5><span id="seriesSubtitlesLanguages"></span></h5>
|
<h5><span id="seriesSubtitlesLanguagesProfile" class="badge badge-secondary"></span></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5><span id="seriesHearingImpaired" class="badge badge-secondary"></span></h5>
|
<h5><span id="seriesHearingImpaired" class="badge badge-secondary"></span></h5>
|
||||||
|
@ -117,7 +119,7 @@
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>Episode</th>
|
<th>Episode</th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Audio Language</th>
|
<th>Audio Languages</th>
|
||||||
<th>Existing Subtitles</th>
|
<th>Existing Subtitles</th>
|
||||||
<th>Missing Subtitles</th>
|
<th>Missing Subtitles</th>
|
||||||
<th>Manual Search</th>
|
<th>Manual Search</th>
|
||||||
|
@ -287,42 +289,19 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Audio Profile
|
Audio Profile Languages
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<span id="edit_audio_language_span"></span>
|
<span id="edit_audio_language_span"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Subtitles Language(s)
|
Languages Profile
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="edit_languages_select" name="languages" multiple
|
<select class="selectpicker" id="edit_languages_select" name="languages"></select>
|
||||||
data-live-search="true"></select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Hearing-Impaired
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1 pl-sm-0">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="hi_checkbox" name="hi">
|
|
||||||
<span class="custom-control-label" for="hi_checkbox"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Forced
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="edit_forced_select" name="forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -564,6 +543,7 @@
|
||||||
episodesDetailsRefresh();
|
episodesDetailsRefresh();
|
||||||
getLanguages();
|
getLanguages();
|
||||||
getEnabledLanguages();
|
getEnabledLanguages();
|
||||||
|
getLanguagesProfiles();
|
||||||
|
|
||||||
var collapsedGroups = {};
|
var collapsedGroups = {};
|
||||||
|
|
||||||
|
@ -636,7 +616,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: 'audio_language.name'
|
data: 'audio_language',
|
||||||
|
render: function (data) {
|
||||||
|
var audio_languages = '';
|
||||||
|
data.forEach(appendFunc);
|
||||||
|
return audio_languages;
|
||||||
|
|
||||||
|
function appendFunc(value) {
|
||||||
|
audio_languages = audio_languages + '<span class="badge badge-secondary">' + value.name + '</span> ';
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
|
@ -686,7 +675,7 @@
|
||||||
var advtag = '';
|
var advtag = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
languages = languages + '<a href="" class="get_subtitle badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + advtag + '" data-episodepath="' + data.mapped_path + '" data-scenename="' + data.scene_name + '" data-title="' + data.title + '" data-language="' + value.code3 + '" data-hi="' + seriesDetails.hearing_impaired + '" data-forced="' + value.forced + '" data-sonarrepisodeid=' + data.sonarrEpisodeId + '>' + value.code2 + advtag + ' <i class="fas fa-search"></i></a> ';
|
languages = languages + '<a href="" class="get_subtitle badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + advtag + '" data-episodepath="' + data.mapped_path + '" data-scenename="' + data.scene_name + '" data-title="' + data.title + '" data-language="' + value.code3 + '" data-hi="' + value.hi + '" data-forced="' + value.forced + '" data-sonarrepisodeid=' + data.sonarrEpisodeId + '>' + value.code2 + advtag + ' <i class="fas fa-search"></i></a> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -694,7 +683,7 @@
|
||||||
data: null,
|
data: null,
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data.desired_languages !== '[]') {
|
if (data.desired_languages !== '[]') {
|
||||||
return '<a href="" class="manual_search badge badge-secondary" data-season=' + data.season + ' data-episode=' + data.episode + ' data-episode_title="' + data.title + '" data-episodePath="' + data.mapped_path + '" data-sceneName="' + data.scene_name + '" data-language="' + data.desired_languages + '" data-sonarrEpisodeId=' + data.sonarrEpisodeId + '><i class="fas fa-user"></i></a>';
|
return '<a href="" class="manual_search badge badge-secondary" data-season=' + data.season + ' data-episode=' + data.episode + ' data-episode_title="' + data.title + '" data-episodePath="' + data.mapped_path + '" data-sceneName="' + data.scene_name + '" data-sonarrEpisodeId=' + data.sonarrEpisodeId + '><i class="fas fa-user"></i></a>';
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -704,7 +693,7 @@
|
||||||
data: null,
|
data: null,
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data.desired_languages !== '[]') {
|
if (data.desired_languages !== '[]') {
|
||||||
return '<a href="" class="upload_subtitle badge badge-secondary" data-episodePath="' + data.mapped_path + '" data-sceneName"' + data.scene_name + '" data-sonarrSeriesId="' + seriesDetails['sonarrSeriesId'] + '" data-sonarrEpisodeId="' + data.sonarrEpisodeId + '" data-season="' + data.season + '" data-episode="' + data.episode + '" data-episode_title="' + data.title + '" data-audio_language="' + data.audio_language.name + '"><i class="fas fa-cloud-upload-alt"></i></a>';
|
return '<a href="" class="upload_subtitle badge badge-secondary" data-episodePath="' + data.mapped_path + '" data-sceneName"' + data.scene_name + '" data-sonarrSeriesId="' + seriesDetails['sonarrSeriesId'] + '" data-sonarrEpisodeId="' + data.sonarrEpisodeId + '" data-season="' + data.season + '" data-episode="' + data.episode + '" data-episode_title="' + data.title + '" data-audio_language=\'' + JSON.stringify(data.audio_language) + '\'><i class="fas fa-cloud-upload-alt"></i></a>';
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -783,9 +772,7 @@
|
||||||
|
|
||||||
episodePath = $(this).attr("data-episodePath");
|
episodePath = $(this).attr("data-episodePath");
|
||||||
sceneName = $(this).attr("data-sceneName");
|
sceneName = $(this).attr("data-sceneName");
|
||||||
language = $(this).attr("data-language");
|
profileId = seriesDetails['profileId'].id;
|
||||||
hi = seriesDetails['hearing_impaired'];
|
|
||||||
forced = seriesDetails['forced'];
|
|
||||||
sonarrSeriesId = seriesDetails['sonarrSeriesId'];
|
sonarrSeriesId = seriesDetails['sonarrSeriesId'];
|
||||||
sonarrEpisodeId = $(this).attr("data-sonarrEpisodeId");
|
sonarrEpisodeId = $(this).attr("data-sonarrEpisodeId");
|
||||||
var languages = Array.from(seriesDetails['languages']);
|
var languages = Array.from(seriesDetails['languages']);
|
||||||
|
@ -795,9 +782,7 @@
|
||||||
const values = {
|
const values = {
|
||||||
episodePath: episodePath,
|
episodePath: episodePath,
|
||||||
sceneName: sceneName,
|
sceneName: sceneName,
|
||||||
language: language,
|
profileId: profileId,
|
||||||
hi: hi,
|
|
||||||
forced: forced,
|
|
||||||
sonarrSeriesId: sonarrSeriesId,
|
sonarrSeriesId: sonarrSeriesId,
|
||||||
sonarrEpisodeId: sonarrEpisodeId,
|
sonarrEpisodeId: sonarrEpisodeId,
|
||||||
title: seriesDetails['title']
|
title: seriesDetails['title']
|
||||||
|
@ -906,7 +891,7 @@
|
||||||
data: null,
|
data: null,
|
||||||
searchable: false,
|
searchable: false,
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
return '<a href="" class="manual_download badge badge-secondary" data-episodePath="' + episodePath + '" data-sceneName="' + sceneName + '" data-sonarrEpisodeId=' + sonarrEpisodeId + ' data-subtitle="' + data.subtitle + '" data-provider="' + data.provider + '" data-language="' + data.language + '" data-forced="' + forced + '"><i class="fas fa-download" style="margin-right:0px" ></i></a>';
|
return '<a href="" class="manual_download badge badge-secondary" data-episodePath="' + episodePath + '" data-sceneName="' + sceneName + '" data-sonarrEpisodeId=' + sonarrEpisodeId + ' data-subtitle="' + data.subtitle + '" data-provider="' + data.provider + '" data-language="' + data.language + '" data-forced="' + data.forced + '"><i class="fas fa-download" style="margin-right:0px" ></i></a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -956,7 +941,7 @@
|
||||||
$('#upload_sonarrSeriesId').val($(this).data("sonarrseriesid"));
|
$('#upload_sonarrSeriesId').val($(this).data("sonarrseriesid"));
|
||||||
$('#upload_sonarrEpisodeId').val($(this).data("sonarrepisodeid"));
|
$('#upload_sonarrEpisodeId').val($(this).data("sonarrepisodeid"));
|
||||||
$('#upload_title').val($(this).data("episode_title"));
|
$('#upload_title').val($(this).data("episode_title"));
|
||||||
$('#upload_audioLanguage').val($(this).data("audio_language"));
|
$('#upload_audioLanguage').val(($(this).data("audio_language").length) ? $(this).data("audio_language")[0].name : 'None');
|
||||||
|
|
||||||
$('#manual_language_select').empty();
|
$('#manual_language_select').empty();
|
||||||
$.each(enabledLanguages, function (i, item) {
|
$.each(enabledLanguages, function (i, item) {
|
||||||
|
@ -1340,26 +1325,20 @@
|
||||||
$('#edit_button').on('click', function (e) {
|
$('#edit_button').on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("#edit_series_title_span").html(seriesDetails['title']);
|
$("#edit_series_title_span").html(seriesDetails['title']);
|
||||||
$("#edit_audio_language_span").text(seriesDetails['audio_language']['name']);
|
$("#edit_audio_language_span").empty();
|
||||||
|
$.each(seriesDetails['audio_language'], function (i, item) {
|
||||||
|
$("#edit_audio_language_span").append('<div class="badge badge-secondary">' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
$('#edit_sonarrSeriesId').val(seriesDetails['sonarrSeriesId']);
|
$('#edit_sonarrSeriesId').val(seriesDetails['sonarrSeriesId']);
|
||||||
|
|
||||||
|
|
||||||
$('#edit_languages_select').empty();
|
$('#edit_languages_select').empty();
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
$('#edit_languages_select').append('<option value="None">None</option>');
|
||||||
$('#edit_languages_select').selectpicker({maxOptions: 1});
|
$.each(languagesProfiles, function (i, item) {
|
||||||
$('#edit_languages_select').append('<option value="None">None</option>');
|
$('#edit_languages_select').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
}
|
|
||||||
$.each(enabledLanguages, function (i, item) {
|
|
||||||
$('#edit_languages_select').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
|
||||||
});
|
});
|
||||||
$("#edit_languages_select").selectpicker("refresh");
|
$("#edit_languages_select").selectpicker("refresh");
|
||||||
var selected_languages = Array();
|
$('#edit_languages_select').selectpicker('val', ((seriesDetails['profileId'].id) ? seriesDetails['profileId'].id : 'None'));
|
||||||
$.each(Array.from(seriesDetails['languages']), function (i, item) {
|
|
||||||
selected_languages.push(item.code2);
|
|
||||||
});
|
|
||||||
$('#edit_languages_select').selectpicker('val', selected_languages);
|
|
||||||
$('#hi_checkbox').prop('checked', (seriesDetails['hearing_impaired'] === 'True'));
|
|
||||||
$('#edit_forced_select').val(seriesDetails['forced']).change();
|
|
||||||
|
|
||||||
$('#editModal')
|
$('#editModal')
|
||||||
.modal({
|
.modal({
|
||||||
|
@ -1826,30 +1805,23 @@
|
||||||
$('#seriesTags').hide();
|
$('#seriesTags').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#seriesAudioLanguage').text(seriesDetails['audio_language']['name']);
|
$("#seriesAudioLanguage").empty();
|
||||||
|
$.each(seriesDetails['audio_language'], function (i, item) {
|
||||||
|
$("#seriesAudioLanguage").append('<div class="badge badge-secondary"><i class="fa fa-music"></i> ' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
$('#seriesMappedPath').text(seriesDetails['mapped_path']);
|
$('#seriesMappedPath').text(seriesDetails['mapped_path']);
|
||||||
$('#seriesMappedPath').attr("data-original-title", seriesDetails['mapped_path']);
|
$('#seriesMappedPath').attr("data-original-title", seriesDetails['mapped_path']);
|
||||||
$('#seriesFileCount').text(seriesDetails['episodeFileCount'] + ' files');
|
$('#seriesFileCount').text(seriesDetails['episodeFileCount'] + ' files');
|
||||||
$('#seriesType').text(seriesDetails['seriesType']);
|
$('#seriesType').text(seriesDetails['seriesType']);
|
||||||
|
|
||||||
var languages = '';
|
$('#seriesSubtitlesLanguagesProfile').text(seriesDetails['profileId'].name);
|
||||||
if (seriesDetails['languages'] && seriesDetails['languages'] !== 'None') {
|
|
||||||
seriesDetails['languages'].forEach(appendFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
|
||||||
languages = languages + '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#seriesSubtitlesLanguages').html(languages);
|
|
||||||
$('#seriesHearingImpaired').text('Hearing-Impaired: ' + seriesDetails['hearing_impaired']);
|
|
||||||
$('#seriesForced').text('Forced: ' + seriesDetails['forced']);
|
|
||||||
$('#seriesDescription').text(seriesDetails['overview']);
|
$('#seriesDescription').text(seriesDetails['overview']);
|
||||||
|
|
||||||
if (seriesDetails['desired_languages'] == '[]') {
|
if (seriesDetails['profileId'].id) {
|
||||||
$('#search_button').hide();
|
|
||||||
} else {
|
|
||||||
$('#search_button').show();
|
$('#search_button').show();
|
||||||
|
} else {
|
||||||
|
$('#search_button').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('[data-toggle="tooltip"]').tooltip({html: true});
|
$('[data-toggle="tooltip"]').tooltip({html: true});
|
||||||
|
@ -1873,5 +1845,14 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLanguagesProfiles() {
|
||||||
|
$.ajax({
|
||||||
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
|
success: function (data) {
|
||||||
|
languagesProfiles = data['data'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock tail %}
|
{% endblock tail %}
|
||||||
|
|
122
views/movie.html
122
views/movie.html
|
@ -94,17 +94,15 @@
|
||||||
<i class="far fa-clone" id="moviealternativeTitles" data-toggle="tooltip" data-placement="right" title="None" data-html="true"></i>
|
<i class="far fa-clone" id="moviealternativeTitles" data-toggle="tooltip" data-placement="right" title="None" data-html="true"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5><span id="movieAudioLanguage" class="badge badge-secondary"></span></h5>
|
<h5><span id="movieAudioLanguage"></span></h5>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<h5><span id="movieMappedPath" data-toggle="tooltip" data-placement="right" title="None" class="badge badge-secondary"></span></h5>
|
<h5><span id="movieMappedPath" data-toggle="tooltip" data-placement="right" title="None" class="badge badge-secondary"></span></h5>
|
||||||
<h5><span id="movieTags" class="badge badge-secondary" data-toggle="tooltip" data-placement="right"
|
<h5><span id="movieTags" class="badge badge-secondary" data-toggle="tooltip" data-placement="right"
|
||||||
title="None" data-html="true">Tags</span></h5>
|
title="None" data-html="true">Tags</span></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5><span id="movieSubtitlesLanguages"></span></h5>
|
<h5><span id="movieSubtitlesLanguagesProfile" class="badge badge-secondary"></span></h5>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<h5><span id="movieHearingImpaired" class="badge badge-secondary"></span></h5>
|
|
||||||
<h5><span id="movieForced" class="badge badge-secondary"></span></h5>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<span id="movieDescription"></span>
|
<span id="movieDescription"></span>
|
||||||
|
@ -244,33 +242,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Subtitles Language(s)
|
Languages Profile
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="edit_languages_select" name="languages" multiple data-live-search="true"></select>
|
<select class="selectpicker" id="edit_languages_select" name="languages"></select>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Hearing-Impaired
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1 pl-sm-0">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="hi_checkbox" name="hi">
|
|
||||||
<span class="custom-control-label" for="hi_checkbox"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Forced
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="edit_forced_select" name="forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -511,6 +486,7 @@
|
||||||
movieDetailsRefresh();
|
movieDetailsRefresh();
|
||||||
getLanguages();
|
getLanguages();
|
||||||
getEnabledLanguages();
|
getEnabledLanguages();
|
||||||
|
getLanguagesProfiles();
|
||||||
|
|
||||||
//test
|
//test
|
||||||
$('#movieSubtitles').on('click', '.remove_subtitles', function(e){
|
$('#movieSubtitles').on('click', '.remove_subtitles', function(e){
|
||||||
|
@ -544,8 +520,8 @@
|
||||||
moviePath: movieDetails['mapped_path'],
|
moviePath: movieDetails['mapped_path'],
|
||||||
sceneName: movieDetails['sceneName'],
|
sceneName: movieDetails['sceneName'],
|
||||||
language: $(this).attr("data-language"),
|
language: $(this).attr("data-language"),
|
||||||
hi: movieDetails['hearing_impaired'],
|
hi: $(this).attr("data-hi"),
|
||||||
forced:$(this).attr("data-forced"),
|
forced: $(this).attr("data-forced"),
|
||||||
radarrId: movieDetails['radarrId'],
|
radarrId: movieDetails['radarrId'],
|
||||||
title: movieDetails['title']
|
title: movieDetails['title']
|
||||||
};
|
};
|
||||||
|
@ -569,9 +545,7 @@
|
||||||
|
|
||||||
moviePath = movieDetails['mapped_path'];
|
moviePath = movieDetails['mapped_path'];
|
||||||
sceneName = movieDetails['sceneName'];
|
sceneName = movieDetails['sceneName'];
|
||||||
language = movieDetails['desired_languages'];
|
profileId = movieDetails['profileId'].id;
|
||||||
hi = movieDetails['hearing_impaired'];
|
|
||||||
forced = movieDetails['forced'];
|
|
||||||
radarrId = movieDetails['radarrId'];
|
radarrId = movieDetails['radarrId'];
|
||||||
var languages = Array.from(movieDetails['languages']);
|
var languages = Array.from(movieDetails['languages']);
|
||||||
var is_pb = languages.includes('pb');
|
var is_pb = languages.includes('pb');
|
||||||
|
@ -580,9 +554,7 @@
|
||||||
const values = {
|
const values = {
|
||||||
moviePath: moviePath,
|
moviePath: moviePath,
|
||||||
sceneName: sceneName,
|
sceneName: sceneName,
|
||||||
language: language,
|
profileId: profileId,
|
||||||
hi: hi,
|
|
||||||
forced: forced,
|
|
||||||
radarrId: radarrId,
|
radarrId: radarrId,
|
||||||
title: movieDetails['title']
|
title: movieDetails['title']
|
||||||
};
|
};
|
||||||
|
@ -683,7 +655,7 @@
|
||||||
{ data: null,
|
{ data: null,
|
||||||
searchable: false,
|
searchable: false,
|
||||||
render: function ( data ) {
|
render: function ( data ) {
|
||||||
return '<a href="" class="manual_download badge badge-secondary" data-moviePath="'+moviePath+'" data-sceneName="'+sceneName+'" data-subtitle="'+data.subtitle+'" data-provider="'+data.provider+'" data-language="'+data.language+'" data-forced="'+forced+'"><i class="fas fa-download" style="margin-right:0px" ></i></a>';
|
return '<a href="" class="manual_download badge badge-secondary" data-moviePath="'+moviePath+'" data-sceneName="'+sceneName+'" data-subtitle="'+data.subtitle+'" data-provider="'+data.provider+'" data-language="'+data.language+'" data-forced="'+data.forced+'"><i class="fas fa-download" style="margin-right:0px" ></i></a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -730,7 +702,7 @@
|
||||||
$('#upload_sceneName').val(movieDetails['sceneName']);
|
$('#upload_sceneName').val(movieDetails['sceneName']);
|
||||||
$('#upload_radarrId').val(movieDetails['radarrId']);
|
$('#upload_radarrId').val(movieDetails['radarrId']);
|
||||||
$('#upload_title').val(movieDetails['title']);
|
$('#upload_title').val(movieDetails['title']);
|
||||||
$('#upload_audioLanguage').val(movieDetails['audio_language']['name']);
|
$('#upload_audioLanguage').val((movieDetails['audio_language'].length) ? movieDetails['audio_language'][0].name : 'None');
|
||||||
|
|
||||||
$('#manual_language_select').empty();
|
$('#manual_language_select').empty();
|
||||||
$.each(enabledLanguages, function (i, item) {
|
$.each(enabledLanguages, function (i, item) {
|
||||||
|
@ -794,26 +766,20 @@
|
||||||
$('#edit_button').on('click', function(e){
|
$('#edit_button').on('click', function(e){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("#edit_movie_title_span").html(movieDetails['title']);
|
$("#edit_movie_title_span").html(movieDetails['title']);
|
||||||
$("#edit_audio_language_span").text(movieDetails['audio_language']['name']);
|
$("#edit_audio_language_span").empty();
|
||||||
$('#edit_radarrId').val(movieDetails['radarrId']);
|
$.each(movieDetails['audio_language'], function (i, item) {
|
||||||
|
$("#edit_audio_language_span").append('<div class="badge badge-secondary">' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
|
$('#edit_radarrId').val(movieDetails['radarrId']);
|
||||||
|
|
||||||
|
|
||||||
$('#edit_languages_select').empty();
|
$('#edit_languages_select').empty();
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
$('#edit_languages_select').append('<option value="None">None</option>');
|
||||||
$('#edit_languages_select').selectpicker({maxOptions: 1});
|
$.each(languagesProfiles, function (i, item) {
|
||||||
$('#edit_languages_select').append('<option value="None">None</option>');
|
$('#edit_languages_select').append('<option value="'+item.profileId+'">'+item.name+'</option>');
|
||||||
}
|
|
||||||
$.each(enabledLanguages, function (i, item) {
|
|
||||||
$('#edit_languages_select').append('<option value="'+item.code2+'">'+item.name+'</option>');
|
|
||||||
});
|
});
|
||||||
$("#edit_languages_select").selectpicker("refresh");
|
$("#edit_languages_select").selectpicker("refresh");
|
||||||
var selected_languages = Array();
|
$('#edit_languages_select').selectpicker('val', ((movieDetails['profileId'].id) ? movieDetails['profileId'].id : 'None'));
|
||||||
$.each(Array.from(movieDetails['languages']), function (i, item) {
|
|
||||||
selected_languages.push(item.code2);
|
|
||||||
});
|
|
||||||
$('#edit_languages_select').selectpicker('val', selected_languages);
|
|
||||||
$('#hi_checkbox').prop('checked', (movieDetails['hearing_impaired'] === 'True'));
|
|
||||||
$('#edit_forced_select').val(movieDetails['forced']).change();
|
|
||||||
|
|
||||||
$('#editModal')
|
$('#editModal')
|
||||||
.modal({
|
.modal({
|
||||||
|
@ -1223,22 +1189,15 @@
|
||||||
$('#movieTags').hide();
|
$('#movieTags').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#movieAudioLanguage').text(movieDetails['audio_language']['name']);
|
$("#movieAudioLanguage").empty();
|
||||||
$('#movieMappedPath').text(movieDetails['mapped_path']);
|
$.each(movieDetails['audio_language'], function (i, item) {
|
||||||
|
$("#movieAudioLanguage").append('<div class="badge badge-secondary"><i class="fa fa-music"></i> ' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
|
$('#movieMappedPath').text(movieDetails['mapped_path']);
|
||||||
$('#movieMappedPath').attr("data-original-title", movieDetails['mapped_path']);
|
$('#movieMappedPath').attr("data-original-title", movieDetails['mapped_path']);
|
||||||
|
|
||||||
var languages = '';
|
$('#movieSubtitlesLanguagesProfile').text(movieDetails['profileId'].name);
|
||||||
if (movieDetails['languages'] && movieDetails['languages'] !== 'None') {
|
|
||||||
movieDetails['languages'].forEach(appendFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
|
||||||
languages += '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#movieSubtitlesLanguages').html(languages);
|
|
||||||
$('#movieHearingImpaired').text('Hearing-Impaired: ' + movieDetails['hearing_impaired']);
|
|
||||||
$('#movieForced').text('Forced: ' + movieDetails['forced']);
|
|
||||||
$('#movieDescription').text(movieDetails['overview']);
|
$('#movieDescription').text(movieDetails['overview']);
|
||||||
|
|
||||||
var missing_languages = '';
|
var missing_languages = '';
|
||||||
|
@ -1248,11 +1207,11 @@
|
||||||
|
|
||||||
function missingAppendFunc(value) {
|
function missingAppendFunc(value) {
|
||||||
if (value.forced) {
|
if (value.forced) {
|
||||||
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-forced=' + value.forced + '>' + value.code2 + ':forced <i class="fas fa-search"></i></button> ';
|
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + ' Forced" data-language="' + value.code3 + '" data-hi="' + value.hi + '" data-forced="' + value.forced + '">' + value.code2 + ':forced <i class="fas fa-search"></i></button> ';
|
||||||
} else if (value.hi) {
|
} else if (value.hi) {
|
||||||
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-forced=' + value.forced + '>' + value.code2 + ':HI <i class="fas fa-search"></i></button> ';
|
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + ' HI" data-language="' + value.code3 + '" data-hi="' + value.hi + '" data-forced="' + value.forced + '">' + value.code2 + ':HI <i class="fas fa-search"></i></button> ';
|
||||||
} else {
|
} else {
|
||||||
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-forced=' + value.forced + '>' + value.code2 + ' <i class="fas fa-search"></i></button> ';
|
missing_languages += '<button class="get_subtitle btn btn-secondary btn-sm" type="button" data-toggle="tooltip" data-placement="right" data-original-title="' + value.name + '" data-language="' + value.code3 + '" data-hi="' + value.hi + '" data-forced="' + value.forced + '">' + value.code2 + ' <i class="fas fa-search"></i></button> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,14 +1219,14 @@
|
||||||
|
|
||||||
$('[data-toggle="tooltip"]').tooltip({html: true});
|
$('[data-toggle="tooltip"]').tooltip({html: true});
|
||||||
|
|
||||||
if (movieDetails['desired_languages'] == '[]') {
|
if (movieDetails['profileId'].id) {
|
||||||
$('#search_button').hide();
|
|
||||||
$('#manual_button').hide();
|
|
||||||
$('#upload_button').hide();
|
|
||||||
} else {
|
|
||||||
$('#search_button').show();
|
$('#search_button').show();
|
||||||
$('#manual_button').show();
|
$('#manual_button').show();
|
||||||
$('#upload_button').show();
|
$('#upload_button').show();
|
||||||
|
} else {
|
||||||
|
$('#search_button').hide();
|
||||||
|
$('#manual_button').hide();
|
||||||
|
$('#upload_button').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1335,5 +1294,14 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLanguagesProfiles() {
|
||||||
|
$.ajax({
|
||||||
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
|
success: function (data) {
|
||||||
|
languagesProfiles = data['data'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock tail %}
|
{% endblock tail %}
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Path Exist</th>
|
<th>Path Exist</th>
|
||||||
<th>Audio Language</th>
|
<th>Audio Language</th>
|
||||||
<th>Subtitles Languages</th>
|
<th>Languages Profile</th>
|
||||||
<th>Hearing-Impaired</th>
|
|
||||||
<th>Forced</th>
|
|
||||||
<th>Missing Subtitles</th>
|
<th>Missing Subtitles</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -55,34 +53,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Subtitles Language(s)
|
Languages Profile
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="edit_languages_select" name="languages" multiple
|
<select class="selectpicker" id="edit_languages_select" name="languages"></select>
|
||||||
data-live-search="true"></select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Hearing-Impaired
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1 pl-sm-0">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="hi_checkbox" name="hi">
|
|
||||||
<span class="custom-control-label" for="hi_checkbox"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Forced
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="edit_forced_select" name="forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -102,8 +76,7 @@
|
||||||
{% block tail %}
|
{% block tail %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
getLanguages();
|
getLanguagesProfiles();
|
||||||
getEnabledLanguages();
|
|
||||||
|
|
||||||
events.on('event', function (event) {
|
events.on('event', function (event) {
|
||||||
var event_json = JSON.parse(event);
|
var event_json = JSON.parse(event);
|
||||||
|
@ -185,29 +158,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{data: "audio_language.name"},
|
|
||||||
{
|
{
|
||||||
data: "languages",
|
data: 'audio_language',
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data && data !== 'None') {
|
var audio_languages = '';
|
||||||
var languages = '';
|
data.forEach(appendFunc);
|
||||||
data.forEach(appendFunc);
|
return audio_languages;
|
||||||
return languages;
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
function appendFunc(value) {
|
||||||
languages = languages + '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
audio_languages = audio_languages + '<span class="badge badge-secondary">' + value.name + '</span> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: "hearing_impaired",
|
data: "profileId.name",
|
||||||
className: "dt-center"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: "forced",
|
|
||||||
className: "dt-center"
|
className: "dt-center"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -229,7 +193,7 @@
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
return '<a href="" class="edit_button badge badge-secondary" data-radarrId=' + data.radarrId + ' data-audiolanguage="' + data.audio_language.name + '" data-title="' + data.title + '" data-languages=' + JSON.stringify(data.languages) + ' data-hi="' + data.hearing_impaired + '" data-forced="' + data.forced + '"><i class="fas fa-wrench"></i></a>';
|
return '<a href="" class="edit_button badge badge-secondary" data-radarrId=' + data.radarrId + ' data-audiolanguage=\'' + JSON.stringify(data.audio_language) + '\' data-title="' + data.title + '" data-languages_profile=' + data.profileId.id + ' data-hi="' + data.hearing_impaired + '" data-forced="' + data.forced + '"><i class="fas fa-wrench"></i></a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -239,28 +203,20 @@
|
||||||
$('#movies').on('click', '.edit_button', function (e) {
|
$('#movies').on('click', '.edit_button', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("#edit_movies_title_span").html($(this).data('title'));
|
$("#edit_movies_title_span").html($(this).data('title'));
|
||||||
$("#edit_audio_language_span").html($(this).data('audiolanguage'));
|
$("#edit_audio_language_span").empty();
|
||||||
|
$.each($(this).data('audiolanguage'), function (i, item) {
|
||||||
|
$("#edit_audio_language_span").append('<div class="badge badge-secondary">' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
$('#edit_radarrId').val($(this).data('radarrid'));
|
$('#edit_radarrId').val($(this).data('radarrid'));
|
||||||
|
|
||||||
|
|
||||||
$('#edit_languages_select').empty();
|
$('#edit_languages_select').empty();
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
$('#edit_languages_select').append('<option value="None">None</option>');
|
||||||
$('#edit_languages_select').selectpicker({maxOptions: 1});
|
$.each(languagesProfiles, function (i, item) {
|
||||||
}
|
$('#edit_languages_select').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
|
||||||
$('#edit_languages_select').append('<option value="None">None</option>');
|
|
||||||
}
|
|
||||||
$.each(enabledLanguages, function (i, item) {
|
|
||||||
$('#edit_languages_select').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
|
||||||
});
|
});
|
||||||
$("#edit_languages_select").selectpicker("refresh");
|
$("#edit_languages_select").selectpicker("refresh");
|
||||||
var selected_languages = Array();
|
$('#edit_languages_select').selectpicker('val', (($(this).data('languages_profile')) ? $(this).data('languages_profile') : 'None'));
|
||||||
$.each(Array.from($(this).data('languages')), function (i, item) {
|
|
||||||
selected_languages.push(item.code2);
|
|
||||||
});
|
|
||||||
$('#edit_languages_select').selectpicker('val', selected_languages);
|
|
||||||
$('#hi_checkbox').prop('checked', ($(this).data('hi') === 'True'));
|
|
||||||
$('#edit_forced_select').val($(this).data('forced')).change();
|
|
||||||
|
|
||||||
$('#editModal')
|
$('#editModal')
|
||||||
.modal({
|
.modal({
|
||||||
|
@ -288,20 +244,11 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getLanguages() {
|
function getLanguagesProfiles() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.languages') }}?enabled=false",
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
availableLanguages = data;
|
languagesProfiles = data['data'];
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnabledLanguages() {
|
|
||||||
$.ajax({
|
|
||||||
url: "{{ url_for('api.languages') }}?enabled=true",
|
|
||||||
success: function (data) {
|
|
||||||
enabledLanguages = data;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,37 +17,16 @@
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Audio Language</th>
|
<th>Audio Language</th>
|
||||||
<th>Subtitles Languages</th>
|
<th>Languages Profile</th>
|
||||||
<th>Hearing-Impaired</th>
|
|
||||||
<th>Forced</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<nav id="edit_bar" class="navbar fixed-bottom navbar-dark bg-dark">
|
<nav id="edit_bar" class="navbar fixed-bottom navbar-dark bg-dark justify-content-end">
|
||||||
<div class="form-check form-check-inline">
|
<div class="form-check form-check-inline">
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
<div class="form-group" style="margin-bottom: 0px;">
|
||||||
<label for="languages_select">Language(s): </label>
|
<label for="languages_select">Languages Profile: </label>
|
||||||
<select class="selectpicker" id="languages_select" name="languages" title="No change" multiple></select>
|
<select class="selectpicker" id="languages_select" name="languages"></select>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
|
||||||
<label for="hi_select">Hearing-Impaired: </label>
|
|
||||||
<select class="selectpicker show-tick" id="hi_select" name="hi" title="No change" multiple>
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
|
||||||
<label for="forced_select">Forced: </label>
|
|
||||||
<select class="selectpicker show-tick" id="forced_select" name="forced" title="No change" multiple>
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check form-check-inline">
|
<div class="form-check form-check-inline">
|
||||||
|
@ -114,29 +93,20 @@
|
||||||
return '<a href="' + "{{ url_for( 'movie', no='tempvalue' ) }}".replace("tempvalue", data.radarrId) + '">' + data.title + '</a>'
|
return '<a href="' + "{{ url_for( 'movie', no='tempvalue' ) }}".replace("tempvalue", data.radarrId) + '">' + data.title + '</a>'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{data: "audio_language.name"},
|
|
||||||
{
|
{
|
||||||
data: "languages",
|
data: 'audio_language',
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data && data !== 'None') {
|
var audio_languages = '';
|
||||||
var languages = '';
|
data.forEach(appendFunc);
|
||||||
data.forEach(appendFunc);
|
return audio_languages;
|
||||||
return languages;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
function appendFunc(value) {
|
||||||
languages = languages + '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
audio_languages = audio_languages + '<span class="badge badge-secondary">' + value.name + '</span> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: "hearing_impaired",
|
data: "profileId.name",
|
||||||
className: "dt-center"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: "forced",
|
|
||||||
className: "dt-center"
|
className: "dt-center"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -180,19 +150,11 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
|
||||||
$('#languages_select').selectpicker({maxOptions: 1});
|
|
||||||
}
|
|
||||||
$('#hi_select').selectpicker({maxOptions: 1});
|
|
||||||
$('#forced_select').selectpicker({maxOptions: 1});
|
|
||||||
|
|
||||||
$('#save_button').on('click', function (e) {
|
$('#save_button').on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const values = {
|
const values = {
|
||||||
radarrid: table.rows({selected: true}).ids().toArray(),
|
radarrid: table.rows({selected: true}).ids().toArray(),
|
||||||
languages: $('#languages_select').val(),
|
languages: $('#languages_select').val()
|
||||||
hi: $('#hi_select').val(),
|
|
||||||
forced: $('#forced_select').val()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -208,9 +170,7 @@
|
||||||
},
|
},
|
||||||
success: function () {
|
success: function () {
|
||||||
table.rows().deselect();
|
table.rows().deselect();
|
||||||
$('#languages_select').selectpicker('val', '');
|
$('#languages_select').selectpicker('val', 'None');
|
||||||
$('#hi_select').selectpicker('val', '');
|
|
||||||
$('#forced_select').selectpicker('val', '');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -218,11 +178,11 @@
|
||||||
|
|
||||||
function getEnabledLanguages() {
|
function getEnabledLanguages() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.languages') }}?enabled=true",
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$('#languages_select').append('<option value="None">None</option>');
|
$('#languages_select').append('<option value="None">None</option>');
|
||||||
$.each(data, function (i, item) {
|
$.each(data['data'], function (i, item) {
|
||||||
$('#languages_select').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
$('#languages_select').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
});
|
});
|
||||||
$("#languages_select").selectpicker("refresh");
|
$("#languages_select").selectpicker("refresh");
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Path Exist</th>
|
<th>Path Exist</th>
|
||||||
<th>Audio Profile</th>
|
<th>Audio Profile Languages</th>
|
||||||
<th>Subtitles Languages</th>
|
<th>Languages Profile</th>
|
||||||
<th>Hearing-Impaired</th>
|
|
||||||
<th>Forced</th>
|
|
||||||
<th>Subtitles</th>
|
<th>Subtitles</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -46,42 +44,19 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Audio Profile
|
Audio Profile Languages
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<span id="edit_audio_language_span"></span>
|
<span id="edit_audio_language_span"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
Subtitles Language(s)
|
Languages Profile
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="edit_languages_select" name="languages" multiple
|
<select class="selectpicker" id="edit_languages_select" name="languages"></select>
|
||||||
data-live-search="true"></select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Hearing-Impaired
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1 pl-sm-0">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="hi_checkbox" name="hi">
|
|
||||||
<span class="custom-control-label" for="hi_checkbox"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-3 text-right">
|
|
||||||
Forced
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="edit_forced_select" name="forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -102,8 +77,7 @@
|
||||||
{% block tail %}
|
{% block tail %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
getLanguages();
|
getLanguagesProfiles();
|
||||||
getEnabledLanguages();
|
|
||||||
|
|
||||||
events.on('event', function (event) {
|
events.on('event', function (event) {
|
||||||
var event_json = JSON.parse(event);
|
var event_json = JSON.parse(event);
|
||||||
|
@ -176,29 +150,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{data: "audio_language.name"},
|
|
||||||
{
|
{
|
||||||
data: "languages",
|
data: 'audio_language',
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data && data !== 'None') {
|
var audio_languages = '';
|
||||||
var languages = '';
|
data.forEach(appendFunc);
|
||||||
data.forEach(appendFunc);
|
return audio_languages;
|
||||||
return languages;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
function appendFunc(value) {
|
||||||
languages = languages + '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
audio_languages = audio_languages + '<span class="badge badge-secondary">' + value.name + '</span> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: "hearing_impaired",
|
data: "profileId.name",
|
||||||
className: "dt-center"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: "forced",
|
|
||||||
className: "dt-center"
|
className: "dt-center"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -209,7 +174,8 @@
|
||||||
var completed = data.episodeFileCount - data.episodeMissingCount;
|
var completed = data.episodeFileCount - data.episodeMissingCount;
|
||||||
var completed_style = '';
|
var completed_style = '';
|
||||||
var completed_text = '';
|
var completed_text = '';
|
||||||
if (data.episodeFileCount && data.languages !== 'None') {
|
console.log(data.profileId);
|
||||||
|
if (data.episodeFileCount && data.profileId.id !== null) {
|
||||||
completed_style = ' style="width: ' + completed / total * 100 + '%;"';
|
completed_style = ' style="width: ' + completed / total * 100 + '%;"';
|
||||||
completed_text = completed + '/' + total;
|
completed_text = completed + '/' + total;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +185,7 @@
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
return '<a href="" class="edit_button badge badge-secondary" data-sonarrSeriesId=' + data.sonarrSeriesId + ' data-audiolanguage="' + data.audio_language.name + '" data-title="' + data.title + '" data-languages=' + JSON.stringify(data.languages) + ' data-hi="' + data.hearing_impaired + '" data-forced="' + data.forced + '"><i class="fas fa-wrench"></i></a>';
|
return '<a href="" class="edit_button badge badge-secondary" data-sonarrSeriesId=' + data.sonarrSeriesId + ' data-audiolanguage=\'' + JSON.stringify(data.audio_language) + '\' data-title="' + data.title + '" data-languages_profile=' + data.profileId.id + ' data-hi="' + data.hearing_impaired + '" data-forced="' + data.forced + '"><i class="fas fa-wrench"></i></a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -229,28 +195,20 @@
|
||||||
$('#series').on('click', '.edit_button', function (e) {
|
$('#series').on('click', '.edit_button', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("#edit_series_title_span").html($(this).data('title'));
|
$("#edit_series_title_span").html($(this).data('title'));
|
||||||
$("#edit_audio_language_span").html($(this).data('audiolanguage'));
|
$("#edit_audio_language_span").empty();
|
||||||
|
$.each($(this).data('audiolanguage'), function (i, item) {
|
||||||
|
$("#edit_audio_language_span").append('<div class="badge badge-secondary">' + item['name'] + '</div> ');
|
||||||
|
})
|
||||||
$('#edit_sonarrSeriesId').val($(this).data('sonarrseriesid'));
|
$('#edit_sonarrSeriesId').val($(this).data('sonarrseriesid'));
|
||||||
|
|
||||||
|
|
||||||
$('#edit_languages_select').empty();
|
$('#edit_languages_select').empty();
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
$('#edit_languages_select').append('<option value="None">None</option>');
|
||||||
$('#edit_languages_select').selectpicker({maxOptions: 1});
|
$.each(languagesProfiles, function (i, item) {
|
||||||
}
|
$('#edit_languages_select').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
|
||||||
$('#edit_languages_select').append('<option value="None">None</option>');
|
|
||||||
}
|
|
||||||
$.each(enabledLanguages, function (i, item) {
|
|
||||||
$('#edit_languages_select').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
|
||||||
});
|
});
|
||||||
$("#edit_languages_select").selectpicker("refresh");
|
$("#edit_languages_select").selectpicker("refresh");
|
||||||
var selected_languages = Array();
|
$('#edit_languages_select').selectpicker('val', (($(this).data('languages_profile')) ? $(this).data('languages_profile') : 'None'));
|
||||||
$.each(Array.from($(this).data('languages')), function (i, item) {
|
|
||||||
selected_languages.push(item.code2);
|
|
||||||
});
|
|
||||||
$('#edit_languages_select').selectpicker('val', selected_languages);
|
|
||||||
$('#hi_checkbox').prop('checked', ($(this).data('hi') === 'True'));
|
|
||||||
$('#edit_forced_select').val($(this).data('forced')).change();
|
|
||||||
|
|
||||||
$('#editModal')
|
$('#editModal')
|
||||||
.modal({
|
.modal({
|
||||||
|
@ -278,20 +236,11 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getLanguages() {
|
function getLanguagesProfiles() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.languages') }}?enabled=false",
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
availableLanguages = data;
|
languagesProfiles = data['data'];
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnabledLanguages() {
|
|
||||||
$.ajax({
|
|
||||||
url: "{{ url_for('api.languages') }}?enabled=true",
|
|
||||||
success: function (data) {
|
|
||||||
enabledLanguages = data;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,38 +16,17 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Audio Profile</th>
|
<th>Audio Profile Languages</th>
|
||||||
<th>Subtitles Languages</th>
|
<th>Languages Profile</th>
|
||||||
<th>Hearing-Impaired</th>
|
|
||||||
<th>Forced</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<nav id="edit_bar" class="navbar fixed-bottom navbar-dark bg-dark">
|
<nav id="edit_bar" class="navbar fixed-bottom navbar-dark bg-dark justify-content-end">
|
||||||
<div class="form-check form-check-inline">
|
<div class="form-check form-check-inline">
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
<div class="form-group" style="margin-bottom: 0px;">
|
||||||
<label for="languages_select">Language(s): </label>
|
<label for="languages_select">Languages Profile: </label>
|
||||||
<select class="selectpicker" id="languages_select" name="languages" title="No change" multiple></select>
|
<select class="selectpicker" id="languages_select" name="languages"></select>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
|
||||||
<label for="hi_select">Hearing-Impaired: </label>
|
|
||||||
<select class="selectpicker show-tick" id="hi_select" name="hi" title="No change" multiple>
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<div class="form-group" style="margin-bottom: 0px;">
|
|
||||||
<label for="forced_select">Forced: </label>
|
|
||||||
<select class="selectpicker show-tick" id="forced_select" name="forced" title="No change" multiple>
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check form-check-inline">
|
<div class="form-check form-check-inline">
|
||||||
|
@ -114,25 +93,19 @@
|
||||||
return '<a href="' + "{{ url_for( 'episodes', no='tempvalue' ) }}".replace("tempvalue", data.sonarrSeriesId) + '">' + data.title + '</a>'
|
return '<a href="' + "{{ url_for( 'episodes', no='tempvalue' ) }}".replace("tempvalue", data.sonarrSeriesId) + '">' + data.title + '</a>'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{data: "audio_language.name"},
|
|
||||||
{
|
{
|
||||||
data: "languages",
|
data: 'audio_language',
|
||||||
render: function (data) {
|
render: function (data) {
|
||||||
if (data && data !== 'None') {
|
var audio_languages = '';
|
||||||
var languages = '';
|
data.forEach(appendFunc);
|
||||||
data.forEach(appendFunc);
|
return audio_languages;
|
||||||
return languages;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendFunc(value) {
|
function appendFunc(value) {
|
||||||
languages = languages + '<span class="badge badge-secondary" data-toggle="tooltip" data-placement="right" title="' + value.name + '">' + value.code2 + '</span> ';
|
audio_languages = audio_languages + '<span class="badge badge-secondary">' + value.name + '</span> ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{data: "hearing_impaired", className: "dt-center"},
|
{data: "profileId.name", className: "dt-center"}
|
||||||
{data: "forced", className: "dt-center"}
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -174,19 +147,11 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ('{{settings.general.single_language}}' === 'True') {
|
|
||||||
$('#languages_select').selectpicker({maxOptions: 1});
|
|
||||||
}
|
|
||||||
$('#hi_select').selectpicker({maxOptions: 1});
|
|
||||||
$('#forced_select').selectpicker({maxOptions: 1});
|
|
||||||
|
|
||||||
$('#save_button').on('click', function (e) {
|
$('#save_button').on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const values = {
|
const values = {
|
||||||
seriesid: table.rows({selected: true}).ids().toArray(),
|
seriesid: table.rows({selected: true}).ids().toArray(),
|
||||||
languages: $('#languages_select').val(),
|
languages: $('#languages_select').val()
|
||||||
hi: $('#hi_select').val(),
|
|
||||||
forced: $('#forced_select').val()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -202,9 +167,7 @@
|
||||||
},
|
},
|
||||||
success: function () {
|
success: function () {
|
||||||
table.rows().deselect();
|
table.rows().deselect();
|
||||||
$('#languages_select').selectpicker('val', '');
|
$('#languages_select').selectpicker('val', 'None');
|
||||||
$('#hi_select').selectpicker('val', '');
|
|
||||||
$('#forced_select').selectpicker('val', '');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -212,11 +175,11 @@
|
||||||
|
|
||||||
function getEnabledLanguages() {
|
function getEnabledLanguages() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.languages') }}?enabled=true",
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$('#languages_select').append('<option value="None">None</option>');
|
$('#languages_select').append('<option value="None">None</option>');
|
||||||
$.each(data, function (i, item) {
|
$.each(data['data'], function (i, item) {
|
||||||
$('#languages_select').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
$('#languages_select').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
});
|
});
|
||||||
$("#languages_select").selectpicker("refresh");
|
$("#languages_select").selectpicker("refresh");
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
.warning {
|
.warning {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.dataTable tbody tr.selected a, table.dataTable tbody th.selected a, table.dataTable tbody td.selected a {
|
||||||
|
color: revert;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock page_head %}
|
{% endblock page_head %}
|
||||||
|
|
||||||
|
@ -31,7 +35,7 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container-fluid" style="padding-top: 3em;">
|
<div class="container-fluid" style="padding-top: 3em;">
|
||||||
<form class="form" name="settings_form" id="settings_form">
|
<form class="form" name="settings_form" id="settings_form">
|
||||||
<h4>Subtitles languages</h4>
|
<h4>Subtitles Languages</h4>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
|
@ -49,7 +53,7 @@
|
||||||
<br>
|
<br>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
<b>Enabled Languages</b>
|
<b>Languages Filter</b>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="enabled_languages" name="enabled_languages" data-live-search="true" multiple></select>
|
<select class="selectpicker" id="enabled_languages" name="enabled_languages" data-live-search="true" multiple></select>
|
||||||
|
@ -57,6 +61,24 @@
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<h4>Languages Profiles</h4>
|
||||||
|
<hr/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<table class="table table-striped" id="languages_profiles" style="width:100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Cutoff</th>
|
||||||
|
<th>Languages</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
<h4>Default Settings</h4>
|
<h4>Default Settings</h4>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -74,38 +96,13 @@
|
||||||
<div id="series_default_div">
|
<div id="series_default_div">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 text-right">
|
<div class="col-sm-4 text-right">
|
||||||
<b>Languages</b>
|
<b>Languages Profile Id</b>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="settings-general-serie_default_language" name="settings-general-serie_default_language" multiple></select>
|
<select class="selectpicker" id="settings-general-serie_default_profile" name="settings-general-serie_default_profile"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<b>Hearing-Impaired</b>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="settings-general-serie_default_hi" name="settings-general-serie_default_hi">
|
|
||||||
<span class="custom-control-label" for="settings-general-serie_default_hi"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<b>Forced</b>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="settings-general-serie_default_forced" name="settings-general-serie_default_forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 text-right">
|
<div class="col-sm-3 text-right">
|
||||||
<b>Movies Default Settings</b>
|
<b>Movies Default Settings</b>
|
||||||
|
@ -121,39 +118,140 @@
|
||||||
<div id="movies_default_div">
|
<div id="movies_default_div">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 text-right">
|
<div class="col-sm-4 text-right">
|
||||||
<b>Languages</b>
|
<b>Languages Profile Id</b>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
<div class="form-group col-sm-8 pl-sm-0">
|
||||||
<select class="selectpicker" id="settings-general-movie_default_language" name="settings-general-movie_default_language" multiple></select>
|
<select class="selectpicker" id="settings-general-movie_default_profile" name="settings-general-movie_default_profile"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<b>Hearing-Impaired</b>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-1">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="settings-general-movie_default_hi" name="settings-general-movie_default_hi">
|
|
||||||
<span class="custom-control-label" for="settings-general-movie_default_hi"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<b>Forced</b>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8 pl-sm-0">
|
|
||||||
<select class="selectpicker" id="settings-general-movie_default_forced" name="settings-general-movie_default_forced">
|
|
||||||
<option value="False">False</option>
|
|
||||||
<option value="True">True</option>
|
|
||||||
<option value="Both">Both</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="addModal" class="modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Add Languages Profile</h5><br>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form class="form" name="add_form" id="add_form">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Profile name
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" id="add_profile_name" name="add_profile_name" value="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Languages
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<table class="table table-striped" id="add_languages_profiles" style="width:100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Language</th>
|
||||||
|
<th>Forced</th>
|
||||||
|
<th>Hearing-Impaired</th>
|
||||||
|
<th>Ignore If Matching Audio Track</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Language ID cutoff (ignore others if existing)
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<select class="selectpicker show-tick" id="add_language_cutoff" name="add_language_cutoff">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" id="add_save_button" class="btn btn-info">Add</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="editModal" class="modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Languages Profile</h5><br>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<form class="form" name="edit_form" id="edit_form">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Profile name
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" id="edit_profile_name" name="edit_profile_name" value="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Languages
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<table class="table table-striped" id="edit_languages_profiles" style="width:100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Language</th>
|
||||||
|
<th>Forced</th>
|
||||||
|
<th>Hearing-Impaired</th>
|
||||||
|
<th>Ignore If Matching Audio Track</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 text-right">
|
||||||
|
Language ID cutoff (ignore others if existing)
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<select class="selectpicker show-tick inline_select_edit" id="edit_language_cutoff" name="edit_language_cutoff">
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="edit_profile_id" value="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" id="edit_save_button" class="btn btn-info">Edit</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block tail %}
|
{% block tail %}
|
||||||
|
@ -173,57 +271,324 @@
|
||||||
$('#save_button_checkmark').hide();
|
$('#save_button_checkmark').hide();
|
||||||
$('#save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
$('#save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
||||||
|
|
||||||
// Listen to selection change on enabled_languages select and keep series and movies default language select synced
|
|
||||||
$('#enabled_languages').on('changed.bs.select', function(event, clickedIndex, isSelected, previousValue) {
|
|
||||||
actual = $("#enabled_languages option:selected").map(function() {
|
|
||||||
return $(this).val();
|
|
||||||
}).get();
|
|
||||||
|
|
||||||
if (previousValue) {
|
|
||||||
var added = actual.filter(x => !previousValue.includes(x));
|
|
||||||
var removed = previousValue.filter(x => !actual.includes(x));
|
|
||||||
|
|
||||||
if (added.length > 0) {
|
|
||||||
$('#settings-general-serie_default_language').append('<option value="' + added[0] + '">' + $("#enabled_languages option[value="+added[0]+"]").text() + '</option>');
|
|
||||||
$('#settings-general-movie_default_language').append('<option value="' + added[0] + '">' + $("#enabled_languages option[value="+added[0]+"]").text() + '</option>');
|
|
||||||
}
|
|
||||||
if (removed.length > 0) {
|
|
||||||
$("#settings-general-serie_default_language option[value="+removed[0]+"]").remove();
|
|
||||||
$("#settings-general-movie_default_language option[value="+removed[0]+"]").remove();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$(actual).each( function(i, item) {
|
|
||||||
if ($('#settings-general-serie_default_language option[value='+item+']').length < 1) {
|
|
||||||
$('#settings-general-serie_default_language').append('<option value="' + item + '">' + $("#enabled_languages option[value="+item+"]").text() + '</option>');
|
|
||||||
$('#settings-general-movie_default_language').append('<option value="' + item + '">' + $("#enabled_languages option[value="+item+"]").text() + '</option>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#settings-general-serie_default_language').selectpicker('val', {{settings.general.serie_default_language|safe}});
|
|
||||||
$('#settings-general-movie_default_language').selectpicker('val', {{settings.general.movie_default_language|safe}});
|
|
||||||
$("#settings-general-serie_default_language").selectpicker("refresh");
|
|
||||||
$("#settings-general-movie_default_language").selectpicker("refresh");
|
|
||||||
})
|
|
||||||
|
|
||||||
// Set Select input values
|
// Set Select input values
|
||||||
$('#settings-general-serie_default_forced').val('{{settings.general.serie_default_forced}}').trigger('change');
|
$('#settings-general-serie_default_profile').val('{{settings.general.serie_default_profile}}').trigger('change');
|
||||||
$('#settings-general-movie_default_forced').val('{{settings.general.movie_default_forced}}').trigger('change');
|
$('#settings-general-movie_default_profile').val('{{settings.general.movie_default_profile}}').trigger('change');
|
||||||
$('.selectpicker').selectpicker('refresh')
|
$('.selectpicker').selectpicker('refresh')
|
||||||
|
|
||||||
// Listen to single language checkbox change to adapt languages menus
|
// Set Checkbox input values
|
||||||
$('#settings-general-single_language').on('change', function() {
|
$('#settings-general-single_language').prop('checked', {{'true' if settings.general.getboolean('single_language') else 'false'}}).trigger('change');
|
||||||
if ($(this).prop('checked')) {
|
$('#settings-general-serie_default_enabled').prop('checked', {{'true' if settings.general.getboolean('serie_default_enabled') else 'false'}}).trigger('change');
|
||||||
$('#settings-general-serie_default_language').selectpicker({maxOptions:1}).selectpicker('refresh');
|
$('#settings-general-movie_default_enabled').prop('checked', {{'true' if settings.general.getboolean('movie_default_enabled') else 'false'}}).trigger('change');
|
||||||
$('#settings-general-movie_default_language').selectpicker({maxOptions:1}).selectpicker('refresh');
|
|
||||||
$('#settings-general-serie_default_language').selectpicker('val', $('#settings-general-serie_default_language').val()[0]);
|
var table = $('#languages_profiles').DataTable({
|
||||||
$('#settings-general-movie_default_language').selectpicker('val', $('#settings-general-movie_default_language').val()[0]);
|
dom: 'Bfrtip',
|
||||||
} else {
|
select: {
|
||||||
$('#settings-general-serie_default_language').selectpicker({maxOptions:false}).selectpicker('refresh');
|
style: 'single'
|
||||||
$('#settings-general-movie_default_language').selectpicker({maxOptions:false}).selectpicker('refresh');
|
},
|
||||||
}
|
language: {
|
||||||
|
zeroRecords: 'No Languages Profiles'
|
||||||
|
},
|
||||||
|
searching: false,
|
||||||
|
ordering: false,
|
||||||
|
lengthChange: true,
|
||||||
|
responsive: false,
|
||||||
|
paging: false,
|
||||||
|
info: false,
|
||||||
|
processing: true,
|
||||||
|
serverSide: false,
|
||||||
|
ajax: {
|
||||||
|
url: "{{ url_for('api.languagesprofiles') }}",
|
||||||
|
type: 'GET'
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ data: 'profileId',
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
{ data: 'name' },
|
||||||
|
{ data: 'cutoff',
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
{ data: 'items',
|
||||||
|
render: function(data, type, row) {
|
||||||
|
var languages = '';
|
||||||
|
$(eval(data)).each(function (index, value) {
|
||||||
|
if (value.forced == 'True') {
|
||||||
|
languages += '<span class="badge badge-secondary"' + ((row.cutoff == '65535' || value.id == row.cutoff) ? ' data-toggle="tooltip" title="Ignore others if this one is available" style="background-color:#911f93;"' : '') + '>' + value.language + ':forced' + ((value.audio_exclude === "True") ? ' <i class="fa fa-ban" data-toggle="tooltip" title="Ignore if matching audio track available"></i>' : '') + '</span> ';
|
||||||
|
} else if (value.hi == 'True') {
|
||||||
|
languages += '<span class="badge badge-secondary"' + ((row.cutoff == '65535' || value.id == row.cutoff) ? ' data-toggle="tooltip" title="Ignore others if this one is available" style="background-color:#911f93;"' : '') + '>' + value.language + ':hi' + ((value.audio_exclude === "True") ? ' <i class="fa fa-ban" data-toggle="tooltip" title="Ignore if matching audio track available"></i>' : '') + '</span> ';
|
||||||
|
} else {
|
||||||
|
languages += '<span class="badge badge-secondary"' + ((row.cutoff == '65535' || value.id == row.cutoff) ? ' data-toggle="tooltip" title="Ignore others if this one is available" style="background-color:#911f93;"' : '') + '>' + value.language + ((value.audio_exclude === "True") ? ' <i class="fa fa-ban" data-toggle="tooltip" title="Ignore if matching audio track available"></i>' : '') + '</span> ';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return languages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
buttons: [{
|
||||||
|
text: 'Add',
|
||||||
|
action: function () {
|
||||||
|
if ($('#add_languages_profiles').DataTable().rows().length) {
|
||||||
|
$('#add_languages_profiles').DataTable().clear();
|
||||||
|
}
|
||||||
|
$('#add_profile_name').val('');
|
||||||
|
$('#add_languages_profiles').DataTable().destroy();
|
||||||
|
var table_add = $('#add_languages_profiles').DataTable({
|
||||||
|
dom: 'Bfrtip',
|
||||||
|
select: {
|
||||||
|
style: 'single'
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
zeroRecords: 'No Languages In This Profile'
|
||||||
|
},
|
||||||
|
searching: false,
|
||||||
|
ordering: false,
|
||||||
|
lengthChange: false,
|
||||||
|
responsive: false,
|
||||||
|
paging: false,
|
||||||
|
info: false,
|
||||||
|
data: null,
|
||||||
|
columns: [
|
||||||
|
{ data: 'id',
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
{ data: 'id' },
|
||||||
|
{ data: 'language',
|
||||||
|
render: function (data) {
|
||||||
|
var enabled_languages = Array();
|
||||||
|
$('#enabled_languages option:selected').each(function(){
|
||||||
|
enabled_languages.push([$(this).val(), $(this).text()]);
|
||||||
|
});
|
||||||
|
|
||||||
|
var html_dropdown = '<select class="selectpicker show-tick inline_select_add" data-width="fit">';
|
||||||
|
for (i = 0; i < enabled_languages.length; i++) {
|
||||||
|
html_dropdown += '<option value="' + enabled_languages[i][0] + '"' + ((data == enabled_languages[i][0]) ? ' selected="selected"' : '') + '>' + enabled_languages[i][1] + '</option>';
|
||||||
|
}
|
||||||
|
html_dropdown += '</select>';
|
||||||
|
|
||||||
|
return html_dropdown;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'forced',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_add" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'hi',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_add" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'audio_exclude',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_add" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
buttons: [{
|
||||||
|
text: 'Add',
|
||||||
|
action: function () {
|
||||||
|
var language_id = 0;
|
||||||
|
if (table_add.rows().data().toArray().length) {
|
||||||
|
language_id = Math.max(...table_add.column(0).data().toArray());
|
||||||
|
}
|
||||||
|
language_id++;
|
||||||
|
table_add.row.add({
|
||||||
|
id: language_id,
|
||||||
|
language: '',
|
||||||
|
forced: 'False',
|
||||||
|
hi: 'False',
|
||||||
|
audio_exclude: 'False'
|
||||||
|
}).draw();
|
||||||
|
$('.inline_select_add').selectpicker('refresh');
|
||||||
|
|
||||||
|
$('.inline_select_add.selectpicker').on('changed.bs.select', function () {
|
||||||
|
table_add.row( $(this).closest('tr') ).cell( $(this).closest('td') ).data($(this).val());
|
||||||
|
$('.inline_select_add').selectpicker('refresh');
|
||||||
|
table_add.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
extend: 'selected',
|
||||||
|
text: 'Delete',
|
||||||
|
action: function () {
|
||||||
|
table_add.row( { selected: true } ).remove().draw();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
$('#addModal').modal('show');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
extend: 'selected',
|
||||||
|
text: 'Edit',
|
||||||
|
action: function () {
|
||||||
|
$('#edit_profile_name').val(table.row( { selected: true } ).data()['name']);
|
||||||
|
var items = $.parseJSON(table.row( { selected: true } ).data()['items']);
|
||||||
|
$('#edit_languages_profiles').DataTable().destroy();
|
||||||
|
var table_edit = $('#edit_languages_profiles').DataTable({
|
||||||
|
dom: 'Bfrtip',
|
||||||
|
select: {
|
||||||
|
style: 'single'
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
zeroRecords: 'No Languages In This Profile'
|
||||||
|
},
|
||||||
|
searching: false,
|
||||||
|
ordering: false,
|
||||||
|
lengthChange: false,
|
||||||
|
responsive: false,
|
||||||
|
paging: false,
|
||||||
|
info: false,
|
||||||
|
data: items,
|
||||||
|
columns: [
|
||||||
|
{ data: 'id',
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
{ data: 'id' },
|
||||||
|
{ data: 'language',
|
||||||
|
render: function (data) {
|
||||||
|
var enabled_languages = Array();
|
||||||
|
$('#enabled_languages option:selected').each(function(){
|
||||||
|
enabled_languages.push([$(this).val(), $(this).text()]);
|
||||||
|
});
|
||||||
|
|
||||||
|
var html_dropdown = '<select class="selectpicker show-tick inline_select_edit" data-width="fit">';
|
||||||
|
for (i = 0; i < enabled_languages.length; i++) {
|
||||||
|
html_dropdown += '<option value="' + enabled_languages[i][0] + '"' + ((data == enabled_languages[i][0]) ? ' selected="selected"' : '') + '>' + enabled_languages[i][1] + '</option>';
|
||||||
|
}
|
||||||
|
html_dropdown += '</select>'
|
||||||
|
|
||||||
|
return html_dropdown;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'forced',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_edit" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'hi',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_edit" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'audio_exclude',
|
||||||
|
render: function(data) {
|
||||||
|
return '<select class="selectpicker show-tick inline_select_edit" data-width="fit"><option value="True"' + ((data === 'True') ? ' selected="selected"' : '') + '>True</option><option value="False"' + ((data === 'False') ? ' selected="selected"' : '') + '>False</option></select>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
buttons: [{
|
||||||
|
text: 'Add',
|
||||||
|
action: function () {
|
||||||
|
var language_id = 0;
|
||||||
|
if (table_edit.rows().data().toArray().length) {
|
||||||
|
language_id = Math.max(...table_edit.column(0).data().toArray());
|
||||||
|
}
|
||||||
|
language_id++;
|
||||||
|
table_edit.row.add({
|
||||||
|
id: language_id,
|
||||||
|
language: '',
|
||||||
|
forced: 'False',
|
||||||
|
hi: 'False',
|
||||||
|
audio_exclude: 'False'
|
||||||
|
}).draw();
|
||||||
|
$('.inline_select_edit').selectpicker('refresh');
|
||||||
|
|
||||||
|
$('.inline_select_edit.selectpicker').on('changed.bs.select', function () {
|
||||||
|
table_edit.row( $(this).closest('tr') ).cell( $(this).closest('td') ).data($(this).val());
|
||||||
|
$('.inline_select_edit').selectpicker('refresh');
|
||||||
|
table_edit.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
extend: 'selected',
|
||||||
|
text: 'Delete',
|
||||||
|
action: function () {
|
||||||
|
table_edit.row( { selected: true } ).remove().draw();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
$('#edit_language_cutoff').val(table.row( { selected: true } ).data()['cutoff']);
|
||||||
|
$('#edit_profile_id').val(table.row( { selected: true } ).data()['profileId']);
|
||||||
|
$('.inline_select_edit').selectpicker('refresh');
|
||||||
|
$('#editModal').modal('show');
|
||||||
|
|
||||||
|
$('.inline_select_edit.selectpicker').on('changed.bs.select', function () {
|
||||||
|
table_edit.row( $(this).closest('tr') ).cell( $(this).closest('td') ).data($(this).val());
|
||||||
|
$('.inline_select_edit').selectpicker('refresh');
|
||||||
|
table_edit.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
extend: 'selected',
|
||||||
|
text: 'Delete',
|
||||||
|
action: function () {
|
||||||
|
table.row( { selected: true } ).remove().draw();
|
||||||
|
$('#settings_form').trigger('change');
|
||||||
|
}
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#add_profile_name').on('input', function() {
|
||||||
|
if ($('#add_languages_profiles').DataTable().rows().count() && $('#add_profile_name').val()) {
|
||||||
|
$('#add_save_button').prop('disabled', false).css('cursor', 'auto');
|
||||||
|
} else {
|
||||||
|
$('#add_save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#add_languages_profiles').DataTable().on( 'draw', function () {
|
||||||
|
if ($('#add_languages_profiles').DataTable().rows().count() && $('#add_profile_name').val()) {
|
||||||
|
$('#add_save_button').prop('disabled', false).css('cursor', 'auto');
|
||||||
|
} else {
|
||||||
|
$('#add_save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousValue = $("#add_language_cutoff").val();
|
||||||
|
$("#add_language_cutoff").empty();
|
||||||
|
$('#add_language_cutoff').append('<option value="">Disabled</option>');
|
||||||
|
$('#add_language_cutoff').append('<option value="65535">Any of them</option>');
|
||||||
|
|
||||||
|
var ids = $('#add_languages_profiles').DataTable().rows().data().pluck( 'id' ).toArray();
|
||||||
|
$(ids).each( function(i, item) {
|
||||||
|
$('#add_language_cutoff').append('<option value="' + item + '">' + item + '</option>');
|
||||||
|
});
|
||||||
|
$("#add_language_cutoff").val(previousValue);
|
||||||
|
$("#add_language_cutoff").selectpicker("refresh");
|
||||||
|
} );
|
||||||
|
|
||||||
|
$('#edit_profile_name').on('input', function() {
|
||||||
|
if ($('#edit_languages_profiles').DataTable().rows().count() && $('#edit_profile_name').val()) {
|
||||||
|
$('#edit_save_button').prop('disabled', false).css('cursor', 'auto');
|
||||||
|
} else {
|
||||||
|
$('#edit_save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#edit_languages_profiles').DataTable().on( 'draw', function () {
|
||||||
|
if ($('#edit_languages_profiles').DataTable().rows().count() && $('#edit_profile_name').val()) {
|
||||||
|
$('#edit_save_button').prop('disabled', false).css('cursor', 'auto');
|
||||||
|
} else {
|
||||||
|
$('#edit_save_button').prop('disabled', true).css('cursor', 'not-allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousValue = $("#edit_language_cutoff").val();
|
||||||
|
$("#edit_language_cutoff").empty();
|
||||||
|
$('#edit_language_cutoff').append('<option value="">Disabled</option>');
|
||||||
|
$('#edit_language_cutoff').append('<option value="65535">Any of them</option>');
|
||||||
|
|
||||||
|
var ids = $('#edit_languages_profiles').DataTable().rows().data().pluck( 'id' ).toArray();
|
||||||
|
$(ids).each( function(i, item) {
|
||||||
|
$('#edit_language_cutoff').append('<option value="' + item + '">' + item + '</option>');
|
||||||
|
});
|
||||||
|
$("#edit_language_cutoff").val(previousValue);
|
||||||
|
$("#edit_language_cutoff").selectpicker("refresh");
|
||||||
|
} );
|
||||||
|
|
||||||
// Hide *_div on default-enabled change
|
// Hide *_div on default-enabled change
|
||||||
$('#settings-general-serie_default_enabled').on('change', function() {
|
$('#settings-general-serie_default_enabled').on('change', function() {
|
||||||
if ($(this).prop('checked')) {
|
if ($(this).prop('checked')) {
|
||||||
|
@ -241,28 +606,55 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set Checkbox input values
|
// Listen to profiles change and populate the default dropdowns accordingly
|
||||||
$('#settings-general-single_language').prop('checked', {{'true' if settings.general.getboolean('single_language') else 'false'}}).trigger('change');
|
$('#languages_profiles').DataTable().on( 'draw', function () {
|
||||||
$('#settings-general-serie_default_enabled').prop('checked', {{'true' if settings.general.getboolean('serie_default_enabled') else 'false'}}).trigger('change');
|
if ($("#settings-general-serie_default_profile").length > 1) {
|
||||||
$('#settings-general-serie_default_hi').prop('checked', {{'true' if settings.general.getboolean('serie_default_hi') else 'false'}}).trigger('change');
|
var previousValueSerie = $("#settings-general-serie_default_profile").val();
|
||||||
$('#settings-general-movie_default_enabled').prop('checked', {{'true' if settings.general.getboolean('movie_default_enabled') else 'false'}}).trigger('change');
|
} else {
|
||||||
$('#settings-general-movie_default_hi').prop('checked', {{'true' if settings.general.getboolean('movie_default_hi') else 'false'}}).trigger('change');
|
var previousValueSerie = '{{settings.general.serie_default_profile}}';
|
||||||
|
}
|
||||||
|
if ($("#settings-general-movie_default_profile").length > 1) {
|
||||||
|
var previousValueMovie = $("#settings-general-movie_default_profile").val();
|
||||||
|
} else {
|
||||||
|
var previousValueMovie = '{{settings.general.movie_default_profile}}';
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#settings-general-serie_default_profile").empty();
|
||||||
|
$("#settings-general-movie_default_profile").empty();
|
||||||
|
$('#settings-general-serie_default_profile').append('<option value="">None</option>');
|
||||||
|
$('#settings-general-movie_default_profile').append('<option value="">None</option>');
|
||||||
|
|
||||||
|
var ids = $('#languages_profiles').DataTable().rows().data().toArray();
|
||||||
|
$(ids).each( function(i, item) {
|
||||||
|
$('#settings-general-serie_default_profile').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
|
$('#settings-general-movie_default_profile').append('<option value="' + item.profileId + '">' + item.name + '</option>');
|
||||||
|
});
|
||||||
|
$("#settings-general-serie_default_profile").val(previousValueSerie);
|
||||||
|
$("#settings-general-movie_default_profile").val(previousValueMovie);
|
||||||
|
$("#settings-general-serie_default_profile").selectpicker("refresh");
|
||||||
|
$("#settings-general-movie_default_profile").selectpicker("refresh");
|
||||||
|
} );
|
||||||
|
|
||||||
|
$('#save_button').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
$('#save_button').on('click', function() {
|
|
||||||
var formdata = new FormData(document.getElementById("settings_form"));
|
var formdata = new FormData(document.getElementById("settings_form"));
|
||||||
|
|
||||||
// Make sure empty default languages select are send (bug in bootstrap-select)
|
// Make sure empty default languages select are send (bug in bootstrap-select)
|
||||||
if (formdata.get('settings-general-serie_default_language') == null) {
|
if (formdata.get('settings-general-serie_default_profile') == null) {
|
||||||
formdata.append('settings-general-serie_default_language', null)
|
formdata.append('settings-general-serie_default_profile', null)
|
||||||
}
|
}
|
||||||
if (formdata.get('settings-general-movie_default_language') == null) {
|
if (formdata.get('settings-general-movie_default_profile') == null) {
|
||||||
formdata.append('settings-general-movie_default_language', null)
|
formdata.append('settings-general-movie_default_profile', null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure all checkbox input are sent with true/false value
|
// Make sure all checkbox input are sent with true/false value
|
||||||
$('input[type=checkbox]').each(function () {
|
$('input[type=checkbox]').each(function () {
|
||||||
formdata.set($(this).prop('id'), $(this).prop('checked'));
|
formdata.set($(this).prop('id'), $(this).prop('checked'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
formdata.append('languages_profiles', JSON.stringify(table.rows().data().toArray()));
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.savesettings') }}",
|
url: "{{ url_for('api.savesettings') }}",
|
||||||
data: formdata,
|
data: formdata,
|
||||||
|
@ -282,42 +674,87 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#add_save_button').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var table_add = $('#add_languages_profiles').DataTable();
|
||||||
|
var items = [];
|
||||||
|
table_add.rows().every( function (row) {
|
||||||
|
var row_item = table_add.cells( row, '' ).render( 'display' );
|
||||||
|
var language = $(row_item[2]).filter('select').selectpicker().val();
|
||||||
|
var forced = $(row_item[3]).filter('select').val();
|
||||||
|
var hi = $(row_item[4]).filter('select').val();
|
||||||
|
var audio_exclude = $(row_item[5]).filter('select').val();
|
||||||
|
items.push({
|
||||||
|
id: row_item[1],
|
||||||
|
language: language,
|
||||||
|
forced: forced,
|
||||||
|
hi: hi,
|
||||||
|
audio_exclude: audio_exclude
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
if (table.rows().data().toArray().length === 0) {
|
||||||
|
var languages_profile_id = 0;
|
||||||
|
} else {
|
||||||
|
var languages_profile_id = Math.max(...table.column(0).data().toArray());
|
||||||
|
}
|
||||||
|
languages_profile_id++
|
||||||
|
table.row.add({
|
||||||
|
profileId: languages_profile_id,
|
||||||
|
name: $('#add_profile_name').val(),
|
||||||
|
cutoff: $('#add_language_cutoff').val(),
|
||||||
|
items: JSON.stringify(items)
|
||||||
|
}).draw();
|
||||||
|
$('#addModal').modal('hide');
|
||||||
|
$('#settings_form').trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#edit_save_button').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var table_edit = $('#edit_languages_profiles').DataTable();
|
||||||
|
var items = [];
|
||||||
|
table_edit.rows().every( function (row) {
|
||||||
|
var row_item = table_edit.cells( row, '' ).render( 'display' );
|
||||||
|
var language = $(row_item[2]).filter('select').selectpicker().val();
|
||||||
|
var forced = $(row_item[3]).filter('select').val();
|
||||||
|
var hi = $(row_item[4]).filter('select').val();
|
||||||
|
var audio_exclude = $(row_item[5]).filter('select').val();
|
||||||
|
items.push({
|
||||||
|
id: row_item[1],
|
||||||
|
language: language,
|
||||||
|
forced: forced,
|
||||||
|
hi: hi,
|
||||||
|
audio_exclude: audio_exclude
|
||||||
|
});
|
||||||
|
})
|
||||||
|
table.row( { selected: true } ).data({
|
||||||
|
profileId: parseInt($('#edit_profile_id').val()),
|
||||||
|
name: $('#edit_profile_name').val(),
|
||||||
|
cutoff: $('#edit_language_cutoff').val(),
|
||||||
|
items: JSON.stringify(items)
|
||||||
|
});
|
||||||
|
$('#editModal').modal('hide');
|
||||||
|
$('#settings_form').trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
function getLanguages() {
|
function getLanguages() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ url_for('api.languages') }}?enabled=false",
|
url: "{{ url_for('api.languages') }}?enabled=false",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$('#enabled_languages').empty();
|
$('#enabled_languages').empty();
|
||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
$('#enabled_languages').append('<option value="' + item.code2 + '">' + item.name + '</option>');
|
$('#enabled_languages').append('<option value="' + item.code2 + '"' + ((item.enabled) ? ' selected="selected"' : '') + '>' + item.name + '</option>');
|
||||||
});
|
});
|
||||||
getEnabledLanguages();
|
|
||||||
$("#enabled_languages").selectpicker("refresh");
|
$("#enabled_languages").selectpicker("refresh");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnabledLanguages() {
|
|
||||||
$.ajax({
|
|
||||||
url: "{{ url_for('api.languages') }}?enabled=true",
|
|
||||||
success: function (data) {
|
|
||||||
let optArr = [];
|
|
||||||
$.each(data, function (i, item) {
|
|
||||||
optArr.push(item.code2);
|
|
||||||
});
|
|
||||||
$('#enabled_languages').selectpicker('val', optArr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// monitor changes to the settings_form
|
// monitor changes to the settings_form
|
||||||
setTimeout(
|
$('#settings_form').on('change', function() {
|
||||||
function()
|
form_changed = true;
|
||||||
{
|
$('#save_button').prop('disabled', false).css('cursor', 'auto');
|
||||||
$('#settings_form').on('change', function() {
|
})
|
||||||
form_changed = true;
|
|
||||||
$('#save_button').prop('disabled', false).css('cursor', 'auto');
|
|
||||||
})
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock tail %}
|
{% endblock tail %}
|
||||||
|
|
|
@ -202,7 +202,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" id="add_save_button" class="btn btn-info">Save</button>
|
<button type="submit" id="add_save_button" class="btn btn-info">Add</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -242,7 +242,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" id="edit_save_button" class="btn btn-info">Save</button>
|
<button type="submit" id="edit_save_button" class="btn btn-info">Edit</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -215,7 +215,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" id="add_save_button" class="btn btn-info">Save</button>
|
<button type="submit" id="add_save_button" class="btn btn-info">Add</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -255,7 +255,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" id="edit_save_button" class="btn btn-info">Save</button>
|
<button type="submit" id="edit_save_button" class="btn btn-info">Edit</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -422,19 +422,19 @@
|
||||||
<label>Enable the automatic subtitles synchronization after downloading a subtitles.</label>
|
<label>Enable the automatic subtitles synchronization after downloading a subtitles.</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-4 text-right">
|
|
||||||
<b>Subtitles synchronization debugging</b>
|
|
||||||
</div>
|
|
||||||
<div class="form-group col-sm-8">
|
|
||||||
<label class="custom-control custom-checkbox">
|
|
||||||
<input type="checkbox" class="custom-control-input" id="settings-subsync-debug" name="settings-subsync-debug">
|
|
||||||
<span class="custom-control-label" for="settings-subsync-debug"></span>
|
|
||||||
</label>
|
|
||||||
<label>Do not actually sync the subtitles but generate a .tar.gz file to be able to open an issue for ffsubsync. This file will reside alongside the media file.</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="subsync_div">
|
<div id="subsync_div">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4 text-right">
|
||||||
|
<b>Subtitles synchronization debugging</b>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-sm-8">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" class="custom-control-input" id="settings-subsync-debug" name="settings-subsync-debug">
|
||||||
|
<span class="custom-control-label" for="settings-subsync-debug"></span>
|
||||||
|
</label>
|
||||||
|
<label>Do not actually sync the subtitles but generate a .tar.gz file to be able to open an issue for ffsubsync. This file will reside alongside the media file.</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 text-right">
|
<div class="col-sm-4 text-right">
|
||||||
<b>Subtitles synchronization score threshold for series</b>
|
<b>Subtitles synchronization score threshold for series</b>
|
||||||
|
|
Loading…
Reference in New Issue