You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bazarr/bazarr/main.py

2050 lines
85 KiB

# coding=utf-8
bazarr_version = '0.8.4'
5 years ago
import os
os.environ["SZ_USER_AGENT"] = "Bazarr/1"
os.environ["BAZARR_VERSION"] = bazarr_version
5 years ago
5 years ago
import gc
import sys
import libs
5 years ago
import six
from six.moves import zip
from functools import reduce
5 years ago
import itertools
import operator
import pretty
import math
import ast
import hashlib
5 years ago
import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
import warnings
import queueconfig
5 years ago
import platform
import apprise
from calendar import day_name
5 years ago
from get_args import args
from logger import empty_log
5 years ago
from config import settings, url_sonarr, url_radarr, url_radarr_short, url_sonarr_short, base_url
from init import *
import logging
5 years ago
from database import database, dict_mapper
from notifier import update_notifier
from cherrypy.wsgiserver import CherryPyWSGIServer
from io import BytesIO
5 years ago
from six import text_type, PY2
5 years ago
from datetime import timedelta
from get_languages import load_language_in_db, language_from_alpha3, language_from_alpha2, alpha2_from_alpha3
4 years ago
from flask import Flask, make_response, request, redirect, abort, render_template, Response
from flask_cors import CORS
from get_providers import get_providers, get_providers_auth, list_throttled_providers
from get_series import *
from get_episodes import *
from get_movies import *
from list_subtitles import store_subtitles, store_subtitles_movie, series_scan_subtitles, movies_scan_subtitles, \
list_missing_subtitles, list_missing_subtitles_movies
from get_subtitle import download_subtitle, series_download_subtitles, movies_download_subtitles, \
manual_search, manual_download_subtitle, manual_upload_subtitle
from utils import history_log, history_log_movie, get_sonarr_version, get_radarr_version
5 years ago
from helper import path_replace_reverse, path_replace_reverse_movie
from scheduler import *
from notifier import send_notifications, send_notifications_movie
from subliminal_patch.extensions import provider_registry as provider_manager
from subliminal_patch.core import SUBTITLE_EXTENSIONS
5 years ago
from flask_debugtoolbar import DebugToolbarExtension
5 years ago
# Flask Setup
5 years ago
app = Flask(__name__,
template_folder=os.path.join(os.path.dirname(__file__), '..', 'views'),
static_folder=os.path.join(os.path.dirname(__file__), '..', 'static'))
app.config["APPLICATION_ROOT"] = base_url
app.config["SECRET_KEY"] = 'test'
if args.dev:
app.config["DEBUG"] = True
# Flask-Debuger
app.config["DEBUG_TB_ENABLED"] = True
app.config["DEBUG_TB_PROFILER_ENABLED"] = True
app.config["DEBUG_TB_TEMPLATE_EDITOR_ENABLED"] = True
app.config["DEBUG_TB_INTERCEPT_REDIRECTS"] = False
else:
app.config["DEBUG"] = False
# Flask-Debuger
app.config["DEBUG_TB_ENABLED"] = False
toolbar = DebugToolbarExtension(app)
from api import api_bp
app.register_blueprint(api_bp)
5 years ago
4 years ago
from SSE import event_stream
# Add Cors
CORS(app)
# Check and install update on startup when running on Windows from installer
if args.release_update:
check_and_apply_update()
if settings.proxy.type != 'None':
if settings.proxy.username != '' and settings.proxy.password != '':
proxy = settings.proxy.type + '://' + settings.proxy.username + ':' + settings.proxy.password + '@' + \
settings.proxy.url + ':' + settings.proxy.port
else:
proxy = settings.proxy.type + '://' + settings.proxy.url + ':' + settings.proxy.port
os.environ['HTTP_PROXY'] = str(proxy)
os.environ['HTTPS_PROXY'] = str(proxy)
os.environ['NO_PROXY'] = str(settings.proxy.exclude)
# Reset restart required warning on start
5 years ago
database.execute("UPDATE system SET configured='0', updated='0'")
# Load languages in database
load_language_in_db()
login_auth = settings.auth.type
update_notifier()
def custom_auth_basic(check):
def decorator(func):
def wrapper(*a, **ka):
if settings.auth.type == 'basic':
user, password = request.auth or (None, None)
if user is None or not check(user, password):
5 years ago
err = abort(401, "Access denied")
err.add_header('WWW-Authenticate', 'Basic realm="Bazarr"')
return err
return func(*a, **ka)
else:
return func(*a, **ka)
5 years ago
return wrapper
5 years ago
return decorator
def check_credentials(user, pw):
username = settings.auth.username
password = settings.auth.password
if hashlib.md5(pw.encode('utf-8')).hexdigest() == password and user == username:
return True
return False
5 years ago
@app.context_processor
def restart_processor():
def restart_required():
5 years ago
restart_required = database.execute("SELECT configured, updated FROM system", only_one=True)
5 years ago
return restart_required
return dict(restart_required=restart_required()['configured'], update_required=restart_required()['updated'], ast=ast, settings=settings, locals=locals(), args=args, os=os)
5 years ago
def api_authorize():
if 'apikey' in request.GET.dict:
if request.GET.dict['apikey'][0] == settings.auth.apikey:
return
else:
abort(401, 'Unauthorized')
else:
abort(401, 'Unauthorized')
def post_get(name, default=''):
return request.POST.get(name, default).strip()
5 years ago
@app.route('/login/')
def login_form():
5 years ago
msg = request.query.get('msg', '')
5 years ago
return render_template('login.html', base_url=base_url, msg=msg)
5 years ago
@app.route('/login/', methods=['POST'])
def login():
username = post_get('username')
password = post_get('password')
if check_credentials(username, password):
return redirect(base_url)
else:
5 years ago
return redirect('/login?msg=fail')
5 years ago
@app.route('/logout/')
def logout():
5 years ago
return abort(401)
5 years ago
@app.route('/shutdown/')
5 years ago
# @custom_auth_basic(check_credentials)
def shutdown():
try:
server.stop()
except:
logging.error('BAZARR Cannot stop CherryPy.')
else:
database.close()
try:
stop_file = open(os.path.join(args.config_dir, "bazarr.stop"), "w")
except Exception as e:
logging.error('BAZARR Cannot create bazarr.stop file.')
else:
stop_file.write('')
stop_file.close()
5 years ago
sys.exit(0)
5 years ago
return ''
5 years ago
@app.route('/restart/')
5 years ago
# @custom_auth_basic(check_credentials)
def restart():
try:
server.stop()
except:
logging.error('BAZARR Cannot stop CherryPy.')
else:
database.close()
try:
restart_file = open(os.path.join(args.config_dir, "bazarr.restart"), "w")
except Exception as e:
logging.error('BAZARR Cannot create bazarr.restart file.')
else:
logging.info('Bazarr is being restarted...')
restart_file.write('')
restart_file.close()
5 years ago
sys.exit(0)
5 years ago
return ''
5 years ago
@app.route('/wizard/')
@custom_auth_basic(check_credentials)
6 years ago
def wizard():
# Get languages list
5 years ago
settings_languages = database.execute("SELECT * FROM table_settings_languages ORDER BY name")
# Get providers list
settings_providers = sorted(provider_manager.names())
5 years ago
return render_template('wizard.html', bazarr_version=bazarr_version, settings=settings,
6 years ago
settings_languages=settings_languages, settings_providers=settings_providers,
5 years ago
base_url=base_url, ast=ast)
6 years ago
5 years ago
@app.route('/save_wizard', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def save_wizard():
5 years ago
settings_general_ip = request.form.get('settings_general_ip')
settings_general_port = request.form.get('settings_general_port')
settings_general_baseurl = request.form.get('settings_general_baseurl')
if not settings_general_baseurl.endswith('/'):
6 years ago
settings_general_baseurl += '/'
5 years ago
settings_general_sourcepath = request.form.getlist('settings_general_sourcepath[]')
settings_general_destpath = request.form.getlist('settings_general_destpath[]')
6 years ago
settings_general_pathmapping = []
settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)])
5 years ago
settings_general_sourcepath_movie = request.form.getlist('settings_general_sourcepath_movie[]')
settings_general_destpath_movie = request.form.getlist('settings_general_destpath_movie[]')
6 years ago
settings_general_pathmapping_movie = []
settings_general_pathmapping_movie.extend(
[list(a) for a in zip(settings_general_sourcepath_movie, settings_general_destpath_movie)])
5 years ago
settings_general_single_language = request.form.get('settings_general_single_language')
6 years ago
if settings_general_single_language is None:
settings_general_single_language = 'False'
else:
settings_general_single_language = 'True'
5 years ago
settings_general_use_sonarr = request.form.get('settings_general_use_sonarr')
6 years ago
if settings_general_use_sonarr is None:
settings_general_use_sonarr = 'False'
else:
settings_general_use_sonarr = 'True'
5 years ago
settings_general_use_radarr = request.form.get('settings_general_use_radarr')
6 years ago
if settings_general_use_radarr is None:
settings_general_use_radarr = 'False'
else:
settings_general_use_radarr = 'True'
5 years ago
settings_general_embedded = request.form.get('settings_general_embedded')
if settings_general_embedded is None:
settings_general_embedded = 'False'
else:
settings_general_embedded = 'True'
5 years ago
settings_subfolder = request.form.get('settings_subfolder')
settings_subfolder_custom = request.form.get('settings_subfolder_custom')
settings_upgrade_subs = request.form.get('settings_upgrade_subs')
if settings_upgrade_subs is None:
settings_upgrade_subs = 'False'
else:
settings_upgrade_subs = 'True'
5 years ago
settings_days_to_upgrade_subs = request.form.get('settings_days_to_upgrade_subs')
settings_upgrade_manual = request.form.get('settings_upgrade_manual')
if settings_upgrade_manual is None:
settings_upgrade_manual = 'False'
else:
settings_upgrade_manual = 'True'
5 years ago
settings.general.ip = text_type(settings_general_ip)
settings.general.port = text_type(settings_general_port)
settings.general.base_url = text_type(settings_general_baseurl)
settings.general.path_mappings = text_type(settings_general_pathmapping)
settings.general.single_language = text_type(settings_general_single_language)
settings.general.use_sonarr = text_type(settings_general_use_sonarr)
settings.general.use_radarr = text_type(settings_general_use_radarr)
settings.general.path_mappings_movie = text_type(settings_general_pathmapping_movie)
settings.general.subfolder = text_type(settings_subfolder)
settings.general.subfolder_custom = text_type(settings_subfolder_custom)
settings.general.use_embedded_subs = text_type(settings_general_embedded)
settings.general.upgrade_subs = text_type(settings_upgrade_subs)
settings.general.days_to_upgrade_subs = text_type(settings_days_to_upgrade_subs)
settings.general.upgrade_manual = text_type(settings_upgrade_manual)
5 years ago
settings_sonarr_ip = request.form.get('settings_sonarr_ip')
settings_sonarr_port = request.form.get('settings_sonarr_port')
settings_sonarr_baseurl = request.form.get('settings_sonarr_baseurl')
settings_sonarr_ssl = request.form.get('settings_sonarr_ssl')
6 years ago
if settings_sonarr_ssl is None:
settings_sonarr_ssl = 'False'
else:
settings_sonarr_ssl = 'True'
5 years ago
settings_sonarr_apikey = request.form.get('settings_sonarr_apikey')
settings_sonarr_only_monitored = request.form.get('settings_sonarr_only_monitored')
if settings_sonarr_only_monitored is None:
settings_sonarr_only_monitored = 'False'
else:
settings_sonarr_only_monitored = 'True'
5 years ago
settings.sonarr.ip = text_type(settings_sonarr_ip)
settings.sonarr.port = text_type(settings_sonarr_port)
settings.sonarr.base_url = text_type(settings_sonarr_baseurl)
settings.sonarr.ssl = text_type(settings_sonarr_ssl)
settings.sonarr.apikey = text_type(settings_sonarr_apikey)
settings.sonarr.only_monitored = text_type(settings_sonarr_only_monitored)
5 years ago
settings_radarr_ip = request.form.get('settings_radarr_ip')
settings_radarr_port = request.form.get('settings_radarr_port')
settings_radarr_baseurl = request.form.get('settings_radarr_baseurl')
settings_radarr_ssl = request.form.get('settings_radarr_ssl')
6 years ago
if settings_radarr_ssl is None:
settings_radarr_ssl = 'False'
else:
settings_radarr_ssl = 'True'
5 years ago
settings_radarr_apikey = request.form.get('settings_radarr_apikey')
settings_radarr_only_monitored = request.form.get('settings_radarr_only_monitored')
if settings_radarr_only_monitored is None:
settings_radarr_only_monitored = 'False'
6 years ago
else:
settings_radarr_only_monitored = 'True'
5 years ago
settings.radarr.ip = text_type(settings_radarr_ip)
settings.radarr.port = text_type(settings_radarr_port)
settings.radarr.base_url = text_type(settings_radarr_baseurl)
settings.radarr.ssl = text_type(settings_radarr_ssl)
settings.radarr.apikey = text_type(settings_radarr_apikey)
settings.radarr.only_monitored = text_type(settings_radarr_only_monitored)
5 years ago
settings_subliminal_providers = request.form.getlist('settings_subliminal_providers')
5 years ago
settings.general.enabled_providers = u'' if not settings_subliminal_providers else ','.join(
settings_subliminal_providers)
5 years ago
settings_addic7ed_random_agents = request.form.get('settings_addic7ed_random_agents')
if settings_addic7ed_random_agents is None:
settings_addic7ed_random_agents = 'False'
else:
settings_addic7ed_random_agents = 'True'
5 years ago
settings_opensubtitles_vip = request.form.get('settings_opensubtitles_vip')
if settings_opensubtitles_vip is None:
settings_opensubtitles_vip = 'False'
else:
settings_opensubtitles_vip = 'True'
5 years ago
settings_opensubtitles_ssl = request.form.get('settings_opensubtitles_ssl')
if settings_opensubtitles_ssl is None:
settings_opensubtitles_ssl = 'False'
else:
settings_opensubtitles_ssl = 'True'
5 years ago
settings_opensubtitles_skip_wrong_fps = request.form.get('settings_opensubtitles_skip_wrong_fps')
if settings_opensubtitles_skip_wrong_fps is None:
settings_opensubtitles_skip_wrong_fps = 'False'
else:
settings_opensubtitles_skip_wrong_fps = 'True'
5 years ago
settings.addic7ed.username = request.form.get('settings_addic7ed_username') or ''
settings.addic7ed.password = request.form.get('settings_addic7ed_password') or ''
settings.addic7ed.random_agents = text_type(settings_addic7ed_random_agents) or ''
settings.assrt.token = request.form.get('settings_assrt_token') or ''
settings.legendastv.username = request.form.get('settings_legendastv_username') or ''
settings.legendastv.password = request.form.get('settings_legendastv_password') or ''
settings.opensubtitles.username = request.form.get('settings_opensubtitles_username') or ''
settings.opensubtitles.password = request.form.get('settings_opensubtitles_password') or ''
settings.opensubtitles.vip = text_type(settings_opensubtitles_vip)
settings.opensubtitles.ssl = text_type(settings_opensubtitles_ssl)
settings.opensubtitles.skip_wrong_fps = text_type(settings_opensubtitles_skip_wrong_fps)
5 years ago
settings.xsubs.username = request.form.get('settings_xsubs_username') or ''
settings.xsubs.password = request.form.get('settings_xsubs_password') or ''
settings.napisy24.username = request.form.get('settings_napisy24_username') or ''
settings.napisy24.password = request.form.get('settings_napisy24_password') or ''
settings.subscene.username = request.form.get('settings_subscene_username') or ''
settings.subscene.password = request.form.get('settings_subscene_password') or ''
settings.titlovi.username = request.form.get('settings_titlovi_username') or ''
settings.titlovi.password = request.form.get('settings_titlovi_password') or ''
settings.betaseries.token = request.form.get('settings_betaseries_token') or ''
settings_subliminal_languages = request.form.getlist('settings_subliminal_languages')
# Disable all languages in DB
5 years ago
database.execute("UPDATE table_settings_languages SET enabled=0")
6 years ago
for item in settings_subliminal_languages:
# Enable each desired language in DB
database.execute("UPDATE table_settings_languages SET enabled=1 WHERE code2=?", (item,))
5 years ago
settings_serie_default_enabled = request.form.get('settings_serie_default_enabled')
6 years ago
if settings_serie_default_enabled is None:
settings_serie_default_enabled = 'False'
else:
settings_serie_default_enabled = 'True'
settings.general.serie_default_enabled = text_type(settings_serie_default_enabled)
5 years ago
settings_serie_default_languages = str(request.form.getlist('settings_serie_default_languages'))
6 years ago
if settings_serie_default_languages == "['None']":
settings_serie_default_languages = 'None'
settings.general.serie_default_language = text_type(settings_serie_default_languages)
5 years ago
settings_serie_default_hi = request.form.get('settings_serie_default_hi')
6 years ago
if settings_serie_default_hi is None:
settings_serie_default_hi = 'False'
else:
settings_serie_default_hi = 'True'
settings.general.serie_default_hi = text_type(settings_serie_default_hi)
5 years ago
settings_movie_default_enabled = request.form.get('settings_movie_default_enabled')
6 years ago
if settings_movie_default_enabled is None:
settings_movie_default_enabled = 'False'
else:
settings_movie_default_enabled = 'True'
settings.general.movie_default_enabled = text_type(settings_movie_default_enabled)
5 years ago
settings_movie_default_languages = str(request.form.getlist('settings_movie_default_languages'))
6 years ago
if settings_movie_default_languages == "['None']":
settings_movie_default_languages = 'None'
settings.general.movie_default_language = text_type(settings_movie_default_languages)
5 years ago
settings_movie_default_hi = request.form.get('settings_movie_default_hi')
6 years ago
if settings_movie_default_hi is None:
settings_movie_default_hi = 'False'
else:
settings_movie_default_hi = 'True'
5 years ago
settings.general.movie_default_hi = text_type(settings_movie_default_hi)
5 years ago
settings_movie_default_forced = str(request.form.get('settings_movie_default_forced'))
settings.general.movie_default_forced = text_type(settings_movie_default_forced)
5 years ago
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle)
6 years ago
configured()
5 years ago
return redirect(base_url)
6 years ago
5 years ago
@app.route('/emptylog')
5 years ago
# @custom_auth_basic(check_credentials)
def emptylog():
ref = request.environ['HTTP_REFERER']
5 years ago
6 years ago
empty_log()
logging.info('BAZARR Log file emptied')
5 years ago
redirect(ref)
5 years ago
@app.route('/bazarr.log')
5 years ago
# @custom_auth_basic(check_credentials)
def download_log():
return static_file('bazarr.log', root=os.path.join(args.config_dir, 'log/'), download='bazarr.log')
5 years ago
@app.route('/image_proxy/<path:url>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def image_proxy(url):
apikey = settings.sonarr.apikey
5 years ago
url_image = url_sonarr_short() + '/' + url + '?apikey=' + apikey
try:
image_buffer = BytesIO(
5 years ago
requests.get(url_sonarr() + '/api' + url_image.split(url_sonarr())[1], timeout=15, verify=False).content)
except:
return None
else:
image_buffer.seek(0)
bytes = image_buffer.read()
5 years ago
request.set_header('Content-type', 'image/jpeg')
return bytes
5 years ago
@app.route('/image_proxy_movies/<path:url>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def image_proxy_movies(url):
apikey = settings.radarr.apikey
try:
5 years ago
url_image = (url_radarr_short() + '/' + url + '?apikey=' + apikey).replace('/fanart.jpg', '/banner.jpg')
image_buffer = BytesIO(
5 years ago
requests.get(url_radarr() + '/api' + url_image.split(url_radarr())[1], timeout=15, verify=False).content)
except:
5 years ago
url_image = url_radarr_short() + '/' + url + '?apikey=' + apikey
image_buffer = BytesIO(
5 years ago
requests.get(url_radarr() + '/api' + url_image.split(url_radarr())[1], timeout=15, verify=False).content)
else:
image_buffer.seek(0)
bytes = image_buffer.read()
5 years ago
request.set_header('Content-type', 'image/jpeg')
return bytes
5 years ago
@app.route(base_url)
# @custom_auth_basic(check_credentials)
def redirect_root():
if settings.general.getboolean('use_sonarr'):
5 years ago
return redirect('/series')
elif settings.general.getboolean('use_radarr'):
5 years ago
return redirect('/movies')
5 years ago
elif not settings.general.enabled_providers:
5 years ago
return redirect('/wizard')
else:
5 years ago
return redirect('/settings')
5 years ago
@app.route('/series/')
5 years ago
# @custom_auth_basic(check_credentials)
def series():
5 years ago
series_count = database.execute("SELECT COUNT(*) as count FROM table_shows", only_one=True)['count']
5 years ago
page = request.data
if not page:
page = "1"
page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size
5 years ago
max_page = int(math.ceil(series_count / (page_size + 0.0)))
5 years ago
# Get list of series
5 years ago
data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, "
"audio_language, forced FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?",
(page_size, offset))
5 years ago
# path_replace
dict_mapper.path_replace(data)
# Get languages list
5 years ago
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
# Build missing subtitles clause depending on only_monitored
if settings.sonarr.getboolean('only_monitored'):
5 years ago
missing_subtitles_clause = " AND table_episodes.monitored='True'"
else:
missing_subtitles_clause = ''
# Get missing subtitles count by series
5 years ago
missing_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, "
5 years ago
"COUNT(table_episodes.missing_subtitles) as missing_subtitles FROM table_shows LEFT JOIN "
5 years ago
"table_episodes ON table_shows.sonarrSeriesId="
"table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' "
"AND table_episodes.missing_subtitles IS NOT '[]'" +
missing_subtitles_clause + " GROUP BY table_shows.sonarrSeriesId")
# Build total subtitles clause depending on only_monitored
if settings.sonarr.getboolean('only_monitored'):
5 years ago
total_subtitles_clause = " AND table_episodes.monitored == 'True'"
else:
total_subtitles_clause = ''
# Get total subtitles count by series
5 years ago
total_subtitles_list = database.execute("SELECT table_shows.sonarrSeriesId, "
5 years ago
"COUNT(table_episodes.missing_subtitles) as missing_subtitles FROM table_shows LEFT JOIN "
5 years ago
"table_episodes ON table_shows.sonarrSeriesId="
"table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None'"
+ total_subtitles_clause + " GROUP BY table_shows.sonarrSeriesId")
5 years ago
return render_template('series.html', bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list,
5 years ago
total_subtitles_list=total_subtitles_list, languages=languages, missing_count=series_count,
5 years ago
page=page, max_page=max_page, base_url=base_url,
single_language=settings.general.getboolean('single_language'), page_size=page_size,
current_port=settings.general.port)
5 years ago
@app.route('/serieseditor/')
5 years ago
# @custom_auth_basic(check_credentials)
def serieseditor():
5 years ago
# Get missing count
5 years ago
missing_count = database.execute("SELECT COUNT(*) as count FROM table_shows", only_one=True)['count']
5 years ago
# Get series list
data = database.execute("SELECT tvdbId, title, path, languages, hearing_impaired, sonarrSeriesId, poster, "
"audio_language, forced FROM table_shows ORDER BY sortTitle ASC")
5 years ago
# path_replace
dict_mapper.path_replace(data)
# Get languages list
5 years ago
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
5 years ago
return render_template('serieseditor.html', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, base_url=base_url,
single_language=settings.general.getboolean('single_language'), current_port=settings.general.port)
5 years ago
@app.route('/search_json/<query>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def search_json(query):
5 years ago
query = '%' + query + '%'
search_list = []
if settings.general.getboolean('use_sonarr'):
# Get matching series
5 years ago
series = database.execute("SELECT title, sonarrSeriesId, year FROM table_shows WHERE title LIKE ? ORDER BY "
"title ASC", (query,))
for serie in series:
5 years ago
search_list.append(dict([('name', re.sub(r'\ \(\d{4}\)', '', serie['title']) + ' (' + serie['year'] + ')'),
5 years ago
('url', '/episodes/' + str(serie['sonarrSeriesId']))]))
5 years ago
if settings.general.getboolean('use_radarr'):
# Get matching movies
5 years ago
movies = database.execute("SELECT title, radarrId, year FROM table_movies WHERE title LIKE ? ORDER BY "
5 years ago
"title ASC", (query,))
for movie in movies:
5 years ago
search_list.append(dict([('name', re.sub(r'\ \(\d{4}\)', '', movie['title']) + ' (' + movie['year'] + ')'),
5 years ago
('url', '/movie/' + str(movie['radarrId']))]))
5 years ago
request.content_type = 'application/json'
return dict(items=search_list)
5 years ago
@app.route('/edit_series/<int:no>', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def edit_series(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
lang = request.form.getlist('languages')
if len(lang) > 0:
pass
else:
lang = 'None'
5 years ago
single_language = settings.general.getboolean('single_language')
5 years ago
if single_language:
if str(lang) == "['None']":
lang = 'None'
else:
lang = str(lang)
else:
if str(lang) == "['']":
lang = '[]'
5 years ago
hi = request.form.get('hearing_impaired')
forced = request.form.get('forced')
if hi == "on":
hi = "True"
else:
hi = "False"
5 years ago
result = database.execute("UPDATE table_shows SET languages=?, hearing_impaired=?, forced=? WHERE "
"sonarrSeriesId=?", (str(lang), hi, forced, no))
list_missing_subtitles(no=no)
5 years ago
redirect(ref)
5 years ago
@app.route('/edit_serieseditor', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def edit_serieseditor():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
series = request.form.get('series')
series = ast.literal_eval(str('[' + series + ']'))
5 years ago
lang = request.form.getlist('languages')
hi = request.form.get('hearing_impaired')
forced = request.form.get('forced')
for serie in series:
if str(lang) != "[]" and str(lang) != "['']":
if str(lang) == "['None']":
lang = 'None'
else:
lang = str(lang)
5 years ago
database.execute("UPDATE table_shows SET languages=? WHERE sonarrSeriesId=?", (lang,serie))
if hi != '':
5 years ago
database.execute("UPDATE table_shows SET hearing_impaired=? WHERE sonarrSeriesId=?", (hi, serie))
if forced != '':
5 years ago
database.execute("UPDATE table_shows SET forced=? WHERE sonarrSeriesId=?", (forced, serie))
5 years ago
for serie in series:
list_missing_subtitles(no=serie)
5 years ago
redirect(ref)
5 years ago
@app.route('/episodes/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def episodes(no):
5 years ago
5 years ago
series_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbId, "
"audio_language, languages, path, forced FROM table_shows WHERE "
5 years ago
"sonarrSeriesId=?", (no,), only_one=True)
5 years ago
# path_replace
dict_mapper.path_replace(series_details)
5 years ago
5 years ago
tvdbid = series_details['tvdbId']
5 years ago
episodes = database.execute("SELECT title, path, season, episode, subtitles, sonarrSeriesId, missing_subtitles, "
"sonarrEpisodeId, scene_name, monitored, failedAttempts FROM table_episodes WHERE "
"sonarrSeriesId=? ORDER BY season DESC, episode DESC", (no,))
5 years ago
# path_replace
dict_mapper.path_replace(episodes)
number = len(episodes)
5 years ago
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
seasons_list = []
5 years ago
for key, season in itertools.groupby(episodes, lambda x: x['season']):
seasons_list.append(list(season))
5 years ago
return render_template('episodes.html', bazarr_version=bazarr_version, no=no, details=series_details,
5 years ago
languages=languages, seasons=seasons_list, url_sonarr_short=url_sonarr_short(), base_url=base_url,
tvdbid=tvdbid, number=number, current_port=settings.general.port)
5 years ago
5 years ago
@app.route('/movies')
5 years ago
# @custom_auth_basic(check_credentials)
def movies():
4 years ago
return render_template('movies.html')
5 years ago
@app.route('/movieseditor')
5 years ago
# @custom_auth_basic(check_credentials)
def movieseditor():
5 years ago
5 years ago
5 years ago
missing_count = database.execute("SELECT COUNT(*) as count FROM table_movies", only_one=True)['count']
5 years ago
data = database.execute("SELECT tmdbId, title, path, languages, hearing_impaired, radarrId, poster, "
"audio_language, forced FROM table_movies ORDER BY sortTitle ASC")
5 years ago
# path_replace
dict_mapper.path_replace_movie(data)
5 years ago
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
5 years ago
return render_template('movieseditor.html', bazarr_version=bazarr_version, rows=data, languages=languages,
5 years ago
missing_count=missing_count, base_url=base_url, single_language=
settings.general.getboolean('single_language'), current_port=settings.general.port)
5 years ago
@app.route('/edit_movieseditor', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def edit_movieseditor():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
movies = request.form.get('movies')
movies = ast.literal_eval(str('[' + movies + ']'))
5 years ago
lang = request.form.getlist('languages')
hi = request.form.get('hearing_impaired')
forced = request.form.get('forced')
for movie in movies:
if str(lang) != "[]" and str(lang) != "['']":
if str(lang) == "['None']":
lang = 'None'
else:
lang = str(lang)
5 years ago
database.execute("UPDATE table_movies SET languages=? WHERE radarrId=?", (lang, movie))
if hi != '':
5 years ago
database.execute("UPDATE table_movies SET hearing_impaired=? WHERE radarrId=?", (hi, movie))
if forced != '':
5 years ago
database.execute("UPDATE table_movies SET forced=? WHERE radarrId=?", (forced, movie))
5 years ago
for movie in movies:
list_missing_subtitles_movies(movie)
5 years ago
redirect(ref)
5 years ago
@app.route('/edit_movie/<int:no>', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def edit_movie(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
lang = request.form.getlist('languages')
if len(lang) > 0:
pass
else:
lang = 'None'
5 years ago
5 years ago
single_language = settings.general.getboolean('single_language')
if single_language:
if str(lang) == "['None']":
lang = 'None'
else:
lang = str(lang)
else:
if str(lang) == "['']":
lang = '[]'
5 years ago
hi = request.form.get('hearing_impaired')
forced = request.form.get('forced')
if hi == "on":
hi = "True"
else:
hi = "False"
5 years ago
5 years ago
database.execute("UPDATE table_movies SET languages=?, hearing_impaired=?, forced=? WHERE radarrId=?",
5 years ago
(str(lang), hi, forced, no))
list_missing_subtitles_movies(no)
5 years ago
redirect(ref)
5 years ago
@app.route('/movie/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def movie(no):
5 years ago
5 years ago
movies_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbId, "
"audio_language, languages, path, subtitles, radarrId, missing_subtitles, "
"scenename, monitored, failedAttempts, forced FROM table_movies "
5 years ago
"WHERE radarrId=?", (no,), only_one=True)
5 years ago
# path_replace
5 years ago
dict_mapper.path_replace_movie(movies_details)
5 years ago
tmdbid = movies_details['tmdbId']
5 years ago
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
5 years ago
return render_template('movie.html', bazarr_version=bazarr_version, no=no, details=movies_details,
5 years ago
languages=languages, url_radarr_short=url_radarr_short(), base_url=base_url, tmdbid=tmdbid,
current_port=settings.general.port)
5 years ago
5 years ago
@app.route('/scan_disk/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def scan_disk(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
series_scan_subtitles(no)
5 years ago
redirect(ref)
5 years ago
@app.route('/scan_disk_movie/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def scan_disk_movie(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
movies_scan_subtitles(no)
5 years ago
redirect(ref)
5 years ago
@app.route('/search_missing_subtitles/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def search_missing_subtitles(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
add_job(series_download_subtitles, args=[no], name=('search_missing_subtitles_' + str(no)))
5 years ago
redirect(ref)
5 years ago
@app.route('/search_missing_subtitles_movie/<int:no>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def search_missing_subtitles_movie(no):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
add_job(movies_download_subtitles, args=[no], name=('movies_download_subtitles_' + str(no)))
5 years ago
redirect(ref)
4 years ago
@app.route('/historyseries/')
5 years ago
# @custom_auth_basic(check_credentials)
def historyseries():
4 years ago
return render_template('historyseries.html')
5 years ago
4 years ago
@app.route('/historymovies/')
5 years ago
# @custom_auth_basic(check_credentials)
def historymovies():
4 years ago
return render_template('historymovies.html')
5 years ago
5 years ago
@app.route('/wanted')
5 years ago
# @custom_auth_basic(check_credentials)
def wanted():
5 years ago
return render_template('wanted.html', bazarr_version=bazarr_version, base_url=base_url, current_port=settings.general.port)
5 years ago
@app.route('/wantedseries')
5 years ago
# @custom_auth_basic(check_credentials)
def wantedseries():
5 years ago
if settings.sonarr.getboolean('only_monitored'):
5 years ago
monitored_only_query_string = " AND monitored='True'"
else:
monitored_only_query_string = ''
5 years ago
5 years ago
missing_count = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
5 years ago
page = request.data
if page == "":
page = "1"
page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0)))
5 years ago
5 years ago
data = database.execute("SELECT table_shows.title as seriesTitle, "
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, "
5 years ago
"table_episodes.path, table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, "
"table_episodes.scene_name, table_episodes.failedAttempts FROM table_episodes "
"INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
"WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string +
" ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset))
5 years ago
# path_replace
dict_mapper.path_replace(data)
5 years ago
return render_template('wantedseries.html', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page,
max_page=max_page, base_url=base_url, page_size=page_size, current_port=settings.general.port)
5 years ago
5 years ago
@app.route('/wantedmovies')
5 years ago
# @custom_auth_basic(check_credentials)
def wantedmovies():
5 years ago
if settings.radarr.getboolean('only_monitored'):
5 years ago
monitored_only_query_string = " AND monitored='True'"
else:
monitored_only_query_string = ''
5 years ago
missing_count = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
5 years ago
page = request.args.page
if page == "":
page = "1"
page_size = int(settings.general.page_size)
offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0)))
5 years ago
data = database.execute("SELECT title, missing_subtitles, radarrId, path, hearing_impaired, sceneName, "
"failedAttempts FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?",
(page_size, offset))
5 years ago
# path_replace
dict_mapper.path_replace_movie(data)
5 years ago
return render_template('wantedmovies.html', bazarr_version=bazarr_version, rows=data,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size,
current_port=settings.general.port)
5 years ago
5 years ago
@app.route('/wanted_search_missing_subtitles')
5 years ago
# @custom_auth_basic(check_credentials)
def wanted_search_missing_subtitles_list():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
add_job(wanted_search_missing_subtitles, name='manual_wanted_search_missing_subtitles')
5 years ago
redirect(ref)
5 years ago
@app.route('/settings/')
5 years ago
# @custom_auth_basic(check_credentials)
def _settings():
5 years ago
5 years ago
settings_languages = database.execute("SELECT * FROM table_settings_languages ORDER BY name")
settings_providers = sorted(provider_manager.names())
5 years ago
settings_notifier = database.execute("SELECT * FROM table_settings_notifier ORDER BY name")
5 years ago
return render_template('settings.html', bazarr_version=bazarr_version, settings=settings, settings_languages=settings_languages,
5 years ago
settings_providers=settings_providers, settings_notifier=settings_notifier, base_url=base_url,
5 years ago
current_port=settings.general.port, ast=ast, args=args, sys=sys)
5 years ago
@app.route('/save_settings', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def save_settings():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
settings_general_ip = request.form.get('settings_general_ip')
settings_general_port = request.form.get('settings_general_port')
settings_general_baseurl = request.form.get('settings_general_baseurl')
if not settings_general_baseurl.endswith('/'):
settings_general_baseurl += '/'
5 years ago
settings_general_debug = request.form.get('settings_general_debug')
if settings_general_debug is None:
settings_general_debug = 'False'
else:
settings_general_debug = 'True'
5 years ago
settings_general_chmod_enabled = request.form.get('settings_general_chmod_enabled')
if settings_general_chmod_enabled is None:
settings_general_chmod_enabled = 'False'
else:
settings_general_chmod_enabled = 'True'
5 years ago
settings_general_chmod = request.form.get('settings_general_chmod')
settings_general_sourcepath = request.form.getlist('settings_general_sourcepath')
settings_general_destpath = request.form.getlist('settings_general_destpath')
settings_general_pathmapping = []
settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)])
5 years ago
settings_general_sourcepath_movie = request.form.getlist('settings_general_sourcepath_movie')
settings_general_destpath_movie = request.form.getlist('settings_general_destpath_movie')
settings_general_pathmapping_movie = []
settings_general_pathmapping_movie.extend(
[list(a) for a in zip(settings_general_sourcepath_movie, settings_general_destpath_movie)])
5 years ago
settings_general_branch = request.form.get('settings_general_branch')
settings_general_automatic = request.form.get('settings_general_automatic')
if settings_general_automatic is None:
settings_general_automatic = 'False'
else:
settings_general_automatic = 'True'
5 years ago
settings_general_update_restart = request.form.get('settings_general_update_restart')
if settings_general_update_restart is None:
settings_general_update_restart = 'False'
else:
settings_general_update_restart = 'True'
5 years ago
settings_analytics_enabled = request.form.get('settings_analytics_enabled')
if settings_analytics_enabled is None:
settings_analytics_enabled = 'False'
else:
settings_analytics_enabled = 'True'
5 years ago
settings_general_single_language = request.form.get('settings_general_single_language')
if settings_general_single_language is None:
settings_general_single_language = 'False'
else:
settings_general_single_language = 'True'
5 years ago
settings_general_wanted_search_frequency = request.form.get('settings_general_wanted_search_frequency')
settings_general_scenename = request.form.get('settings_general_scenename')
if settings_general_scenename is None:
settings_general_scenename = 'False'
else:
settings_general_scenename = 'True'
5 years ago
settings_general_embedded = request.form.get('settings_general_embedded')
if settings_general_embedded is None:
settings_general_embedded = 'False'
else:
settings_general_embedded = 'True'
5 years ago
settings_general_utf8_encode = request.form.get('settings_general_utf8_encode')
if settings_general_utf8_encode is None:
settings_general_utf8_encode = 'False'
else:
settings_general_utf8_encode = 'True'
5 years ago
settings_general_ignore_pgs = request.form.get('settings_general_ignore_pgs')
if settings_general_ignore_pgs is None:
settings_general_ignore_pgs = 'False'
else:
settings_general_ignore_pgs = 'True'
5 years ago
settings_general_adaptive_searching = request.form.get('settings_general_adaptive_searching')
if settings_general_adaptive_searching is None:
settings_general_adaptive_searching = 'False'
else:
settings_general_adaptive_searching = 'True'
5 years ago
settings_general_multithreading = request.form.get('settings_general_multithreading')
if settings_general_multithreading is None:
settings_general_multithreading = 'False'
else:
settings_general_multithreading = 'True'
5 years ago
settings_general_minimum_score = request.form.get('settings_general_minimum_score')
settings_general_minimum_score_movies = request.form.get('settings_general_minimum_score_movies')
settings_general_use_postprocessing = request.form.get('settings_general_use_postprocessing')
if settings_general_use_postprocessing is None:
settings_general_use_postprocessing = 'False'
else:
settings_general_use_postprocessing = 'True'
5 years ago
settings_general_postprocessing_cmd = request.form.get('settings_general_postprocessing_cmd')
settings_general_use_sonarr = request.form.get('settings_general_use_sonarr')
if settings_general_use_sonarr is None:
settings_general_use_sonarr = 'False'
else:
settings_general_use_sonarr = 'True'
5 years ago
settings_general_use_radarr = request.form.get('settings_general_use_radarr')
if settings_general_use_radarr is None:
settings_general_use_radarr = 'False'
else:
settings_general_use_radarr = 'True'
5 years ago
settings_page_size = request.form.get('settings_page_size')
settings_subfolder = request.form.get('settings_subfolder')
settings_subfolder_custom = request.form.get('settings_subfolder_custom')
settings_upgrade_subs = request.form.get('settings_upgrade_subs')
if settings_upgrade_subs is None:
settings_upgrade_subs = 'False'
else:
settings_upgrade_subs = 'True'
5 years ago
settings_upgrade_subs_frequency = request.form.get('settings_upgrade_subs_frequency')
settings_days_to_upgrade_subs = request.form.get('settings_days_to_upgrade_subs')
settings_upgrade_manual = request.form.get('settings_upgrade_manual')
if settings_upgrade_manual is None:
settings_upgrade_manual = 'False'
else:
settings_upgrade_manual = 'True'
5 years ago
settings_anti_captcha_provider = request.form.get('settings_anti_captcha_provider')
settings_anti_captcha_key = request.form.get('settings_anti_captcha_key')
settings_death_by_captcha_username = request.form.get('settings_death_by_captcha_username')
settings_death_by_captcha_password = request.form.get('settings_death_by_captcha_password')
5 years ago
before = (six.text_type(settings.general.ip), int(settings.general.port), six.text_type(settings.general.base_url),
six.text_type(settings.general.path_mappings), six.text_type(settings.general.getboolean('use_sonarr')),
six.text_type(settings.general.getboolean('use_radarr')), six.text_type(settings.general.path_mappings_movie))
after = (six.text_type(settings_general_ip), int(settings_general_port), six.text_type(settings_general_baseurl),
six.text_type(settings_general_pathmapping), six.text_type(settings_general_use_sonarr),
six.text_type(settings_general_use_radarr), six.text_type(settings_general_pathmapping_movie))
5 years ago
settings.general.ip = text_type(settings_general_ip)
settings.general.port = text_type(settings_general_port)
settings.general.base_url = text_type(settings_general_baseurl)
settings.general.path_mappings = text_type(settings_general_pathmapping)
settings.general.debug = text_type(settings_general_debug)
settings.general.chmod_enabled = text_type(settings_general_chmod_enabled)
settings.general.chmod = text_type(settings_general_chmod)
settings.general.branch = text_type(settings_general_branch)
settings.general.auto_update = text_type(settings_general_automatic)
settings.general.update_restart = text_type(settings_general_update_restart)
settings.analytics.enabled = text_type(settings_analytics_enabled)
settings.general.single_language = text_type(settings_general_single_language)
settings.general.minimum_score = text_type(settings_general_minimum_score)
settings.general.wanted_search_frequency = text_type(settings_general_wanted_search_frequency)
settings.general.use_scenename = text_type(settings_general_scenename)
settings.general.use_postprocessing = text_type(settings_general_use_postprocessing)
settings.general.postprocessing_cmd = text_type(settings_general_postprocessing_cmd)
settings.general.use_sonarr = text_type(settings_general_use_sonarr)
settings.general.use_radarr = text_type(settings_general_use_radarr)
settings.general.path_mappings_movie = text_type(settings_general_pathmapping_movie)
settings.general.page_size = text_type(settings_page_size)
settings.general.subfolder = text_type(settings_subfolder)
if settings.general.subfolder == 'current':
settings.general.subfolder_custom = ''
else:
settings.general.subfolder_custom = text_type(settings_subfolder_custom)
settings.general.upgrade_subs = text_type(settings_upgrade_subs)
settings.general.upgrade_frequency = text_type(settings_upgrade_subs_frequency)
settings.general.days_to_upgrade_subs = text_type(settings_days_to_upgrade_subs)
settings.general.upgrade_manual = text_type(settings_upgrade_manual)
settings.general.anti_captcha_provider = text_type(settings_anti_captcha_provider)
settings.anticaptcha.anti_captcha_key = text_type(settings_anti_captcha_key)
settings.deathbycaptcha.username = text_type(settings_death_by_captcha_username)
settings.deathbycaptcha.password = text_type(settings_death_by_captcha_password)
5 years ago
# set anti-captcha provider and key
if settings.general.anti_captcha_provider == 'anti-captcha':
os.environ["ANTICAPTCHA_CLASS"] = 'AntiCaptchaProxyLess'
5 years ago
os.environ["ANTICAPTCHA_ACCOUNT_KEY"] = str(settings.anticaptcha.anti_captcha_key)
5 years ago
elif settings.general.anti_captcha_provider == 'death-by-captcha':
5 years ago
os.environ["ANTICAPTCHA_CLASS"] = 'DeathByCaptchaProxyLess'
5 years ago
os.environ["ANTICAPTCHA_ACCOUNT_KEY"] = str(':'.join(
{settings.deathbycaptcha.username, settings.deathbycaptcha.password}))
else:
os.environ["ANTICAPTCHA_CLASS"] = ''
5 years ago
settings.general.minimum_score_movie = text_type(settings_general_minimum_score_movies)
settings.general.use_embedded_subs = text_type(settings_general_embedded)
settings.general.utf8_encode = text_type(settings_general_utf8_encode)
settings.general.ignore_pgs_subs = text_type(settings_general_ignore_pgs)
settings.general.adaptive_searching = text_type(settings_general_adaptive_searching)
settings.general.multithreading = text_type(settings_general_multithreading)
5 years ago
if after != before:
configured()
5 years ago
settings_proxy_type = request.form.get('settings_proxy_type')
settings_proxy_url = request.form.get('settings_proxy_url')
settings_proxy_port = request.form.get('settings_proxy_port')
settings_proxy_username = request.form.get('settings_proxy_username')
settings_proxy_password = request.form.get('settings_proxy_password')
settings_proxy_exclude = request.form.get('settings_proxy_exclude')
5 years ago
before_proxy_password = (six.text_type(settings.proxy.type), six.text_type(settings.proxy.exclude))
if before_proxy_password[0] != settings_proxy_type:
configured()
if before_proxy_password[1] == settings_proxy_password:
settings.proxy.type = text_type(settings_proxy_type)
settings.proxy.url = text_type(settings_proxy_url)
settings.proxy.port = text_type(settings_proxy_port)
settings.proxy.username = text_type(settings_proxy_username)
settings.proxy.exclude = text_type(settings_proxy_exclude)
else:
settings.proxy.type = text_type(settings_proxy_type)
settings.proxy.url = text_type(settings_proxy_url)
settings.proxy.port = text_type(settings_proxy_port)
settings.proxy.username = text_type(settings_proxy_username)
settings.proxy.password = text_type(settings_proxy_password)
settings.proxy.exclude = text_type(settings_proxy_exclude)
5 years ago
settings_auth_type = request.form.get('settings_auth_type')
settings_auth_username = request.form.get('settings_auth_username')
settings_auth_password = request.form.get('settings_auth_password')
if settings.auth.type != settings_auth_type:
configured()
if settings.auth.password == settings_auth_password:
settings.auth.type = text_type(settings_auth_type)
settings.auth.username = text_type(settings_auth_username)
else:
settings.auth.type = text_type(settings_auth_type)
settings.auth.username = text_type(settings_auth_username)
settings.auth.password = hashlib.md5(settings_auth_password.encode('utf-8')).hexdigest()
5 years ago
settings.auth.apikey = request.form.get('settings_auth_apikey')
5 years ago
settings_sonarr_ip = request.form.get('settings_sonarr_ip')
settings_sonarr_port = request.form.get('settings_sonarr_port')
settings_sonarr_baseurl = request.form.get('settings_sonarr_baseurl')
settings_sonarr_ssl = request.form.get('settings_sonarr_ssl')
if settings_sonarr_ssl is None:
settings_sonarr_ssl = 'False'
else:
settings_sonarr_ssl = 'True'
5 years ago
settings_sonarr_apikey = request.form.get('settings_sonarr_apikey')
settings_sonarr_only_monitored = request.form.get('settings_sonarr_only_monitored')
if settings_sonarr_only_monitored is None:
settings_sonarr_only_monitored = 'False'
else:
settings_sonarr_only_monitored = 'True'
5 years ago
settings_sonarr_sync = request.form.get('settings_sonarr_sync')
settings_sonarr_sync_day = request.form.get('settings_sonarr_sync_day')
settings_sonarr_sync_hour = request.form.get('settings_sonarr_sync_hour')
settings.sonarr.ip = text_type(settings_sonarr_ip)
settings.sonarr.port = text_type(settings_sonarr_port)
settings.sonarr.base_url = text_type(settings_sonarr_baseurl)
settings.sonarr.ssl = text_type(settings_sonarr_ssl)
settings.sonarr.apikey = text_type(settings_sonarr_apikey)
settings.sonarr.only_monitored = text_type(settings_sonarr_only_monitored)
settings.sonarr.full_update = text_type(settings_sonarr_sync)
settings.sonarr.full_update_day = text_type(settings_sonarr_sync_day)
settings.sonarr.full_update_hour = text_type(settings_sonarr_sync_hour)
5 years ago
settings_radarr_ip = request.form.get('settings_radarr_ip')
settings_radarr_port = request.form.get('settings_radarr_port')
settings_radarr_baseurl = request.form.get('settings_radarr_baseurl')
settings_radarr_ssl = request.form.get('settings_radarr_ssl')
if settings_radarr_ssl is None:
settings_radarr_ssl = 'False'
else:
settings_radarr_ssl = 'True'
5 years ago
settings_radarr_apikey = request.form.get('settings_radarr_apikey')
settings_radarr_only_monitored = request.form.get('settings_radarr_only_monitored')
if settings_radarr_only_monitored is None:
settings_radarr_only_monitored = 'False'
else:
settings_radarr_only_monitored = 'True'
5 years ago
settings_radarr_sync = request.form.get('settings_radarr_sync')
settings_radarr_sync_day = request.form.get('settings_radarr_sync_day')
settings_radarr_sync_hour = request.form.get('settings_radarr_sync_hour')
settings.radarr.ip = text_type(settings_radarr_ip)
settings.radarr.port = text_type(settings_radarr_port)
settings.radarr.base_url = text_type(settings_radarr_baseurl)
settings.radarr.ssl = text_type(settings_radarr_ssl)
settings.radarr.apikey = text_type(settings_radarr_apikey)
settings.radarr.only_monitored = text_type(settings_radarr_only_monitored)
settings.radarr.full_update = text_type(settings_radarr_sync)
settings.radarr.full_update_day = text_type(settings_radarr_sync_day)
settings.radarr.full_update_hour = text_type(settings_radarr_sync_hour)
5 years ago
settings_subliminal_providers = request.form.getlist('settings_subliminal_providers')
5 years ago
settings.general.enabled_providers = u'' if not settings_subliminal_providers else ','.join(
settings_subliminal_providers)
5 years ago
settings_addic7ed_random_agents = request.form.get('settings_addic7ed_random_agents')
if settings_addic7ed_random_agents is None:
settings_addic7ed_random_agents = 'False'
else:
settings_addic7ed_random_agents = 'True'
5 years ago
settings_opensubtitles_vip = request.form.get('settings_opensubtitles_vip')
if settings_opensubtitles_vip is None:
settings_opensubtitles_vip = 'False'
else:
settings_opensubtitles_vip = 'True'
5 years ago
settings_opensubtitles_ssl = request.form.get('settings_opensubtitles_ssl')
if settings_opensubtitles_ssl is None:
settings_opensubtitles_ssl = 'False'
else:
settings_opensubtitles_ssl = 'True'
5 years ago
settings_opensubtitles_skip_wrong_fps = request.form.get('settings_opensubtitles_skip_wrong_fps')
if settings_opensubtitles_skip_wrong_fps is None:
settings_opensubtitles_skip_wrong_fps = 'False'
else:
settings_opensubtitles_skip_wrong_fps = 'True'
5 years ago
settings.addic7ed.username = request.form.get('settings_addic7ed_username')
settings.addic7ed.password = request.form.get('settings_addic7ed_password')
settings.addic7ed.random_agents = text_type(settings_addic7ed_random_agents)
5 years ago
settings.assrt.token = request.form.get('settings_assrt_token')
settings.legendastv.username = request.form.get('settings_legendastv_username')
settings.legendastv.password = request.form.get('settings_legendastv_password')
settings.opensubtitles.username = request.form.get('settings_opensubtitles_username')
settings.opensubtitles.password = request.form.get('settings_opensubtitles_password')
settings.opensubtitles.vip = text_type(settings_opensubtitles_vip)
settings.opensubtitles.ssl = text_type(settings_opensubtitles_ssl)
settings.opensubtitles.skip_wrong_fps = text_type(settings_opensubtitles_skip_wrong_fps)
5 years ago
settings.xsubs.username = request.form.get('settings_xsubs_username')
settings.xsubs.password = request.form.get('settings_xsubs_password')
settings.napisy24.username = request.form.get('settings_napisy24_username')
settings.napisy24.password = request.form.get('settings_napisy24_password')
settings.subscene.username = request.form.get('settings_subscene_username')
settings.subscene.password = request.form.get('settings_subscene_password')
settings.titlovi.username = request.form.get('settings_titlovi_username')
settings.titlovi.password = request.form.get('settings_titlovi_password')
settings.betaseries.token = request.form.get('settings_betaseries_token')
settings_subliminal_languages = request.form.getlist('settings_subliminal_languages')
5 years ago
database.execute("UPDATE table_settings_languages SET enabled=0")
for item in settings_subliminal_languages:
5 years ago
database.execute("UPDATE table_settings_languages SET enabled=1 WHERE code2=?", (item,))
5 years ago
settings_serie_default_enabled = request.form.get('settings_serie_default_enabled')
if settings_serie_default_enabled is None:
settings_serie_default_enabled = 'False'
else:
settings_serie_default_enabled = 'True'
settings.general.serie_default_enabled = text_type(settings_serie_default_enabled)
5 years ago
settings_serie_default_languages = str(request.form.getlist('settings_serie_default_languages'))
if settings_serie_default_languages == "['None']":
settings_serie_default_languages = 'None'
settings.general.serie_default_language = text_type(settings_serie_default_languages)
5 years ago
settings_serie_default_hi = request.form.get('settings_serie_default_hi')
if settings_serie_default_hi is None:
settings_serie_default_hi = 'False'
else:
settings_serie_default_hi = 'True'
settings.general.serie_default_hi = text_type(settings_serie_default_hi)
5 years ago
settings_serie_default_forced = str(request.form.get('settings_serie_default_forced'))
settings.general.serie_default_forced = text_type(settings_serie_default_forced)
5 years ago
settings_movie_default_enabled = request.form.get('settings_movie_default_enabled')
if settings_movie_default_enabled is None:
settings_movie_default_enabled = 'False'
else:
settings_movie_default_enabled = 'True'
settings.general.movie_default_enabled = text_type(settings_movie_default_enabled)
5 years ago
settings_movie_default_languages = str(request.form.getlist('settings_movie_default_languages'))
if settings_movie_default_languages == "['None']":
settings_movie_default_languages = 'None'
settings.general.movie_default_language = text_type(settings_movie_default_languages)
5 years ago
5 years ago
settings_movie_default_hi = request.form.get('settings_movie_default_hi')
if settings_movie_default_hi is None:
settings_movie_default_hi = 'False'
else:
settings_movie_default_hi = 'True'
5 years ago
settings.general.movie_default_hi = text_type(settings_movie_default_hi)
5 years ago
5 years ago
settings_movie_default_forced = str(request.form.get('settings_movie_default_forced'))
settings.general.movie_default_forced = text_type(settings_movie_default_forced)
5 years ago
with open(os.path.join(args.config_dir, 'config', 'config.ini'), 'w+') as handle:
settings.write(handle)
5 years ago
configure_logging(settings.general.getboolean('debug') or args.debug)
5 years ago
5 years ago
notifiers = database.execute("SELECT * FROM table_settings_notifier ORDER BY name")
for notifier in notifiers:
5 years ago
enabled = request.form.get('settings_notifier_' + notifier['name'] + '_enabled')
if enabled == 'on':
enabled = 1
else:
enabled = 0
5 years ago
notifier_url = request.form.get('settings_notifier_' + notifier['name'] + '_url')
5 years ago
database.execute("UPDATE table_settings_notifier SET enabled=?, url=? WHERE name=?",
5 years ago
(enabled,notifier_url,notifier['name']))
5 years ago
schedule_update_job()
sonarr_full_update()
radarr_full_update()
schedule_wanted_search()
schedule_upgrade_subs()
5 years ago
logging.info('BAZARR Settings saved succesfully.')
5 years ago
if ref.find('saved=true') > 0:
5 years ago
return redirect(ref)
else:
5 years ago
return redirect(ref + "?saved=true")
5 years ago
@app.route('/check_update')
5 years ago
# @custom_auth_basic(check_credentials)
def check_update():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
if not args.no_update:
check_and_apply_update()
5 years ago
redirect(ref)
5 years ago
@app.route('/system')
5 years ago
# @custom_auth_basic(check_credentials)
def system():
5 years ago
def get_time_from_interval(td_object):
seconds = int(td_object.total_seconds())
periods = [
('year', 60 * 60 * 24 * 365),
('month', 60 * 60 * 24 * 30),
('day', 60 * 60 * 24),
('hour', 60 * 60),
('minute', 60),
('second', 1)
]
5 years ago
strings = []
for period_name, period_seconds in periods:
if seconds > period_seconds:
period_value, seconds = divmod(seconds, period_seconds)
has_s = 's' if period_value > 1 else ''
strings.append("%s %s%s" % (period_value, period_name, has_s))
5 years ago
return ", ".join(strings)
def get_time_from_cron(cron):
year = str(cron[0])
if year == "2100":
return "Never"
day = str(cron[4])
hour = str(cron[5])
text = ""
if day == "*":
text = "everyday"
else:
text = "every " + day_name[int(day)]
if hour != "*":
text += " at " + hour + ":00"
return text
task_list = []
for job in scheduler.get_jobs():
if isinstance(job.trigger, CronTrigger):
if str(job.trigger.__getstate__()['fields'][0]) == "2100":
next_run = 'Never'
else:
next_run = pretty.date(job.next_run_time.replace(tzinfo=None))
else:
next_run = pretty.date(job.next_run_time.replace(tzinfo=None))
5 years ago
if isinstance(job.trigger, IntervalTrigger):
interval = "every " + get_time_from_interval(job.trigger.__getstate__()['interval'])
task_list.append([job.name, interval, next_run, job.id])
elif isinstance(job.trigger, CronTrigger):
task_list.append([job.name, get_time_from_cron(job.trigger.fields), next_run, job.id])
5 years ago
throttled_providers = list_throttled_providers()
5 years ago
5 years ago
try:
with open(os.path.join(args.config_dir, 'config', 'releases.txt'), 'r') as f:
releases = ast.literal_eval(f.read())
except Exception as e:
releases = []
5 years ago
logging.exception(
'BAZARR cannot parse releases caching file: ' + os.path.join(args.config_dir, 'config', 'releases.txt'))
sonarr_version = get_sonarr_version()
5 years ago
radarr_version = get_radarr_version()
5 years ago
page_size = int(settings.general.page_size)
5 years ago
5 years ago
return render_template('system.html', bazarr_version=bazarr_version,
sonarr_version=sonarr_version, radarr_version=radarr_version,
operating_system=platform.platform(), python_version=platform.python_version(),
config_dir=args.config_dir, bazarr_dir=os.path.normcase(os.path.dirname(os.path.dirname(__file__))),
base_url=base_url, task_list=task_list, page_size=page_size, releases=releases,
current_port=settings.general.port, throttled_providers=throttled_providers)
5 years ago
@app.route('/logs')
5 years ago
# @custom_auth_basic(check_credentials)
def get_logs():
5 years ago
logs = []
5 years ago
with open(os.path.join(args.config_dir, 'log', 'bazarr.log')) as file:
for line in file.readlines():
lin = []
lin = line.split('|')
logs.append(lin)
logs.reverse()
5 years ago
return dict(data=logs)
5 years ago
@app.route('/execute/<taskid>')
5 years ago
# @custom_auth_basic(check_credentials)
def execute_task(taskid):
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
execute_now(taskid)
5 years ago
redirect(ref)
5 years ago
@app.route('/remove_subtitles', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def remove_subtitles():
5 years ago
5 years ago
episodePath = request.form.get('episodePath')
language = request.form.get('language')
subtitlesPath = request.form.get('subtitlesPath')
sonarrSeriesId = request.form.get('sonarrSeriesId')
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
5 years ago
try:
os.remove(subtitlesPath)
result = language_from_alpha3(language) + " subtitles deleted from disk."
history_log(0, sonarrSeriesId, sonarrEpisodeId, result, language=alpha2_from_alpha3(language))
except OSError as e:
logging.exception('BAZARR cannot delete subtitles file: ' + subtitlesPath)
5 years ago
store_subtitles(path_replace_reverse(episodePath), episodePath)
5 years ago
@app.route('/remove_subtitles_movie', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def remove_subtitles_movie():
5 years ago
5 years ago
moviePath = request.form.get('moviePath')
language = request.form.get('language')
subtitlesPath = request.form.get('subtitlesPath')
radarrId = request.form.get('radarrId')
5 years ago
try:
os.remove(subtitlesPath)
result = language_from_alpha3(language) + " subtitles deleted from disk."
history_log_movie(0, radarrId, result, language=alpha2_from_alpha3(language))
except OSError as e:
logging.exception('BAZARR cannot delete subtitles file: ' + subtitlesPath)
5 years ago
store_subtitles_movie(path_replace_reverse_movie(moviePath), moviePath)
5 years ago
@app.route('/get_subtitle', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def get_subtitle():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
5 years ago
episodePath = request.form.get('episodePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
sonarrSeriesId = request.form.get('sonarrSeriesId')
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
title = request.form.get('title')
5 years ago
providers_list = get_providers()
providers_auth = get_providers_auth()
5 years ago
try:
result = download_subtitle(episodePath, language, hi, forced, providers_list, providers_auth, sceneName, title,
'series')
if result is not None:
message = result[0]
path = result[1]
forced = result[5]
language_code = result[2] + ":forced" if forced else result[2]
provider = result[3]
score = result[4]
history_log(1, sonarrSeriesId, sonarrEpisodeId, message, path, language_code, provider, score)
send_notifications(sonarrSeriesId, sonarrEpisodeId, message)
5 years ago
store_subtitles(path, episodePath)
redirect(ref)
except OSError:
pass
5 years ago
@app.route('/manual_search', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def manual_search_json():
5 years ago
5 years ago
episodePath = request.form.get('episodePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
title = request.form.get('title')
5 years ago
providers_list = get_providers()
providers_auth = get_providers_auth()
5 years ago
data = manual_search(episodePath, language, hi, forced, providers_list, providers_auth, sceneName, title, 'series')
return dict(data=data)
5 years ago
@app.route('/manual_get_subtitle', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def manual_get_subtitle():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
5 years ago
episodePath = request.form.get('episodePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
selected_provider = request.form.get('provider')
subtitle = request.form.get('subtitle')
sonarrSeriesId = request.form.get('sonarrSeriesId')
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
title = request.form.get('title')
5 years ago
providers_auth = get_providers_auth()
5 years ago
try:
5 years ago
result = manual_download_subtitle(episodePath, language, hi, forced, subtitle, selected_provider,
providers_auth,
sceneName, title, 'series')
if result is not None:
message = result[0]
path = result[1]
forced = result[5]
language_code = result[2] + ":forced" if forced else result[2]
provider = result[3]
score = result[4]
history_log(2, sonarrSeriesId, sonarrEpisodeId, message, path, language_code, provider, score)
send_notifications(sonarrSeriesId, sonarrEpisodeId, message)
5 years ago
store_subtitles(path, episodePath)
redirect(ref)
except OSError:
pass
5 years ago
@app.route('/manual_upload_subtitle', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def perform_manual_upload_subtitle():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
episodePath = request.form.get('episodePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
forced = True if request.form.get('forced') == '1' else False
upload = request.files.get('upload')
5 years ago
sonarrSeriesId = request.form.get('sonarrSeriesId')
sonarrEpisodeId = request.form.get('sonarrEpisodeId')
title = request.form.get('title')
_, ext = os.path.splitext(upload.filename)
if ext not in SUBTITLE_EXTENSIONS:
raise ValueError('A subtitle of an invalid format was uploaded.')
try:
result = manual_upload_subtitle(path=episodePath,
language=language,
forced=forced,
title=title,
scene_name=sceneName,
media_type='series',
subtitle=upload)
if result is not None:
message = result[0]
path = result[1]
language_code = language + ":forced" if forced else language
provider = "manual"
score = 360
history_log(4, sonarrSeriesId, sonarrEpisodeId, message, path, language_code, provider, score)
send_notifications(sonarrSeriesId, sonarrEpisodeId, message)
5 years ago
store_subtitles(path, episodePath)
redirect(ref)
except OSError:
pass
5 years ago
@app.route('/get_subtitle_movie', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def get_subtitle_movie():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
5 years ago
moviePath = request.form.get('moviePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
radarrId = request.form.get('radarrId')
title = request.form.get('title')
5 years ago
providers_list = get_providers()
providers_auth = get_providers_auth()
5 years ago
try:
5 years ago
result = download_subtitle(moviePath, language, hi, forced, providers_list, providers_auth, sceneName, title,
'movie')
if result is not None:
message = result[0]
path = result[1]
forced = result[5]
language_code = result[2] + ":forced" if forced else result[2]
provider = result[3]
score = result[4]
history_log_movie(1, radarrId, message, path, language_code, provider, score)
send_notifications_movie(radarrId, message)
5 years ago
store_subtitles_movie(path, moviePath)
redirect(ref)
except OSError:
pass
5 years ago
@app.route('/manual_search_movie', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def manual_search_movie_json():
5 years ago
5 years ago
5 years ago
moviePath = request.form.get('moviePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
title = request.form.get('title')
5 years ago
providers_list = get_providers()
providers_auth = get_providers_auth()
5 years ago
data = manual_search(moviePath, language, hi, forced, providers_list, providers_auth, sceneName, title, 'movie')
return dict(data=data)
5 years ago
@app.route('/manual_get_subtitle_movie', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def manual_get_subtitle_movie():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
5 years ago
moviePath = request.form.get('moviePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
hi = request.form.get('hi')
forced = request.form.get('forced')
selected_provider = request.form.get('provider')
subtitle = request.form.get('subtitle')
radarrId = request.form.get('radarrId')
title = request.form.get('title')
5 years ago
providers_auth = get_providers_auth()
5 years ago
try:
result = manual_download_subtitle(moviePath, language, hi, forced, subtitle, selected_provider, providers_auth,
sceneName, title, 'movie')
if result is not None:
message = result[0]
path = result[1]
forced = result[5]
language_code = result[2] + ":forced" if forced else result[2]
provider = result[3]
score = result[4]
history_log_movie(2, radarrId, message, path, language_code, provider, score)
send_notifications_movie(radarrId, message)
5 years ago
store_subtitles_movie(path, moviePath)
redirect(ref)
except OSError:
pass
5 years ago
@app.route('/manual_upload_subtitle_movie', methods=['POST'])
5 years ago
# @custom_auth_basic(check_credentials)
def perform_manual_upload_subtitle_movie():
5 years ago
ref = request.environ['HTTP_REFERER']
5 years ago
moviePath = request.form.get('moviePath')
sceneName = request.form.get('sceneName')
language = request.form.get('language')
forced = True if request.form.get('forced') == '1' else False
upload = request.files.get('upload')
5 years ago
radarrId = request.form.get('radarrId')
title = request.form.get('title')
_, ext = os.path.splitext(upload.filename)
if ext not in SUBTITLE_EXTENSIONS:
raise ValueError('A subtitle of an invalid format was uploaded.')
try:
result = manual_upload_subtitle(path=moviePath,
language=language,
forced=forced,
title=title,
scene_name=sceneName,
media_type='series',
subtitle=upload)
if result is not None:
message = result[0]
path = result[1]
language_code = language + ":forced" if forced else language
provider = "manual"
score = 120
history_log_movie(4, radarrId, message, path, language_code, provider, score)
send_notifications_movie(radarrId, message)
5 years ago
store_subtitles_movie(path, moviePath)
redirect(ref)
except OSError:
pass
def configured():
database.execute("UPDATE system SET configured = 1")
5 years ago
@app.route('/api/series/wanted')
def api_wanted():
5 years ago
data = database.execute("SELECT table_shows.title as seriesTitle, table_episodes.season || 'x' || table_episodes.episode as episode_number, "
"table_episodes.title as episodeTitle, table_episodes.missing_subtitles FROM table_episodes "
5 years ago
"INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId "
"WHERE table_episodes.missing_subtitles != '[]' ORDER BY table_episodes._rowid_ DESC "
"LIMIT 10")
wanted_subs = []
for item in data:
5 years ago
wanted_subs.append([item['seriesTitle'], item['episode_number'], item['episodeTitle'], item['missing_subtitles']])
return dict(subtitles=wanted_subs)
5 years ago
@app.route('/api/series/history')
def api_history():
5 years ago
data = database.execute("SELECT table_shows.title as seriesTitle, "
"table_episodes.season || 'x' || table_episodes.episode as episode_number, "
"table_episodes.title as episodeTitle, "
"strftime('%Y-%m-%d', datetime(table_history.timestamp, 'unixepoch')) as date, "
"table_history.description FROM table_history "
5 years ago
"INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId "
"INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId "
"WHERE table_history.action != '0' ORDER BY id DESC LIMIT 10")
history_subs = []
for item in data:
5 years ago
history_subs.append([item['seriesTitle'], item['episode_number'], item['episodeTitle'], item['date'], item['description']])
return dict(subtitles=history_subs)
5 years ago
@app.route('/api/movies/wanted/')
5 years ago
def api_movies_wanted():
5 years ago
data = database.execute("SELECT table_movies.title, table_movies.missing_subtitles FROM table_movies "
"WHERE table_movies.missing_subtitles != '[]' ORDER BY table_movies._rowid_ DESC LIMIT 10")
wanted_subs = []
for item in data:
5 years ago
wanted_subs.append([item['title'], item['missing_subtitles']])
return dict(subtitles=wanted_subs)
5 years ago
@app.route('/api/movies/history/')
5 years ago
def api_movies_history():
5 years ago
data = database.execute("SELECT table_movies.title, strftime('%Y-%m-%d', "
5 years ago
"datetime(table_history_movie.timestamp, 'unixepoch')) as date, "
"table_history_movie.description FROM table_history_movie "
5 years ago
"INNER JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId "
"WHERE table_history_movie.action != '0' ORDER BY id DESC LIMIT 10")
history_subs = []
for item in data:
5 years ago
history_subs.append([item['title'], item['date'], item['description']])
return dict(subtitles=history_subs)
5 years ago
@app.route('/test_url/<protocol>/<path:url>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def test_url(protocol, url):
5 years ago
5 years ago
url = six.moves.urllib.parse.unquote(url)
try:
result = requests.get(protocol + "://" + url, allow_redirects=False, verify=False).json()['version']
except:
return dict(status=False)
else:
return dict(status=True, version=result)
5 years ago
@app.route('/test_notification/<protocol>/<path:provider>', methods=['GET'])
5 years ago
# @custom_auth_basic(check_credentials)
def test_notification(protocol, provider):
5 years ago
5 years ago
provider = six.moves.urllib.parse.unquote(provider)
apobj = apprise.Apprise()
apobj.add(protocol + "://" + provider)
5 years ago
apobj.notify(
title='Bazarr test notification',
body=('Test notification')
)
5 years ago
@app.route('/notifications')
5 years ago
# @custom_auth_basic(check_credentials)
def notifications():
if queueconfig.notifications:
5 years ago
test = queueconfig.notifications
return queueconfig.notifications.read() or ''
else:
5 years ago
return abort(400)
6 years ago
5 years ago
@app.route('/running_tasks')
5 years ago
# @custom_auth_basic(check_credentials)
def running_tasks_list():
5 years ago
return dict(tasks=running_tasks)
6 years ago
5 years ago
5 years ago
@app.route('/episode_history/<int:no>')
5 years ago
# @custom_auth_basic(check_credentials)
def episode_history(no):
5 years ago
episode_history = database.execute("SELECT action, timestamp, language, provider, score FROM table_history "
"WHERE sonarrEpisodeId=? ORDER BY timestamp DESC", (no,))
for item in episode_history:
if item['action'] == 0:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"erased.' data-inverted='' data-position='top left'><i class='ui trash icon'></i></div>"
elif item['action'] == 1:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"downloaded.' data-inverted='' data-position='top left'><i class='ui download " \
"icon'></i></div>"
elif item['action'] == 2:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"manually downloaded.' data-inverted='' data-position='top left'><i class='ui user " \
"icon'></i></div>"
elif item['action'] == 3:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"upgraded.' data-inverted='' data-position='top left'><i class='ui recycle " \
"icon'></i></div>"
elif item['action'] == 4:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"manually uploaded.' data-inverted='' data-position='top left'><i class='ui cloud " \
"upload icon'></i></div>"
item['timestamp'] = "<div data-tooltip='" + \
time.strftime('%d/%m/%Y %H:%M:%S', time.localtime(item['timestamp'])) + "'>" + \
pretty.date(datetime.fromtimestamp(item['timestamp'])) + "</div>"
if item['language']:
item['language'] = language_from_alpha2(item['language'])
else:
item['language'] = "<i>undefined</i>"
if item['score']:
item['score'] = str(round((int(item['score']) * 100 / 360), 2)) + "%"
return dict(data=episode_history)
5 years ago
@app.route('/movie_history/<int:no>')
5 years ago
# @custom_auth_basic(check_credentials)
def movie_history(no):
5 years ago
movie_history = database.execute("SELECT action, timestamp, language, provider, score FROM table_history_movie "
"WHERE radarrId=? ORDER BY timestamp DESC", (no,))
for item in movie_history:
if item['action'] == 0:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"erased.' data-inverted='' data-position='top left'><i class='ui trash icon'></i></div>"
elif item['action'] == 1:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"downloaded.' data-inverted='' data-position='top left'><i class='ui download " \
"icon'></i></div>"
elif item['action'] == 2:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"manually downloaded.' data-inverted='' data-position='top left'><i class='ui user " \
"icon'></i></div>"
elif item['action'] == 3:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"upgraded.' data-inverted='' data-position='top left'><i class='ui recycle " \
"icon'></i></div>"
elif item['action'] == 4:
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
"manually uploaded.' data-inverted='' data-position='top left'><i class='ui cloud " \
"upload icon'></i></div>"
item['timestamp'] = "<div data-tooltip='" + \
time.strftime('%d/%m/%Y %H:%M:%S', time.localtime(item['timestamp'])) + "'>" + \
pretty.date(datetime.fromtimestamp(item['timestamp'])) + "</div>"
if item['language']:
item['language'] = language_from_alpha2(item['language'])
else:
item['language'] = "<i>undefined</i>"
if item['score']:
item['score'] = str(round((int(item['score']) * 100 / 120), 2)) + '%'
return dict(data=movie_history)
4 years ago
@app.route('/event')
def event():
return Response(event_stream.read(), mimetype="text/event-stream")
# Don't put any route under this one
5 years ago
@app.route('/api/help')
def api_help():
endpoints = []
for route in app.app.routes:
if '/api/' in route.rule:
endpoints.append(route.rule)
return dict(endpoints=endpoints)
# Mute DeprecationWarning
warnings.simplefilter("ignore", DeprecationWarning)
if six.PY3:
warnings.simplefilter("ignore", BrokenPipeError)
5 years ago
if args.dev:
5 years ago
server = app.run(
5 years ago
host=str(settings.general.ip), port=(int(args.port) if args.port else int(settings.general.port)))
5 years ago
else:
server = CherryPyWSGIServer((str(settings.general.ip), (int(args.port) if args.port else int(settings.general.port))), app)
try:
logging.info('BAZARR is started and waiting for request on http://' + str(settings.general.ip) + ':' + (str(
args.port) if args.port else str(settings.general.port)) + str(base_url))
5 years ago
if not args.dev:
server.start()
except KeyboardInterrupt:
shutdown()