From db2378943fad97cfef80cca10e2db675036b0941 Mon Sep 17 00:00:00 2001 From: halali Date: Thu, 23 Aug 2018 21:58:15 +0200 Subject: [PATCH] Move settings from Database to Config file (#126) * Move settings from Database to Config file * Delete unused config and forgot upload init * Fix * Update get_subtitles and fix provider auth * Revert "Update get_subtitles and fix provider auth" This reverts commit c904bf6b5a61b291d4e5764a885578e66ae7d5d3. * Update get_sebtitles * more fixes * Update requirements --- bazarr.py | 2811 ++++++++++++++++++++------------------- check_update.py | 4 +- create_db.sql | 63 +- get_auth_settings.py | 21 - get_episodes.py | 8 +- get_general_settings.py | 140 -- get_movies.py | 24 +- get_radarr_settings.py | 42 - get_series.py | 18 +- get_settings.py | 416 ++++++ get_sonarr_settings.py | 42 - get_subtitle.py | 16 +- init.py | 220 +++ init_db.py | 50 - list_subtitles.py | 6 +- requirements.txt | 1 + scheduler.py | 17 +- update_db.py | 152 +-- views/episodes.tpl | 8 +- views/history.tpl | 12 +- views/menu.tpl | 21 +- views/movie.tpl | 6 +- views/movies.tpl | 2 +- views/movieseditor.tpl | 2 +- views/series.tpl | 4 +- views/serieseditor.tpl | 2 +- views/settings.tpl | 46 +- views/wanted.tpl | 15 +- 28 files changed, 2199 insertions(+), 1970 deletions(-) delete mode 100644 get_auth_settings.py delete mode 100644 get_general_settings.py delete mode 100644 get_radarr_settings.py create mode 100644 get_settings.py delete mode 100644 get_sonarr_settings.py create mode 100644 init.py delete mode 100644 init_db.py diff --git a/bazarr.py b/bazarr.py index 56075d041..87b570ed5 100644 --- a/bazarr.py +++ b/bazarr.py @@ -1,1390 +1,1421 @@ -bazarr_version = '0.6.0' - -import gc -gc.enable() - -from get_argv import config_dir - -import os -import sys -reload(sys) -sys.setdefaultencoding('utf8') -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'libs/')) - -import sqlite3 -from init_db import * -from update_db import * - -import logging -from logging.handlers import TimedRotatingFileHandler - -logger = logging.getLogger('waitress') -db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) -c = db.cursor() -c.execute("SELECT log_level FROM table_settings_general") -log_level = c.fetchone() -c.close() -log_level = log_level[0] -if log_level is None: - log_level = "INFO" -log_level = getattr(logging, log_level) - -class OneLineExceptionFormatter(logging.Formatter): - def formatException(self, exc_info): - """ - Format an exception so that it prints on a single line. - """ - result = super(OneLineExceptionFormatter, self).formatException(exc_info) - return repr(result) # or format into one line however you want to - - def format(self, record): - s = super(OneLineExceptionFormatter, self).format(record) - if record.exc_text: - s = s.replace('\n', '') + '|' - return s - -def configure_logging(): - global fh - fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, backupCount=7) - f = OneLineExceptionFormatter('%(asctime)s|%(levelname)s|%(message)s|', - '%d/%m/%Y %H:%M:%S') - fh.setFormatter(f) - logging.getLogger("enzyme").setLevel(logging.CRITICAL) - logging.getLogger("apscheduler").setLevel(logging.WARNING) - logging.getLogger("subliminal").setLevel(logging.CRITICAL) - logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) - root = logging.getLogger() - root.setLevel(log_level) - root.addHandler(fh) - -configure_logging() - -from update_modules import * - -from bottle import route, run, template, static_file, request, redirect, response, HTTPError -import bottle -bottle.TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(__file__), 'views/')) -bottle.debug(True) -bottle.TEMPLATES.clear() - -from json import dumps -import itertools -import operator -import requests -import pretty -from datetime import datetime, timedelta -from PIL import Image -from io import BytesIO -from fdsend import send_file -import urllib -import math -import ast -import hashlib - -from get_languages import load_language_in_db, language_from_alpha3 -from get_providers import * - -from get_series import * -from get_episodes import * -from get_general_settings import base_url, ip, port, path_replace, path_replace_movie -from get_sonarr_settings import get_sonarr_settings -from check_update import check_and_apply_update -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, wanted_download_subtitles, wanted_search_missing_subtitles -from utils import history_log, history_log_movie -from scheduler import * -from notifier import send_notifications, send_notifications_movie - -# Reset restart required warning on start -conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) -c = conn.cursor() -c.execute("UPDATE table_settings_general SET configured = 0, updated = 0") -conn.commit() -c.close() - -# Load languages in database -load_language_in_db() - -from get_auth_settings import get_auth_settings -auth_enabled = get_auth_settings()[0] - -def custom_auth_basic(check): - def decorator(func): - def wrapper(*a, **ka): - if auth_enabled == "True": - user, password = request.auth or (None, None) - if user is None or not check(user, password): - err = HTTPError(401, "Access denied") - err.add_header('WWW-Authenticate', 'Basic realm="Bazarr"') - return err - return func(*a, **ka) - else: - return func(*a, **ka) - - return wrapper - return decorator - -def check_credentials(user, pw): - from get_auth_settings import get_auth_settings - auth_enabled = get_auth_settings() - - username = auth_enabled[1] - password = auth_enabled[2] - if hashlib.md5(pw).hexdigest() == password and user == username: - return True - return False - -@route('/') -@custom_auth_basic(check_credentials) -def redirect_root(): - redirect (base_url) - -@route(base_url + 'static/:path#.+#', name='static') -@custom_auth_basic(check_credentials) -def static(path): - return static_file(path, root=os.path.join(os.path.dirname(__file__), 'static')) - -@route(base_url + 'emptylog') -@custom_auth_basic(check_credentials) -def emptylog(): - ref = request.environ['HTTP_REFERER'] - - fh.doRollover() - logging.info('Log file emptied') - - redirect(ref) - -@route(base_url + 'bazarr.log') -@custom_auth_basic(check_credentials) -def download_log(): - return static_file('bazarr.log', root=os.path.join(config_dir, 'log/'), download='bazarr.log') - -@route(base_url + 'image_proxy/', method='GET') -@custom_auth_basic(check_credentials) -def image_proxy(url): - from get_sonarr_settings import get_sonarr_settings - url_sonarr = get_sonarr_settings()[0] - url_sonarr_short = get_sonarr_settings()[1] - apikey = get_sonarr_settings()[2] - url_image = url_sonarr_short + '/' + url + '?apikey=' + apikey - try: - img_pil = Image.open(BytesIO(requests.get(url_sonarr_short + '/api' + url_image.split(url_sonarr)[1], timeout=15).content)) - except: - return None - else: - img_buffer = BytesIO() - img_pil.tobytes() - img_pil.save(img_buffer, img_pil.format) - img_buffer.seek(0) - return send_file(img_buffer, ctype=img_pil.format) - -@route(base_url + 'image_proxy_movies/', method='GET') -@custom_auth_basic(check_credentials) -def image_proxy_movies(url): - from get_radarr_settings import get_radarr_settings - url_radarr = get_radarr_settings()[0] - url_radarr_short = get_radarr_settings()[1] - apikey = get_radarr_settings()[2] - try: - url_image = (url_radarr_short + '/' + url + '?apikey=' + apikey).replace('/fanart.jpg', '/banner.jpg') - img_pil = Image.open(BytesIO(requests.get(url_radarr_short + '/api' + url_image.split(url_radarr)[1], timeout=15).content)) - except: - url_image = url_radarr_short + '/' + url + '?apikey=' + apikey - img_pil = Image.open(BytesIO(requests.get(url_radarr_short + '/api' + url_image.split(url_radarr)[1], timeout=15).content)) - - img_buffer = BytesIO() - img_pil.tobytes() - img_pil.save(img_buffer, img_pil.format) - img_buffer.seek(0) - return send_file(img_buffer, ctype=img_pil.format) - - -@route(base_url) -@custom_auth_basic(check_credentials) -def redirect_root(): - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - integration = c.execute("SELECT use_sonarr, use_radarr FROM table_settings_general").fetchone() - c.close() - - if integration[0] == "True": - redirect(base_url + 'series') - elif integration[1] == "True": - redirect(base_url + 'movies') - else: - redirect(base_url + 'settings') - - -@route(base_url + 'series') -@custom_auth_basic(check_credentials) -def series(): - single_language = get_general_settings()[7] - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_shows") - missing_count = c.fetchone() - missing_count = missing_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(missing_count / (page_size + 0.0))) - - c.execute("SELECT tvdbId, title, path_substitution(path), languages, hearing_impaired, sonarrSeriesId, poster, audio_language FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") - languages = c.fetchall() - c.execute("SELECT table_shows.sonarrSeriesId, COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN table_episodes ON table_shows.sonarrSeriesId=table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' AND table_episodes.missing_subtitles IS NOT '[]' GROUP BY table_shows.sonarrSeriesId") - missing_subtitles_list = c.fetchall() - c.execute("SELECT table_shows.sonarrSeriesId, COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN table_episodes ON table_shows.sonarrSeriesId=table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' GROUP BY table_shows.sonarrSeriesId") - total_subtitles_list = c.fetchall() - c.close() - output = template('series', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list, total_subtitles_list=total_subtitles_list, languages=languages, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, single_language=single_language, page_size=page_size) - return output - -@route(base_url + 'serieseditor') -@custom_auth_basic(check_credentials) -def serieseditor(): - single_language = get_general_settings()[7] - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_shows") - missing_count = c.fetchone() - missing_count = missing_count[0] - - c.execute("SELECT tvdbId, title, path_substitution(path), languages, hearing_impaired, sonarrSeriesId, poster, audio_language FROM table_shows ORDER BY title ASC") - data = c.fetchall() - c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") - languages = c.fetchall() - c.close() - output = template('serieseditor', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, base_url=base_url, single_language=single_language) - return output - -@route(base_url + 'search_json/', method='GET') -@custom_auth_basic(check_credentials) -def search_json(query): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - c.execute("SELECT title, sonarrSeriesId FROM table_shows WHERE title LIKE ? ORDER BY title", ('%'+query+'%',)) - series = c.fetchall() - - c.execute("SELECT title, radarrId FROM table_movies WHERE title LIKE ? ORDER BY title", ('%' + query + '%',)) - movies = c.fetchall() - - search_list = [] - for serie in series: - search_list.append(dict([('name', serie[0]), ('url', base_url + 'episodes/' + str(serie[1]))])) - - for movie in movies: - search_list.append(dict([('name', movie[0]), ('url', base_url + 'movie/' + str(movie[1]))])) - - response.content_type = 'application/json' - return dict(items=search_list) - - -@route(base_url + 'edit_series/', method='POST') -@custom_auth_basic(check_credentials) -def edit_series(no): - ref = request.environ['HTTP_REFERER'] - - lang = request.forms.getall('languages') - if len(lang) > 0: - pass - else: - lang = 'None' - - single_language = get_general_settings()[7] - if single_language == 'True': - if str(lang) == "['None']": - lang = 'None' - else: - lang = str(lang) - else: - if str(lang) == "['']": - lang = '[]' - - hi = request.forms.get('hearing_impaired') - - if hi == "on": - hi = "True" - else: - hi = "False" - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - c.execute("UPDATE table_shows SET languages = ?, hearing_impaired = ? WHERE sonarrSeriesId LIKE ?", (str(lang), hi, no)) - conn.commit() - c.close() - - list_missing_subtitles(no) - - redirect(ref) - -@route(base_url + 'edit_serieseditor', method='POST') -@custom_auth_basic(check_credentials) -def edit_serieseditor(): - ref = request.environ['HTTP_REFERER'] - - series = request.forms.get('series') - series = ast.literal_eval(str('[' + series + ']')) - lang = request.forms.getall('languages') - hi = request.forms.get('hearing_impaired') - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - - for serie in series: - if str(lang) != "[]" and str(lang) != "['']": - if str(lang) == "['None']": - lang = 'None' - else: - lang = str(lang) - c.execute("UPDATE table_shows SET languages = ? WHERE sonarrSeriesId LIKE ?", (lang, serie)) - if hi != '': - c.execute("UPDATE table_shows SET hearing_impaired = ? WHERE sonarrSeriesId LIKE ?", (hi, serie)) - - conn.commit() - c.close() - - for serie in series: - list_missing_subtitles(serie) - - redirect(ref) - -@route(base_url + 'episodes/', method='GET') -@custom_auth_basic(check_credentials) -def episodes(no): - # single_language = get_general_settings()[7] - url_sonarr_short = get_sonarr_settings()[1] - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - conn.create_function("path_substitution", 1, path_replace) - c = conn.cursor() - - series_details = [] - series_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbid, audio_language, languages, path_substitution(path) FROM table_shows WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchone() - tvdbid = series_details[5] - - episodes = c.execute("SELECT title, path_substitution(path), season, episode, subtitles, sonarrSeriesId, missing_subtitles, sonarrEpisodeId, scene_name, monitored FROM table_episodes WHERE sonarrSeriesId LIKE ? ORDER BY episode ASC", (str(no),)).fetchall() - number = len(episodes) - languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall() - c.close() - episodes = reversed(sorted(episodes, key=operator.itemgetter(2))) - seasons_list = [] - for key, season in itertools.groupby(episodes,operator.itemgetter(2)): - seasons_list.append(list(season)) - - return template('episodes', __file__=__file__, bazarr_version=bazarr_version, no=no, details=series_details, languages=languages, seasons=seasons_list, url_sonarr_short=url_sonarr_short, base_url=base_url, tvdbid=tvdbid, number=number) - -@route(base_url + 'movies') -@custom_auth_basic(check_credentials) -def movies(): - single_language = get_general_settings()[7] - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace_movie) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_movies") - missing_count = c.fetchone() - missing_count = missing_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(missing_count / (page_size + 0.0))) - - c.execute("SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language, monitored FROM table_movies ORDER BY title ASC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") - languages = c.fetchall() - c.close() - output = template('movies', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, single_language=single_language, page_size=page_size) - return output - -@route(base_url + 'movieseditor') -@custom_auth_basic(check_credentials) -def movieseditor(): - single_language = get_general_settings()[7] - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace_movie) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_movies") - missing_count = c.fetchone() - missing_count = missing_count[0] - - c.execute("SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language FROM table_movies ORDER BY title ASC") - data = c.fetchall() - c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") - languages = c.fetchall() - c.close() - output = template('movieseditor', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, base_url=base_url, single_language=single_language) - return output - -@route(base_url + 'edit_movieseditor', method='POST') -@custom_auth_basic(check_credentials) -def edit_movieseditor(): - ref = request.environ['HTTP_REFERER'] - - movies = request.forms.get('movies') - movies = ast.literal_eval(str('[' + movies + ']')) - lang = request.forms.getall('languages') - hi = request.forms.get('hearing_impaired') - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - - for movie in movies: - if str(lang) != "[]" and str(lang) != "['']": - if str(lang) == "['None']": - lang = 'None' - else: - lang = str(lang) - c.execute("UPDATE table_movies SET languages = ? WHERE radarrId LIKE ?", (lang, movie)) - if hi != '': - c.execute("UPDATE table_movies SET hearing_impaired = ? WHERE radarrId LIKE ?", (hi, movie)) - - conn.commit() - c.close() - - for movie in movies: - list_missing_subtitles_movies(movie) - - redirect(ref) - -@route(base_url + 'edit_movie/', method='POST') -@custom_auth_basic(check_credentials) -def edit_movie(no): - ref = request.environ['HTTP_REFERER'] - - lang = request.forms.getall('languages') - if len(lang) > 0: - pass - else: - lang = 'None' - - if str(lang) == "['']": - lang = '[]' - - hi = request.forms.get('hearing_impaired') - - if hi == "on": - hi = "True" - else: - hi = "False" - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - c.execute("UPDATE table_movies SET languages = ?, hearing_impaired = ? WHERE radarrId LIKE ?", (str(lang), hi, no)) - conn.commit() - c.close() - - list_missing_subtitles_movies(no) - - redirect(ref) - -@route(base_url + 'movie/', method='GET') -@custom_auth_basic(check_credentials) -def movie(no): - from get_radarr_settings import get_radarr_settings - # single_language = get_general_settings()[7] - url_radarr_short = get_radarr_settings()[1] - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - conn.create_function("path_substitution", 1, path_replace_movie) - c = conn.cursor() - - movies_details = [] - movies_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbid, audio_language, languages, path_substitution(path), subtitles, radarrId, missing_subtitles, sceneName, monitored FROM table_movies WHERE radarrId LIKE ?", (str(no),)).fetchone() - tmdbid = movies_details[5] - - languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall() - c.close() - - return template('movie', __file__=__file__, bazarr_version=bazarr_version, no=no, details=movies_details, languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid) - -@route(base_url + 'scan_disk/', method='GET') -@custom_auth_basic(check_credentials) -def scan_disk(no): - ref = request.environ['HTTP_REFERER'] - - series_scan_subtitles(no) - - redirect(ref) - -@route(base_url + 'scan_disk_movie/', method='GET') -@custom_auth_basic(check_credentials) -def scan_disk_movie(no): - ref = request.environ['HTTP_REFERER'] - - movies_scan_subtitles(no) - - redirect(ref) - -@route(base_url + 'search_missing_subtitles/', method='GET') -@custom_auth_basic(check_credentials) -def search_missing_subtitles(no): - ref = request.environ['HTTP_REFERER'] - - series_download_subtitles(no) - - redirect(ref) - -@route(base_url + 'search_missing_subtitles_movie/', method='GET') -@custom_auth_basic(check_credentials) -def search_missing_subtitles_movie(no): - ref = request.environ['HTTP_REFERER'] - - movies_download_subtitles(no) - - redirect(ref) - -@route(base_url + 'history') -@custom_auth_basic(check_credentials) -def history(): - return template('history', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url) - -@route(base_url + 'historyseries') -@custom_auth_basic(check_credentials) -def historyseries(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_history") - row_count = c.fetchone() - row_count = row_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(row_count / (page_size + 0.0))) - - now = datetime.now() - today = [] - thisweek = [] - thisyear = [] - stats = c.execute("SELECT timestamp FROM table_history WHERE action LIKE '1'").fetchall() - total = len(stats) - for stat in stats: - if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: - today.append(datetime.fromtimestamp(stat[0]).date()) - if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: - thisweek.append(datetime.fromtimestamp(stat[0]).date()) - if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: - thisyear.append(datetime.fromtimestamp(stat[0]).date()) - stats = [len(today), len(thisweek), len(thisyear), total] - - c.execute("SELECT table_history.action, table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_history.timestamp, table_history.description, table_history.sonarrSeriesId FROM table_history LEFT JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId LEFT JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId ORDER BY id DESC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.close() - data = reversed(sorted(data, key=operator.itemgetter(4))) - return template('historyseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size) - -@route(base_url + 'historymovies') -@custom_auth_basic(check_credentials) -def historymovies(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - c.execute("SELECT COUNT(*) FROM table_history_movie") - row_count = c.fetchone() - row_count = row_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(row_count / (page_size + 0.0))) - - now = datetime.now() - today = [] - thisweek = [] - thisyear = [] - stats = c.execute("SELECT timestamp FROM table_history_movie WHERE action LIKE '1'").fetchall() - total = len(stats) - for stat in stats: - if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: - today.append(datetime.fromtimestamp(stat[0]).date()) - if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: - thisweek.append(datetime.fromtimestamp(stat[0]).date()) - if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: - thisyear.append(datetime.fromtimestamp(stat[0]).date()) - stats = [len(today), len(thisweek), len(thisyear), total] - - c.execute("SELECT table_history_movie.action, table_movies.title, table_history_movie.timestamp, table_history_movie.description, table_history_movie.radarrId FROM table_history_movie LEFT JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId ORDER BY id DESC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.close() - data = reversed(sorted(data, key=operator.itemgetter(2))) - return template('historymovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size) - -@route(base_url + 'wanted') -@custom_auth_basic(check_credentials) -def wanted(): - return template('wanted', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url) - -@route(base_url + 'wantedseries') -@custom_auth_basic(check_credentials) -def wantedseries(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace) - c = db.cursor() - - if get_general_settings()[24] == "True": - monitored_only_query_string = ' AND monitored = "True"' - else: - monitored_only_query_string = "" - - c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string) - missing_count = c.fetchone() - missing_count = missing_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(missing_count / (page_size + 0.0))) - - c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, path_substitution(table_episodes.path), table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, table_episodes.scene_name FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string + " ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.close() - return template('wantedseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size) - -@route(base_url + 'wantedmovies') -@custom_auth_basic(check_credentials) -def wantedmovies(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - db.create_function("path_substitution", 1, path_replace_movie) - c = db.cursor() - - if get_general_settings()[24] == "True": - monitored_only_query_string = ' AND monitored = "True"' - else: - monitored_only_query_string = "" - - c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string) - missing_count = c.fetchone() - missing_count = missing_count[0] - page = request.GET.page - if page == "": - page = "1" - page_size = int(get_general_settings()[21]) - offset = (int(page) - 1) * page_size - max_page = int(math.ceil(missing_count / (page_size + 0.0))) - - c.execute("SELECT title, missing_subtitles, radarrId, path_substitution(path), hearing_impaired, sceneName FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset,)) - data = c.fetchall() - c.close() - return template('wantedmovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size) - -@route(base_url + 'wanted_search_missing_subtitles') -@custom_auth_basic(check_credentials) -def wanted_search_missing_subtitles_list(): - ref = request.environ['HTTP_REFERER'] - - wanted_search_missing_subtitles() - - redirect(ref) - -@route(base_url + 'settings') -@custom_auth_basic(check_credentials) -def settings(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - c.execute("SELECT * FROM table_settings_general") - settings_general = c.fetchone() - c.execute("SELECT * FROM table_settings_auth") - settings_auth = c.fetchone() - c.execute("SELECT * FROM table_settings_languages ORDER BY name") - settings_languages = c.fetchall() - c.execute("SELECT * FROM table_settings_providers ORDER BY name") - settings_providers = c.fetchall() - c.execute("SELECT * FROM table_settings_sonarr") - settings_sonarr = c.fetchone() - c.execute("SELECT * FROM table_settings_radarr") - settings_radarr = c.fetchone() - c.execute("SELECT * FROM table_settings_notifier ORDER BY name") - settings_notifier = c.fetchall() - c.close() - return template('settings', __file__=__file__, bazarr_version=bazarr_version, settings_general=settings_general, settings_auth=settings_auth, settings_languages=settings_languages, settings_providers=settings_providers, settings_sonarr=settings_sonarr, settings_radarr=settings_radarr, settings_notifier=settings_notifier, base_url=base_url) - -@route(base_url + 'save_settings', method='POST') -@custom_auth_basic(check_credentials) -def save_settings(): - ref = request.environ['HTTP_REFERER'] - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - - settings_general_ip = request.forms.get('settings_general_ip') - settings_general_port = request.forms.get('settings_general_port') - settings_general_baseurl = request.forms.get('settings_general_baseurl') - settings_general_loglevel = request.forms.get('settings_general_loglevel') - settings_general_auth_enabled = request.forms.get('settings_general_auth_enabled') - if settings_general_auth_enabled is None: - settings_general_auth_enabled = 'False' - else: - settings_general_auth_enabled = 'True' - settings_general_auth_username = request.forms.get('settings_general_auth_username') - settings_general_auth_password = request.forms.get('settings_general_auth_password') - settings_general_sourcepath = request.forms.getall('settings_general_sourcepath') - settings_general_destpath = request.forms.getall('settings_general_destpath') - settings_general_pathmapping = [] - settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)]) - settings_general_sourcepath_movie = request.forms.getall('settings_general_sourcepath_movie') - settings_general_destpath_movie = request.forms.getall('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)]) - settings_general_branch = request.forms.get('settings_general_branch') - settings_general_automatic = request.forms.get('settings_general_automatic') - if settings_general_automatic is None: - settings_general_automatic = 'False' - else: - settings_general_automatic = 'True' - settings_general_single_language = request.forms.get('settings_general_single_language') - if settings_general_single_language is None: - settings_general_single_language = 'False' - else: - settings_general_single_language = 'True' - settings_general_scenename = request.forms.get('settings_general_scenename') - if settings_general_scenename is None: - settings_general_scenename = 'False' - else: - settings_general_scenename = 'True' - settings_general_embedded = request.forms.get('settings_general_embedded') - if settings_general_embedded is None: - settings_general_embedded = 'False' - else: - settings_general_embedded = 'True' - settings_general_only_monitored = request.forms.get('settings_general_only_monitored') - if settings_general_only_monitored is None: - settings_general_only_monitored = 'False' - else: - settings_general_only_monitored = 'True' - settings_general_minimum_score = request.forms.get('settings_general_minimum_score') - settings_general_minimum_score_movies = request.forms.get('settings_general_minimum_score_movies') - settings_general_use_postprocessing = request.forms.get('settings_general_use_postprocessing') - if settings_general_use_postprocessing is None: - settings_general_use_postprocessing = 'False' - else: - settings_general_use_postprocessing = 'True' - settings_general_postprocessing_cmd = request.forms.get('settings_general_postprocessing_cmd') - settings_general_use_sonarr = request.forms.get('settings_general_use_sonarr') - if settings_general_use_sonarr is None: - settings_general_use_sonarr = 'False' - else: - settings_general_use_sonarr = 'True' - settings_general_use_radarr = request.forms.get('settings_general_use_radarr') - if settings_general_use_radarr is None: - settings_general_use_radarr = 'False' - else: - settings_general_use_radarr = 'True' - settings_page_size = request.forms.get('settings_page_size') - - before = c.execute("SELECT ip, port, base_url, log_level, path_mapping, use_sonarr, use_radarr, path_mapping_movie FROM table_settings_general").fetchone() - after = (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_loglevel), unicode(settings_general_pathmapping), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie)) - c.execute("UPDATE table_settings_general SET ip = ?, port = ?, base_url = ?, path_mapping = ?, log_level = ?, branch=?, auto_update=?, single_language=?, minimum_score=?, use_scenename=?, use_postprocessing=?, postprocessing_cmd=?, use_sonarr=?, use_radarr=?, path_mapping_movie=?, page_size=?, use_embedded_subs=?, minimum_score_movie=?, only_monitored=?", (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_pathmapping), unicode(settings_general_loglevel), unicode(settings_general_branch), unicode(settings_general_automatic), unicode(settings_general_single_language), unicode(settings_general_minimum_score), unicode(settings_general_scenename), unicode(settings_general_use_postprocessing), unicode(settings_general_postprocessing_cmd), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie), unicode(settings_page_size), unicode(settings_general_embedded), unicode(settings_general_minimum_score_movies), unicode(settings_general_only_monitored))) - conn.commit() - if after != before: - configured() - get_general_settings() - - before_auth_password = c.execute("SELECT enabled, password FROM table_settings_auth").fetchone() - if before_auth_password[0] != settings_general_auth_enabled: - configured() - if before_auth_password[1] == settings_general_auth_password: - c.execute("UPDATE table_settings_auth SET enabled = ?, username = ?", (unicode(settings_general_auth_enabled), unicode(settings_general_auth_username))) - else: - c.execute("UPDATE table_settings_auth SET enabled = ?, username = ?, password = ?", (unicode(settings_general_auth_enabled), unicode(settings_general_auth_username), unicode(hashlib.md5(settings_general_auth_password.encode('utf-8')).hexdigest()))) - conn.commit() - - settings_sonarr_ip = request.forms.get('settings_sonarr_ip') - settings_sonarr_port = request.forms.get('settings_sonarr_port') - settings_sonarr_baseurl = request.forms.get('settings_sonarr_baseurl') - settings_sonarr_ssl = request.forms.get('settings_sonarr_ssl') - if settings_sonarr_ssl is None: - settings_sonarr_ssl = 'False' - else: - settings_sonarr_ssl = 'True' - settings_sonarr_apikey = request.forms.get('settings_sonarr_apikey') - settings_sonarr_sync = request.forms.get('settings_sonarr_sync') - c.execute("UPDATE table_settings_sonarr SET ip = ?, port = ?, base_url = ?, ssl = ?, apikey = ?, full_update = ?", (settings_sonarr_ip, settings_sonarr_port, settings_sonarr_baseurl, settings_sonarr_ssl, settings_sonarr_apikey, settings_sonarr_sync)) - - settings_radarr_ip = request.forms.get('settings_radarr_ip') - settings_radarr_port = request.forms.get('settings_radarr_port') - settings_radarr_baseurl = request.forms.get('settings_radarr_baseurl') - settings_radarr_ssl = request.forms.get('settings_radarr_ssl') - if settings_radarr_ssl is None: - settings_radarr_ssl = 'False' - else: - settings_radarr_ssl = 'True' - settings_radarr_apikey = request.forms.get('settings_radarr_apikey') - settings_radarr_sync = request.forms.get('settings_radarr_sync') - c.execute("UPDATE table_settings_radarr SET ip = ?, port = ?, base_url = ?, ssl = ?, apikey = ?, full_update = ?", (settings_radarr_ip, settings_radarr_port, settings_radarr_baseurl, settings_radarr_ssl, settings_radarr_apikey, settings_radarr_sync)) - - settings_subliminal_providers = request.forms.getall('settings_subliminal_providers') - c.execute("UPDATE table_settings_providers SET enabled = 0") - for item in settings_subliminal_providers: - c.execute("UPDATE table_settings_providers SET enabled = '1' WHERE name = ?", (item,)) - - settings_addic7ed_username = request.forms.get('settings_addic7ed_username') - settings_addic7ed_password = request.forms.get('settings_addic7ed_password') - c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'addic7ed'", (settings_addic7ed_username, settings_addic7ed_password)) - settings_legendastv_username = request.forms.get('settings_legendastv_username') - settings_legendastv_password = request.forms.get('settings_legendastv_password') - c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'legendastv'", (settings_legendastv_username, settings_legendastv_password)) - settings_opensubtitles_username = request.forms.get('settings_opensubtitles_username') - settings_opensubtitles_password = request.forms.get('settings_opensubtitles_password') - c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'opensubtitles'", (settings_opensubtitles_username, settings_opensubtitles_password)) - - settings_subliminal_languages = request.forms.getall('settings_subliminal_languages') - c.execute("UPDATE table_settings_languages SET enabled = 0") - for item in settings_subliminal_languages: - c.execute("UPDATE table_settings_languages SET enabled = '1' WHERE code2 = ?", (item,)) - - settings_serie_default_enabled = request.forms.get('settings_serie_default_enabled') - if settings_serie_default_enabled is None: - settings_serie_default_enabled = 'False' - else: - settings_serie_default_enabled = 'True' - c.execute("UPDATE table_settings_general SET serie_default_enabled = ?", (settings_serie_default_enabled,)) - - settings_serie_default_languages = str(request.forms.getall('settings_serie_default_languages')) - if settings_serie_default_languages == "['None']": - settings_serie_default_languages = 'None' - c.execute("UPDATE table_settings_general SET serie_default_languages = ?", (settings_serie_default_languages,)) - - settings_serie_default_hi = request.forms.get('settings_serie_default_hi') - if settings_serie_default_hi is None: - settings_serie_default_hi = 'False' - else: - settings_serie_default_hi = 'True' - c.execute("UPDATE table_settings_general SET serie_default_hi = ?", (settings_serie_default_hi,)) - - settings_movie_default_enabled = request.forms.get('settings_movie_default_enabled') - if settings_movie_default_enabled is None: - settings_movie_default_enabled = 'False' - else: - settings_movie_default_enabled = 'True' - c.execute("UPDATE table_settings_general SET movie_default_enabled = ?", (settings_movie_default_enabled,)) - - settings_movie_default_languages = str(request.forms.getall('settings_movie_default_languages')) - if settings_movie_default_languages == "['None']": - settings_movie_default_languages = 'None' - c.execute("UPDATE table_settings_general SET movie_default_languages = ?", (settings_movie_default_languages,)) - - settings_movie_default_hi = request.forms.get('settings_movie_default_hi') - if settings_movie_default_hi is None: - settings_movie_default_hi = 'False' - else: - settings_movie_default_hi = 'True' - c.execute("UPDATE table_settings_general SET movie_default_hi = ?", (settings_movie_default_hi,)) - - settings_notifier_Boxcar_enabled = request.forms.get('settings_notifier_Boxcar_enabled') - if settings_notifier_Boxcar_enabled == 'on': - settings_notifier_Boxcar_enabled = 1 - else: - settings_notifier_Boxcar_enabled = 0 - settings_notifier_Boxcar_url = request.forms.get('settings_notifier_Boxcar_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Boxcar'", (settings_notifier_Boxcar_enabled, settings_notifier_Boxcar_url)) - - settings_notifier_Faast_enabled = request.forms.get('settings_notifier_Faast_enabled') - if settings_notifier_Faast_enabled == 'on': - settings_notifier_Faast_enabled = 1 - else: - settings_notifier_Faast_enabled = 0 - settings_notifier_Faast_url = request.forms.get('settings_notifier_Faast_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Faast'", (settings_notifier_Faast_enabled, settings_notifier_Faast_url)) - - settings_notifier_Growl_enabled = request.forms.get('settings_notifier_Growl_enabled') - if settings_notifier_Growl_enabled == 'on': - settings_notifier_Growl_enabled = 1 - else: - settings_notifier_Growl_enabled = 0 - settings_notifier_Growl_url = request.forms.get('settings_notifier_Growl_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Growl'", (settings_notifier_Growl_enabled, settings_notifier_Growl_url)) - - settings_notifier_Join_enabled = request.forms.get('settings_notifier_Join_enabled') - if settings_notifier_Join_enabled == 'on': - settings_notifier_Join_enabled = 1 - else: - settings_notifier_Join_enabled = 0 - settings_notifier_Join_url = request.forms.get('settings_notifier_Join_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Join'", (settings_notifier_Join_enabled, settings_notifier_Join_url)) - - settings_notifier_KODI_enabled = request.forms.get('settings_notifier_KODI_enabled') - if settings_notifier_KODI_enabled == 'on': - settings_notifier_KODI_enabled = 1 - else: - settings_notifier_KODI_enabled = 0 - settings_notifier_KODI_url = request.forms.get('settings_notifier_KODI_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'KODI'", (settings_notifier_KODI_enabled, settings_notifier_KODI_url)) - - settings_notifier_Mattermost_enabled = request.forms.get('settings_notifier_Mattermost_enabled') - if settings_notifier_Mattermost_enabled == 'on': - settings_notifier_Mattermost_enabled = 1 - else: - settings_notifier_Mattermost_enabled = 0 - settings_notifier_Mattermost_url = request.forms.get('settings_notifier_Mattermost_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Mattermost'", (settings_notifier_Mattermost_enabled, settings_notifier_Mattermost_url)) - - settings_notifier_NMA_enabled = request.forms.get('settings_notifier_Notify My Android_enabled') - if settings_notifier_NMA_enabled == 'on': - settings_notifier_NMA_enabled = 1 - else: - settings_notifier_NMA_enabled = 0 - settings_notifier_NMA_url = request.forms.get('settings_notifier_Notify My Android_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Notify My Android'", (settings_notifier_NMA_enabled, settings_notifier_NMA_url)) - - settings_notifier_Prowl_enabled = request.forms.get('settings_notifier_Prowl_enabled') - if settings_notifier_Prowl_enabled == 'on': - settings_notifier_Prowl_enabled = 1 - else: - settings_notifier_Prowl_enabled = 0 - settings_notifier_Prowl_url = request.forms.get('settings_notifier_Prowl_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Prowl'", (settings_notifier_Prowl_enabled, settings_notifier_Prowl_url)) - - settings_notifier_Pushalot_enabled = request.forms.get('settings_notifier_Pushalot_enabled') - if settings_notifier_Pushalot_enabled == 'on': - settings_notifier_Pushalot_enabled = 1 - else: - settings_notifier_Pushalot_enabled = 0 - settings_notifier_Pushalot_url = request.forms.get('settings_notifier_Pushalot_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushalot'", (settings_notifier_Pushalot_enabled, settings_notifier_Pushalot_url)) - - settings_notifier_PushBullet_enabled = request.forms.get('settings_notifier_PushBullet_enabled') - if settings_notifier_PushBullet_enabled == 'on': - settings_notifier_PushBullet_enabled = 1 - else: - settings_notifier_PushBullet_enabled = 0 - settings_notifier_PushBullet_url = request.forms.get('settings_notifier_PushBullet_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'PushBullet'", (settings_notifier_PushBullet_enabled, settings_notifier_PushBullet_url)) - - settings_notifier_Pushjet_enabled = request.forms.get('settings_notifier_Pushjet_enabled') - if settings_notifier_Pushjet_enabled == 'on': - settings_notifier_Pushjet_enabled = 1 - else: - settings_notifier_Pushjet_enabled = 0 - settings_notifier_Pushjet_url = request.forms.get('settings_notifier_Pushjet_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushjet'", (settings_notifier_Pushjet_enabled, settings_notifier_Pushjet_url)) - - settings_notifier_Pushover_enabled = request.forms.get('settings_notifier_Pushover_enabled') - if settings_notifier_Pushover_enabled == 'on': - settings_notifier_Pushover_enabled = 1 - else: - settings_notifier_Pushover_enabled = 0 - settings_notifier_Pushover_url = request.forms.get('settings_notifier_Pushover_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushover'", (settings_notifier_Pushover_enabled, settings_notifier_Pushover_url)) - - settings_notifier_RocketChat_enabled = request.forms.get('settings_notifier_Rocket.Chat_enabled') - if settings_notifier_RocketChat_enabled == 'on': - settings_notifier_RocketChat_enabled = 1 - else: - settings_notifier_RocketChat_enabled = 0 - settings_notifier_RocketChat_url = request.forms.get('settings_notifier_Rocket.Chat_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Rocket.Chat'", (settings_notifier_RocketChat_enabled, settings_notifier_RocketChat_url)) - - settings_notifier_Slack_enabled = request.forms.get('settings_notifier_Slack_enabled') - if settings_notifier_Slack_enabled == 'on': - settings_notifier_Slack_enabled = 1 - else: - settings_notifier_Slack_enabled = 0 - settings_notifier_Slack_url = request.forms.get('settings_notifier_Slack_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Slack'", (settings_notifier_Slack_enabled, settings_notifier_Slack_url)) - - settings_notifier_SuperToasty_enabled = request.forms.get('settings_notifier_Super Toasty_enabled') - if settings_notifier_SuperToasty_enabled == 'on': - settings_notifier_SuperToasty_enabled = 1 - else: - settings_notifier_SuperToasty_enabled = 0 - settings_notifier_SuperToasty_url = request.forms.get('settings_notifier_Super Toasty_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Super Toasty'", (settings_notifier_SuperToasty_enabled, settings_notifier_SuperToasty_url)) - - settings_notifier_Telegram_enabled = request.forms.get('settings_notifier_Telegram_enabled') - if settings_notifier_Telegram_enabled == 'on': - settings_notifier_Telegram_enabled = 1 - else: - settings_notifier_Telegram_enabled = 0 - settings_notifier_Telegram_url = request.forms.get('settings_notifier_Telegram_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Telegram'", (settings_notifier_Telegram_enabled, settings_notifier_Telegram_url)) - - settings_notifier_Twitter_enabled = request.forms.get('settings_notifier_Twitter_enabled') - if settings_notifier_Twitter_enabled == 'on': - settings_notifier_Twitter_enabled = 1 - else: - settings_notifier_Twitter_enabled = 0 - settings_notifier_Twitter_url = request.forms.get('settings_notifier_Twitter_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Twitter'", (settings_notifier_Twitter_enabled, settings_notifier_Twitter_url)) - - settings_notifier_XBMC_enabled = request.forms.get('settings_notifier_XBMC_enabled') - if settings_notifier_XBMC_enabled == 'on': - settings_notifier_XBMC_enabled = 1 - else: - settings_notifier_XBMC_enabled = 0 - settings_notifier_XBMC_url = request.forms.get('settings_notifier_XBMC_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'XBMC'", (settings_notifier_XBMC_enabled, settings_notifier_XBMC_url)) - - settings_notifier_Discord_enabled = request.forms.get('settings_notifier_Discord_enabled') - if settings_notifier_Discord_enabled == 'on': - settings_notifier_Discord_enabled = 1 - else: - settings_notifier_Discord_enabled = 0 - settings_notifier_Discord_url = request.forms.get('settings_notifier_Discord_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Discord'", (settings_notifier_Discord_enabled, settings_notifier_Discord_url)) - - settings_notifier_E_Mail_enabled = request.forms.get('settings_notifier_E-Mail_enabled') - if settings_notifier_E_Mail_enabled == 'on': - settings_notifier_E_Mail_enabled = 1 - else: - settings_notifier_E_Mail_enabled = 0 - settings_notifier_E_Mail_url = request.forms.get('settings_notifier_E-Mail_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'E-Mail'", (settings_notifier_E_Mail_enabled, settings_notifier_E_Mail_url)) - - settings_notifier_Emby_enabled = request.forms.get('settings_notifier_Emby_enabled') - if settings_notifier_Emby_enabled == 'on': - settings_notifier_Emby_enabled = 1 - else: - settings_notifier_Emby_enabled = 0 - settings_notifier_Emby_url = request.forms.get('settings_notifier_Emby_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Emby'", (settings_notifier_Emby_enabled, settings_notifier_Emby_url)) - - settings_notifier_IFTTT_enabled = request.forms.get('settings_notifier_IFTTT_enabled') - if settings_notifier_IFTTT_enabled == 'on': - settings_notifier_IFTTT_enabled = 1 - else: - settings_notifier_IFTTT_enabled = 0 - settings_notifier_IFTTT_url = request.forms.get('settings_notifier_IFTTT_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'IFTTT'", (settings_notifier_IFTTT_enabled, settings_notifier_IFTTT_url)) - - settings_notifier_Stride_enabled = request.forms.get('settings_notifier_Stride_enabled') - if settings_notifier_Stride_enabled == 'on': - settings_notifier_Stride_enabled = 1 - else: - settings_notifier_Stride_enabled = 0 - settings_notifier_Stride_url = request.forms.get('settings_notifier_Stride_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Stride'", (settings_notifier_Stride_enabled, settings_notifier_Stride_url)) - - settings_notifier_Windows_enabled = request.forms.get('settings_notifier_Windows_enabled') - if settings_notifier_Windows_enabled == 'on': - settings_notifier_Windows_enabled = 1 - else: - settings_notifier_Windows_enabled = 0 - settings_notifier_Windows_url = request.forms.get('settings_notifier_Windows_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Windows'", (settings_notifier_Windows_enabled, settings_notifier_Windows_url)) - - conn.commit() - c.close() - - sonarr_full_update() - radarr_full_update() - - logging.info('Settings saved succesfully.') - - # reschedule full update task according to settings - sonarr_full_update() - - redirect(ref) - -@route(base_url + 'check_update') -@custom_auth_basic(check_credentials) -def check_update(): - ref = request.environ['HTTP_REFERER'] - - check_and_apply_update() - - redirect(ref) - -@route(base_url + 'system') -@custom_auth_basic(check_credentials) -def system(): - def get_time_from_interval(interval): - interval_clean = interval.split('[') - interval_clean = interval_clean[1][:-1] - interval_split = interval_clean.split(':') - - hour = interval_split[0] - minute = interval_split[1].lstrip("0") - second = interval_split[2].lstrip("0") - - text = "every " - if hour != "0": - text = text + hour - if hour == "1": - text = text + " hour" - else: - text = text + " hours" - - if minute != "" and second != "": - text = text + ", " - elif minute == "" and second != "": - text = text + " and " - elif minute != "" and second == "": - text = text + " and " - if minute != "": - text = text + minute - if minute == "1": - text = text + " minute" - else: - text = text + " minutes" - - if second != "": - text = text + " and " - if second != "": - text = text + second - if second == "1": - text = text + " second" - else: - text = text + " seconds" - - return text - - def get_time_from_cron(cron): - text = "at " - hour = str(cron[5]) - minute = str(cron[6]) - second = str(cron[7]) - - if hour != "0" and hour != "*": - text = text + hour - if hour == "0" or hour == "1": - text = text + " hour" - else: - text = text + " hours" - - if minute != "*" and second != "0": - text = text + ", " - elif minute == "*" and second != "0": - text = text + " and " - elif minute != "0" and minute != "*" and second == "0": - text = text + " and " - if minute != "0" and minute != "*": - text = text + minute - if minute == "0" or minute == "1": - text = text + " minute" - else: - text = text + " minutes" - - if second != "0" and second != "*": - text = text + " and " - if second != "0" and second != "*": - text = text + second - if second == "0" or second == "1": - text = text + " second" - else: - text = text + " seconds" - - return text - - - task_list = [] - for job in scheduler.get_jobs(): - if job.next_run_time is not None: - next_run = pretty.date(job.next_run_time.replace(tzinfo=None)) - else: - next_run = "Never" - - if job.trigger.__str__().startswith('interval'): - task_list.append([job.name, get_time_from_interval(str(job.trigger)), next_run, job.id]) - elif job.trigger.__str__().startswith('cron'): - task_list.append([job.name, get_time_from_cron(job.trigger.fields), next_run, job.id]) - - i = 0 - with open(os.path.join(config_dir, 'log/bazarr.log')) as f: - for i, l in enumerate(f, 1): - pass - row_count = i - page_size = int(get_general_settings()[21]) - max_page = int(math.ceil(row_count / (page_size + 0.0))) - - return template('system', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url, task_list=task_list, row_count=row_count, max_page=max_page, page_size=page_size) - -@route(base_url + 'logs/') -@custom_auth_basic(check_credentials) -def get_logs(page): - page_size = int(get_general_settings()[21]) - begin = (page * page_size) - page_size - end = (page * page_size) - 1 - logs_complete = [] - for line in reversed(open(os.path.join(config_dir, 'log/bazarr.log')).readlines()): - logs_complete.append(line.rstrip()) - logs = logs_complete[begin:end] - - return template('logs', logs=logs, base_url=base_url) - -@route(base_url + 'execute/') -@custom_auth_basic(check_credentials) -def execute_task(taskid): - ref = request.environ['HTTP_REFERER'] - - execute_now(taskid) - - redirect(ref) - - -@route(base_url + 'remove_subtitles', method='POST') -@custom_auth_basic(check_credentials) -def remove_subtitles(): - episodePath = request.forms.get('episodePath') - language = request.forms.get('language') - subtitlesPath = request.forms.get('subtitlesPath') - sonarrSeriesId = request.forms.get('sonarrSeriesId') - sonarrEpisodeId = request.forms.get('sonarrEpisodeId') - - try: - os.remove(subtitlesPath) - result = language_from_alpha3(language) + " subtitles deleted from disk." - history_log(0, sonarrSeriesId, sonarrEpisodeId, result) - except OSError: - pass - store_subtitles(unicode(episodePath)) - list_missing_subtitles(sonarrSeriesId) - - -@route(base_url + 'remove_subtitles_movie', method='POST') -@custom_auth_basic(check_credentials) -def remove_subtitles_movie(): - moviePath = request.forms.get('moviePath') - language = request.forms.get('language') - subtitlesPath = request.forms.get('subtitlesPath') - radarrId = request.forms.get('radarrId') - - try: - os.remove(subtitlesPath) - result = language_from_alpha3(language) + " subtitles deleted from disk." - history_log_movie(0, radarrId, result) - except OSError: - pass - store_subtitles_movie(unicode(moviePath)) - list_missing_subtitles_movies(radarrId) - - -@route(base_url + 'get_subtitle', method='POST') -@custom_auth_basic(check_credentials) -def get_subtitle(): - ref = request.environ['HTTP_REFERER'] - - episodePath = request.forms.get('episodePath') - sceneName = request.forms.get('sceneName') - language = request.forms.get('language') - hi = request.forms.get('hi') - sonarrSeriesId = request.forms.get('sonarrSeriesId') - sonarrEpisodeId = request.forms.get('sonarrEpisodeId') - # tvdbid = request.forms.get('tvdbid') - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1") - enabled_providers = c.fetchall() - c.close() - - providers_list = [] - providers_auth = {} - if len(enabled_providers) > 0: - for provider in enabled_providers: - providers_list.append(provider[0]) - try: - if provider[2] is not '' and provider[3] is not '': - provider_auth = providers_auth.append(provider[0]) - provider_auth.update({'username':providers[2], 'password':providers[3]}) - else: - providers_auth = None - except: - providers_auth = None - else: - providers_list = None - providers_auth = None - - try: - result = download_subtitle(episodePath, language, hi, providers_list, providers_auth, sceneName, 'series') - if result is not None: - history_log(1, sonarrSeriesId, sonarrEpisodeId, result) - send_notifications(sonarrSeriesId, sonarrEpisodeId, result) - store_subtitles(unicode(episodePath)) - list_missing_subtitles(sonarrSeriesId) - redirect(ref) - except OSError: - pass - -@route(base_url + 'get_subtitle_movie', method='POST') -@custom_auth_basic(check_credentials) -def get_subtitle_movie(): - ref = request.environ['HTTP_REFERER'] - - moviePath = request.forms.get('moviePath') - sceneName = request.forms.get('sceneName') - language = request.forms.get('language') - hi = request.forms.get('hi') - radarrId = request.forms.get('radarrId') - # tmdbid = request.forms.get('tmdbid') - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1") - enabled_providers = c.fetchall() - c.close() - - providers_list = [] - providers_auth = {} - if len(enabled_providers) > 0: - for provider in enabled_providers: - providers_list.append(provider[0]) - try: - if provider[2] is not '' and provider[3] is not '': - provider_auth = providers_auth.append(provider[0]) - provider_auth.update({'username':providers[2], 'password':providers[3]}) - else: - providers_auth = None - except: - providers_auth = None - else: - providers_list = None - providers_auth = None - - try: - result = download_subtitle(moviePath, language, hi, providers_list, providers_auth, sceneName, 'movies') - if result is not None: - history_log_movie(1, radarrId, result) - send_notifications_movie(radarrId, result) - store_subtitles_movie(unicode(moviePath)) - list_missing_subtitles_movies(radarrId) - redirect(ref) - except OSError: - pass - -def configured(): - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = conn.cursor() - c.execute("UPDATE table_settings_general SET configured = 1") - conn.commit() - c.close() - -@route(base_url + 'api/wanted') -def api_wanted(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - data = c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_episodes.missing_subtitles FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]' ORDER BY table_episodes._rowid_ DESC").fetchall() - c.close() - return dict(subtitles=data) - -@route(base_url + 'api/history') -def api_history(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - data = c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, strftime('%Y-%m-%d', datetime(table_history.timestamp, 'unixepoch')), table_history.description FROM table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE table_history.action = '1' ORDER BY id DESC").fetchall() - c.close() - return dict(subtitles=data) - -logging.info('Bazarr is started and waiting for request on http://' + str(ip) + ':' + str(port) + str(base_url)) -run(host=ip, port=port, server='waitress') -logging.info('Bazarr has been stopped.') +bazarr_version = '0.6.0' + +import gc +gc.enable() + +from get_argv import config_dir + +import os +import sys +reload(sys) +sys.setdefaultencoding('utf8') +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'libs/')) + +import sqlite3 +from update_modules import * +from init import * +from update_db import * + + +from get_settings import get_general_settings +import logging +from logging.handlers import TimedRotatingFileHandler + +logger = logging.getLogger('waitress') +log_level = get_general_settings()[4] +if log_level is None: + log_level = "INFO" + +class OneLineExceptionFormatter(logging.Formatter): + def formatException(self, exc_info): + """ + Format an exception so that it prints on a single line. + """ + result = super(OneLineExceptionFormatter, self).formatException(exc_info) + return repr(result) # or format into one line however you want to + + def format(self, record): + s = super(OneLineExceptionFormatter, self).format(record) + if record.exc_text: + s = s.replace('\n', '') + '|' + return s + +def configure_logging(): + global fh + fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, backupCount=7) + f = OneLineExceptionFormatter('%(asctime)s|%(levelname)s|%(message)s|', + '%d/%m/%Y %H:%M:%S') + fh.setFormatter(f) + logging.getLogger("enzyme").setLevel(logging.CRITICAL) + logging.getLogger("apscheduler").setLevel(logging.WARNING) + logging.getLogger("subliminal").setLevel(logging.CRITICAL) + logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) + root = logging.getLogger() + root.setLevel(log_level) + root.addHandler(fh) + +configure_logging() + +from bottle import route, run, template, static_file, request, redirect, response, HTTPError +import bottle +bottle.TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(__file__), 'views/')) +bottle.debug(True) +bottle.TEMPLATES.clear() + +from json import dumps +import itertools +import operator +import requests +import pretty +from datetime import datetime, timedelta +from PIL import Image +from io import BytesIO +from fdsend import send_file +import urllib +import math +import ast +import hashlib + +from get_languages import load_language_in_db, language_from_alpha3 +from get_providers import * + +from get_series import * +from get_episodes import * +from get_settings import base_url, ip, port, path_replace, path_replace_movie +from check_update import check_and_apply_update +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, wanted_download_subtitles, wanted_search_missing_subtitles +from utils import history_log, history_log_movie +from scheduler import * +from notifier import send_notifications, send_notifications_movie + +# Reset restart required warning on start +conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) +c = conn.cursor() +c.execute("UPDATE system SET configured = 0, updated = 0") +conn.commit() +c.close() + +# Load languages in database +load_language_in_db() + +from get_settings import get_auth_settings + +def custom_auth_basic(check): + def decorator(func): + def wrapper(*a, **ka): + if get_auth_settings()[0] is True: + user, password = request.auth or (None, None) + if user is None or not check(user, password): + err = HTTPError(401, "Access denied") + err.add_header('WWW-Authenticate', 'Basic realm="Bazarr"') + return err + return func(*a, **ka) + else: + return func(*a, **ka) + + return wrapper + return decorator + +def check_credentials(user, pw): + from get_settings import get_auth_settings + + username = get_auth_settings()[1] + password = get_auth_settings()[2] + if hashlib.md5(pw).hexdigest() == password and user == username: + return True + return False + +@route('/') +@custom_auth_basic(check_credentials) +def redirect_root(): + redirect (base_url) + +@route(base_url + 'static/:path#.+#', name='static') +@custom_auth_basic(check_credentials) +def static(path): + return static_file(path, root=os.path.join(os.path.dirname(__file__), 'static')) + +@route(base_url + 'emptylog') +@custom_auth_basic(check_credentials) +def emptylog(): + ref = request.environ['HTTP_REFERER'] + + fh.doRollover() + logging.info('Log file emptied') + + redirect(ref) + +@route(base_url + 'bazarr.log') +@custom_auth_basic(check_credentials) +def download_log(): + return static_file('bazarr.log', root=os.path.join(config_dir, 'log/'), download='bazarr.log') + +@route(base_url + 'image_proxy/', method='GET') +@custom_auth_basic(check_credentials) +def image_proxy(url): + url_sonarr = get_sonarr_settings()[6] + url_sonarr_short = get_sonarr_settings()[7] + apikey = get_sonarr_settings()[4] + url_image = url_sonarr_short + '/' + url + '?apikey=' + apikey + try: + img_pil = Image.open(BytesIO(requests.get(url_sonarr_short + '/api' + url_image.split(url_sonarr)[1], timeout=15).content)) + except: + return None + else: + img_buffer = BytesIO() + img_pil.tobytes() + img_pil.save(img_buffer, img_pil.format) + img_buffer.seek(0) + return send_file(img_buffer, ctype=img_pil.format) + +@route(base_url + 'image_proxy_movies/', method='GET') +@custom_auth_basic(check_credentials) +def image_proxy_movies(url): + url_radarr = get_radarr_settings()[6] + url_radarr_short = get_radarr_settings()[7] + apikey = get_radarr_settings()[4] + try: + url_image = (url_radarr_short + '/' + url + '?apikey=' + apikey).replace('/fanart.jpg', '/banner.jpg') + img_pil = Image.open(BytesIO(requests.get(url_radarr_short + '/api' + url_image.split(url_radarr)[1], timeout=15).content)) + except: + url_image = url_radarr_short + '/' + url + '?apikey=' + apikey + img_pil = Image.open(BytesIO(requests.get(url_radarr_short + '/api' + url_image.split(url_radarr)[1], timeout=15).content)) + + img_buffer = BytesIO() + img_pil.tobytes() + img_pil.save(img_buffer, img_pil.format) + img_buffer.seek(0) + return send_file(img_buffer, ctype=img_pil.format) + + +@route(base_url) +@custom_auth_basic(check_credentials) +def redirect_root(): + + if get_general_settings()[12] is True: + redirect(base_url + 'series') + elif get_general_settings()[13] is True: + redirect(base_url + 'movies') + else: + redirect(base_url + 'settings') + + +@route(base_url + 'series') +@custom_auth_basic(check_credentials) +def series(): + single_language = get_general_settings()[7] + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_shows") + missing_count = c.fetchone() + missing_count = missing_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(missing_count / (page_size + 0.0))) + + c.execute("SELECT tvdbId, title, path_substitution(path), languages, hearing_impaired, sonarrSeriesId, poster, audio_language FROM table_shows ORDER BY sortTitle ASC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") + languages = c.fetchall() + c.execute("SELECT table_shows.sonarrSeriesId, COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN table_episodes ON table_shows.sonarrSeriesId=table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' AND table_episodes.missing_subtitles IS NOT '[]' GROUP BY table_shows.sonarrSeriesId") + missing_subtitles_list = c.fetchall() + c.execute("SELECT table_shows.sonarrSeriesId, COUNT(table_episodes.missing_subtitles) FROM table_shows LEFT JOIN table_episodes ON table_shows.sonarrSeriesId=table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None' GROUP BY table_shows.sonarrSeriesId") + total_subtitles_list = c.fetchall() + c.close() + output = template('series', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list, total_subtitles_list=total_subtitles_list, languages=languages, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, single_language=single_language, page_size=page_size) + return output + +@route(base_url + 'serieseditor') +@custom_auth_basic(check_credentials) +def serieseditor(): + single_language = get_general_settings()[7] + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_shows") + missing_count = c.fetchone() + missing_count = missing_count[0] + + c.execute("SELECT tvdbId, title, path_substitution(path), languages, hearing_impaired, sonarrSeriesId, poster, audio_language FROM table_shows ORDER BY title ASC") + data = c.fetchall() + c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") + languages = c.fetchall() + c.close() + output = template('serieseditor', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, base_url=base_url, single_language=single_language) + return output + +@route(base_url + 'search_json/', method='GET') +@custom_auth_basic(check_credentials) +def search_json(query): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + + c.execute("SELECT title, sonarrSeriesId FROM table_shows WHERE title LIKE ? ORDER BY title", ('%'+query+'%',)) + series = c.fetchall() + + c.execute("SELECT title, radarrId FROM table_movies WHERE title LIKE ? ORDER BY title", ('%' + query + '%',)) + movies = c.fetchall() + + search_list = [] + for serie in series: + search_list.append(dict([('name', serie[0]), ('url', base_url + 'episodes/' + str(serie[1]))])) + + for movie in movies: + search_list.append(dict([('name', movie[0]), ('url', base_url + 'movie/' + str(movie[1]))])) + + response.content_type = 'application/json' + return dict(items=search_list) + + +@route(base_url + 'edit_series/', method='POST') +@custom_auth_basic(check_credentials) +def edit_series(no): + ref = request.environ['HTTP_REFERER'] + + lang = request.forms.getall('languages') + if len(lang) > 0: + pass + else: + lang = 'None' + + single_language = get_general_settings()[7] + if single_language is True: + if str(lang) == "['None']": + lang = 'None' + else: + lang = str(lang) + else: + if str(lang) == "['']": + lang = '[]' + + hi = request.forms.get('hearing_impaired') + + if hi == "on": + hi = "True" + else: + hi = "False" + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + c.execute("UPDATE table_shows SET languages = ?, hearing_impaired = ? WHERE sonarrSeriesId LIKE ?", (str(lang), hi, no)) + conn.commit() + c.close() + + list_missing_subtitles(no) + + redirect(ref) + +@route(base_url + 'edit_serieseditor', method='POST') +@custom_auth_basic(check_credentials) +def edit_serieseditor(): + ref = request.environ['HTTP_REFERER'] + + series = request.forms.get('series') + series = ast.literal_eval(str('[' + series + ']')) + lang = request.forms.getall('languages') + hi = request.forms.get('hearing_impaired') + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + + for serie in series: + if str(lang) != "[]" and str(lang) != "['']": + if str(lang) == "['None']": + lang = 'None' + else: + lang = str(lang) + c.execute("UPDATE table_shows SET languages = ? WHERE sonarrSeriesId LIKE ?", (lang, serie)) + if hi != '': + c.execute("UPDATE table_shows SET hearing_impaired = ? WHERE sonarrSeriesId LIKE ?", (hi, serie)) + + conn.commit() + c.close() + + for serie in series: + list_missing_subtitles(serie) + + redirect(ref) + +@route(base_url + 'episodes/', method='GET') +@custom_auth_basic(check_credentials) +def episodes(no): + # single_language = get_general_settings()[7] + url_sonarr_short = get_sonarr_settings()[7] + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn.create_function("path_substitution", 1, path_replace) + c = conn.cursor() + + series_details = [] + series_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbid, audio_language, languages, path_substitution(path) FROM table_shows WHERE sonarrSeriesId LIKE ?", (str(no),)).fetchone() + tvdbid = series_details[5] + + episodes = c.execute("SELECT title, path_substitution(path), season, episode, subtitles, sonarrSeriesId, missing_subtitles, sonarrEpisodeId, scene_name, monitored FROM table_episodes WHERE sonarrSeriesId LIKE ? ORDER BY episode ASC", (str(no),)).fetchall() + number = len(episodes) + languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall() + c.close() + episodes = reversed(sorted(episodes, key=operator.itemgetter(2))) + seasons_list = [] + for key, season in itertools.groupby(episodes,operator.itemgetter(2)): + seasons_list.append(list(season)) + + return template('episodes', __file__=__file__, bazarr_version=bazarr_version, no=no, details=series_details, languages=languages, seasons=seasons_list, url_sonarr_short=url_sonarr_short, base_url=base_url, tvdbid=tvdbid, number=number) + +@route(base_url + 'movies') +@custom_auth_basic(check_credentials) +def movies(): + single_language = get_general_settings()[7] + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace_movie) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_movies") + missing_count = c.fetchone() + missing_count = missing_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(missing_count / (page_size + 0.0))) + + c.execute("SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language, monitored FROM table_movies ORDER BY title ASC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") + languages = c.fetchall() + c.close() + output = template('movies', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, single_language=single_language, page_size=page_size) + return output + +@route(base_url + 'movieseditor') +@custom_auth_basic(check_credentials) +def movieseditor(): + single_language = get_general_settings()[7] + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace_movie) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_movies") + missing_count = c.fetchone() + missing_count = missing_count[0] + + c.execute("SELECT tmdbId, title, path_substitution(path), languages, hearing_impaired, radarrId, poster, audio_language FROM table_movies ORDER BY title ASC") + data = c.fetchall() + c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") + languages = c.fetchall() + c.close() + output = template('movieseditor', __file__=__file__, bazarr_version=bazarr_version, rows=data, languages=languages, missing_count=missing_count, base_url=base_url, single_language=single_language) + return output + +@route(base_url + 'edit_movieseditor', method='POST') +@custom_auth_basic(check_credentials) +def edit_movieseditor(): + ref = request.environ['HTTP_REFERER'] + + movies = request.forms.get('movies') + movies = ast.literal_eval(str('[' + movies + ']')) + lang = request.forms.getall('languages') + hi = request.forms.get('hearing_impaired') + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + + for movie in movies: + if str(lang) != "[]" and str(lang) != "['']": + if str(lang) == "['None']": + lang = 'None' + else: + lang = str(lang) + c.execute("UPDATE table_movies SET languages = ? WHERE radarrId LIKE ?", (lang, movie)) + if hi != '': + c.execute("UPDATE table_movies SET hearing_impaired = ? WHERE radarrId LIKE ?", (hi, movie)) + + conn.commit() + c.close() + + for movie in movies: + list_missing_subtitles_movies(movie) + + redirect(ref) + +@route(base_url + 'edit_movie/', method='POST') +@custom_auth_basic(check_credentials) +def edit_movie(no): + ref = request.environ['HTTP_REFERER'] + + lang = request.forms.getall('languages') + if len(lang) > 0: + pass + else: + lang = 'None' + + if str(lang) == "['']": + lang = '[]' + + hi = request.forms.get('hearing_impaired') + + if hi == "on": + hi = "True" + else: + hi = "False" + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + c.execute("UPDATE table_movies SET languages = ?, hearing_impaired = ? WHERE radarrId LIKE ?", (str(lang), hi, no)) + conn.commit() + c.close() + + list_missing_subtitles_movies(no) + + redirect(ref) + +@route(base_url + 'movie/', method='GET') +@custom_auth_basic(check_credentials) +def movie(no): + # single_language = get_general_settings()[7] + url_radarr_short = get_radarr_settings()[7] + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn.create_function("path_substitution", 1, path_replace_movie) + c = conn.cursor() + + movies_details = [] + movies_details = c.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbid, audio_language, languages, path_substitution(path), subtitles, radarrId, missing_subtitles, sceneName, monitored FROM table_movies WHERE radarrId LIKE ?", (str(no),)).fetchone() + tmdbid = movies_details[5] + + languages = c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1").fetchall() + c.close() + + return template('movie', __file__=__file__, bazarr_version=bazarr_version, no=no, details=movies_details, languages=languages, url_radarr_short=url_radarr_short, base_url=base_url, tmdbid=tmdbid) + +@route(base_url + 'scan_disk/', method='GET') +@custom_auth_basic(check_credentials) +def scan_disk(no): + ref = request.environ['HTTP_REFERER'] + + series_scan_subtitles(no) + + redirect(ref) + +@route(base_url + 'scan_disk_movie/', method='GET') +@custom_auth_basic(check_credentials) +def scan_disk_movie(no): + ref = request.environ['HTTP_REFERER'] + + movies_scan_subtitles(no) + + redirect(ref) + +@route(base_url + 'search_missing_subtitles/', method='GET') +@custom_auth_basic(check_credentials) +def search_missing_subtitles(no): + ref = request.environ['HTTP_REFERER'] + + series_download_subtitles(no) + + redirect(ref) + +@route(base_url + 'search_missing_subtitles_movie/', method='GET') +@custom_auth_basic(check_credentials) +def search_missing_subtitles_movie(no): + ref = request.environ['HTTP_REFERER'] + + movies_download_subtitles(no) + + redirect(ref) + +@route(base_url + 'history') +@custom_auth_basic(check_credentials) +def history(): + return template('history', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url) + +@route(base_url + 'historyseries') +@custom_auth_basic(check_credentials) +def historyseries(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_history") + row_count = c.fetchone() + row_count = row_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(row_count / (page_size + 0.0))) + + now = datetime.now() + today = [] + thisweek = [] + thisyear = [] + stats = c.execute("SELECT timestamp FROM table_history WHERE action LIKE '1'").fetchall() + total = len(stats) + for stat in stats: + if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: + today.append(datetime.fromtimestamp(stat[0]).date()) + if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: + thisweek.append(datetime.fromtimestamp(stat[0]).date()) + if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: + thisyear.append(datetime.fromtimestamp(stat[0]).date()) + stats = [len(today), len(thisweek), len(thisyear), total] + + c.execute("SELECT table_history.action, table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_history.timestamp, table_history.description, table_history.sonarrSeriesId FROM table_history LEFT JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId LEFT JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId ORDER BY id DESC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.close() + data = reversed(sorted(data, key=operator.itemgetter(4))) + return template('historyseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size) + +@route(base_url + 'historymovies') +@custom_auth_basic(check_credentials) +def historymovies(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + + c.execute("SELECT COUNT(*) FROM table_history_movie") + row_count = c.fetchone() + row_count = row_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(row_count / (page_size + 0.0))) + + now = datetime.now() + today = [] + thisweek = [] + thisyear = [] + stats = c.execute("SELECT timestamp FROM table_history_movie WHERE action LIKE '1'").fetchall() + total = len(stats) + for stat in stats: + if now - timedelta(hours=24) <= datetime.fromtimestamp(stat[0]) <= now: + today.append(datetime.fromtimestamp(stat[0]).date()) + if now - timedelta(weeks=1) <= datetime.fromtimestamp(stat[0]) <= now: + thisweek.append(datetime.fromtimestamp(stat[0]).date()) + if now - timedelta(weeks=52) <= datetime.fromtimestamp(stat[0]) <= now: + thisyear.append(datetime.fromtimestamp(stat[0]).date()) + stats = [len(today), len(thisweek), len(thisyear), total] + + c.execute("SELECT table_history_movie.action, table_movies.title, table_history_movie.timestamp, table_history_movie.description, table_history_movie.radarrId FROM table_history_movie LEFT JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId ORDER BY id DESC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.close() + data = reversed(sorted(data, key=operator.itemgetter(2))) + return template('historymovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, row_count=row_count, page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size) + +@route(base_url + 'wanted') +@custom_auth_basic(check_credentials) +def wanted(): + return template('wanted', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url) + +@route(base_url + 'wantedseries') +@custom_auth_basic(check_credentials) +def wantedseries(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace) + c = db.cursor() + + if get_general_settings()[24] is True: + monitored_only_query_string = ' AND monitored = "True"' + else: + monitored_only_query_string = "" + + c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string) + missing_count = c.fetchone() + missing_count = missing_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(missing_count / (page_size + 0.0))) + + c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_episodes.missing_subtitles, table_episodes.sonarrSeriesId, path_substitution(table_episodes.path), table_shows.hearing_impaired, table_episodes.sonarrEpisodeId, table_episodes.scene_name FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string + " ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.close() + return template('wantedseries', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size) + +@route(base_url + 'wantedmovies') +@custom_auth_basic(check_credentials) +def wantedmovies(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db.create_function("path_substitution", 1, path_replace_movie) + c = db.cursor() + + if get_general_settings()[24] is True: + monitored_only_query_string = ' AND monitored = "True"' + else: + monitored_only_query_string = "" + + c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string) + missing_count = c.fetchone() + missing_count = missing_count[0] + page = request.GET.page + if page == "": + page = "1" + page_size = int(get_general_settings()[21]) + offset = (int(page) - 1) * page_size + max_page = int(math.ceil(missing_count / (page_size + 0.0))) + + c.execute("SELECT title, missing_subtitles, radarrId, path_substitution(path), hearing_impaired, sceneName FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string + " ORDER BY _rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset,)) + data = c.fetchall() + c.close() + return template('wantedmovies', __file__=__file__, bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size) + +@route(base_url + 'wanted_search_missing_subtitles') +@custom_auth_basic(check_credentials) +def wanted_search_missing_subtitles_list(): + ref = request.environ['HTTP_REFERER'] + + wanted_search_missing_subtitles() + + redirect(ref) + +@route(base_url + 'settings') +@custom_auth_basic(check_credentials) +def settings(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + c.execute("SELECT * FROM table_settings_languages ORDER BY name") + settings_languages = c.fetchall() + c.execute("SELECT * FROM table_settings_providers ORDER BY name") + settings_providers = c.fetchall() + c.execute("SELECT * FROM table_settings_notifier ORDER BY name") + settings_notifier = c.fetchall() + c.close() + from get_settings import get_general_settings, get_auth_settings, get_radarr_settings, get_sonarr_settings + settings_general = get_general_settings() + settings_auth = get_auth_settings() + settings_sonarr = get_sonarr_settings() + settings_radarr = get_radarr_settings() + + return template('settings', __file__=__file__, bazarr_version=bazarr_version, settings_general=settings_general, settings_auth=settings_auth, settings_languages=settings_languages, settings_providers=settings_providers, settings_sonarr=settings_sonarr, settings_radarr=settings_radarr, settings_notifier=settings_notifier, base_url=base_url) + +@route(base_url + 'save_settings', method='POST') +@custom_auth_basic(check_credentials) +def save_settings(): + ref = request.environ['HTTP_REFERER'] + + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + + settings_general_ip = request.forms.get('settings_general_ip') + settings_general_port = request.forms.get('settings_general_port') + settings_general_baseurl = request.forms.get('settings_general_baseurl') + settings_general_loglevel = request.forms.get('settings_general_loglevel') + settings_general_auth_enabled = request.forms.get('settings_general_auth_enabled') + if settings_general_auth_enabled is None: + settings_general_auth_enabled = 'False' + else: + settings_general_auth_enabled = 'True' + settings_general_auth_username = request.forms.get('settings_general_auth_username') + settings_general_auth_password = request.forms.get('settings_general_auth_password') + settings_general_sourcepath = request.forms.getall('settings_general_sourcepath') + settings_general_destpath = request.forms.getall('settings_general_destpath') + settings_general_pathmapping = [] + settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)]) + settings_general_sourcepath_movie = request.forms.getall('settings_general_sourcepath_movie') + settings_general_destpath_movie = request.forms.getall('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)]) + settings_general_branch = request.forms.get('settings_general_branch') + settings_general_automatic = request.forms.get('settings_general_automatic') + if settings_general_automatic is None: + settings_general_automatic = 'False' + else: + settings_general_automatic = 'True' + settings_general_single_language = request.forms.get('settings_general_single_language') + if settings_general_single_language is None: + settings_general_single_language = 'False' + else: + settings_general_single_language = 'True' + settings_general_scenename = request.forms.get('settings_general_scenename') + if settings_general_scenename is None: + settings_general_scenename = 'False' + else: + settings_general_scenename = 'True' + settings_general_embedded = request.forms.get('settings_general_embedded') + if settings_general_embedded is None: + settings_general_embedded = 'False' + else: + settings_general_embedded = 'True' + settings_general_only_monitored = request.forms.get('settings_general_only_monitored') + if settings_general_only_monitored is None: + settings_general_only_monitored = 'False' + else: + settings_general_only_monitored = 'True' + settings_general_minimum_score = request.forms.get('settings_general_minimum_score') + settings_general_minimum_score_movies = request.forms.get('settings_general_minimum_score_movies') + settings_general_use_postprocessing = request.forms.get('settings_general_use_postprocessing') + if settings_general_use_postprocessing is None: + settings_general_use_postprocessing = 'False' + else: + settings_general_use_postprocessing = 'True' + settings_general_postprocessing_cmd = request.forms.get('settings_general_postprocessing_cmd') + settings_general_use_sonarr = request.forms.get('settings_general_use_sonarr') + if settings_general_use_sonarr is None: + settings_general_use_sonarr = 'False' + else: + settings_general_use_sonarr = 'True' + settings_general_use_radarr = request.forms.get('settings_general_use_radarr') + if settings_general_use_radarr is None: + settings_general_use_radarr = 'False' + else: + settings_general_use_radarr = 'True' + settings_page_size = request.forms.get('settings_page_size') + + settings_general = get_general_settings() + + before = (unicode(settings_general[0]), int(settings_general[1]), unicode(settings_general[2]), unicode(settings_general[4]), unicode(settings_general[3]), unicode(settings_general[12]), unicode(settings_general[13]), unicode(settings_general[14])) + after = (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_loglevel), unicode(settings_general_pathmapping), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie)) + from six import text_type + + cfg = ConfigParser() + + with open(config_file, 'r') as f: + cfg.read_file(f) + + cfg.set('general', 'ip', text_type(settings_general_ip)) + cfg.set('general', 'port', text_type(settings_general_port)) + cfg.set('general', 'base_url', text_type(settings_general_baseurl)) + cfg.set('general', 'path_mappings', text_type(settings_general_pathmapping)) + cfg.set('general', 'log_level', text_type(settings_general_loglevel)) + cfg.set('general', 'branch', text_type(settings_general_branch)) + cfg.set('general', 'auto_update', text_type(settings_general_automatic)) + cfg.set('general', 'single_language', text_type(settings_general_single_language)) + cfg.set('general', 'minimum_score', text_type(settings_general_minimum_score)) + cfg.set('general', 'use_scenename', text_type(settings_general_scenename)) + cfg.set('general', 'use_postprocessing', text_type(settings_general_use_postprocessing)) + cfg.set('general', 'postprocessing_cmd', text_type(settings_general_postprocessing_cmd)) + cfg.set('general', 'use_sonarr', text_type(settings_general_use_sonarr)) + cfg.set('general', 'use_radarr', text_type(settings_general_use_radarr)) + cfg.set('general', 'path_mappings_movie', text_type(settings_general_pathmapping_movie)) + cfg.set('general', 'page_size', text_type(settings_page_size)) + cfg.set('general', 'minimum_score_movie', text_type(settings_general_minimum_score_movies)) + cfg.set('general', 'use_embedded_subs', text_type(settings_general_embedded)) + cfg.set('general', 'only_monitored', text_type(settings_general_only_monitored)) + # cfg.set('general', 'configured', text_type(configured)) + # cfg.set('general', 'updated', text_type(updated)) + + if after != before: + configured() + get_general_settings() + + settings_auth = get_auth_settings() + + before_auth_password = (unicode(settings_auth[0]), unicode(settings_auth[2])) + if before_auth_password[0] != settings_general_auth_enabled: + configured() + if before_auth_password[1] == settings_general_auth_password: + cfg.set('auth', 'enabled', text_type(settings_general_auth_enabled)) + cfg.set('auth', 'username', text_type(settings_general_auth_username)) + else: + cfg.set('auth', 'enabled', text_type(settings_general_auth_enabled)) + cfg.set('auth', 'username', text_type(settings_general_auth_username)) + cfg.set('auth', 'password', hashlib.md5(settings_general_auth_password).hexdigest()) + + settings_sonarr_ip = request.forms.get('settings_sonarr_ip') + settings_sonarr_port = request.forms.get('settings_sonarr_port') + settings_sonarr_baseurl = request.forms.get('settings_sonarr_baseurl') + settings_sonarr_ssl = request.forms.get('settings_sonarr_ssl') + if settings_sonarr_ssl is None: + settings_sonarr_ssl = 'False' + else: + settings_sonarr_ssl = 'True' + settings_sonarr_apikey = request.forms.get('settings_sonarr_apikey') + settings_sonarr_sync = request.forms.get('settings_sonarr_sync') + + cfg.set('sonarr', 'ip', text_type(settings_sonarr_ip)) + cfg.set('sonarr', 'port', text_type(settings_sonarr_port)) + cfg.set('sonarr', 'base_url', text_type(settings_sonarr_baseurl)) + cfg.set('sonarr', 'ssl', text_type(settings_sonarr_ssl)) + cfg.set('sonarr', 'apikey', text_type(settings_sonarr_apikey)) + cfg.set('sonarr', 'full_update', text_type(settings_sonarr_sync)) + + settings_radarr_ip = request.forms.get('settings_radarr_ip') + settings_radarr_port = request.forms.get('settings_radarr_port') + settings_radarr_baseurl = request.forms.get('settings_radarr_baseurl') + settings_radarr_ssl = request.forms.get('settings_radarr_ssl') + if settings_radarr_ssl is None: + settings_radarr_ssl = 'False' + else: + settings_radarr_ssl = 'True' + settings_radarr_apikey = request.forms.get('settings_radarr_apikey') + settings_radarr_sync = request.forms.get('settings_radarr_sync') + + cfg.set('radarr', 'ip', text_type(settings_radarr_ip)) + cfg.set('radarr', 'port', text_type(settings_radarr_port)) + cfg.set('radarr', 'base_url', text_type(settings_radarr_baseurl)) + cfg.set('radarr', 'ssl', text_type(settings_radarr_ssl)) + cfg.set('radarr', 'apikey', text_type(settings_radarr_apikey)) + cfg.set('radarr', 'full_update', text_type(settings_radarr_sync)) + + settings_subliminal_providers = request.forms.getall('settings_subliminal_providers') + c.execute("UPDATE table_settings_providers SET enabled = 0") + for item in settings_subliminal_providers: + c.execute("UPDATE table_settings_providers SET enabled = '1' WHERE name = ?", (item,)) + + settings_addic7ed_username = request.forms.get('settings_addic7ed_username') + settings_addic7ed_password = request.forms.get('settings_addic7ed_password') + c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'addic7ed'", (settings_addic7ed_username, settings_addic7ed_password)) + settings_legendastv_username = request.forms.get('settings_legendastv_username') + settings_legendastv_password = request.forms.get('settings_legendastv_password') + c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'legendastv'", (settings_legendastv_username, settings_legendastv_password)) + settings_opensubtitles_username = request.forms.get('settings_opensubtitles_username') + settings_opensubtitles_password = request.forms.get('settings_opensubtitles_password') + c.execute("UPDATE table_settings_providers SET username = ?, password = ? WHERE name = 'opensubtitles'", (settings_opensubtitles_username, settings_opensubtitles_password)) + + settings_subliminal_languages = request.forms.getall('settings_subliminal_languages') + c.execute("UPDATE table_settings_languages SET enabled = 0") + for item in settings_subliminal_languages: + c.execute("UPDATE table_settings_languages SET enabled = '1' WHERE code2 = ?", (item,)) + + settings_serie_default_enabled = request.forms.get('settings_serie_default_enabled') + if settings_serie_default_enabled is None: + settings_serie_default_enabled = 'False' + else: + settings_serie_default_enabled = 'True' + cfg.set('general', 'serie_default_enabled', text_type(settings_serie_default_enabled)) + + settings_serie_default_languages = str(request.forms.getall('settings_serie_default_languages')) + if settings_serie_default_languages == "['None']": + settings_serie_default_languages = 'None' + cfg.set('general', 'serie_default_language', text_type(settings_serie_default_languages)) + + settings_serie_default_hi = request.forms.get('settings_serie_default_hi') + if settings_serie_default_hi is None: + settings_serie_default_hi = 'False' + else: + settings_serie_default_hi = 'True' + cfg.set('general', 'serie_default_hi', text_type(settings_serie_default_hi)) + + settings_movie_default_enabled = request.forms.get('settings_movie_default_enabled') + if settings_movie_default_enabled is None: + settings_movie_default_enabled = 'False' + else: + settings_movie_default_enabled = 'True' + cfg.set('general', 'movie_default_enabled', text_type(settings_movie_default_enabled)) + + settings_movie_default_languages = str(request.forms.getall('settings_movie_default_languages')) + if settings_movie_default_languages == "['None']": + settings_movie_default_languages = 'None' + cfg.set('general', 'movie_default_language', text_type(settings_movie_default_languages)) + + settings_movie_default_hi = request.forms.get('settings_movie_default_hi') + if settings_movie_default_hi is None: + settings_movie_default_hi = 'False' + else: + settings_movie_default_hi = 'True' + cfg.set('general', 'movie_default_hi', text_type(settings_movie_default_hi)) + + with open(config_file, 'wb') as f: + cfg.write(f) + + settings_notifier_Boxcar_enabled = request.forms.get('settings_notifier_Boxcar_enabled') + if settings_notifier_Boxcar_enabled == 'on': + settings_notifier_Boxcar_enabled = 1 + else: + settings_notifier_Boxcar_enabled = 0 + settings_notifier_Boxcar_url = request.forms.get('settings_notifier_Boxcar_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Boxcar'", (settings_notifier_Boxcar_enabled, settings_notifier_Boxcar_url)) + + settings_notifier_Faast_enabled = request.forms.get('settings_notifier_Faast_enabled') + if settings_notifier_Faast_enabled == 'on': + settings_notifier_Faast_enabled = 1 + else: + settings_notifier_Faast_enabled = 0 + settings_notifier_Faast_url = request.forms.get('settings_notifier_Faast_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Faast'", (settings_notifier_Faast_enabled, settings_notifier_Faast_url)) + + settings_notifier_Growl_enabled = request.forms.get('settings_notifier_Growl_enabled') + if settings_notifier_Growl_enabled == 'on': + settings_notifier_Growl_enabled = 1 + else: + settings_notifier_Growl_enabled = 0 + settings_notifier_Growl_url = request.forms.get('settings_notifier_Growl_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Growl'", (settings_notifier_Growl_enabled, settings_notifier_Growl_url)) + + settings_notifier_Join_enabled = request.forms.get('settings_notifier_Join_enabled') + if settings_notifier_Join_enabled == 'on': + settings_notifier_Join_enabled = 1 + else: + settings_notifier_Join_enabled = 0 + settings_notifier_Join_url = request.forms.get('settings_notifier_Join_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Join'", (settings_notifier_Join_enabled, settings_notifier_Join_url)) + + settings_notifier_KODI_enabled = request.forms.get('settings_notifier_KODI_enabled') + if settings_notifier_KODI_enabled == 'on': + settings_notifier_KODI_enabled = 1 + else: + settings_notifier_KODI_enabled = 0 + settings_notifier_KODI_url = request.forms.get('settings_notifier_KODI_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'KODI'", (settings_notifier_KODI_enabled, settings_notifier_KODI_url)) + + settings_notifier_Mattermost_enabled = request.forms.get('settings_notifier_Mattermost_enabled') + if settings_notifier_Mattermost_enabled == 'on': + settings_notifier_Mattermost_enabled = 1 + else: + settings_notifier_Mattermost_enabled = 0 + settings_notifier_Mattermost_url = request.forms.get('settings_notifier_Mattermost_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Mattermost'", (settings_notifier_Mattermost_enabled, settings_notifier_Mattermost_url)) + + settings_notifier_NMA_enabled = request.forms.get('settings_notifier_Notify My Android_enabled') + if settings_notifier_NMA_enabled == 'on': + settings_notifier_NMA_enabled = 1 + else: + settings_notifier_NMA_enabled = 0 + settings_notifier_NMA_url = request.forms.get('settings_notifier_Notify My Android_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Notify My Android'", (settings_notifier_NMA_enabled, settings_notifier_NMA_url)) + + settings_notifier_Prowl_enabled = request.forms.get('settings_notifier_Prowl_enabled') + if settings_notifier_Prowl_enabled == 'on': + settings_notifier_Prowl_enabled = 1 + else: + settings_notifier_Prowl_enabled = 0 + settings_notifier_Prowl_url = request.forms.get('settings_notifier_Prowl_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Prowl'", (settings_notifier_Prowl_enabled, settings_notifier_Prowl_url)) + + settings_notifier_Pushalot_enabled = request.forms.get('settings_notifier_Pushalot_enabled') + if settings_notifier_Pushalot_enabled == 'on': + settings_notifier_Pushalot_enabled = 1 + else: + settings_notifier_Pushalot_enabled = 0 + settings_notifier_Pushalot_url = request.forms.get('settings_notifier_Pushalot_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushalot'", (settings_notifier_Pushalot_enabled, settings_notifier_Pushalot_url)) + + settings_notifier_PushBullet_enabled = request.forms.get('settings_notifier_PushBullet_enabled') + if settings_notifier_PushBullet_enabled == 'on': + settings_notifier_PushBullet_enabled = 1 + else: + settings_notifier_PushBullet_enabled = 0 + settings_notifier_PushBullet_url = request.forms.get('settings_notifier_PushBullet_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'PushBullet'", (settings_notifier_PushBullet_enabled, settings_notifier_PushBullet_url)) + + settings_notifier_Pushjet_enabled = request.forms.get('settings_notifier_Pushjet_enabled') + if settings_notifier_Pushjet_enabled == 'on': + settings_notifier_Pushjet_enabled = 1 + else: + settings_notifier_Pushjet_enabled = 0 + settings_notifier_Pushjet_url = request.forms.get('settings_notifier_Pushjet_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushjet'", (settings_notifier_Pushjet_enabled, settings_notifier_Pushjet_url)) + + settings_notifier_Pushover_enabled = request.forms.get('settings_notifier_Pushover_enabled') + if settings_notifier_Pushover_enabled == 'on': + settings_notifier_Pushover_enabled = 1 + else: + settings_notifier_Pushover_enabled = 0 + settings_notifier_Pushover_url = request.forms.get('settings_notifier_Pushover_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushover'", (settings_notifier_Pushover_enabled, settings_notifier_Pushover_url)) + + settings_notifier_RocketChat_enabled = request.forms.get('settings_notifier_Rocket.Chat_enabled') + if settings_notifier_RocketChat_enabled == 'on': + settings_notifier_RocketChat_enabled = 1 + else: + settings_notifier_RocketChat_enabled = 0 + settings_notifier_RocketChat_url = request.forms.get('settings_notifier_Rocket.Chat_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Rocket.Chat'", (settings_notifier_RocketChat_enabled, settings_notifier_RocketChat_url)) + + settings_notifier_Slack_enabled = request.forms.get('settings_notifier_Slack_enabled') + if settings_notifier_Slack_enabled == 'on': + settings_notifier_Slack_enabled = 1 + else: + settings_notifier_Slack_enabled = 0 + settings_notifier_Slack_url = request.forms.get('settings_notifier_Slack_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Slack'", (settings_notifier_Slack_enabled, settings_notifier_Slack_url)) + + settings_notifier_SuperToasty_enabled = request.forms.get('settings_notifier_Super Toasty_enabled') + if settings_notifier_SuperToasty_enabled == 'on': + settings_notifier_SuperToasty_enabled = 1 + else: + settings_notifier_SuperToasty_enabled = 0 + settings_notifier_SuperToasty_url = request.forms.get('settings_notifier_Super Toasty_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Super Toasty'", (settings_notifier_SuperToasty_enabled, settings_notifier_SuperToasty_url)) + + settings_notifier_Telegram_enabled = request.forms.get('settings_notifier_Telegram_enabled') + if settings_notifier_Telegram_enabled == 'on': + settings_notifier_Telegram_enabled = 1 + else: + settings_notifier_Telegram_enabled = 0 + settings_notifier_Telegram_url = request.forms.get('settings_notifier_Telegram_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Telegram'", (settings_notifier_Telegram_enabled, settings_notifier_Telegram_url)) + + settings_notifier_Twitter_enabled = request.forms.get('settings_notifier_Twitter_enabled') + if settings_notifier_Twitter_enabled == 'on': + settings_notifier_Twitter_enabled = 1 + else: + settings_notifier_Twitter_enabled = 0 + settings_notifier_Twitter_url = request.forms.get('settings_notifier_Twitter_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Twitter'", (settings_notifier_Twitter_enabled, settings_notifier_Twitter_url)) + + settings_notifier_XBMC_enabled = request.forms.get('settings_notifier_XBMC_enabled') + if settings_notifier_XBMC_enabled == 'on': + settings_notifier_XBMC_enabled = 1 + else: + settings_notifier_XBMC_enabled = 0 + settings_notifier_XBMC_url = request.forms.get('settings_notifier_XBMC_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'XBMC'", (settings_notifier_XBMC_enabled, settings_notifier_XBMC_url)) + + settings_notifier_Discord_enabled = request.forms.get('settings_notifier_Discord_enabled') + if settings_notifier_Discord_enabled == 'on': + settings_notifier_Discord_enabled = 1 + else: + settings_notifier_Discord_enabled = 0 + settings_notifier_Discord_url = request.forms.get('settings_notifier_Discord_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Discord'", (settings_notifier_Discord_enabled, settings_notifier_Discord_url)) + + settings_notifier_E_Mail_enabled = request.forms.get('settings_notifier_E-Mail_enabled') + if settings_notifier_E_Mail_enabled == 'on': + settings_notifier_E_Mail_enabled = 1 + else: + settings_notifier_E_Mail_enabled = 0 + settings_notifier_E_Mail_url = request.forms.get('settings_notifier_E-Mail_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'E-Mail'", (settings_notifier_E_Mail_enabled, settings_notifier_E_Mail_url)) + + settings_notifier_Emby_enabled = request.forms.get('settings_notifier_Emby_enabled') + if settings_notifier_Emby_enabled == 'on': + settings_notifier_Emby_enabled = 1 + else: + settings_notifier_Emby_enabled = 0 + settings_notifier_Emby_url = request.forms.get('settings_notifier_Emby_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Emby'", (settings_notifier_Emby_enabled, settings_notifier_Emby_url)) + + settings_notifier_IFTTT_enabled = request.forms.get('settings_notifier_IFTTT_enabled') + if settings_notifier_IFTTT_enabled == 'on': + settings_notifier_IFTTT_enabled = 1 + else: + settings_notifier_IFTTT_enabled = 0 + settings_notifier_IFTTT_url = request.forms.get('settings_notifier_IFTTT_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'IFTTT'", (settings_notifier_IFTTT_enabled, settings_notifier_IFTTT_url)) + + settings_notifier_Stride_enabled = request.forms.get('settings_notifier_Stride_enabled') + if settings_notifier_Stride_enabled == 'on': + settings_notifier_Stride_enabled = 1 + else: + settings_notifier_Stride_enabled = 0 + settings_notifier_Stride_url = request.forms.get('settings_notifier_Stride_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Stride'", (settings_notifier_Stride_enabled, settings_notifier_Stride_url)) + + settings_notifier_Windows_enabled = request.forms.get('settings_notifier_Windows_enabled') + if settings_notifier_Windows_enabled == 'on': + settings_notifier_Windows_enabled = 1 + else: + settings_notifier_Windows_enabled = 0 + settings_notifier_Windows_url = request.forms.get('settings_notifier_Windows_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Windows'", (settings_notifier_Windows_enabled, settings_notifier_Windows_url)) + + conn.commit() + c.close() + + sonarr_full_update() + radarr_full_update() + + logging.info('Settings saved succesfully.') + + # reschedule full update task according to settings + sonarr_full_update() + + redirect(ref) + +@route(base_url + 'check_update') +@custom_auth_basic(check_credentials) +def check_update(): + ref = request.environ['HTTP_REFERER'] + + check_and_apply_update() + + redirect(ref) + +@route(base_url + 'system') +@custom_auth_basic(check_credentials) +def system(): + def get_time_from_interval(interval): + interval_clean = interval.split('[') + interval_clean = interval_clean[1][:-1] + interval_split = interval_clean.split(':') + + hour = interval_split[0] + minute = interval_split[1].lstrip("0") + second = interval_split[2].lstrip("0") + + text = "every " + if hour != "0": + text = text + hour + if hour == "1": + text = text + " hour" + else: + text = text + " hours" + + if minute != "" and second != "": + text = text + ", " + elif minute == "" and second != "": + text = text + " and " + elif minute != "" and second == "": + text = text + " and " + if minute != "": + text = text + minute + if minute == "1": + text = text + " minute" + else: + text = text + " minutes" + + if second != "": + text = text + " and " + if second != "": + text = text + second + if second == "1": + text = text + " second" + else: + text = text + " seconds" + + return text + + def get_time_from_cron(cron): + text = "at " + hour = str(cron[5]) + minute = str(cron[6]) + second = str(cron[7]) + + if hour != "0" and hour != "*": + text = text + hour + if hour == "0" or hour == "1": + text = text + " hour" + else: + text = text + " hours" + + if minute != "*" and second != "0": + text = text + ", " + elif minute == "*" and second != "0": + text = text + " and " + elif minute != "0" and minute != "*" and second == "0": + text = text + " and " + if minute != "0" and minute != "*": + text = text + minute + if minute == "0" or minute == "1": + text = text + " minute" + else: + text = text + " minutes" + + if second != "0" and second != "*": + text = text + " and " + if second != "0" and second != "*": + text = text + second + if second == "0" or second == "1": + text = text + " second" + else: + text = text + " seconds" + + return text + + + task_list = [] + for job in scheduler.get_jobs(): + if job.next_run_time is not None: + next_run = pretty.date(job.next_run_time.replace(tzinfo=None)) + else: + next_run = "Never" + + if job.trigger.__str__().startswith('interval'): + task_list.append([job.name, get_time_from_interval(str(job.trigger)), next_run, job.id]) + elif job.trigger.__str__().startswith('cron'): + task_list.append([job.name, get_time_from_cron(job.trigger.fields), next_run, job.id]) + + i = 0 + with open(os.path.join(config_dir, 'log/bazarr.log')) as f: + for i, l in enumerate(f, 1): + pass + row_count = i + page_size = int(get_general_settings()[21]) + max_page = int(math.ceil(row_count / (page_size + 0.0))) + + return template('system', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url, task_list=task_list, row_count=row_count, max_page=max_page, page_size=page_size) + +@route(base_url + 'logs/') +@custom_auth_basic(check_credentials) +def get_logs(page): + page_size = int(get_general_settings()[21]) + begin = (page * page_size) - page_size + end = (page * page_size) - 1 + logs_complete = [] + for line in reversed(open(os.path.join(config_dir, 'log/bazarr.log')).readlines()): + logs_complete.append(line.rstrip()) + logs = logs_complete[begin:end] + + return template('logs', logs=logs, base_url=base_url) + +@route(base_url + 'execute/') +@custom_auth_basic(check_credentials) +def execute_task(taskid): + ref = request.environ['HTTP_REFERER'] + + execute_now(taskid) + + redirect(ref) + + +@route(base_url + 'remove_subtitles', method='POST') +@custom_auth_basic(check_credentials) +def remove_subtitles(): + episodePath = request.forms.get('episodePath') + language = request.forms.get('language') + subtitlesPath = request.forms.get('subtitlesPath') + sonarrSeriesId = request.forms.get('sonarrSeriesId') + sonarrEpisodeId = request.forms.get('sonarrEpisodeId') + + try: + os.remove(subtitlesPath) + result = language_from_alpha3(language) + " subtitles deleted from disk." + history_log(0, sonarrSeriesId, sonarrEpisodeId, result) + except OSError: + pass + store_subtitles(unicode(episodePath)) + list_missing_subtitles(sonarrSeriesId) + + +@route(base_url + 'remove_subtitles_movie', method='POST') +@custom_auth_basic(check_credentials) +def remove_subtitles_movie(): + moviePath = request.forms.get('moviePath') + language = request.forms.get('language') + subtitlesPath = request.forms.get('subtitlesPath') + radarrId = request.forms.get('radarrId') + + try: + os.remove(subtitlesPath) + result = language_from_alpha3(language) + " subtitles deleted from disk." + history_log_movie(0, radarrId, result) + except OSError: + pass + store_subtitles_movie(unicode(moviePath)) + list_missing_subtitles_movies(radarrId) + + +@route(base_url + 'get_subtitle', method='POST') +@custom_auth_basic(check_credentials) +def get_subtitle(): + ref = request.environ['HTTP_REFERER'] + + episodePath = request.forms.get('episodePath') + sceneName = request.forms.get('sceneName') + language = request.forms.get('language') + hi = request.forms.get('hi') + sonarrSeriesId = request.forms.get('sonarrSeriesId') + sonarrEpisodeId = request.forms.get('sonarrEpisodeId') + # tvdbid = request.forms.get('tvdbid') + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1") + enabled_providers = c.fetchall() + c.close() + + providers_list = [] + providers_auth = {} + if len(enabled_providers) > 0: + for provider in enabled_providers: + providers_list.append(provider[0]) + try: + if provider[2] is not '' and provider[3] is not '': + provider_auth = providers_auth.append(provider[0]) + provider_auth.update({'username':providers[2], 'password':providers[3]}) + else: + providers_auth = None + except: + providers_auth = None + else: + providers_list = None + providers_auth = None + + try: + result = download_subtitle(episodePath, language, hi, providers_list, providers_auth, sceneName, 'series') + if result is not None: + history_log(1, sonarrSeriesId, sonarrEpisodeId, result) + send_notifications(sonarrSeriesId, sonarrEpisodeId, result) + store_subtitles(unicode(episodePath)) + list_missing_subtitles(sonarrSeriesId) + redirect(ref) + except OSError: + pass + +@route(base_url + 'get_subtitle_movie', method='POST') +@custom_auth_basic(check_credentials) +def get_subtitle_movie(): + ref = request.environ['HTTP_REFERER'] + + moviePath = request.forms.get('moviePath') + sceneName = request.forms.get('sceneName') + language = request.forms.get('language') + hi = request.forms.get('hi') + radarrId = request.forms.get('radarrId') + # tmdbid = request.forms.get('tmdbid') + + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1") + enabled_providers = c.fetchall() + c.close() + + providers_list = [] + providers_auth = {} + if len(enabled_providers) > 0: + for provider in enabled_providers: + providers_list.append(provider[0]) + try: + if provider[2] is not '' and provider[3] is not '': + provider_auth = providers_auth.append(provider[0]) + provider_auth.update({'username':providers[2], 'password':providers[3]}) + else: + providers_auth = None + except: + providers_auth = None + else: + providers_list = None + providers_auth = None + + try: + result = download_subtitle(moviePath, language, hi, providers_list, providers_auth, sceneName, 'movies') + if result is not None: + history_log_movie(1, radarrId, result) + send_notifications_movie(radarrId, result) + store_subtitles_movie(unicode(moviePath)) + list_missing_subtitles_movies(radarrId) + redirect(ref) + except OSError: + pass + +def configured(): + conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = conn.cursor() + c.execute("UPDATE system SET configured = 1") + conn.commit() + c.close() + +@route(base_url + 'api/wanted') +def api_wanted(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + data = c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, table_episodes.missing_subtitles FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]' ORDER BY table_episodes._rowid_ DESC").fetchall() + c.close() + return dict(subtitles=data) + +@route(base_url + 'api/history') +def api_history(): + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + data = c.execute("SELECT table_shows.title, table_episodes.season || 'x' || table_episodes.episode, table_episodes.title, strftime('%Y-%m-%d', datetime(table_history.timestamp, 'unixepoch')), table_history.description FROM table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE table_history.action = '1' ORDER BY id DESC").fetchall() + c.close() + return dict(subtitles=data) + +logging.info('Bazarr is started and waiting for request on http://' + str(ip) + ':' + str(port) + str(base_url)) +run(host=ip, port=port, server='waitress') +logging.info('Bazarr has been stopped.') diff --git a/check_update.py b/check_update.py index 2fbc7a19d..787c18956 100644 --- a/check_update.py +++ b/check_update.py @@ -1,6 +1,6 @@ from get_argv import config_dir -from get_general_settings import get_general_settings +from get_settings import get_general_settings import os import logging @@ -44,6 +44,6 @@ def check_and_apply_update(): def updated(): conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) c = conn.cursor() - c.execute("UPDATE table_settings_general SET updated = 1") + c.execute("UPDATE system SET updated = 1") conn.commit() c.close() \ No newline at end of file diff --git a/create_db.sql b/create_db.sql index bf454cd58..96561f9fd 100644 --- a/create_db.sql +++ b/create_db.sql @@ -9,19 +9,15 @@ CREATE TABLE "table_shows" ( `overview` TEXT, `poster` TEXT, `fanart` TEXT, + `audio_language` "text", + `sortTitle` "text", PRIMARY KEY(`tvdbId`) ); -CREATE TABLE "table_settings_sonarr" ( - `ip` TEXT NOT NULL, - `port` INTEGER NOT NULL, - `base_url` TEXT, - `ssl` INTEGER, - `apikey` TEXT -); -INSERT INTO `table_settings_sonarr` (ip,port,base_url,ssl,apikey) VALUES ('127.0.0.1',8989,'/','False',Null); CREATE TABLE "table_settings_providers" ( `name` TEXT NOT NULL UNIQUE, `enabled` INTEGER, + `username` "text", + `password` "text", PRIMARY KEY(`name`) ); CREATE TABLE "table_settings_languages" ( @@ -31,25 +27,6 @@ CREATE TABLE "table_settings_languages" ( `enabled` INTEGER, PRIMARY KEY(`code3`) ); -CREATE TABLE "table_settings_general" ( - `ip` TEXT NOT NULL, - `port` INTEGER NOT NULL, - `base_url` TEXT, - `path_mapping` TEXT, - `log_level` TEXT, - `branch` TEXT, - `auto_update` INTEGER, - `configured` INTEGER, - `updated` INTEGER, - `single_language` TEXT, - `minimum_score` TEXT, - `use_scenename` TEXT, - `use_postprocessing` TEXT, - `postprocessing_cmd` TEXT, - `use_sonarr` TEXT, - `use_radarr` TEXT -); -INSERT INTO `table_settings_general` (ip,port,base_url,path_mapping,log_level, branch, auto_update, configured, updated, single_language, minimum_score, use_scenename, use_postprocessing, postprocessing_cmd, use_sonarr, use_radarr) VALUES ('0.0.0.0',6767,'/',Null,'INFO','master','True',0,0,'False','0','False','False',Null,'False','False'); CREATE TABLE "table_history" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `action` INTEGER NOT NULL, @@ -66,6 +43,36 @@ CREATE TABLE "table_episodes" ( `season` INTEGER NOT NULL, `episode` INTEGER NOT NULL, `subtitles` TEXT, - `missing_subtitles` TEXT + `missing_subtitles` TEXT, + `scene_name` TEXT, + `monitored` TEXT +); +CREATE TABLE "table_movies" ( + `tmdbId` TEXT NOT NULL UNIQUE, + `title` TEXT NOT NULL, + `path` TEXT NOT NULL UNIQUE, + `languages` TEXT, + `subtitles` TEXT, + `missing_subtitles` TEXT, + `hearing_impaired` TEXT, + `radarrId` INTEGER NOT NULL UNIQUE, + `overview` TEXT, + `poster` TEXT, + `fanart` TEXT, + `audio_language` "text", + `sceneName` TEXT, + `monitored` TEXT, PRIMARY KEY(`tmdbId`) +); +CREATE TABLE "table_history_movie" ( + `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, + `action` INTEGER NOT NULL, + `radarrId` INTEGER NOT NULL, + `timestamp` INTEGER NOT NULL, + `description` TEXT NOT NULL +); +CREATE TABLE "system" ( + `configured` TEXT, + `updated` TEXT ); +INSERT INTO `system` (configured, updated) VALUES ('0', '0'); COMMIT; diff --git a/get_auth_settings.py b/get_auth_settings.py deleted file mode 100644 index fe313535a..000000000 --- a/get_auth_settings.py +++ /dev/null @@ -1,21 +0,0 @@ -from get_argv import config_dir - -import sqlite3 -import os - -def get_auth_settings(): - # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - c.execute('''SELECT * FROM table_settings_auth''') - config_auth = c.fetchone() - - # Close database connection - db.close() - - auth_enabled = config_auth[0] - auth_username = config_auth[1] - auth_password = config_auth[2] - - return [auth_enabled, auth_username, auth_password] \ No newline at end of file diff --git a/get_episodes.py b/get_episodes.py index 583fd6189..e3b16e115 100644 --- a/get_episodes.py +++ b/get_episodes.py @@ -5,7 +5,7 @@ import sqlite3 import requests import logging -from get_general_settings import path_replace +from get_settings import path_replace from list_subtitles import list_missing_subtitles, store_subtitles, series_full_scan_subtitles, movies_full_scan_subtitles def update_all_episodes(): @@ -21,9 +21,9 @@ def update_all_movies(): logging.info('All missing movie subtitles updated in database.') def sync_episodes(): - from get_sonarr_settings import get_sonarr_settings - url_sonarr = get_sonarr_settings()[0] - apikey_sonarr = get_sonarr_settings()[2] + from get_settings import get_sonarr_settings + url_sonarr = get_sonarr_settings()[6] + apikey_sonarr = get_sonarr_settings()[4] # Open database connection db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) diff --git a/get_general_settings.py b/get_general_settings.py deleted file mode 100644 index 690c190ce..000000000 --- a/get_general_settings.py +++ /dev/null @@ -1,140 +0,0 @@ -from get_argv import config_dir - -import sqlite3 -import os -import ast -import re - -def get_general_settings(): - # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - # Get general settings from database table - c.execute("SELECT * FROM table_settings_general") - general_settings = c.fetchone() - - # Close database connection - db.close() - - ip = general_settings[0] - port = general_settings[1] - base_url = general_settings[2] - if base_url == None: - base_url = "/" - if base_url.startswith("/") == False: - base_url = "/" + base_url - if base_url.endswith("/") == False: - base_url = base_url + "/" - - if general_settings[3] is None: - path_mappings = [] - else: - path_mappings = ast.literal_eval(general_settings[3]) - log_level = general_settings[4] - branch = general_settings[5] - automatic = general_settings[6] - single_language = general_settings[9] - minimum_score = general_settings[10] - use_scenename = general_settings[11] - use_postprocessing = general_settings[12] - postprocessing_cmd = general_settings[13] - use_sonarr = general_settings[14] - use_radarr = general_settings[15] - if general_settings[16] is None: - path_mappings_movie = [] - else: - path_mappings_movie = ast.literal_eval(general_settings[16]) - serie_default_enabled = general_settings[17] - serie_default_language = general_settings[18] - serie_default_hi = general_settings[19] - movie_default_enabled = general_settings[20] - movie_default_language = general_settings[21] - movie_default_hi = general_settings[22] - page_size = general_settings[23] - minimum_score_movie = general_settings[24] - use_embedded_subs = general_settings[25] - only_monitored = general_settings[26] - - return [ip, port, base_url, path_mappings, log_level, branch, automatic, single_language, minimum_score, use_scenename, use_postprocessing, postprocessing_cmd, use_sonarr, use_radarr, path_mappings_movie, serie_default_enabled, serie_default_language, serie_default_hi, movie_default_enabled,movie_default_language, movie_default_hi, page_size, minimum_score_movie, use_embedded_subs, only_monitored] - -def path_replace(path): - for path_mapping in path_mappings: - if path_mapping[0] in path: - path = path.replace(path_mapping[0], path_mapping[1]) - if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): - path = path.replace('/', '\\') - elif path.startswith('/'): - path = path.replace('\\', '/') - break - return path - -def path_replace_reverse(path): - for path_mapping in path_mappings: - if path_mapping[1] in path: - path = path.replace(path_mapping[1], path_mapping[0]) - if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): - path = path.replace('/', '\\') - elif path.startswith('/'): - path = path.replace('\\', '/') - break - return path - -def path_replace_movie(path): - for path_mapping in path_mappings_movie: - if path_mapping[0] in path: - path = path.replace(path_mapping[0], path_mapping[1]) - if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): - path = path.replace('/', '\\') - elif path.startswith('/'): - path = path.replace('\\', '/') - break - return path - -def path_replace_reverse_movie(path): - for path_mapping in path_mappings_movie: - if path_mapping[1] in path: - path = path.replace(path_mapping[1], path_mapping[0]) - if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): - path = path.replace('/', '\\') - elif path.startswith('/'): - path = path.replace('\\', '/') - break - return path - -def pp_replace(pp_command, episode, subtitles, language, language_code2, language_code3): - pp_command = pp_command.replace('{{directory}}', os.path.dirname(episode)) - pp_command = pp_command.replace('{{episode}}', episode) - pp_command = pp_command.replace('{{episode_name}}', os.path.splitext(os.path.basename(episode))[0]) - pp_command = pp_command.replace('{{subtitles}}', subtitles) - pp_command = pp_command.replace('{{subtitles_language}}', language) - pp_command = pp_command.replace('{{subtitles_language_code2}}', language_code2) - pp_command = pp_command.replace('{{subtitles_language_code3}}', language_code3) - return pp_command - -result = get_general_settings() -ip = result[0] -port = result[1] -base_url = result[2] -path_mappings = result[3] -log_level = result[4] -branch = result[5] -automatic = result[6] -single_language = result[7] -minimum_score = result[8] -use_scenename = result[9] -use_processing = result[10] -postprocessing_cmd = result[11] -use_sonarr = result[12] -use_radarr = result[13] -path_mappings_movie = result[14] -serie_default_enabled = result[15] -serie_default_language = result[16] -serie_default_hi = result[17] -movie_default_enabled = result[18] -movie_default_language = result[19] -movie_default_hi = result[20] -page_size = result[21] -minimum_score_movie = result[22] -use_embedded_subs = result[23] -only_monitored = result[24] \ No newline at end of file diff --git a/get_movies.py b/get_movies.py index fc43dfb5d..dbf8b5de1 100644 --- a/get_movies.py +++ b/get_movies.py @@ -5,14 +5,14 @@ import sqlite3 import requests import logging -from get_general_settings import get_general_settings, path_replace_movie +from get_settings import get_general_settings, path_replace_movie from list_subtitles import store_subtitles_movie, list_missing_subtitles_movies def update_movies(): - from get_radarr_settings import get_radarr_settings - url_radarr = get_radarr_settings()[0] - # url_radarr_short = get_radarr_settings()[1] - apikey_radarr = get_radarr_settings()[2] + from get_settings import get_radarr_settings + url_radarr = get_radarr_settings()[6] + # url_radarr_short = get_radarr_settings()[7] + apikey_radarr = get_radarr_settings()[4] movie_default_enabled = get_general_settings()[18] movie_default_language = get_general_settings()[19] movie_default_hi = get_general_settings()[20] @@ -80,10 +80,10 @@ def update_movies(): # Update or insert movies list in database table try: - if movie_default_enabled == 'True': - c.execute('''INSERT INTO table_movies(title, path, tmdbId, languages,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?, ?, ?)''', (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie_default_language, movie_default_hi, movie["id"], overview, poster, fanart, profile_id_to_language(movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])))) + if movie_default_enabled is True: + c.execute('''INSERT INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?, ?, ?, ?)''', (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie_default_language, '[]', movie_default_hi, movie["id"], overview, poster, fanart, profile_id_to_language(movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])))) else: - c.execute('''INSERT INTO table_movies(title, path, tmdbId, languages,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,(SELECT languages FROM table_movies WHERE tmdbId = ?),(SELECT `hearing_impaired` FROM table_movies WHERE tmdbId = ?), ?, ?, ?, ?, ?, ?, ?)''', (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie["tmdbId"], movie["tmdbId"], movie["id"], overview, poster, fanart, profile_id_to_language(movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])))) + c.execute('''INSERT INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,(SELECT languages FROM table_movies WHERE tmdbId = ?), '[]',(SELECT `hearing_impaired` FROM table_movies WHERE tmdbId = ?), ?, ?, ?, ?, ?, ?, ?)''', (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie["tmdbId"], movie["tmdbId"], movie["id"], overview, poster, fanart, profile_id_to_language(movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])))) except: c.execute('''UPDATE table_movies SET title = ?, path = ?, tmdbId = ?, radarrId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ?, sceneName = ?, monitored = ? WHERE tmdbid = ?''', (movie["title"],movie["path"] + separator + movie['movieFile']['relativePath'],movie["tmdbId"],movie["id"],overview,poster,fanart,profile_id_to_language(movie['qualityProfileId']),sceneName,unicode(bool(movie['monitored'])),movie["tmdbId"])) @@ -108,10 +108,10 @@ def update_movies(): list_missing_subtitles_movies() def get_profile_list(): - from get_radarr_settings import get_radarr_settings - url_radarr = get_radarr_settings()[0] - # url_radarr_short = get_radarr_settings()[1] - apikey_radarr = get_radarr_settings()[2] + from get_settings import get_radarr_settings + url_radarr = get_radarr_settings()[6] + # url_radarr_short = get_radarr_settings()[7] + apikey_radarr = get_radarr_settings()[4] # Get profiles data from radarr global profiles_list diff --git a/get_radarr_settings.py b/get_radarr_settings.py deleted file mode 100644 index 985a5615b..000000000 --- a/get_radarr_settings.py +++ /dev/null @@ -1,42 +0,0 @@ -from get_argv import config_dir - -import sqlite3 -import os -import ast - -def get_radarr_settings(): - # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - # Get Radarr API URL from database config table - c.execute('''SELECT * FROM table_settings_radarr''') - config_radarr = c.fetchone() - - # Close database connection - db.close() - - # Build radarr URL - ip_radarr = config_radarr[0] - port_radarr = str(config_radarr[1]) - baseurl_radarr = config_radarr[2] - ssl_radarr = config_radarr[3] - apikey_radarr = config_radarr[4] - full_update = config_radarr[5] - - if ssl_radarr == 1: - protocol_radarr = "https" - else: - protocol_radarr = "http" - - if baseurl_radarr == None: - baseurl_radarr = "/" - if baseurl_radarr.startswith("/") == False: - baseurl_radarr = "/" + baseurl_radarr - if baseurl_radarr.endswith("/"): - baseurl_radarr = baseurl_radarr[:-1] - - url_radarr = protocol_radarr + "://" + ip_radarr + ":" + port_radarr + baseurl_radarr - url_radarr_short = protocol_radarr + "://" + ip_radarr + ":" + port_radarr - - return [url_radarr, url_radarr_short, apikey_radarr, full_update] \ No newline at end of file diff --git a/get_series.py b/get_series.py index 03342b78a..8c440869d 100644 --- a/get_series.py +++ b/get_series.py @@ -5,13 +5,13 @@ import sqlite3 import requests import logging -from get_general_settings import get_general_settings +from get_settings import get_general_settings from list_subtitles import list_missing_subtitles def update_series(): - from get_sonarr_settings import get_sonarr_settings - url_sonarr = get_sonarr_settings()[0] - apikey_sonarr = get_sonarr_settings()[2] + from get_settings import get_sonarr_settings + url_sonarr = get_sonarr_settings()[6] + apikey_sonarr = get_sonarr_settings()[4] serie_default_enabled = get_general_settings()[15] serie_default_language = get_general_settings()[16] serie_default_hi = get_general_settings()[17] @@ -64,7 +64,7 @@ def update_series(): # Update or insert shows list in database table try: - if serie_default_enabled == 'True': + if serie_default_enabled is True: c.execute('''INSERT INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (show["title"], show["path"], show["tvdbId"], serie_default_language, serie_default_hi, show["id"], overview, poster, fanart, profile_id_to_language(show['qualityProfileId']), show['sortTitle'])) list_missing_subtitles(show["id"]) else: @@ -86,10 +86,10 @@ def update_series(): db.close() def get_profile_list(): - from get_sonarr_settings import get_sonarr_settings - url_sonarr = get_sonarr_settings()[0] - # url_sonarr_short = get_sonarr_settings()[1] - apikey_sonarr = get_sonarr_settings()[2] + from get_settings import get_sonarr_settings + url_sonarr = get_sonarr_settings()[6] + # url_sonarr_short = get_sonarr_settings()[5] + apikey_sonarr = get_sonarr_settings()[4] # Get profiles data from Sonarr error = False diff --git a/get_settings.py b/get_settings.py new file mode 100644 index 000000000..6eae7569d --- /dev/null +++ b/get_settings.py @@ -0,0 +1,416 @@ +from get_argv import config_dir + +import os +import re + +import ast +from configparser import ConfigParser + +config_file = os.path.normpath(os.path.join(config_dir, 'config/config.ini')) + +def get_general_settings(): + cfg = ConfigParser() + try: + with open(config_file, 'r') as f: + cfg.read_file(f) + except Exception: + pass + + if cfg.has_section('general'): + if cfg.has_option('general', 'ip'): + ip = cfg.get('general', 'ip') + else: + ip = '0.0.0.0' + + if cfg.has_option('general', 'port'): + port = cfg.get('general', 'port') + else: + port = '6767' + + if cfg.has_option('general', 'base_url'): + base_url = cfg.get('general', 'base_url') + else: + base_url = '/' + + if cfg.has_option('general', 'path_mappings'): + path_mappings = cfg.get('general', 'path_mappings') + else: + path_mappings = [] + + if cfg.has_option('general', 'log_level'): + log_level = cfg.get('general', 'log_level') + else: + log_level = 'INFO' + + if cfg.has_option('general', 'branch'): + branch = cfg.get('general', 'branch') + else: + branch = 'master' + + if cfg.has_option('general', 'auto_update'): + auto_update = cfg.getboolean('general', 'auto_update') + else: + auto_update = True + + if cfg.has_option('general', 'single_language'): + single_language = cfg.getboolean('general', 'single_language') + else: + single_language = False + + if cfg.has_option('general', 'minimum_score'): + minimum_score = cfg.get('general', 'minimum_score') + else: + minimum_score = '100' + + if cfg.has_option('general', 'use_scenename'): + use_scenename = cfg.getboolean('general', 'use_scenename') + else: + use_scenename = False + + if cfg.has_option('general', 'use_postprocessing'): + use_postprocessing = cfg.getboolean('general', 'use_postprocessing') + else: + use_postprocessing = False + + if cfg.has_option('general', 'postprocessing_cmd'): + postprocessing_cmd = cfg.get('general', 'postprocessing_cmd') + else: + postprocessing_cmd = '' + + if cfg.has_option('general', 'use_sonarr'): + use_sonarr = cfg.getboolean('general', 'use_sonarr') + else: + use_sonarr = False + + if cfg.has_option('general', 'use_radarr'): + use_radarr = cfg.getboolean('general', 'use_radarr') + else: + use_radarr = False + + if cfg.has_option('general', 'path_mappings_movie'): + path_mappings_movie = cfg.get('general', 'path_mappings_movie') + else: + path_mappings_movie = [] + + if cfg.has_option('general', 'serie_default_enabled'): + serie_default_enabled = cfg.getboolean('general', 'serie_default_enabled') + else: + serie_default_enabled = False + + if cfg.has_option('general', 'serie_default_language'): + serie_default_language = cfg.get('general', 'serie_default_language') + else: + serie_default_language = [] + + if cfg.has_option('general', 'serie_default_hi'): + serie_default_hi = cfg.getboolean('general', 'serie_default_hi') + else: + serie_default_hi = False + + if cfg.has_option('general', 'movie_default_enabled'): + movie_default_enabled = cfg.getboolean('general', 'movie_default_enabled') + else: + movie_default_enabled = False + + if cfg.has_option('general', 'movie_default_language'): + movie_default_language = cfg.get('general', 'movie_default_language') + else: + movie_default_language = [] + + if cfg.has_option('general', 'movie_default_hi'): + movie_default_hi = cfg.getboolean('general', 'movie_default_hi') + else: + movie_default_hi = False + + if cfg.has_option('general', 'page_size'): + page_size = cfg.get('general', 'page_size') + else: + page_size = '25' + + if cfg.has_option('general', 'minimum_score_movie'): + minimum_score_movie = cfg.get('general', 'minimum_score_movie') + else: + minimum_score_movie = '100' + + if cfg.has_option('general', 'use_embedded_subs'): + use_embedded_subs = cfg.getboolean('general', 'use_embedded_subs') + else: + use_embedded_subs = False + + if cfg.has_option('general', 'only_monitored'): + only_monitored = cfg.getboolean('general', 'only_monitored') + else: + only_monitored = False + + else: + ip = '0.0.0.0' + port = '6768' + base_url = '/' + path_mappings = [] + log_level = 'INFO' + branch = 'master' + auto_update = True + single_language = False + minimum_score = '100' + use_scenename = False + use_postprocessing = False + postprocessing_cmd = False + use_sonarr = False + use_radarr = False + path_mappings_movie = [] + serie_default_enabled = False + serie_default_language = [] + serie_default_hi = False + movie_default_enabled = False + movie_default_language = [] + movie_default_hi = False + page_size = '25' + minimum_score_movie = '100' + use_embedded_subs = False + only_monitored = False + + return [ip, port, base_url, path_mappings, log_level, branch, auto_update, single_language, minimum_score, use_scenename, use_postprocessing, postprocessing_cmd, use_sonarr, use_radarr, path_mappings_movie, serie_default_enabled, serie_default_language, serie_default_hi, movie_default_enabled,movie_default_language, movie_default_hi, page_size, minimum_score_movie, use_embedded_subs, only_monitored] + + +def get_auth_settings(): + cfg = ConfigParser() + try: + with open(config_file, 'r') as f: + cfg.read_file(f) + except Exception: + pass + + if cfg.has_section('auth'): + if cfg.has_option('auth', 'enabled'): + enabled = cfg.getboolean('auth', 'enabled') + else: + enabled = False + + if cfg.has_option('auth', 'username'): + username = cfg.get('auth', 'username') + else: + username = '' + + if cfg.has_option('auth', 'password'): + password = cfg.get('auth', 'password') + else: + password = '' + else: + enabled = False + username = '' + password = '' + + return [enabled, username, password] + + +def get_sonarr_settings(): + cfg = ConfigParser() + try: + with open(config_file, 'r') as f: + cfg.read_file(f) + except Exception: + pass + + if cfg.has_section('sonarr'): + if cfg.has_option('sonarr', 'ip'): + ip = cfg.get('sonarr', 'ip') + else: + ip = '127.0.0.1' + + if cfg.has_option('sonarr', 'port'): + port = cfg.get('sonarr', 'port') + else: + port = '8989' + + if cfg.has_option('sonarr', 'base_url'): + base_url = cfg.get('sonarr', 'base_url') + else: + base_url = '/' + + if cfg.has_option('sonarr', 'ssl'): + ssl = cfg.get('sonarr', 'ssl') + else: + ssl = False + + if cfg.has_option('sonarr', 'apikey'): + apikey = cfg.get('sonarr', 'apikey') + else: + apikey = '' + + if cfg.has_option('sonarr', 'full_update'): + full_update = cfg.get('sonarr', 'full_update') + else: + full_update = 'Dayly' + else: + ip = '127.0.0.1' + port = '8989' + base_url = '/' + ssl = False + apikey = '' + full_update = 'Daily' + + if ssl == 1: + protocol_sonarr = "https" + else: + protocol_sonarr = "http" + + if base_url == None: + base_url = "/" + if base_url.startswith("/") == False: + base_url = "/" + base_url + if base_url.endswith("/"): + base_url = base_url[:-1] + + url_sonarr = protocol_sonarr + "://" + ip + ":" + port + base_url + url_sonarr_short = protocol_sonarr + "://" + ip + ":" + port + + + + return [ip, port, base_url, ssl, apikey, full_update, url_sonarr, url_sonarr_short] + + +def get_radarr_settings(): + cfg = ConfigParser() + try: + with open(config_file, 'r') as f: + cfg.read_file(f) + except Exception: + pass + + if cfg.has_section('radarr'): + if cfg.has_option('radarr', 'ip'): + ip = cfg.get('radarr', 'ip') + else: + ip = '127.0.0.1' + + if cfg.has_option('radarr', 'port'): + port = cfg.get('radarr', 'port') + else: + port = '7878' + + if cfg.has_option('radarr', 'base_url'): + base_url = cfg.get('radarr', 'base_url') + else: + base_url = '/' + + if cfg.has_option('radarr', 'ssl'): + ssl = cfg.get('radarr', 'ssl') + else: + ssl = False + + if cfg.has_option('radarr', 'apikey'): + apikey = cfg.get('radarr', 'apikey') + else: + apikey = '' + + if cfg.has_option('radarr', 'full_update'): + full_update = cfg.get('radarr', 'full_update') + else: + full_update = 'Dayly' + else: + ip = '127.0.0.1' + port = '8989' + base_url = '/' + ssl = False + apikey = '' + full_update = 'Daily' + + if ssl == 1: + protocol_radarr = "https" + else: + protocol_radarr = "http" + + if base_url is None: + base_url = "/" + if base_url.startswith("/") is False: + base_url = "/" + base_url + if base_url.endswith("/"): + base_url = base_url[:-1] + + url_radarr = protocol_radarr + "://" + ip + ":" + port + base_url + url_radarr_short = protocol_radarr + "://" + ip + ":" + port + + return [ip, port, base_url, ssl, apikey, full_update, url_radarr , url_radarr_short] + + + +def path_replace(path): + for path_mapping in path_mappings: + if path_mapping[0] in path: + path = path.replace(path_mapping[0], path_mapping[1]) + if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): + path = path.replace('/', '\\') + elif path.startswith('/'): + path = path.replace('\\', '/') + break + return path + +def path_replace_reverse(path): + for path_mapping in path_mappings: + if path_mapping[1] in path: + path = path.replace(path_mapping[1], path_mapping[0]) + if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): + path = path.replace('/', '\\') + elif path.startswith('/'): + path = path.replace('\\', '/') + break + return path + +def path_replace_movie(path): + for path_mapping in path_mappings_movie: + if path_mapping[0] in path: + path = path.replace(path_mapping[0], path_mapping[1]) + if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): + path = path.replace('/', '\\') + elif path.startswith('/'): + path = path.replace('\\', '/') + break + return path + +def path_replace_reverse_movie(path): + for path_mapping in path_mappings_movie: + if path_mapping[1] in path: + path = path.replace(path_mapping[1], path_mapping[0]) + if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path): + path = path.replace('/', '\\') + elif path.startswith('/'): + path = path.replace('\\', '/') + break + return path + +def pp_replace(pp_command, episode, subtitles, language, language_code2, language_code3): + pp_command = pp_command.replace('{{directory}}', os.path.dirname(episode)) + pp_command = pp_command.replace('{{episode}}', episode) + pp_command = pp_command.replace('{{episode_name}}', os.path.splitext(os.path.basename(episode))[0]) + pp_command = pp_command.replace('{{subtitles}}', subtitles) + pp_command = pp_command.replace('{{subtitles_language}}', language) + pp_command = pp_command.replace('{{subtitles_language_code2}}', language_code2) + pp_command = pp_command.replace('{{subtitles_language_code3}}', language_code3) + return pp_command + +result = get_general_settings() +ip = result[0] +port = result[1] +base_url = result[2] +path_mappings = ast.literal_eval(result[3]) +log_level = result[4] +branch = result[5] +automatic = result[6] +single_language = result[7] +minimum_score = result[8] +use_scenename = result[9] +use_processing = result[10] +postprocessing_cmd = result[11] +use_sonarr = result[12] +use_radarr = result[13] +path_mappings_movie = ast.literal_eval(result[14]) +serie_default_enabled = result[15] +serie_default_language = result[16] +serie_default_hi = result[17] +movie_default_enabled = result[18] +movie_default_language = result[19] +movie_default_hi = result[20] +page_size = result[21] +minimum_score_movie = result[22] +use_embedded_subs = result[23] +only_monitored = result[24] \ No newline at end of file diff --git a/get_sonarr_settings.py b/get_sonarr_settings.py deleted file mode 100644 index 7636226a3..000000000 --- a/get_sonarr_settings.py +++ /dev/null @@ -1,42 +0,0 @@ -from get_argv import config_dir - -import sqlite3 -import os -import ast - -def get_sonarr_settings(): - # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - # Get Sonarr API URL from database config table - c.execute('''SELECT * FROM table_settings_sonarr''') - config_sonarr = c.fetchone() - - # Close database connection - db.close() - - # Build Sonarr URL - ip_sonarr = config_sonarr[0] - port_sonarr = str(config_sonarr[1]) - baseurl_sonarr = config_sonarr[2] - ssl_sonarr = config_sonarr[3] - apikey_sonarr = config_sonarr[4] - full_update = config_sonarr[5] - - if ssl_sonarr == 1: - protocol_sonarr = "https" - else: - protocol_sonarr = "http" - - if baseurl_sonarr == None: - baseurl_sonarr = "/" - if baseurl_sonarr.startswith("/") == False: - baseurl_sonarr = "/" + baseurl_sonarr - if baseurl_sonarr.endswith("/"): - baseurl_sonarr = baseurl_sonarr[:-1] - - url_sonarr = protocol_sonarr + "://" + ip_sonarr + ":" + port_sonarr + baseurl_sonarr - url_sonarr_short = protocol_sonarr + "://" + ip_sonarr + ":" + port_sonarr - - return [url_sonarr, url_sonarr_short, apikey_sonarr, full_update] \ No newline at end of file diff --git a/get_subtitle.py b/get_subtitle.py index e653a5533..eee90e4c4 100644 --- a/get_subtitle.py +++ b/get_subtitle.py @@ -9,7 +9,7 @@ from babelfish import Language from subliminal import region, scan_video, Video, download_best_subtitles, compute_score, save_subtitles from get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2 from bs4 import UnicodeDammit -from get_general_settings import get_general_settings, pp_replace, path_replace, path_replace_movie, path_replace_reverse, path_replace_reverse_movie +from get_settings import get_general_settings, pp_replace, path_replace, path_replace_movie, path_replace_reverse, path_replace_reverse_movie from list_subtitles import store_subtitles, list_missing_subtitles, store_subtitles_movie, list_missing_subtitles_movies from utils import history_log, history_log_movie from notifier import send_notifications, send_notifications_movie @@ -34,7 +34,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, lang_obj = Language(language) try: - if sceneName is None or use_scenename == "False": + if sceneName is None or use_scenename is False: used_sceneName = False video = scan_video(path) else: @@ -61,7 +61,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, score = round(float(compute_score(best_subtitle, video)) / type_of_score * 100, 2) if used_sceneName == True: video = scan_video(path) - if single == 'True': + if single is True: result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8') else: result = save_subtitles(video, [best_subtitle], encoding='utf-8') @@ -79,7 +79,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, else: message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(score) + "% using filename guessing." - if use_postprocessing == "True": + if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': @@ -109,7 +109,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, return message def series_download_subtitles(no): - if get_general_settings()[24] == "True": + if get_general_settings()[24] is True: monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" @@ -257,7 +257,7 @@ def wanted_search_missing_subtitles(): db.create_function("path_substitution_movie", 1, path_replace_movie) c = db.cursor() - if get_general_settings()[24] == "True": + if get_general_settings()[24] is True: monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" @@ -272,11 +272,11 @@ def wanted_search_missing_subtitles(): integration = get_general_settings() - if integration[12] == "True": + if integration[12] is True: for episode in episodes: wanted_download_subtitles(episode[0]) - if integration[13] == "True": + if integration[13] is True: for movie in movies: wanted_download_subtitles_movie(movie[0]) diff --git a/init.py b/init.py new file mode 100644 index 000000000..f57d07010 --- /dev/null +++ b/init.py @@ -0,0 +1,220 @@ +import os +import sqlite3 +import logging + +from configparser import ConfigParser +from get_argv import config_dir + +# Check if config_dir exist +if os.path.exists(config_dir) is False: + # Create config_dir directory tree + try: + os.mkdir(os.path.join(config_dir)) + logging.debug("Created data directory") + except OSError: + logging.exception("The configuration directory doesn't exist and Bazarr cannot create it (permission issue?).") + exit(2) + +if os.path.exists(os.path.join(config_dir, 'config')) is False: + os.mkdir(os.path.join(config_dir, 'config')) + logging.debug("Created config folder") +if os.path.exists(os.path.join(config_dir, 'db')) is False: + os.mkdir(os.path.join(config_dir, 'db')) + logging.debug("Created db folder") +if os.path.exists(os.path.join(config_dir, 'log')) is False: + os.mkdir(os.path.join(config_dir, 'log')) + logging.debug("Created log folder") + +config_file = os.path.normpath(os.path.join(config_dir, 'config/config.ini')) + +# if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) is True and os.path.exists(config_file) is False: +try: + # Open database connection + db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30) + c = db.cursor() + + # Get general settings from database table + c.execute("SELECT * FROM table_settings_general") + general_settings = c.fetchone() + c.execute('''SELECT * FROM table_settings_auth''') + auth_settings = c.fetchone() + c.execute('''SELECT * FROM table_settings_sonarr''') + sonarr_settings = c.fetchone() + c.execute('''SELECT * FROM table_settings_radarr''') + radarr_settings = c.fetchone() + + c.execute("DROP TABLE table_settings_general") + c.execute("DROP TABLE table_settings_auth") + c.execute("DROP TABLE table_settings_sonarr") + c.execute("DROP TABLE table_settings_radarr") + + # Close database connection + db.close() + + cfg = ConfigParser() + + section = 'general' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', str(general_settings[0])) + cfg.set(section, 'port', str(general_settings[1])) + cfg.set(section, 'base_url', general_settings[2]) + cfg.set(section, 'path_mappings', general_settings[3]) + cfg.set(section, 'log_level', general_settings[4]) + cfg.set(section, 'branch', general_settings[5]) + cfg.set(section, 'auto_update', general_settings[6]) + cfg.set(section, 'single_language', general_settings[9]) + cfg.set(section, 'minimum_score', general_settings[10]) + cfg.set(section, 'use_scenename', general_settings[11]) + cfg.set(section, 'use_postprocessing', general_settings[12]) + cfg.set(section, 'postprocessing_cmd', general_settings[13]) + cfg.set(section, 'use_sonarr', general_settings[14]) + cfg.set(section, 'use_radarr', general_settings[15]) + cfg.set(section, 'path_mappings_movie', general_settings[16]) + cfg.set(section, 'serie_default_enabled', general_settings[17]) + cfg.set(section, 'serie_default_language', general_settings[18]) + cfg.set(section, 'serie_default_hi', general_settings[19]) + cfg.set(section, 'movie_default_enabled', general_settings[20]) + cfg.set(section, 'movie_default_language', general_settings[21]) + cfg.set(section, 'movie_default_hi', general_settings[22]) + cfg.set(section, 'page_size', general_settings[23]) + cfg.set(section, 'minimum_score_movie', general_settings[24]) + cfg.set(section, 'use_embedded_subs', general_settings[25]) + cfg.set(section, 'only_monitored', general_settings[26]) + + section = 'auth' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'enabled', auth_settings[0]) + cfg.set(section, 'username', auth_settings[1]) + cfg.set(section, 'password', auth_settings[2]) + + section = 'sonarr' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', sonarr_settings[0]) + cfg.set(section, 'port', str(sonarr_settings[1])) + cfg.set(section, 'base_url', sonarr_settings[2]) + cfg.set(section, 'ssl', sonarr_settings[3]) + cfg.set(section, 'apikey', sonarr_settings[4]) + cfg.set(section, 'full_update', sonarr_settings[5]) + + section = 'radarr' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', radarr_settings[0]) + cfg.set(section, 'port', str(radarr_settings[1])) + cfg.set(section, 'base_url', radarr_settings[2]) + cfg.set(section, 'ssl', radarr_settings[3]) + cfg.set(section, 'apikey', radarr_settings[4]) + cfg.set(section, 'full_update', radarr_settings[5]) + + with open(config_file, 'w+') as configfile: + cfg.write(configfile) + + + logging.info('Config file succesfully migrated from database') + +except sqlite3.OperationalError: +# if not os.path.exists(config_file): + if os.path.exists(config_file) is False: + cfg = ConfigParser() + + section = 'general' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', "0.0.0.0") + cfg.set(section, 'port', "6767") + cfg.set(section, 'base_url', "/") + cfg.set(section, 'path_mappings', '[]') + cfg.set(section, 'log_level', "INFO") + cfg.set(section, 'branch', "master") + cfg.set(section, 'auto_update', "True") + cfg.set(section, 'single_language', "False") + cfg.set(section, 'minimum_score', "100") + cfg.set(section, 'use_scenename', "False") + cfg.set(section, 'use_postprocessing', "False") + cfg.set(section, 'postprocessing_cmd', "False") + cfg.set(section, 'use_sonarr', "False") + cfg.set(section, 'use_radarr', "False") + cfg.set(section, 'path_mappings_movie', '[]') + cfg.set(section, 'serie_default_enabled', "False") + cfg.set(section, 'serie_default_language', '') + cfg.set(section, 'serie_default_hi', "False") + cfg.set(section, 'movie_default_enabled', "False") + cfg.set(section, 'movie_default_language', '') + cfg.set(section, 'movie_default_hi', "False") + cfg.set(section, 'page_size', "25") + cfg.set(section, 'minimum_score_movie', "100") + cfg.set(section, 'use_embedded_subs', "False") + cfg.set(section, 'only_monitored', "False") + + section = 'auth' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'enabled', "False") + cfg.set(section, 'username', "") + cfg.set(section, 'password', "") + + section = 'sonarr' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', "127.0.0.1") + cfg.set(section, 'port', "8989") + cfg.set(section, 'base_url', "/") + cfg.set(section, 'ssl', "False") + cfg.set(section, 'apikey', "") + cfg.set(section, 'full_update', "Daily") + + section = 'radarr' + + if not cfg.has_section(section): + cfg.add_section(section) + + cfg.set(section, 'ip', "127.0.0.1") + cfg.set(section, 'port', "7878") + cfg.set(section, 'base_url', "/") + cfg.set(section, 'ssl', "False") + cfg.set(section, 'apikey', "") + cfg.set(section, 'full_update', "Daily") + + + with open(config_file, 'w+') as configfile: + cfg.write(configfile) + + logging.info('Config file created successfully') +try: + # Get SQL script from file + fd = open(os.path.join(os.path.dirname(__file__), 'create_db.sql'), 'r') + script = fd.read() + + # Close SQL script file + fd.close() + + # Open database connection + db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + c = db.cursor() + + # Execute script and commit change to database + c.executescript(script) + + # Close database connection + db.close() + + logging.info('Database created successfully') +except: + pass diff --git a/init_db.py b/init_db.py deleted file mode 100644 index b9b633b28..000000000 --- a/init_db.py +++ /dev/null @@ -1,50 +0,0 @@ -from get_argv import config_dir - -import os -import sqlite3 -import logging - -# Check if config_dir exist -if os.path.exists(config_dir) == True: - pass -else: - # Create config_dir directory tree - try: - os.mkdir(os.path.join(config_dir)) - except OSError: - logging.exception("The configuration directory doesn't exist and Bazarr cannot create it (permission issue?).") - exit(2) - -# Check if database exist -if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: - pass -else: - # Create data directory tree - try: - os.mkdir(os.path.join(config_dir, 'db')) - except OSError: - pass - - try: - os.mkdir(os.path.join(config_dir, 'log')) - except OSError: - pass - - # Get SQL script from file - fd = open(os.path.join(os.path.dirname(__file__), 'create_db.sql'), 'r') - script = fd.read() - - # Close SQL script file - fd.close() - - # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - c = db.cursor() - - # Execute script and commit change to database - c.executescript(script) - - # Close database connection - db.close() - - logging.info('Database created successfully') \ No newline at end of file diff --git a/list_subtitles.py b/list_subtitles.py index 58e80e569..8d809fb82 100644 --- a/list_subtitles.py +++ b/list_subtitles.py @@ -12,7 +12,7 @@ import langdetect from bs4 import UnicodeDammit from itertools import islice -from get_general_settings import path_replace_reverse, path_replace, path_replace_reverse_movie, path_replace_movie, get_general_settings +from get_settings import path_replace_reverse, path_replace, path_replace_reverse_movie, path_replace_movie, get_general_settings from get_languages import alpha2_from_alpha3 gc.enable() @@ -143,7 +143,7 @@ def list_missing_subtitles(*no): desired_subtitles = [] missing_subtitles = [] if episode_subtitles[1] != None: - if use_embedded_subs == "True": + if use_embedded_subs is True: actual_subtitles = ast.literal_eval(episode_subtitles[1]) else: actual_subtitles_temp = ast.literal_eval(episode_subtitles[1]) @@ -190,7 +190,7 @@ def list_missing_subtitles_movies(*no): desired_subtitles = [] missing_subtitles = [] if movie_subtitles[1] != None: - if use_embedded_subs == "True": + if use_embedded_subs is True: actual_subtitles = ast.literal_eval(movie_subtitles[1]) else: actual_subtitles_temp = ast.literal_eval(movie_subtitles[1]) diff --git a/requirements.txt b/requirements.txt index 7fe75cc1c..68d6a6f87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,7 @@ requests>=2.18.4 tzlocal>=1.5.1 urllib3<1.23,>=1.21.1 waitress>=1.1.0 +configparser==3.5.0 #Subliminal requirements click>=6.7 diff --git a/scheduler.py b/scheduler.py index 5d4c06dcd..766b2dd69 100644 --- a/scheduler.py +++ b/scheduler.py @@ -1,9 +1,6 @@ from get_argv import no_update -from get_general_settings import automatic -from get_sonarr_settings import get_sonarr_settings -from get_radarr_settings import get_radarr_settings -from get_general_settings import get_general_settings +from get_settings import get_general_settings, automatic, get_radarr_settings, get_sonarr_settings from get_series import update_series from get_episodes import update_all_episodes, update_all_movies, sync_episodes from get_movies import update_movies @@ -20,7 +17,7 @@ integration = get_general_settings() def sonarr_full_update(): - full_update = get_sonarr_settings()[3] + full_update = get_sonarr_settings()[5] if full_update == "Daily": scheduler.add_job(update_all_episodes, 'cron', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', name='Update all episodes subtitles from disk', replace_existing=True) elif full_update == "Weekly": @@ -29,7 +26,7 @@ def sonarr_full_update(): scheduler.add_job(update_all_episodes, 'cron', year='2100', hour=4, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_episodes', name='Update all episodes subtitles from disk', replace_existing=True) def radarr_full_update(): - full_update = get_radarr_settings()[3] + full_update = get_radarr_settings()[5] if full_update == "Daily": scheduler.add_job(update_all_movies, 'cron', hour=5, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_all_movies', name='Update all movies subtitles from disk', replace_existing=True) elif full_update == "Weekly": @@ -47,19 +44,19 @@ else: scheduler = BackgroundScheduler() if no_update is False: - if automatic == 'True': + if automatic is True: scheduler.add_job(check_and_apply_update, 'interval', hours=6, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_bazarr', name='Update bazarr from source on Github') else: scheduler.add_job(check_and_apply_update, 'cron', year='2100', hour=4, id='update_bazarr', name='Update bazarr from source on Github') -if integration[12] == "True": +if integration[12] is True: scheduler.add_job(update_series, 'interval', minutes=1, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_series', name='Update series list from Sonarr') scheduler.add_job(sync_episodes, 'interval', minutes=5, max_instances=1, coalesce=True, misfire_grace_time=15, id='sync_episodes', name='Sync episodes with Sonarr') -if integration[13] == "True": +if integration[13] is True: scheduler.add_job(update_movies, 'interval', minutes=5, max_instances=1, coalesce=True, misfire_grace_time=15, id='update_movies', name='Update movies list from Radarr') -if integration[12] == "True" or integration[13] == "True": +if integration[12] is True or integration[13] is True: scheduler.add_job(wanted_search_missing_subtitles, 'interval', hours=3, max_instances=1, coalesce=True, misfire_grace_time=15, id='wanted_search_missing_subtitles', name='Search for wanted subtitles') sonarr_full_update() diff --git a/update_db.py b/update_db.py index 7382d25e1..667fecb30 100644 --- a/update_db.py +++ b/update_db.py @@ -29,19 +29,6 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: except: pass - try: - c.execute('alter table table_settings_general add column "configured" "integer"') - c.execute('alter table table_settings_general add column "updated" "integer"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "single_language" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET single_language="False"') - try: c.execute('CREATE TABLE `table_settings_notifier` (`name` TEXT, `url` TEXT, `enabled` INTEGER);') except: @@ -51,51 +38,11 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: for provider in providers: c.execute('INSERT INTO `table_settings_notifier` (name, enabled) VALUES (?, ?);', (provider,'0')) - try: - c.execute('alter table table_settings_general add column "minimum_score" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET minimum_score="0"') - - try: - c.execute('alter table table_settings_general add column "use_scenename" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET use_scenename="True"') - - try: - c.execute('alter table table_settings_general add column "use_postprocessing" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET use_postprocessing="False"') - - try: - c.execute('alter table table_settings_general add column "postprocessing_cmd" "text"') - except: - pass - - try: - c.execute('alter table table_settings_sonarr add column "full_update" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_sonarr SET full_update="Daily"') - try: c.execute('alter table table_shows add column "sortTitle" "text"') except: pass - try: - c.execute('CREATE TABLE "table_settings_radarr" ( `ip` TEXT NOT NULL, `port` INTEGER NOT NULL, `base_url` TEXT, `ssl` INTEGER, `apikey` TEXT , "full_update" TEXT)') - except: - pass - else: - c.execute('INSERT INTO `table_settings_radarr` (ip, port, base_url, ssl, apikey, full_update) VALUES ("127.0.0.1", "7878", "/", "False", Null, "Daily")') - try: c.execute('CREATE TABLE "table_movies" ( `tmdbId` TEXT NOT NULL UNIQUE, `title` TEXT NOT NULL, `path` TEXT NOT NULL UNIQUE, `languages` TEXT, `subtitles` TEXT, `missing_subtitles` TEXT, `hearing_impaired` TEXT, `radarrId` INTEGER NOT NULL UNIQUE, `overview` TEXT, `poster` TEXT, `fanart` TEXT, "audio_language" "text", `sceneName` TEXT, PRIMARY KEY(`tmdbId`) )') except: @@ -106,73 +53,6 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: except: pass - try: - c.execute('alter table table_settings_general add column "use_sonarr" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET use_sonarr="True"') - - try: - c.execute('alter table table_settings_general add column "use_radarr" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET use_radarr="False"') - - try: - c.execute('alter table table_settings_general add column "path_mapping_movie" "text"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "serie_default_enabled" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET serie_default_enabled="False"') - - try: - c.execute('alter table table_settings_general add column "serie_default_languages" "text"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "serie_default_hi" "text"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "movie_default_enabled" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET movie_default_enabled="False"') - - try: - c.execute('alter table table_settings_general add column "movie_default_languages" "text"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "movie_default_hi" "text"') - except: - pass - - try: - c.execute('alter table table_settings_general add column "page_size" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET page_size="25"') - - try: - c.execute('alter table table_settings_general add column "minimum_score_movie" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET minimum_score_movie="0"') - try: c.execute('DELETE FROM table_settings_notifier WHERE rowid > 24') #Modify this if we add more notification provider rows = c.execute('SELECT name FROM table_settings_notifier WHERE name = "Discord"').fetchall() @@ -184,25 +64,11 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: pass try: - c.execute('alter table table_settings_general add column "use_embedded_subs" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET use_embedded_subs="True"') - - try: - c.execute('CREATE TABLE `table_settings_auth` ( `enabled` TEXT, `username` TEXT, `password` TEXT);') + c.execute('CREATE TABLE `system` ( `configured` TEXT, `updated` TEXT)') + c.execute('INSERT INTO `system` (configured, updated) VALUES (?, ?);', ('0', '0')) except: pass - else: - c.execute('INSERT INTO `table_settings_auth` (enabled, username, password) VALUES ("False", "", "")') - try: - c.execute('alter table table_settings_general add column "only_monitored" "text"') - except: - pass - else: - c.execute('UPDATE table_settings_general SET only_monitored="False"') # Commit change to db db.commit() @@ -214,11 +80,11 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: pass else: from scheduler import execute_now - from get_general_settings import get_general_settings + from get_settings import get_general_settings integration = get_general_settings() - if integration[12] == "True": + if integration[12] is True: execute_now('sync_episodes') - if integration[13] == "True": + if integration[13] is True: execute_now('update_movies') @@ -229,9 +95,9 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: pass else: from scheduler import execute_now - from get_general_settings import get_general_settings + from get_settings import get_general_settings integration = get_general_settings() - if integration[12] == "True": + if integration[12] is True: execute_now('sync_episodes') try: @@ -241,9 +107,9 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: pass else: from scheduler import execute_now - from get_general_settings import get_general_settings + from get_settings import get_general_settings integration = get_general_settings() - if integration[13] == "True": + if integration[13] is True: execute_now('update_movies') db.close() \ No newline at end of file diff --git a/views/episodes.tpl b/views/episodes.tpl index 3b6be2437..0f876c0f3 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -75,7 +75,7 @@ %import ast %from get_languages import * - %from get_general_settings import * + %from get_settings import * %single_language = get_general_settings()[7]
@@ -159,7 +159,7 @@ %for episode in season: - %if episode[9] == "True": + %if episode[9] is True: %else: @@ -248,9 +248,9 @@
- - %if single_language == 'True': + %if single_language is True: %end %for language in languages: diff --git a/views/history.tpl b/views/history.tpl index a5fd2e386..971ff7ba4 100644 --- a/views/history.tpl +++ b/views/history.tpl @@ -51,18 +51,12 @@ % from get_argv import config_dir % import os - % import sqlite3 + % from get_settings import get_general_settings - % conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - % c = conn.cursor() - - % integration = c.execute("SELECT use_sonarr, use_radarr FROM table_settings_general").fetchone() - - % c.close()
diff --git a/views/menu.tpl b/views/menu.tpl index 5fd4ea0ee..c908cff36 100644 --- a/views/menu.tpl +++ b/views/menu.tpl @@ -25,9 +25,9 @@ % import os % import sqlite3 - % from get_general_settings import * + % from get_settings import get_general_settings - %if get_general_settings()[24] == "True": + %if get_general_settings()[24] is True: % monitored_only_query_string = ' AND monitored = "True"' %else: % monitored_only_query_string = "" @@ -37,7 +37,6 @@ % c = conn.cursor() % wanted_series = c.execute("SELECT COUNT(*) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string).fetchone() % wanted_movies = c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string).fetchone() - % integration = c.execute("SELECT use_sonarr, use_radarr FROM table_settings_general").fetchone()
@@ -52,13 +51,13 @@
- % restart_required = c.execute("SELECT updated, configured FROM table_settings_general").fetchone() + % restart_required = c.execute("SELECT configured, updated FROM system").fetchone() % c.close() - % if restart_required[0] == 1 and restart_required[1] == 1: + % if restart_required[1] == '1' and restart_required[0] == '1':
Bazarr need to be restarted to apply last update and changes to general settings.
- % elif restart_required[0] == 1: + % elif restart_required[1] == '1':
Bazarr need to be restarted to apply last update.
- % elif restart_required[1] == 1: + % elif restart_required[0] == '1':
Bazarr need to be restarted to apply changes to general settings.
% end diff --git a/views/movie.tpl b/views/movie.tpl index 1be4bbdea..f95c9f59a 100644 --- a/views/movie.tpl +++ b/views/movie.tpl @@ -66,7 +66,7 @@ %import ast %from get_languages import * - %from get_general_settings import * + %from get_settings import * %single_language = get_general_settings()[7]
@@ -92,7 +92,7 @@

- %if details[13] == "True": + %if details[13] is True: %else: @@ -201,7 +201,7 @@

- %for language in languages: diff --git a/views/movies.tpl b/views/movies.tpl index 3a008f4b5..ea1d27671 100644 --- a/views/movies.tpl +++ b/views/movies.tpl @@ -174,7 +174,7 @@
- %for language in languages: diff --git a/views/movieseditor.tpl b/views/movieseditor.tpl index f4ba3122e..bc3e96f98 100644 --- a/views/movieseditor.tpl +++ b/views/movieseditor.tpl @@ -102,7 +102,7 @@
- %for language in languages: diff --git a/views/series.tpl b/views/series.tpl index 3d5228c3a..6c6acfb74 100644 --- a/views/series.tpl +++ b/views/series.tpl @@ -190,9 +190,9 @@
- - %if single_language == 'True': + %if single_language is True: %end %for language in languages: diff --git a/views/serieseditor.tpl b/views/serieseditor.tpl index 61113f954..cfc311db1 100644 --- a/views/serieseditor.tpl +++ b/views/serieseditor.tpl @@ -102,7 +102,7 @@
- %for language in languages: diff --git a/views/settings.tpl b/views/settings.tpl index f1df793fc..37a4978bf 100644 --- a/views/settings.tpl +++ b/views/settings.tpl @@ -259,7 +259,7 @@
-
+
@@ -278,7 +278,7 @@
-
+
@@ -372,8 +372,8 @@
%import ast - %if settings_general[16] is not None: - % path_substitutions_movie = ast.literal_eval(settings_general[16]) + %if settings_general[14] is not None: + % path_substitutions_movie = ast.literal_eval(settings_general[14]) %else: % path_substitutions_movie = [] %end @@ -453,7 +453,7 @@
-
+
@@ -473,7 +473,7 @@
- +
@@ -798,7 +798,7 @@
-
+
@@ -819,7 +819,7 @@
- +
@@ -839,7 +839,7 @@
- +
@@ -857,7 +857,7 @@
-
+
@@ -876,7 +876,7 @@
-
+
@@ -1009,7 +1009,7 @@
-
+
@@ -1054,7 +1054,7 @@
-
+
@@ -1076,7 +1076,7 @@
@@ -1111,7 +1111,7 @@
-
+
@@ -1133,7 +1133,7 @@
@@ -1466,7 +1466,7 @@ $('#settings_loglevel').dropdown('clear'); $('#settings_loglevel').dropdown('set selected','{{!settings_general[4]}}'); $('#settings_page_size').dropdown('clear'); - $('#settings_page_size').dropdown('set selected','{{!settings_general[23]}}'); + $('#settings_page_size').dropdown('set selected','{{!settings_general[21]}}'); $('#settings_providers').dropdown('clear'); $('#settings_providers').dropdown('set selected',{{!enabled_providers}}); $('#settings_languages').dropdown('clear'); @@ -1483,11 +1483,11 @@ $('#settings_languages').dropdown(); $('#settings_serie_default_languages').dropdown(); $('#settings_movie_default_languages').dropdown(); - %if settings_general[18] is not None: - $('#settings_serie_default_languages').dropdown('set selected',{{!settings_general[18]}}); + %if settings_general[16] is not None: + $('#settings_serie_default_languages').dropdown('set selected',{{!settings_general[16]}}); %end - %if settings_general[21] is not None: - $('#settings_movie_default_languages').dropdown('set selected',{{!settings_general[21]}}); + %if settings_general[19] is not None: + $('#settings_movie_default_languages').dropdown('set selected',{{!settings_general[19]}}); %end $('#settings_branch').dropdown(); $('#settings_sonarr_sync').dropdown(); diff --git a/views/wanted.tpl b/views/wanted.tpl index a7b080b92..8ed18f9fb 100644 --- a/views/wanted.tpl +++ b/views/wanted.tpl @@ -48,9 +48,9 @@ % import os % import sqlite3 - % from get_general_settings import * + % from get_settings import get_general_settings - %if get_general_settings()[24] == "True": + %if get_general_settings()[24] is True: % monitored_only_query_string = ' AND monitored = "True"' %else: % monitored_only_query_string = "" @@ -68,22 +68,15 @@ % include('menu.tpl') % import os - % import sqlite3 - - % conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) - % c = conn.cursor() - - % integration = c.execute("SELECT use_sonarr, use_radarr FROM table_settings_general").fetchone() - % c.close()