From f692930e267ccf7d948556f2ae34eaf53adefcd8 Mon Sep 17 00:00:00 2001 From: panni Date: Wed, 31 Oct 2018 20:34:40 +0100 Subject: [PATCH] rewrite get_argv to get_args; use in daemon and bazarr; fix os.path.join usage; PEPify most --- bazarr.py | 13 +- bazarr/check_update.py | 21 +- bazarr/get_args.py | 25 +++ bazarr/get_argv.py | 29 --- bazarr/get_episodes.py | 37 ++-- bazarr/get_languages.py | 47 +++-- bazarr/get_movies.py | 47 +++-- bazarr/get_providers.py | 22 ++- bazarr/get_series.py | 43 +++-- bazarr/get_settings.py | 40 ++-- bazarr/get_subtitle.py | 162 ++++++++++------ bazarr/init.py | 41 ++-- bazarr/libs.py | 11 ++ bazarr/list_subtitles.py | 85 +++++--- bazarr/main.py | 407 +++++++++++++++++++++++++-------------- bazarr/notifier.py | 40 ++-- bazarr/scheduler.py | 60 +++--- bazarr/update_db.py | 13 +- bazarr/utils.py | 19 +- views/menu.tpl | 2 +- views/wanted.tpl | 2 +- 21 files changed, 741 insertions(+), 425 deletions(-) create mode 100644 bazarr/get_args.py delete mode 100644 bazarr/get_argv.py create mode 100644 bazarr/libs.py diff --git a/bazarr.py b/bazarr.py index 5411e6585..93abf9ddc 100644 --- a/bazarr.py +++ b/bazarr.py @@ -1,16 +1,19 @@ +# coding=utf-8 + import subprocess as sp import threading import time import os import sys -from bazarr.get_argv import config_dir, arguments +from bazarr import libs +from bazarr.get_args import args dir_name = os.path.dirname(__file__) def start_bazarr(): - script = [sys.executable, "-u", os.path.normcase(os.path.join(globals()['dir_name'], 'bazarr/main.py'))] + arguments + script = [sys.executable, "-u", os.path.normcase(os.path.join(dir_name, 'bazarr', 'main.py'))] + sys.argv[1:] ep = sp.Popen(script, stdout=sp.PIPE, stderr=sp.STDOUT, stdin=sp.PIPE) print "Bazarr starting..." @@ -22,8 +25,8 @@ def start_bazarr(): if __name__ == '__main__': - restartfile = os.path.normcase(os.path.join(config_dir, 'bazarr.restart')) - stopfile = os.path.normcase(os.path.join(config_dir, 'bazarr.stop')) + restartfile = os.path.normcase(os.path.join(args.config_dir, 'bazarr.restart')) + stopfile = os.path.normcase(os.path.join(args.config_dir, 'bazarr.stop')) try: os.remove(restartfile) @@ -62,4 +65,4 @@ if __name__ == '__main__': # Keep the script running forever. while True: - time.sleep(0.001) \ No newline at end of file + time.sleep(0.001) diff --git a/bazarr/check_update.py b/bazarr/check_update.py index d20facf80..28c0a31d5 100644 --- a/bazarr/check_update.py +++ b/bazarr/check_update.py @@ -1,32 +1,34 @@ -from get_argv import config_dir - -from get_settings import get_general_settings +# coding=utf-8 import os import logging import sqlite3 - import git +from get_args import args +from get_settings import get_general_settings + current_working_directory = os.path.dirname(os.path.dirname(__file__)) + def gitconfig(): g = git.Repo.init(current_working_directory) config_read = g.config_reader() config_write = g.config_writer() - + try: username = config_read.get_value("user", "name") except: logging.debug('BAZARR Settings git username') config_write.set_value("user", "name", "Bazarr") - + try: email = config_read.get_value("user", "email") except: logging.debug('BAZARR Settings git email') config_write.set_value("user", "email", "bazarr@fake.email") + def check_and_apply_update(): gitconfig() branch = get_general_settings()[5] @@ -38,14 +40,15 @@ def check_and_apply_update(): else: g.reset('--hard', 'HEAD') g.checkout(branch) - g.reset('--hard','origin/' + branch) + g.reset('--hard', 'origin/' + branch) g.pull() logging.info('BAZARR Updated to latest version. Restart required. ' + result) updated() + def updated(): - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = conn.cursor() c.execute("UPDATE system SET updated = 1") conn.commit() - c.close() \ No newline at end of file + c.close() diff --git a/bazarr/get_args.py b/bazarr/get_args.py new file mode 100644 index 000000000..b3a5f6df5 --- /dev/null +++ b/bazarr/get_args.py @@ -0,0 +1,25 @@ +# coding=utf-8 +import os +import argparse +import arghelper + +from distutils.util import strtobool + +parser = argparse.ArgumentParser() + + +def get_args(): + parser.register('type', bool, strtobool) + + config_dir = os.path.join(os.path.dirname(__file__), '../data/') + parser.add_argument('-c', '--config', default=config_dir, type=arghelper.extant_dir, metavar="DIR", + dest="config_dir", help="Directory containing the configuration (default: %s)" % config_dir) + parser.add_argument('--no-update', default=False, type=bool, const=True, metavar="BOOL", nargs="?", + help="Disable update functionality (default: False)") + parser.add_argument('--debug', default=False, type=bool, const=True, metavar="BOOL", nargs="?", + help="Enable console debugging (default: False)") + + return parser.parse_args() + + +args = get_args() diff --git a/bazarr/get_argv.py b/bazarr/get_argv.py deleted file mode 100644 index 4b24615f2..000000000 --- a/bazarr/get_argv.py +++ /dev/null @@ -1,29 +0,0 @@ -import os -import sys -import getopt - -config_dir = os.path.join(os.path.dirname(__file__), '../data/') -no_update = False -console_debug = False -arguments = [] - - -try: - opts, args = getopt.getopt(sys.argv[1:],"h:",["no-update", "config=", "debug"]) -except getopt.GetoptError: - print 'bazarr.py -h --no-update --config ' - sys.exit(2) - -for opt, arg in opts: - arguments.append(opt) - if arg != '': - arguments.append(arg) - if opt == '-h': - print 'bazarr.py -h --no-update --config ' - sys.exit() - elif opt in "--no-update": - no_update = True - elif opt in "--config": - config_dir = arg - elif opt in "--debug": - console_debug = True diff --git a/bazarr/get_episodes.py b/bazarr/get_episodes.py index a1c430cf1..9d29f70ff 100644 --- a/bazarr/get_episodes.py +++ b/bazarr/get_episodes.py @@ -1,33 +1,38 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 import requests import logging +from get_args import args from get_settings import path_replace -from list_subtitles import list_missing_subtitles, store_subtitles, series_full_scan_subtitles, movies_full_scan_subtitles - +from list_subtitles import list_missing_subtitles, store_subtitles, series_full_scan_subtitles, \ + movies_full_scan_subtitles + + def update_all_episodes(): series_full_scan_subtitles() logging.info('BAZARR All existing episode subtitles indexed from disk.') list_missing_subtitles() logging.info('BAZARR All missing episode subtitles updated in database.') + def update_all_movies(): movies_full_scan_subtitles() logging.info('BAZARR All existing movie subtitles indexed from disk.') list_missing_subtitles() logging.info('BAZARR All missing movie subtitles updated in database.') + def sync_episodes(): logging.debug('BAZARR Starting episode sync from Sonarr.') 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) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Get current episodes id in DB @@ -74,20 +79,30 @@ def sync_episodes(): current_episodes_sonarr.append(episode['id']) if episode['id'] in current_episodes_db_list: - episodes_to_update.append((episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], sceneName, str(bool(episode['monitored'])), episode['id'])) + episodes_to_update.append((episode['title'], episode['episodeFile']['path'], + episode['seasonNumber'], episode['episodeNumber'], + sceneName, str(bool(episode['monitored'])), + episode['id'])) else: - episodes_to_add.append((episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], sceneName, str(bool(episode['monitored'])))) + episodes_to_add.append((episode['seriesId'], episode['id'], episode['title'], + episode['episodeFile']['path'], episode['seasonNumber'], + episode['episodeNumber'], sceneName, + str(bool(episode['monitored'])))) removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr)) # Update or insert movies in DB - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - updated_result = c.executemany('''UPDATE table_episodes SET title = ?, path = ?, season = ?, episode = ?, scene_name = ?, monitored = ? WHERE sonarrEpisodeId = ?''', episodes_to_update) + updated_result = c.executemany( + '''UPDATE table_episodes SET title = ?, path = ?, season = ?, episode = ?, scene_name = ?, monitored = ? WHERE sonarrEpisodeId = ?''', + episodes_to_update) db.commit() - added_result = c.executemany('''INSERT OR IGNORE INTO table_episodes(sonarrSeriesId, sonarrEpisodeId, title, path, season, episode, scene_name, monitored) VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', episodes_to_add) + added_result = c.executemany( + '''INSERT OR IGNORE INTO table_episodes(sonarrSeriesId, sonarrEpisodeId, title, path, season, episode, scene_name, monitored) VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', + episodes_to_add) db.commit() for removed_episode in removed_episodes: @@ -103,4 +118,4 @@ def sync_episodes(): logging.debug('BAZARR All episodes synced from Sonarr into database.') list_missing_subtitles() - logging.debug('BAZARR All missing subtitles updated in database.') \ No newline at end of file + logging.debug('BAZARR All missing subtitles updated in database.') diff --git a/bazarr/get_languages.py b/bazarr/get_languages.py index bcacbd947..a7cc85ac2 100644 --- a/bazarr/get_languages.py +++ b/bazarr/get_languages.py @@ -1,26 +1,30 @@ -from get_argv import config_dir +# coding=utf-8 import sqlite3 import pycountry import os +from get_args import args + + def load_language_in_db(): # Get languages list in langs tuple - langs = [[lang.alpha_3,lang.alpha_2,lang.name] - for lang in pycountry.languages - if hasattr(lang, 'alpha_2')] + langs = [[lang.alpha_3, lang.alpha_2, lang.name] + for lang in pycountry.languages + if hasattr(lang, 'alpha_2')] # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Insert languages in database table c.executemany('''INSERT OR IGNORE INTO table_settings_languages(code3, code2, name) VALUES(?, ?, ?)''', langs) - c.execute('''INSERT OR IGNORE INTO table_settings_languages(code3, code2, name) VALUES(?, ?, ?)''', ('pob','pb','Brazilian Portuguese')) + c.execute('''INSERT OR IGNORE INTO table_settings_languages(code3, code2, name) VALUES(?, ?, ?)''', + ('pob', 'pb', 'Brazilian Portuguese')) - langs = [[lang.bibliographic,lang.alpha_3] - for lang in pycountry.languages - if hasattr(lang, 'alpha_2') and hasattr(lang, 'bibliographic')] + langs = [[lang.bibliographic, lang.alpha_3] + for lang in pycountry.languages + if hasattr(lang, 'alpha_2') and hasattr(lang, 'bibliographic')] # Update languages in database table c.executemany('''UPDATE table_settings_languages SET code3b = ? WHERE code3 = ?''', langs) @@ -31,8 +35,9 @@ def load_language_in_db(): # Close database connection db.close() + def language_from_alpha2(lang): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: result = c.execute('''SELECT name FROM table_settings_languages WHERE code2 = ?''', (lang,)).fetchone()[0] @@ -41,32 +46,37 @@ def language_from_alpha2(lang): db.close() return result + def language_from_alpha3(lang): if lang == 'fre': lang = 'fra' - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: - result = c.execute('''SELECT name FROM table_settings_languages WHERE code3 = ? OR code3b = ?''', (lang,lang)).fetchone()[0] + result = c.execute('''SELECT name FROM table_settings_languages WHERE code3 = ? OR code3b = ?''', + (lang, lang)).fetchone()[0] except: result = None db.close() return result + def alpha2_from_alpha3(lang): if lang == 'fre': lang = 'fra' - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: - result = c.execute('''SELECT code2 FROM table_settings_languages WHERE code3 = ? OR code3b = ?''', (lang,lang)).fetchone()[0] + result = c.execute('''SELECT code2 FROM table_settings_languages WHERE code3 = ? OR code3b = ?''', + (lang, lang)).fetchone()[0] except: result = None db.close() return result + def alpha2_from_language(lang): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: result = c.execute('''SELECT code2 FROM table_settings_languages WHERE name = ?''', (lang,)).fetchone()[0] @@ -75,8 +85,9 @@ def alpha2_from_language(lang): db.close() return result + def alpha3_from_alpha2(lang): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: result = c.execute('''SELECT code3 FROM table_settings_languages WHERE code2 = ?''', (lang,)).fetchone()[0] @@ -85,8 +96,9 @@ def alpha3_from_alpha2(lang): db.close() return result + def alpha3_from_language(lang): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() try: result = c.execute('''SELECT code3 FROM table_settings_languages WHERE name = ?''', (lang,)).fetchone()[0] @@ -95,5 +107,6 @@ def alpha3_from_language(lang): db.close() return result + if __name__ == '__main__': load_language_in_db() diff --git a/bazarr/get_movies.py b/bazarr/get_movies.py index 24aa76497..9ddd7cbb6 100644 --- a/bazarr/get_movies.py +++ b/bazarr/get_movies.py @@ -1,13 +1,15 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 import requests import logging +from get_args import args from get_settings import get_general_settings, path_replace_movie from list_subtitles import store_subtitles_movie, list_missing_subtitles_movies + def update_movies(): logging.debug('BAZARR Starting movie sync from Radarr.') from get_settings import get_radarr_settings @@ -37,7 +39,7 @@ def update_movies(): logging.exception("BAZARR Error trying to get movies from Radarr.") else: # Get current movies in DB - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() current_movies_db = c.execute('SELECT tmdbId FROM table_movies').fetchall() db.close() @@ -79,39 +81,59 @@ def update_movies(): separator = "\\" if unicode(movie['tmdbId']) in current_movies_db_list: - movies_to_update.append((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"])) + movies_to_update.append((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"])) else: if movie_default_enabled is True: - movies_to_add.append((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'])))) + movies_to_add.append((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: - movies_to_add.append((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'])))) + movies_to_add.append((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'])))) # Update or insert movies in DB - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - updated_result = c.executemany('''UPDATE table_movies SET title = ?, path = ?, tmdbId = ?, radarrId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ?, sceneName = ?, monitored = ? WHERE tmdbid = ?''', movies_to_update) + updated_result = c.executemany( + '''UPDATE table_movies SET title = ?, path = ?, tmdbId = ?, radarrId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ?, sceneName = ?, monitored = ? WHERE tmdbid = ?''', + movies_to_update) db.commit() if movie_default_enabled is True: - added_result = c.executemany('''INSERT OR IGNORE INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?, ?, ?, ?)''', movies_to_add) + added_result = c.executemany( + '''INSERT OR IGNORE INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?, ?, ?, ?)''', + movies_to_add) db.commit() else: - added_result = c.executemany('''INSERT OR IGNORE 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 = ?), ?, ?, ?, ?, ?, ?, ?)''', movies_to_add) + added_result = c.executemany( + '''INSERT OR IGNORE 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 = ?), ?, ?, ?, ?, ?, ?, ?)''', + movies_to_add) db.commit() db.close() added_movies = list(set(current_movies_radarr) - set(current_movies_db_list)) removed_movies = list(set(current_movies_db_list) - set(current_movies_radarr)) - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() for removed_movie in removed_movies: c.execute('DELETE FROM table_movies WHERE tmdbId = ?', (removed_movie,)) db.commit() db.close() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() for added_movie in added_movies: added_path = c.execute('SELECT path FROM table_movies WHERE tmdbId = ?', (added_movie,)).fetchone() @@ -123,6 +145,7 @@ def update_movies(): list_missing_subtitles_movies() logging.debug('BAZARR All movie missing subtitles updated in database.') + def get_profile_list(): from get_settings import get_radarr_settings url_radarr = get_radarr_settings()[6] @@ -147,10 +170,12 @@ def get_profile_list(): for profile in profiles_json.json(): profiles_list.append([profile['id'], profile['language'].capitalize()]) + def profile_id_to_language(id): for profile in profiles_list: if id == profile[0]: return profile[1] + if __name__ == '__main__': update_movies() diff --git a/bazarr/get_providers.py b/bazarr/get_providers.py index 92ab7c568..e38dada49 100644 --- a/bazarr/get_providers.py +++ b/bazarr/get_providers.py @@ -1,30 +1,33 @@ -from get_argv import config_dir +# coding=utf-8 import sqlite3 import os -from subliminal_patch.extensions import provider_registry as provider_manager import collections +from subliminal_patch.extensions import provider_registry as provider_manager +from get_args import args + + def load_providers(): # Get providers list from subliminal providers_list = sorted(provider_manager.names()) # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Remove unsupported providers providers_in_db = c.execute('SELECT name FROM table_settings_providers').fetchall() for provider_in_db in providers_in_db: if provider_in_db[0] not in providers_list: - c.execute('DELETE FROM table_settings_providers WHERE name = ?', (provider_in_db[0], )) + c.execute('DELETE FROM table_settings_providers WHERE name = ?', (provider_in_db[0],)) # Commit changes to database table db.commit() # Insert providers in database table for provider_name in providers_list: - c.execute('''INSERT OR IGNORE INTO table_settings_providers(name) VALUES(?)''', (provider_name, )) + c.execute('''INSERT OR IGNORE INTO table_settings_providers(name) VALUES(?)''', (provider_name,)) # Commit changes to database table db.commit() @@ -34,7 +37,7 @@ def load_providers(): def get_providers(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() enabled_providers = c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1").fetchall() c.close() @@ -50,9 +53,10 @@ def get_providers(): def get_providers_auth(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - enabled_providers = c.execute("SELECT * FROM table_settings_providers WHERE enabled = 1 AND username is not NULL AND password is not NULL").fetchall() + enabled_providers = c.execute( + "SELECT * FROM table_settings_providers WHERE enabled = 1 AND username is not NULL AND password is not NULL").fetchall() c.close() providers_auth = collections.defaultdict(dict) @@ -64,4 +68,4 @@ def get_providers_auth(): else: providers_auth = None - return providers_auth \ No newline at end of file + return providers_auth diff --git a/bazarr/get_series.py b/bazarr/get_series.py index 74fa6b2c9..4c7f30505 100644 --- a/bazarr/get_series.py +++ b/bazarr/get_series.py @@ -1,13 +1,15 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 import requests import logging +from get_args import args from get_settings import get_general_settings from list_subtitles import list_missing_subtitles + def update_series(): from get_settings import get_sonarr_settings url_sonarr = get_sonarr_settings()[6] @@ -20,7 +22,7 @@ def update_series(): pass else: get_profile_list() - + # Get shows data from Sonarr url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr try: @@ -36,7 +38,7 @@ def update_series(): logging.exception("BAZARR Error trying to get series from Sonarr.") else: # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Get current shows in DB @@ -69,25 +71,38 @@ def update_series(): current_shows_sonarr.append(show['tvdbId']) if show['tvdbId'] in current_shows_db_list: - series_to_update.append((show["title"],show["path"],show["tvdbId"],show["id"],overview,poster,fanart,profile_id_to_language((show['qualityProfileId'] if sonarr_version == 2 else show['languageProfileId'])),show['sortTitle'],show["tvdbId"])) + series_to_update.append((show["title"], show["path"], show["tvdbId"], show["id"], overview, poster, + fanart, profile_id_to_language( + (show['qualityProfileId'] if sonarr_version == 2 else show['languageProfileId'])), + show['sortTitle'], show["tvdbId"])) else: if serie_default_enabled is True: - series_to_add.append((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'])) + series_to_add.append((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'])) else: - series_to_add.append((show["title"], show["path"], show["tvdbId"], show["tvdbId"], show["tvdbId"], show["id"], overview, poster, fanart, profile_id_to_language(show['qualityProfileId']), show['sortTitle'])) + series_to_add.append((show["title"], show["path"], show["tvdbId"], show["tvdbId"], + show["tvdbId"], show["id"], overview, poster, fanart, + profile_id_to_language(show['qualityProfileId']), show['sortTitle'])) # Update or insert series in DB - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - updated_result = c.executemany('''UPDATE table_shows SET title = ?, path = ?, tvdbId = ?, sonarrSeriesId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ? , sortTitle = ? WHERE tvdbid = ?''', series_to_update) + updated_result = c.executemany( + '''UPDATE table_shows SET title = ?, path = ?, tvdbId = ?, sonarrSeriesId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ? , sortTitle = ? WHERE tvdbid = ?''', + series_to_update) db.commit() if serie_default_enabled is True: - added_result = c.executemany('''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', series_to_add) + added_result = c.executemany( + '''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', + series_to_add) db.commit() else: - added_result = c.executemany('''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle) VALUES (?,?,?,(SELECT languages FROM table_shows WHERE tvdbId = ?),(SELECT `hearing_impaired` FROM table_shows WHERE tvdbId = ?), ?, ?, ?, ?, ?, ?)''', series_to_add) + added_result = c.executemany( + '''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle) VALUES (?,?,?,(SELECT languages FROM table_shows WHERE tvdbId = ?),(SELECT `hearing_impaired` FROM table_shows WHERE tvdbId = ?), ?, ?, ?, ?, ?, ?)''', + series_to_add) db.commit() db.close() @@ -99,12 +114,13 @@ def update_series(): for item in current_shows_db_list: if item not in current_shows_sonarr: deleted_items.append(tuple([item])) - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - c.executemany('DELETE FROM table_shows WHERE tvdbId = ?',deleted_items) + c.executemany('DELETE FROM table_shows WHERE tvdbId = ?', deleted_items) db.commit() db.close() + def get_profile_list(): from get_settings import get_sonarr_settings url_sonarr = get_sonarr_settings()[6] @@ -143,7 +159,7 @@ def get_profile_list(): global profiles_list profiles_list = [] - if error is False: + if not error: # Parsing data returned from Sonarr global sonarr_version if type(profiles_json_v3.json()) != list: @@ -155,6 +171,7 @@ def get_profile_list(): for profile in profiles_json_v3.json(): profiles_list.append([profile['id'], profile['name'].capitalize()]) + def profile_id_to_language(id): for profile in profiles_list: if id == profile[0]: diff --git a/bazarr/get_settings.py b/bazarr/get_settings.py index ebe291686..20e079883 100644 --- a/bazarr/get_settings.py +++ b/bazarr/get_settings.py @@ -1,12 +1,14 @@ -from get_argv import config_dir +# coding=utf-8 import os import re - import ast + +from get_args import args from configparser import ConfigParser -config_file = os.path.normpath(os.path.join(config_dir, 'config/config.ini')) +config_file = os.path.normpath(os.path.join(args.config_dir, 'config', 'config.ini')) + def get_general_settings(): cfg = ConfigParser() @@ -29,7 +31,7 @@ def get_general_settings(): if cfg.has_option('general', 'base_url'): base_url = cfg.get('general', 'base_url') - if base_url.endswith('/') is False: + if not base_url.endswith('/'): base_url += '/' else: base_url = '/' @@ -110,7 +112,7 @@ def get_general_settings(): serie_default_hi = 'False' if cfg.has_option('general', 'movie_default_enabled'): - movie_default_enabled = cfg.getboolean('general', 'movie_default_enabled') + movie_default_enabled = cfg.getboolean('general', 'movie_default_enabled') else: movie_default_enabled = False @@ -143,7 +145,7 @@ def get_general_settings(): only_monitored = cfg.getboolean('general', 'only_monitored') else: only_monitored = False - + if cfg.has_option('general', 'adaptive_searching'): adaptive_searching = cfg.getboolean('general', 'adaptive_searching') else: @@ -177,7 +179,11 @@ def get_general_settings(): only_monitored = False adaptive_searching = 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, adaptive_searching] + 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, + adaptive_searching] def get_auth_settings(): @@ -224,12 +230,12 @@ def get_proxy_settings(): proxy_type = cfg.get('proxy', 'type') else: proxy_type = 'None' - + if cfg.has_option('proxy', 'url'): url = cfg.get('proxy', 'url') else: url = '' - + if cfg.has_option('proxy', 'port'): port = cfg.get('proxy', 'port') else: @@ -244,7 +250,7 @@ def get_proxy_settings(): password = cfg.get('proxy', 'password') else: password = '' - + if cfg.has_option('proxy', 'exclude'): exclude = cfg.get('proxy', 'exclude') else: @@ -321,8 +327,6 @@ def get_sonarr_settings(): 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] @@ -379,7 +383,7 @@ def get_radarr_settings(): if base_url is None: base_url = "/" - if base_url.startswith("/") is False: + if not base_url.startswith("/"): base_url = "/" + base_url if base_url.endswith("/"): base_url = base_url[:-1] @@ -387,8 +391,7 @@ def get_radarr_settings(): 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] - + return [ip, port, base_url, ssl, apikey, full_update, url_radarr, url_radarr_short] def path_replace(path): @@ -402,6 +405,7 @@ def path_replace(path): break return path + def path_replace_reverse(path): for path_mapping in path_mappings: if path_mapping[1] in path: @@ -413,6 +417,7 @@ def path_replace_reverse(path): break return path + def path_replace_movie(path): for path_mapping in path_mappings_movie: if path_mapping[0] in path: @@ -424,6 +429,7 @@ def path_replace_movie(path): break return path + def path_replace_reverse_movie(path): for path_mapping in path_mappings_movie: if path_mapping[1] in path: @@ -435,6 +441,7 @@ def path_replace_reverse_movie(path): 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) @@ -445,6 +452,7 @@ def pp_replace(pp_command, episode, subtitles, language, language_code2, languag pp_command = pp_command.replace('{{subtitles_language_code3}}', language_code3) return pp_command + result = get_general_settings() ip = result[0] port = result[1] @@ -471,4 +479,4 @@ page_size = result[21] minimum_score_movie = result[22] use_embedded_subs = result[23] only_monitored = result[24] -adaptive_searching = result[25] \ No newline at end of file +adaptive_searching = result[25] diff --git a/bazarr/get_subtitle.py b/bazarr/get_subtitle.py index 7f16cd251..a85eae490 100644 --- a/bazarr/get_subtitle.py +++ b/bazarr/get_subtitle.py @@ -1,4 +1,4 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 @@ -7,6 +7,8 @@ import logging import operator import subprocess import time +import cPickle as pickle +import codecs import subliminal import subliminal_patch from datetime import datetime, timedelta @@ -18,13 +20,13 @@ from subliminal_patch.score import compute_score from subliminal.subtitle import get_subtitle_path from get_languages import language_from_alpha3, alpha2_from_alpha3, alpha3_from_alpha2 from bs4 import UnicodeDammit -from get_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 -import cPickle as pickle -import codecs from get_providers import get_providers, get_providers_auth +from get_args import args # configure the cache @@ -108,7 +110,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, """ try: - if sceneName == "None" or use_scenename is False: + if sceneName == "None" or not use_scenename: used_sceneName = False video = parse_video(path, None, providers=providers) else: @@ -131,7 +133,8 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, else: subtitles_list = [] try: - sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], key=operator.itemgetter(1), reverse=True) + sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], + key=operator.itemgetter(1), reverse=True) except Exception as e: logging.exception('BAZARR Exception raised while trying to compute score for this file: ' + path) return None @@ -158,27 +161,32 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, if any(elem in required for elem in not_matched): continue subtitles_list.append(s) - logging.debug('BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path) + logging.debug( + 'BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path) if len(subtitles_list) > 0: try: pdownload_result = False for subtitle in subtitles_list: download_result = p.download_subtitle(subtitle) if download_result == True: - logging.debug('BAZARR Subtitles file downloaded from ' + str(subtitle.provider_name) + ' for this file: ' + path) + logging.debug('BAZARR Subtitles file downloaded from ' + str( + subtitle.provider_name) + ' for this file: ' + path) break else: - logging.warning('BAZARR Subtitles file skipped from ' + str(subtitle.provider_name) + ' for this file: ' + path + ' because no content was returned by the provider (probably throttled).') + logging.warning('BAZARR Subtitles file skipped from ' + str( + subtitle.provider_name) + ' for this file: ' + path + ' because no content was returned by the provider (probably throttled).') continue if download_result == False: - logging.error('BAZARR Tried to download a subtitles for file: ' + path + " but we weren't able to do it this time (probably being throttled). Going to retry on next search.") + logging.error( + 'BAZARR Tried to download a subtitles for file: ' + path + " but we weren't able to do it this time (probably being throttled). Going to retry on next search.") return None except Exception as e: logging.exception('BAZARR Error downloading subtitles for this file ' + path) return None else: try: - calculated_score = round(float(compute_score(subtitle, video, hearing_impaired=hi)) / max_score * 100, 2) + calculated_score = round( + float(compute_score(subtitle, video, hearing_impaired=hi)) / max_score * 100, 2) if used_sceneName == True: video = parse_video(path, None, providers=providers) single = get_general_settings()[7] @@ -197,20 +205,25 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, downloaded_path = get_subtitle_path(path, language=language_set) logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) if used_sceneName == True: - message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using this scene name: " + sceneName + message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode( + calculated_score) + "% using this scene name: " + sceneName else: - message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using filename guessing." + message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode( + calculated_score) + "% using filename guessing." if use_postprocessing is True: - command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) + command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, + downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': - codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() @@ -219,12 +232,14 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, except: if out == "": - logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') + logging.error( + 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out) else: if out == "": - logging.info('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') + logging.info( + 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out) @@ -234,6 +249,7 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, return None logging.debug('BAZARR Ended searching subtitles for file: ' + path) + def manual_search(path, language, hi, providers, providers_auth, sceneName, media_type): logging.debug('BAZARR Manually searching subtitles for this file: ' + path) if hi == "True": @@ -253,7 +269,7 @@ def manual_search(path, language, hi, providers, providers_auth, sceneName, medi postprocessing_cmd = get_general_settings()[11] try: - if sceneName == "None" or use_scenename is False: + if sceneName == "None" or not use_scenename: used_sceneName = False video = parse_video(path, None, providers=providers) else: @@ -296,12 +312,17 @@ def manual_search(path, language, hi, providers, providers_auth, sceneName, medi continue if used_sceneName: not_matched.remove('hash') - subtitles_list.append(dict(score=round((compute_score(s, video, hearing_impaired=hi) / max_score * 100), 2), language=alpha2_from_alpha3(s.language.alpha3), hearing_impaired=str(s.hearing_impaired), provider=s.provider_name, subtitle=codecs.encode(pickle.dumps(s), "base64").decode(), url=s.page_link, matches=list(matched), dont_matches=list(not_matched))) + subtitles_list.append( + dict(score=round((compute_score(s, video, hearing_impaired=hi) / max_score * 100), 2), + language=alpha2_from_alpha3(s.language.alpha3), hearing_impaired=str(s.hearing_impaired), + provider=s.provider_name, subtitle=codecs.encode(pickle.dumps(s), "base64").decode(), + url=s.page_link, matches=list(matched), dont_matches=list(not_matched))) subtitles_dict = {} subtitles_dict = sorted(subtitles_list, key=lambda x: x['score'], reverse=True) logging.debug('BAZARR ' + str(len(subtitles_dict)) + " subtitles have been found for this file: " + path) logging.debug('BAZARR Ended searching subtitles for this file: ' + path) - return(subtitles_dict) + return (subtitles_dict) + def manual_download_subtitle(path, language, hi, subtitle, provider, providers_auth, sceneName, media_type): logging.debug('BAZARR Manually downloading subtitles for this file: ' + path) @@ -325,7 +346,7 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a lang_obj = Language(language) try: - if sceneName is None or use_scenename is False: + if sceneName is None or not use_scenename: used_sceneName = False video = parse_video(path, None, providers={provider}) else: @@ -362,18 +383,22 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, language=lang_obj) logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) - message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(score) + "% using manual search." + message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode( + score) + "% using manual search." if use_postprocessing is True: - command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) + command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, + downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': - codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate() encoding = out_codepage.split(':')[-1].strip() - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() @@ -382,40 +407,48 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a except: if out == "": - logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') + logging.error( + 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out) else: if out == "": - logging.info('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') + logging.info( + 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution') else: logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out) return message else: - logging.error('BAZARR Tried to manually download a subtitles for file: ' + path + " but we weren't able to do (probably throttled by ' + str(subtitle.provider_name) + '. Please retry later or select a subtitles from another provider.") + logging.error( + 'BAZARR Tried to manually download a subtitles for file: ' + path + " but we weren't able to do (probably throttled by ' + str(subtitle.provider_name) + '. Please retry later or select a subtitles from another provider.") return None logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path) + def series_download_subtitles(no): if get_general_settings()[24] is True: monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - episodes_details = c_db.execute('SELECT path, missing_subtitles, sonarrEpisodeId, scene_name FROM table_episodes WHERE sonarrSeriesId = ? AND missing_subtitles != "[]"' + monitored_only_query_string, (no,)).fetchall() + episodes_details = c_db.execute( + 'SELECT path, missing_subtitles, sonarrEpisodeId, scene_name FROM table_episodes WHERE sonarrSeriesId = ? AND missing_subtitles != "[]"' + monitored_only_query_string, + (no,)).fetchall() series_details = c_db.execute("SELECT hearing_impaired FROM table_shows WHERE sonarrSeriesId = ?", (no,)).fetchone() c_db.close() - + providers_list = get_providers() providers_auth = get_providers_auth() - + for episode in episodes_details: for language in ast.literal_eval(episode[1]): if language is not None: - message = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), series_details[0], providers_list, providers_auth, str(episode[3]), 'series') + message = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), + series_details[0], providers_list, providers_auth, str(episode[3]), + 'series') if message is not None: store_subtitles(path_replace(episode[0])) history_log(1, no, episode[2], message) @@ -424,9 +457,11 @@ def series_download_subtitles(no): def movies_download_subtitles(no): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - movie = c_db.execute("SELECT path, missing_subtitles, radarrId, sceneName, hearing_impaired FROM table_movies WHERE radarrId = ?", (no,)).fetchone() + movie = c_db.execute( + "SELECT path, missing_subtitles, radarrId, sceneName, hearing_impaired FROM table_movies WHERE radarrId = ?", + (no,)).fetchone() c_db.close() providers_list = get_providers() @@ -434,7 +469,8 @@ def movies_download_subtitles(no): for language in ast.literal_eval(movie[1]): if language is not None: - message = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], providers_list, providers_auth, str(movie[3]), 'movie') + message = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], + providers_list, providers_auth, str(movie[3]), 'movie') if message is not None: store_subtitles_movie(path_replace_movie(movie[0])) history_log_movie(1, no, message) @@ -443,14 +479,16 @@ def movies_download_subtitles(no): def wanted_download_subtitles(path): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - episodes_details = c_db.execute("SELECT table_episodes.path, table_episodes.missing_subtitles, table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, table_shows.hearing_impaired, table_episodes.scene_name, table_episodes.failedAttempts FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.path = ? AND missing_subtitles != '[]'", (path_replace_reverse(path),)).fetchall() + episodes_details = c_db.execute( + "SELECT table_episodes.path, table_episodes.missing_subtitles, table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, table_shows.hearing_impaired, table_episodes.scene_name, table_episodes.failedAttempts FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.path = ? AND missing_subtitles != '[]'", + (path_replace_reverse(path),)).fetchall() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() - + for episode in episodes_details: attempt = episode[6] if type(attempt) == unicode: @@ -463,30 +501,36 @@ def wanted_download_subtitles(path): att = zip(*attempt)[0] if language not in att: attempt.append([language, time.time()]) - - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - c_db.execute('UPDATE table_episodes SET failedAttempts = ? WHERE sonarrEpisodeId = ?', (unicode(attempt), episode[2])) + c_db.execute('UPDATE table_episodes SET failedAttempts = ? WHERE sonarrEpisodeId = ?', + (unicode(attempt), episode[2])) conn_db.commit() c_db.close() - + for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]) is True: - message = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), episode[4], providers_list, providers_auth, str(episode[5]), 'series') + message = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), + episode[4], providers_list, providers_auth, str(episode[5]), + 'series') if message is not None: store_subtitles(path_replace(episode[0])) list_missing_subtitles(episode[3]) history_log(1, episode[3], episode[2], message) send_notifications(episode[3], episode[2], message) else: - logging.debug('BAZARR Search is not active for episode ' + episode[0] + ' Language: ' + attempt[i][0]) + logging.debug( + 'BAZARR Search is not active for episode ' + episode[0] + ' Language: ' + attempt[i][0]) def wanted_download_subtitles_movie(path): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - movies_details = c_db.execute("SELECT path, missing_subtitles, radarrId, radarrId, hearing_impaired, sceneName, failedAttempts FROM table_movies WHERE path = ? AND missing_subtitles != '[]'", (path_replace_reverse_movie(path),)).fetchall() + movies_details = c_db.execute( + "SELECT path, missing_subtitles, radarrId, radarrId, hearing_impaired, sceneName, failedAttempts FROM table_movies WHERE path = ? AND missing_subtitles != '[]'", + (path_replace_reverse_movie(path),)).fetchall() c_db.close() providers_list = get_providers() @@ -504,28 +548,30 @@ def wanted_download_subtitles_movie(path): att = zip(*attempt)[0] if language not in att: attempt.append([language, time.time()]) - - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() c_db.execute('UPDATE table_movies SET failedAttempts = ? WHERE radarrId = ?', (unicode(attempt), movie[2])) conn_db.commit() c_db.close() - + for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]) is True: - message = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], providers_list, providers_auth, str(movie[5]), 'movie') + message = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), + movie[4], providers_list, providers_auth, str(movie[5]), 'movie') if message is not None: store_subtitles_movie(path_replace_movie(movie[0])) list_missing_subtitles_movies(movie[3]) history_log_movie(1, movie[3], message) send_notifications_movie(movie[3], message) else: - logging.info('BAZARR Search is not active for movie ' + movie[0] + ' Language: ' + attempt[i][0]) + logging.info( + 'BAZARR Search is not active for movie ' + movie[0] + ' Language: ' + attempt[i][0]) def wanted_search_missing_subtitles(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace) db.create_function("path_substitution_movie", 1, path_replace_movie) c = db.cursor() @@ -535,10 +581,12 @@ def wanted_search_missing_subtitles(): else: monitored_only_query_string = "" - c.execute("SELECT path_substitution(path) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string) + c.execute( + "SELECT path_substitution(path) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string) episodes = c.fetchall() - c.execute("SELECT path_substitution_movie(path) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string) + c.execute( + "SELECT path_substitution_movie(path) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string) movies = c.fetchall() c.close() @@ -554,7 +602,7 @@ def wanted_search_missing_subtitles(): wanted_download_subtitles_movie(movie[0]) logging.info('BAZARR Finished searching for missing subtitles. Check histories for more information.') - + def search_active(timestamp): if get_general_settings()[25] is True: diff --git a/bazarr/init.py b/bazarr/init.py index 8078a48a1..8b11acb3a 100644 --- a/bazarr/init.py +++ b/bazarr/init.py @@ -1,31 +1,36 @@ +# coding=utf-8 + import os import sqlite3 import logging +import time +from cork import Cork from configparser import ConfigParser -from get_argv import config_dir +from get_args import args -# Check if config_dir exist -if os.path.exists(config_dir) is False: +# Check if args.config_dir exist +if not os.path.exists(args.config_dir): # Create config_dir directory tree try: - os.mkdir(os.path.join(config_dir)) + os.mkdir(os.path.join(args.config_dir)) logging.debug("BAZARR Created data directory") except OSError: - logging.exception("BAZARR The configuration directory doesn't exist and Bazarr cannot create it (permission issue?).") + logging.exception( + "BAZARR 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')) +if not os.path.exists(os.path.join(args.config_dir, 'config')): + os.mkdir(os.path.join(args.config_dir, 'config')) logging.debug("BAZARR Created config folder") -if os.path.exists(os.path.join(config_dir, 'db')) is False: - os.mkdir(os.path.join(config_dir, 'db')) +if not os.path.exists(os.path.join(args.config_dir, 'db')): + os.mkdir(os.path.join(args.config_dir, 'db')) logging.debug("BAZARR Created db folder") -if os.path.exists(os.path.join(config_dir, 'log')) is False: - os.mkdir(os.path.join(config_dir, 'log')) +if not os.path.exists(os.path.join(args.config_dir, 'log')): + os.mkdir(os.path.join(args.config_dir, 'log')) logging.debug("BAZARR Created log folder") -config_file = os.path.normpath(os.path.join(config_dir, 'config/config.ini')) +config_file = os.path.normpath(os.path.join(args.config_dir, 'config', 'config.ini')) cfg = ConfigParser() try: @@ -37,7 +42,7 @@ try: fd.close() # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Execute script and commit change to database @@ -59,18 +64,16 @@ except Exception: if cfg.has_section('auth'): if cfg.has_option('auth', 'enabled'): enabled = cfg.getboolean('auth', 'enabled') - if enabled is True: + if enabled: cfg.set('auth', 'type', 'basic') - elif enabled is False: + else: cfg.set('auth', 'type', 'None') cfg.remove_option('auth', 'enabled') with open(config_file, 'w+') as configfile: cfg.write(configfile) -from cork import Cork -import time -if os.path.exists(os.path.normpath(os.path.join(config_dir, 'config/users.json'))) is False: - cork = Cork(os.path.normpath(os.path.join(config_dir, 'config')), initialize=True) +if not os.path.exists(os.path.normpath(os.path.join(args.config_dir, 'config', 'users.json'))): + cork = Cork(os.path.normpath(os.path.join(args.config_dir, 'config')), initialize=True) cork._store.roles[''] = 100 cork._store.save_roles() diff --git a/bazarr/libs.py b/bazarr/libs.py new file mode 100644 index 000000000..6c2a92c2c --- /dev/null +++ b/bazarr/libs.py @@ -0,0 +1,11 @@ +# coding=utf-8 + +import sys +import os + + +def set_libs(): + sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../libs/')) + + +set_libs() diff --git a/bazarr/list_subtitles.py b/bazarr/list_subtitles.py index fc27f9689..719982409 100644 --- a/bazarr/list_subtitles.py +++ b/bazarr/list_subtitles.py @@ -1,24 +1,27 @@ -from get_argv import config_dir +# coding=utf-8 import gc import os import enzyme import babelfish import logging -import subliminal -import subliminal_patch -from subliminal import core import sqlite3 import ast import langdetect +import subliminal +import subliminal_patch +from subliminal import core from bs4 import UnicodeDammit from itertools import islice -from get_settings import path_replace_reverse, path_replace, path_replace_reverse_movie, path_replace_movie, get_general_settings +from get_args import args +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() + def store_subtitles(file): # languages = [] actual_subtitles = [] @@ -27,17 +30,16 @@ def store_subtitles(file): try: with open(file, 'rb') as f: mkv = enzyme.MKV(f) - + for subtitle_track in mkv.subtitle_tracks: try: if alpha2_from_alpha3(subtitle_track.language) != None: - actual_subtitles.append([str(alpha2_from_alpha3(subtitle_track.language)),None]) + actual_subtitles.append([str(alpha2_from_alpha3(subtitle_track.language)), None]) except: pass except: pass - brazilian_portuguese = [".pt-br", ".pob", "pb"] try: subtitles = core.search_external_subtitles(file) @@ -46,9 +48,11 @@ def store_subtitles(file): else: for subtitle, language in subtitles.iteritems(): if str(os.path.splitext(subtitle)[0]).lower().endswith(tuple(brazilian_portuguese)) is True: - actual_subtitles.append([str("pb"), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append( + [str("pb"), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))]) elif str(language) != 'und': - actual_subtitles.append([str(language), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append( + [str(language), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))]) else: with open(path_replace(os.path.join(os.path.dirname(file), subtitle)), 'r') as f: text = list(islice(f, 100)) @@ -57,16 +61,21 @@ def store_subtitles(file): try: text = text.decode(encoding.original_encoding) except Exception as e: - logging.exception('BAZARR Error trying to detect character encoding for this subtitles file: ' + path_replace(os.path.join(os.path.dirname(file), subtitle)) + ' You should try to delete this subtitles file manually and ask Bazarr to download it again.') + logging.exception( + 'BAZARR Error trying to detect character encoding for this subtitles file: ' + path_replace( + os.path.join(os.path.dirname(file), + subtitle)) + ' You should try to delete this subtitles file manually and ask Bazarr to download it again.') else: detected_language = langdetect.detect(text) if len(detected_language) > 0: - actual_subtitles.append([str(detected_language), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append([str(detected_language), path_replace_reverse( + os.path.join(os.path.dirname(file), subtitle))]) - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - c_db.execute("UPDATE table_episodes SET subtitles = ? WHERE path = ?", (str(actual_subtitles), path_replace_reverse(file))) + c_db.execute("UPDATE table_episodes SET subtitles = ? WHERE path = ?", + (str(actual_subtitles), path_replace_reverse(file))) conn_db.commit() c_db.close() @@ -97,9 +106,11 @@ def store_subtitles_movie(file): for subtitle, language in subtitles.iteritems(): if str(os.path.splitext(subtitle)[0]).lower().endswith(tuple(brazilian_portuguese)) is True: - actual_subtitles.append([str("pb"), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append( + [str("pb"), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))]) elif str(language) != 'und': - actual_subtitles.append([str(language), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append( + [str(language), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))]) else: if os.path.splitext(subtitle)[1] != ".sub": with open(path_replace_movie(os.path.join(os.path.dirname(file), subtitle)), 'r') as f: @@ -109,16 +120,21 @@ def store_subtitles_movie(file): try: text = text.decode(encoding.original_encoding) except Exception as e: - logging.exception('BAZARR Error trying to detect character encoding for this subtitles file: ' + path_replace_movie(os.path.join(os.path.dirname(file), subtitle)) + ' You should try to delete this subtitles file manually and ask Bazarr to download it again.') + logging.exception( + 'BAZARR Error trying to detect character encoding for this subtitles file: ' + path_replace_movie( + os.path.join(os.path.dirname(file), + subtitle)) + ' You should try to delete this subtitles file manually and ask Bazarr to download it again.') else: detected_language = langdetect.detect(text) if len(detected_language) > 0: - actual_subtitles.append([str(detected_language), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))]) + actual_subtitles.append([str(detected_language), path_replace_reverse_movie( + os.path.join(os.path.dirname(file), subtitle))]) - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - c_db.execute("UPDATE table_movies SET subtitles = ? WHERE path = ?", (str(actual_subtitles), path_replace_reverse_movie(file))) + c_db.execute("UPDATE table_movies SET subtitles = ? WHERE path = ?", + (str(actual_subtitles), path_replace_reverse_movie(file))) conn_db.commit() c_db.close() @@ -132,9 +148,10 @@ def list_missing_subtitles(*no): query_string = " WHERE table_shows.sonarrSeriesId = " + str(no[0]) except: pass - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - episodes_subtitles = c_db.execute("SELECT table_episodes.sonarrEpisodeId, table_episodes.subtitles, table_shows.languages FROM table_episodes INNER JOIN table_shows on table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId" + query_string).fetchall() + episodes_subtitles = c_db.execute( + "SELECT table_episodes.sonarrEpisodeId, table_episodes.subtitles, table_shows.languages FROM table_episodes INNER JOIN table_shows on table_episodes.sonarrSeriesId = table_shows.sonarrSeriesId" + query_string).fetchall() c_db.close() missing_subtitles_global = [] @@ -165,10 +182,11 @@ def list_missing_subtitles(*no): actual_subtitles_list.append(item[0]) missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list)) missing_subtitles_global.append(tuple([str(missing_subtitles), episode_subtitles[0]])) - - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - c_db.executemany("UPDATE table_episodes SET missing_subtitles = ? WHERE sonarrEpisodeId = ?", (missing_subtitles_global)) + c_db.executemany("UPDATE table_episodes SET missing_subtitles = ? WHERE sonarrEpisodeId = ?", + (missing_subtitles_global)) conn_db.commit() c_db.close() @@ -179,7 +197,7 @@ def list_missing_subtitles_movies(*no): query_string = " WHERE table_movies.radarrId = " + str(no[0]) except: pass - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movies_subtitles = c_db.execute("SELECT radarrId, subtitles, languages FROM table_movies" + query_string).fetchall() c_db.close() @@ -213,14 +231,15 @@ def list_missing_subtitles_movies(*no): missing_subtitles = list(set(desired_subtitles) - set(actual_subtitles_list)) missing_subtitles_global.append(tuple([str(missing_subtitles), movie_subtitles[0]])) - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() c_db.executemany("UPDATE table_movies SET missing_subtitles = ? WHERE radarrId = ?", (missing_subtitles_global)) conn_db.commit() c_db.close() + def series_full_scan_subtitles(): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() episodes = c_db.execute("SELECT path FROM table_episodes").fetchall() c_db.close() @@ -230,8 +249,9 @@ def series_full_scan_subtitles(): gc.collect() + def movies_full_scan_subtitles(): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movies = c_db.execute("SELECT path FROM table_movies").fetchall() c_db.close() @@ -241,12 +261,13 @@ def movies_full_scan_subtitles(): gc.collect() + def series_scan_subtitles(no): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() episodes = c_db.execute("SELECT path FROM table_episodes WHERE sonarrSeriesId = ?", (no,)).fetchall() c_db.close() - + for episode in episodes: store_subtitles(path_replace(episode[0])) @@ -254,7 +275,7 @@ def series_scan_subtitles(no): def movies_scan_subtitles(no): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movies = c_db.execute("SELECT path FROM table_movies WHERE radarrId = ?", (no,)).fetchall() c_db.close() diff --git a/bazarr/main.py b/bazarr/main.py index 5d4b6a927..6e42ce00c 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1,30 +1,27 @@ -bazarr_version = '0.6.7' +# coding=utf-8 import gc -gc.enable() - -from get_argv import config_dir, no_update, console_debug - -import os import sys -reload(sys) -sys.setdefaultencoding('utf8') -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../libs/')) - import os -import sys import signal import sqlite3 +import logging +import libs + +from get_args import args from init import * from update_db import * from notifier import update_notifier -update_notifier() - - from get_settings import get_general_settings, get_proxy_settings -import logging from logging.handlers import TimedRotatingFileHandler +reload(sys) +sys.setdefaultencoding('utf8') +gc.enable() +update_notifier() + +bazarr_version = '0.6.7' + log_level = get_general_settings()[4] if log_level is None: log_level = "INFO" @@ -36,7 +33,7 @@ class OneLineExceptionFormatter(logging.Formatter): 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 + return repr(result) # or format into one line however you want to def format(self, record): s = super(OneLineExceptionFormatter, self).format(record) @@ -45,8 +42,13 @@ class OneLineExceptionFormatter(logging.Formatter): return s +fh = None + + def configure_logging(console_debug=False): - fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, backupCount=7) + global fh + fh = TimedRotatingFileHandler(os.path.join(args.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) @@ -74,13 +76,14 @@ def configure_logging(console_debug=False): root.addHandler(sh) -configure_logging(console_debug=console_debug) - +configure_logging(console_debug=args.debug) import requests + if get_proxy_settings()[0] != 'None': if get_proxy_settings()[3] != '' and get_proxy_settings()[4] != '': - proxy = get_proxy_settings()[0] + '://' + get_proxy_settings()[3] + ':' + get_proxy_settings()[4] + '@' + get_proxy_settings()[1] + ':' + get_proxy_settings()[2] + proxy = get_proxy_settings()[0] + '://' + get_proxy_settings()[3] + ':' + get_proxy_settings()[4] + '@' + \ + get_proxy_settings()[1] + ':' + get_proxy_settings()[2] else: proxy = get_proxy_settings()[0] + '://' + get_proxy_settings()[1] + ':' + get_proxy_settings()[2] os.environ['HTTP_PROXY'] = str(proxy) @@ -89,6 +92,7 @@ if get_proxy_settings()[0] != 'None': from bottle import route, run, template, static_file, request, redirect, response, HTTPError, app, hook import bottle + bottle.TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(__file__), '../views/')) bottle.debug(True) bottle.TEMPLATES.clear() @@ -112,21 +116,25 @@ from six import text_type from get_languages import load_language_in_db, language_from_alpha3 from get_providers import load_providers, get_providers, get_providers_auth + load_providers() from get_series import * from get_episodes import * from get_settings import base_url, ip, port, path_replace, path_replace_movie -if no_update is False: + +if not args.no_update: 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, manual_search, manual_download_subtitle +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, manual_search, manual_download_subtitle 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) +conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = conn.cursor() c.execute("UPDATE system SET configured = 0, updated = 0") conn.commit() @@ -137,7 +145,7 @@ load_language_in_db() from get_settings import get_auth_settings -aaa = Cork(os.path.normpath(os.path.join(config_dir, 'config'))) +aaa = Cork(os.path.normpath(os.path.join(args.config_dir, 'config'))) app = app() session_opts = { @@ -166,8 +174,10 @@ def custom_auth_basic(check): return func(*a, **ka) return wrapper + return decorator + def check_credentials(user, pw): from get_settings import get_auth_settings @@ -180,7 +190,7 @@ def check_credentials(user, pw): def authorize(): if login_auth == 'form': - aaa = Cork(os.path.normpath(os.path.join(config_dir, 'config'))) + aaa = Cork(os.path.normpath(os.path.join(args.config_dir, 'config'))) aaa.require(fail_redirect=(base_url + 'login')) @@ -201,7 +211,7 @@ def login_form(): @route(base_url + 'login', method='POST') def login(): - aaa = Cork(os.path.normpath(os.path.join(config_dir, 'config'))) + aaa = Cork(os.path.normpath(os.path.join(args.config_dir, 'config'))) username = post_get('username') password = post_get('password') aaa.login(username, password, success_redirect=base_url, fail_redirect=(base_url + 'login?msg=fail')) @@ -216,12 +226,13 @@ def logout(): @custom_auth_basic(check_credentials) def redirect_root(): authorize() - redirect (base_url) + redirect(base_url) + @route(base_url + 'shutdown') def shutdown(): try: - stop_file = open(os.path.join(config_dir, "bazarr.stop"), "w") + stop_file = open(os.path.join(args.config_dir, "bazarr.stop"), "w") except Exception as e: logging.error('BAZARR Cannot create bazarr.stop file.') else: @@ -229,6 +240,7 @@ def shutdown(): stop_file.close() server.stop() + @route(base_url + 'restart') def restart(): try: @@ -237,7 +249,7 @@ def restart(): logging.error('BAZARR Cannot stop CherryPy.') else: try: - restart_file = open(os.path.join(config_dir, "bazarr.restart"), "w") + restart_file = open(os.path.join(args.config_dir, "bazarr.restart"), "w") except Exception as e: logging.error('BAZARR Cannot create bazarr.restart file.') else: @@ -251,16 +263,16 @@ def restart(): @custom_auth_basic(check_credentials) def wizard(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() settings_languages = c.execute("SELECT * FROM table_settings_languages ORDER BY name").fetchall() settings_providers = c.execute("SELECT * FROM table_settings_providers ORDER BY name").fetchall() c.close() - + settings_general = get_general_settings() settings_sonarr = get_sonarr_settings() settings_radarr = get_radarr_settings() - + return template('wizard', __file__=__file__, bazarr_version=bazarr_version, settings_general=settings_general, settings_languages=settings_languages, settings_providers=settings_providers, settings_sonarr=settings_sonarr, settings_radarr=settings_radarr, base_url=base_url) @@ -270,14 +282,14 @@ def wizard(): @custom_auth_basic(check_credentials) def save_wizard(): authorize() - - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + conn = sqlite3.connect(os.path.join(args.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') - if settings_general_baseurl.endswith('/') is False: + if not settings_general_baseurl.endswith('/'): settings_general_baseurl += '/' settings_general_sourcepath = request.forms.getall('settings_general_sourcepath') settings_general_destpath = request.forms.getall('settings_general_destpath') @@ -308,12 +320,12 @@ def save_wizard(): settings_general_use_radarr = 'False' else: settings_general_use_radarr = 'True' - + cfg = ConfigParser() - + if not cfg.has_section('general'): cfg.add_section('general') - + 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)) @@ -334,24 +346,24 @@ def save_wizard(): cfg.set('general', 'use_embedded_subs', text_type(get_general_settings()[23])) cfg.set('general', 'only_monitored', text_type(get_general_settings()[24])) cfg.set('general', 'adaptive_searching', text_type(settings_general_adaptive_searching)) - + if not cfg.has_section('proxy'): cfg.add_section('proxy') - + cfg.set('proxy', 'type', text_type(get_proxy_settings()[0])) cfg.set('proxy', 'url', text_type(get_proxy_settings()[1])) cfg.set('proxy', 'port', text_type(get_proxy_settings()[2])) cfg.set('proxy', 'username', text_type(get_proxy_settings()[3])) cfg.set('proxy', 'password', text_type(get_proxy_settings()[4])) cfg.set('proxy', 'exclude', text_type(get_proxy_settings()[5])) - + if not cfg.has_section('auth'): cfg.add_section('auth') - + cfg.set('auth', 'type', text_type(get_auth_settings()[0])) cfg.set('auth', 'username', text_type(get_auth_settings()[1])) cfg.set('auth', 'password', text_type(get_auth_settings()[2])) - + 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') @@ -361,17 +373,17 @@ def save_wizard(): else: settings_sonarr_ssl = 'True' settings_sonarr_apikey = request.forms.get('settings_sonarr_apikey') - + if not cfg.has_section('sonarr'): cfg.add_section('sonarr') - + 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(get_sonarr_settings()[5])) - + 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') @@ -385,73 +397,73 @@ def save_wizard(): cfg.set('general', 'use_radarr', 'True') else: cfg.set('general', 'use_radarr', 'False') - + if not cfg.has_section('radarr'): cfg.add_section('radarr') - + 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(get_radarr_settings()[5])) - + settings_subliminal_providers = request.forms.getall('settings_subliminal_providers') c.execute("UPDATE table_settings_providers SET enabled = 0") for item in settings_subliminal_providers: c.execute("UPDATE table_settings_providers SET enabled = '1' WHERE name = ?", (item,)) - + settings_subliminal_languages = request.forms.getall('settings_subliminal_languages') c.execute("UPDATE table_settings_languages SET enabled = 0") for item in settings_subliminal_languages: c.execute("UPDATE table_settings_languages SET enabled = '1' WHERE code2 = ?", (item,)) - + 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, 'w+') as f: cfg.write(f) - + logging.info('Config file created successfully') - + conn.commit() c.close() - + configured() redirect(base_url) @@ -461,6 +473,7 @@ def save_wizard(): 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(): @@ -472,11 +485,13 @@ def emptylog(): redirect(ref) + @route(base_url + 'bazarr.log') @custom_auth_basic(check_credentials) def download_log(): authorize() - return static_file('bazarr.log', root=os.path.join(config_dir, 'log/'), download='bazarr.log') + return static_file('bazarr.log', root=os.path.join(args.config_dir, 'log/'), download='bazarr.log') + @route(base_url + 'image_proxy/', method='GET') @custom_auth_basic(check_credentials) @@ -487,7 +502,8 @@ def image_proxy(url): apikey = get_sonarr_settings()[4] url_image = url_sonarr_short + '/' + url + '?apikey=' + apikey try: - image_buffer = BytesIO(requests.get(url_sonarr + '/api' + url_image.split(url_sonarr)[1], timeout=15, verify=False).content) + image_buffer = BytesIO( + requests.get(url_sonarr + '/api' + url_image.split(url_sonarr)[1], timeout=15, verify=False).content) except: return None else: @@ -496,6 +512,7 @@ def image_proxy(url): response.set_header('Content-type', 'image/jpeg') return bytes + @route(base_url + 'image_proxy_movies/', method='GET') @custom_auth_basic(check_credentials) def image_proxy_movies(url): @@ -505,10 +522,12 @@ def image_proxy_movies(url): apikey = get_radarr_settings()[4] try: url_image = (url_radarr_short + '/' + url + '?apikey=' + apikey).replace('/fanart.jpg', '/banner.jpg') - image_buffer = BytesIO(requests.get(url_radarr + '/api' + url_image.split(url_radarr)[1], timeout=15, verify=False).content) + image_buffer = BytesIO( + requests.get(url_radarr + '/api' + url_image.split(url_radarr)[1], timeout=15, verify=False).content) except: url_image = url_radarr_short + '/' + url + '?apikey=' + apikey - image_buffer = BytesIO(requests.get(url_radarr + '/api' + url_image.split(url_radarr)[1], timeout=15, verify=False).content) + image_buffer = BytesIO( + requests.get(url_radarr + '/api' + url_image.split(url_radarr)[1], timeout=15, verify=False).content) else: image_buffer.seek(0) bytes = image_buffer.read() @@ -524,7 +543,7 @@ def redirect_root(): redirect(base_url + 'series') elif get_general_settings()[13] is True: redirect(base_url + 'movies') - elif os.path.exists(os.path.join(config_dir, 'config/config.ini')) is False: + elif not os.path.exists(os.path.join(args.config_dir, 'config', 'config.ini')): redirect(base_url + 'wizard') else: redirect(base_url + 'settings') @@ -535,11 +554,11 @@ def redirect_root(): def series(): authorize() single_language = get_general_settings()[7] - - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + db = sqlite3.connect(os.path.join(args.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] @@ -549,19 +568,23 @@ def series(): page_size = int(get_general_settings()[21]) offset = (int(page) - 1) * page_size max_page = int(math.ceil(missing_count / (page_size + 0.0))) - + if get_general_settings()[24] is True: monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" - - 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,)) + + 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 '[]'" + monitored_only_query_string + " GROUP BY table_shows.sonarrSeriesId") + 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 '[]'" + monitored_only_query_string + " 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'" + monitored_only_query_string + " GROUP BY table_shows.sonarrSeriesId") + 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'" + monitored_only_query_string + " GROUP BY table_shows.sonarrSeriesId") total_subtitles_list = c.fetchall() c.close() output = template('series', __file__=__file__, bazarr_version=bazarr_version, rows=data, @@ -577,7 +600,7 @@ def serieseditor(): authorize() single_language = get_general_settings()[7] - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace) c = db.cursor() @@ -585,12 +608,15 @@ def serieseditor(): 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") + 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, current_port=port) + 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, + current_port=port) return output @@ -598,9 +624,9 @@ def serieseditor(): @custom_auth_basic(check_credentials) def search_json(query): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - + search_list = [] if get_general_settings()[12] is True: c.execute("SELECT title, sonarrSeriesId FROM table_shows WHERE title LIKE ? ORDER BY title", @@ -608,14 +634,14 @@ def search_json(query): series = c.fetchall() for serie in series: search_list.append(dict([('name', serie[0]), ('url', base_url + 'episodes/' + str(serie[1]))])) - + if get_general_settings()[13] is True: c.execute("SELECT title, radarrId FROM table_movies WHERE title LIKE ? ORDER BY title", ('%' + query + '%',)) movies = c.fetchall() for movie in movies: search_list.append(dict([('name', movie[0]), ('url', base_url + 'movie/' + str(movie[1]))])) c.close() - + response.content_type = 'application/json' return dict(items=search_list) @@ -649,9 +675,10 @@ def edit_series(no): else: hi = "False" - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.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)) + c.execute("UPDATE table_shows SET languages = ?, hearing_impaired = ? WHERE sonarrSeriesId LIKE ?", + (str(lang), hi, no)) conn.commit() c.close() @@ -659,6 +686,7 @@ def edit_series(no): redirect(ref) + @route(base_url + 'edit_serieseditor', method='POST') @custom_auth_basic(check_credentials) def edit_serieseditor(): @@ -670,7 +698,7 @@ def edit_serieseditor(): lang = request.forms.getall('languages') hi = request.forms.get('hearing_impaired') - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = conn.cursor() for serie in series: @@ -691,6 +719,7 @@ def edit_serieseditor(): redirect(ref) + @route(base_url + 'episodes/', method='GET') @custom_auth_basic(check_credentials) def episodes(no): @@ -698,24 +727,31 @@ 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 = sqlite3.connect(os.path.join(args.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() + 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() + 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)): + 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, current_port=port) + 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, current_port=port) + @route(base_url + 'movies') @custom_auth_basic(check_credentials) @@ -723,7 +759,7 @@ def movies(): authorize() single_language = get_general_settings()[7] - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace_movie) c = db.cursor() @@ -737,21 +773,26 @@ def movies(): 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,)) + 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, current_port=port) + 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, current_port=port) return output + @route(base_url + 'movieseditor') @custom_auth_basic(check_credentials) def movieseditor(): authorize() single_language = get_general_settings()[7] - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace_movie) c = db.cursor() @@ -759,14 +800,18 @@ def movieseditor(): 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") + 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, current_port=port) + 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, + current_port=port) return output + @route(base_url + 'edit_movieseditor', method='POST') @custom_auth_basic(check_credentials) def edit_movieseditor(): @@ -778,7 +823,7 @@ def edit_movieseditor(): lang = request.forms.getall('languages') hi = request.forms.get('hearing_impaired') - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = conn.cursor() for movie in movies: @@ -799,6 +844,7 @@ def edit_movieseditor(): redirect(ref) + @route(base_url + 'edit_movie/', method='POST') @custom_auth_basic(check_credentials) def edit_movie(no): @@ -821,7 +867,7 @@ def edit_movie(no): else: hi = "False" - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.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() @@ -831,6 +877,7 @@ def edit_movie(no): redirect(ref) + @route(base_url + 'movie/', method='GET') @custom_auth_basic(check_credentials) def movie(no): @@ -838,18 +885,23 @@ 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 = sqlite3.connect(os.path.join(args.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() + 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, current_port=port) + 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, + current_port=port) + @route(base_url + 'scan_disk/', method='GET') @custom_auth_basic(check_credentials) @@ -861,6 +913,7 @@ def scan_disk(no): redirect(ref) + @route(base_url + 'scan_disk_movie/', method='GET') @custom_auth_basic(check_credentials) def scan_disk_movie(no): @@ -871,6 +924,7 @@ def scan_disk_movie(no): redirect(ref) + @route(base_url + 'search_missing_subtitles/', method='GET') @custom_auth_basic(check_credentials) def search_missing_subtitles(no): @@ -881,6 +935,7 @@ def search_missing_subtitles(no): redirect(ref) + @route(base_url + 'search_missing_subtitles_movie/', method='GET') @custom_auth_basic(check_credentials) def search_missing_subtitles_movie(no): @@ -891,17 +946,19 @@ def search_missing_subtitles_movie(no): redirect(ref) + @route(base_url + 'history') @custom_auth_basic(check_credentials) def history(): authorize() return template('history', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url, current_port=port) + @route(base_url + 'historyseries') @custom_auth_basic(check_credentials) def historyseries(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() c.execute("SELECT COUNT(*) FROM table_history") @@ -929,17 +986,22 @@ def historyseries(): 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,)) + 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, current_port=port) + 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, + current_port=port) + @route(base_url + 'historymovies') @custom_auth_basic(check_credentials) def historymovies(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() c.execute("SELECT COUNT(*) FROM table_history_movie") @@ -967,11 +1029,16 @@ def historymovies(): 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,)) + 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, current_port=port) + 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, + current_port=port) + @route(base_url + 'wanted') @custom_auth_basic(check_credentials) @@ -979,11 +1046,12 @@ def wanted(): authorize() return template('wanted', __file__=__file__, bazarr_version=bazarr_version, base_url=base_url, current_port=port) + @route(base_url + 'wantedseries') @custom_auth_basic(check_credentials) def wantedseries(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace) c = db.cursor() @@ -1002,16 +1070,21 @@ def wantedseries(): 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,)) + 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, current_port=port) + 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, + current_port=port) + @route(base_url + 'wantedmovies') @custom_auth_basic(check_credentials) def wantedmovies(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace_movie) c = db.cursor() @@ -1030,10 +1103,15 @@ def wantedmovies(): 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,)) + 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, current_port=port) + 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, + current_port=port) + @route(base_url + 'wanted_search_missing_subtitles') @custom_auth_basic(check_credentials) @@ -1045,11 +1123,12 @@ def wanted_search_missing_subtitles_list(): redirect(ref) + @route(base_url + 'settings') @custom_auth_basic(check_credentials) def settings(): authorize() - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() c.execute("SELECT * FROM table_settings_languages ORDER BY name") settings_languages = c.fetchall() @@ -1059,14 +1138,20 @@ def settings(): settings_notifier = c.fetchall() c.close() - from get_settings import get_general_settings, get_proxy_settings, get_auth_settings, get_radarr_settings, get_sonarr_settings + from get_settings import get_general_settings, get_proxy_settings, get_auth_settings, get_radarr_settings, \ + get_sonarr_settings settings_general = get_general_settings() settings_proxy = get_proxy_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_proxy=settings_proxy, 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, current_port=port) + return template('settings', __file__=__file__, bazarr_version=bazarr_version, settings_general=settings_general, + settings_proxy=settings_proxy, 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, + current_port=port) + @route(base_url + 'save_settings', method='POST') @custom_auth_basic(check_credentials) @@ -1074,13 +1159,13 @@ def save_settings(): authorize() ref = request.environ['HTTP_REFERER'] - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.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') - if settings_general_baseurl.endswith('/') is False: + if not settings_general_baseurl.endswith('/'): settings_general_baseurl += '/' settings_general_loglevel = request.forms.get('settings_general_loglevel') settings_general_sourcepath = request.forms.getall('settings_general_sourcepath') @@ -1090,7 +1175,8 @@ def save_settings(): 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_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: @@ -1144,8 +1230,14 @@ def save_settings(): 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)) + 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() @@ -1177,7 +1269,7 @@ def save_settings(): if after != before: configured() get_general_settings() - + settings_proxy = get_proxy_settings() if not cfg.has_section('proxy'): @@ -1189,7 +1281,7 @@ def save_settings(): settings_proxy_username = request.forms.get('settings_proxy_username') settings_proxy_password = request.forms.get('settings_proxy_password') settings_proxy_exclude = request.forms.get('settings_proxy_exclude') - + before_proxy_password = (unicode(settings_proxy[0]), unicode(settings_proxy[5])) if before_proxy_password[0] != settings_proxy_type: configured() @@ -1223,7 +1315,7 @@ def save_settings(): cfg.set('auth', 'username', text_type(settings_auth_username)) cfg.set('auth', 'password', hashlib.md5(settings_auth_password).hexdigest()) if settings_auth_username not in aaa._store.users: - cork = Cork(os.path.normpath(os.path.join(config_dir, 'config')), initialize=True) + cork = Cork(os.path.normpath(os.path.join(args.config_dir, 'config')), initialize=True) cork._store.roles[''] = 100 cork._store.save_roles() cork._store.users[settings_auth_username] = { @@ -1289,13 +1381,16 @@ def save_settings(): 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)) + 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)) + 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)) + 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") @@ -1367,21 +1462,24 @@ def save_settings(): redirect(ref) + @route(base_url + 'check_update') @custom_auth_basic(check_credentials) def check_update(): authorize() ref = request.environ['HTTP_REFERER'] - if no_update is False: + if not args.no_update: check_and_apply_update() redirect(ref) + @route(base_url + 'system') @custom_auth_basic(check_credentials) def system(): authorize() + def get_time_from_interval(interval): interval_clean = interval.split('[') interval_clean = interval_clean[1][:-1] @@ -1460,7 +1558,6 @@ def system(): return text - task_list = [] for job in scheduler.get_jobs(): if job.next_run_time is not None: @@ -1474,7 +1571,7 @@ def system(): 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: + with open(os.path.join(args.config_dir, 'log', 'bazarr.log')) as f: for i, l in enumerate(f, 1): pass row_count = i @@ -1496,9 +1593,11 @@ def system(): logging.exception("BAZARR Error trying to get releases from Github.") else: for release in r.json(): - releases.append([release['name'],release['body']]) + releases.append([release['name'], release['body']]) + + 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, releases=releases, current_port=port) - 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, releases=releases, current_port=port) @route(base_url + 'logs/') @custom_auth_basic(check_credentials) @@ -1508,12 +1607,13 @@ def get_logs(page): 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()): + for line in reversed(open(os.path.join(args.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, current_port=port) + @route(base_url + 'execute/') @custom_auth_basic(check_credentials) def execute_task(taskid): @@ -1592,6 +1692,7 @@ def get_subtitle(): except OSError: pass + @route(base_url + 'manual_search', method='POST') @custom_auth_basic(check_credentials) def manual_search_json(): @@ -1609,6 +1710,7 @@ def manual_search_json(): data = manual_search(episodePath, language, hi, providers_list, providers_auth, sceneName, 'series') return dict(data=data) + @route(base_url + 'manual_get_subtitle', method='POST') @custom_auth_basic(check_credentials) def manual_get_subtitle(): @@ -1628,7 +1730,8 @@ def manual_get_subtitle(): providers_auth = get_providers_auth() try: - result = manual_download_subtitle(episodePath, language, hi, subtitle, selected_provider, providers_auth, sceneName, 'series') + result = manual_download_subtitle(episodePath, language, hi, subtitle, selected_provider, providers_auth, + sceneName, 'series') if result is not None: history_log(1, sonarrSeriesId, sonarrEpisodeId, result) send_notifications(sonarrSeriesId, sonarrEpisodeId, result) @@ -1638,6 +1741,7 @@ def manual_get_subtitle(): except OSError: pass + @route(base_url + 'get_subtitle_movie', method='POST') @custom_auth_basic(check_credentials) def get_subtitle_movie(): @@ -1665,6 +1769,7 @@ def get_subtitle_movie(): except OSError: pass + @route(base_url + 'manual_search_movie', method='POST') @custom_auth_basic(check_credentials) def manual_search_movie_json(): @@ -1682,6 +1787,7 @@ def manual_search_movie_json(): data = manual_search(moviePath, language, hi, providers_list, providers_auth, sceneName, 'movie') return dict(data=data) + @route(base_url + 'manual_get_subtitle_movie', method='POST') @custom_auth_basic(check_credentials) def manual_get_subtitle_movie(): @@ -1700,7 +1806,8 @@ def manual_get_subtitle_movie(): providers_auth = get_providers_auth() try: - result = manual_download_subtitle(moviePath, language, hi, subtitle, selected_provider, providers_auth, sceneName, 'movie') + result = manual_download_subtitle(moviePath, language, hi, subtitle, selected_provider, providers_auth, + sceneName, 'movie') if result is not None: history_log_movie(1, radarrId, result) send_notifications_movie(radarrId, result) @@ -1710,45 +1817,55 @@ def manual_get_subtitle_movie(): except OSError: pass + def configured(): - conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn = sqlite3.connect(os.path.join(args.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/series/wanted') def api_wanted(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.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() + 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/series/history') def api_history(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.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() + 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) + @route(base_url + 'api/movies/wanted') def api_wanted(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - data = c.execute("SELECT table_movies.title, table_movies.missing_subtitles FROM table_movies WHERE table_movies.missing_subtitles != '[]' ORDER BY table_movies._rowid_ DESC").fetchall() + data = c.execute( + "SELECT table_movies.title, table_movies.missing_subtitles FROM table_movies WHERE table_movies.missing_subtitles != '[]' ORDER BY table_movies._rowid_ DESC").fetchall() c.close() return dict(subtitles=data) + @route(base_url + 'api/movies/history') def api_history(): - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - data = c.execute("SELECT table_movies.title, strftime('%Y-%m-%d', datetime(table_history_movie.timestamp, 'unixepoch')), table_history_movie.description FROM table_history_movie INNER JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId WHERE table_history_movie.action = '1' ORDER BY id DESC").fetchall() + data = c.execute( + "SELECT table_movies.title, strftime('%Y-%m-%d', datetime(table_history_movie.timestamp, 'unixepoch')), table_history_movie.description FROM table_history_movie INNER JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId WHERE table_history_movie.action = '1' ORDER BY id DESC").fetchall() c.close() return dict(subtitles=data) + @route(base_url + 'test_url//', method='GET') @custom_auth_basic(check_credentials) def test_url(protocol, url): @@ -1760,7 +1877,9 @@ def test_url(protocol, url): else: return dict(status=True, version=result) + import warnings + # Mute DeprecationWarning warnings.simplefilter("ignore", DeprecationWarning) diff --git a/bazarr/notifier.py b/bazarr/notifier.py index 52d7533c1..8dbf566a0 100644 --- a/bazarr/notifier.py +++ b/bazarr/notifier.py @@ -1,22 +1,24 @@ -from get_argv import config_dir +# coding=utf-8 import apprise import os import sqlite3 import logging +from get_args import args + def update_notifier(): # define apprise object a = apprise.Apprise() - + # Retrieve all of the details results = a.details() - + notifiers_new = [] notifiers_old = [] - - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() notifiers_current = c_db.execute('SELECT name FROM table_settings_notifier').fetchall() for x in results['schemas']: @@ -26,51 +28,56 @@ def update_notifier(): else: notifiers_old.append(x['service_name']) notifier_current = [i[0] for i in notifiers_current] - + notifiers_to_delete = list(set(notifier_current) - set(notifiers_old)) - + for notifier_new in notifiers_new: c_db.execute('INSERT INTO `table_settings_notifier` (name, enabled) VALUES (?, ?);', (notifier_new, '0')) - + for notifier_to_delete in notifiers_to_delete: c_db.execute('DELETE FROM `table_settings_notifier` WHERE name=?', (notifier_to_delete,)) - + conn_db.commit() c_db.close() def get_notifier_providers(): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() providers = c_db.execute('SELECT name, url FROM table_settings_notifier WHERE enabled = 1').fetchall() c_db.close() return providers + def get_series_name(sonarrSeriesId): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() data = c_db.execute('SELECT title FROM table_shows WHERE sonarrSeriesId = ?', (sonarrSeriesId,)).fetchone() c_db.close() return data[0] + def get_episode_name(sonarrEpisodeId): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() - data = c_db.execute('SELECT title, season, episode FROM table_episodes WHERE sonarrEpisodeId = ?', (sonarrEpisodeId,)).fetchone() + data = c_db.execute('SELECT title, season, episode FROM table_episodes WHERE sonarrEpisodeId = ?', + (sonarrEpisodeId,)).fetchone() c_db.close() return data[0], data[1], data[2] + def get_movies_name(radarrId): - conn_db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() data = c_db.execute('SELECT title FROM table_movies WHERE radarrId = ?', (radarrId,)).fetchone() c_db.close() return data[0] + def send_notifications(sonarrSeriesId, sonarrEpisodeId, message): providers = get_notifier_providers() series = get_series_name(sonarrSeriesId) @@ -84,7 +91,8 @@ def send_notifications(sonarrSeriesId, sonarrEpisodeId, message): apobj.notify( title='Bazarr notification', - body=(series + ' - S' + str(episode[1]).zfill(2) + 'E' + str(episode[2]).zfill(2) + ' - ' + episode[0] + ' : ' + message), + body=(series + ' - S' + str(episode[1]).zfill(2) + 'E' + str(episode[2]).zfill(2) + ' - ' + episode[ + 0] + ' : ' + message), ) @@ -101,4 +109,4 @@ def send_notifications_movie(radarrId, message): apobj.notify( title='Bazarr notification', body=movie + ' : ' + message, - ) \ No newline at end of file + ) diff --git a/bazarr/scheduler.py b/bazarr/scheduler.py index 0a2f3a351..356a1d66c 100644 --- a/bazarr/scheduler.py +++ b/bazarr/scheduler.py @@ -1,4 +1,4 @@ -from get_argv import no_update +# coding=utf-8 from get_settings import get_general_settings, automatic, get_radarr_settings, get_sonarr_settings from get_series import update_series @@ -6,7 +6,9 @@ from get_episodes import update_all_episodes, update_all_movies, sync_episodes from get_movies import update_movies from list_subtitles import store_subtitles from get_subtitle import wanted_search_missing_subtitles -if no_update is False: +from get_args import args + +if not args.no_update: from check_update import check_and_apply_update from apscheduler.schedulers.background import BackgroundScheduler @@ -24,32 +26,37 @@ def sonarr_full_update(): full_update = get_sonarr_settings()[5] if full_update == "Daily": scheduler.add_job(update_all_episodes, CronTrigger(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) + misfire_grace_time=15, id='update_all_episodes', + name='Update all episodes subtitles from disk', replace_existing=True) elif full_update == "Weekly": - scheduler.add_job(update_all_episodes, CronTrigger(day_of_week='sun'), 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) + scheduler.add_job(update_all_episodes, CronTrigger(day_of_week='sun'), 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 == "Manually": scheduler.add_job(update_all_episodes, CronTrigger(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) + misfire_grace_time=15, id='update_all_episodes', + name='Update all episodes subtitles from disk', replace_existing=True) def radarr_full_update(): if integration[13] is True: full_update = get_radarr_settings()[5] if full_update == "Daily": - scheduler.add_job(update_all_movies, CronTrigger(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) + scheduler.add_job(update_all_movies, CronTrigger(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": scheduler.add_job(update_all_movies, CronTrigger(day_of_week='sun'), 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) + misfire_grace_time=15, id='update_all_movies', + name='Update all movies subtitles from disk', + replace_existing=True) elif full_update == "Manually": scheduler.add_job(update_all_movies, CronTrigger(year='2100'), 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) + misfire_grace_time=15, id='update_all_movies', + name='Update all movies subtitles from disk', + replace_existing=True) def execute_now(taskid): @@ -61,25 +68,32 @@ if str(get_localzone()) == "local": else: scheduler = BackgroundScheduler() -if no_update is False: +if not args.no_update: if automatic is True: - scheduler.add_job(check_and_apply_update, IntervalTrigger(hours=6), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_bazarr', name='Update bazarr from source on Github') + scheduler.add_job(check_and_apply_update, IntervalTrigger(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, CronTrigger(year='2100'), hour=4, id='update_bazarr', name='Update bazarr from source on Github') + scheduler.add_job(check_and_apply_update, CronTrigger(year='2100'), hour=4, id='update_bazarr', + name='Update bazarr from source on Github') if integration[12] is True: - scheduler.add_job(update_series, IntervalTrigger(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, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, id='sync_episodes', name='Sync episodes with Sonarr') + scheduler.add_job(update_series, IntervalTrigger(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, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, + id='sync_episodes', name='Sync episodes with Sonarr') if integration[13] is True: - scheduler.add_job(update_movies, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, id='update_movies', name='Update movies list from Radarr') + scheduler.add_job(update_movies, IntervalTrigger(minutes=5), max_instances=1, coalesce=True, misfire_grace_time=15, + id='update_movies', name='Update movies list from Radarr') if integration[12] is True or integration[13] is True: - scheduler.add_job(wanted_search_missing_subtitles, IntervalTrigger(hours=3), max_instances=1, coalesce=True, misfire_grace_time=15, id='wanted_search_missing_subtitles', name='Search for wanted subtitles') + scheduler.add_job(wanted_search_missing_subtitles, IntervalTrigger(hours=3), max_instances=1, coalesce=True, + misfire_grace_time=15, id='wanted_search_missing_subtitles', name='Search for wanted subtitles') sonarr_full_update() radarr_full_update() scheduler.start() + def shutdown_scheduler(): - scheduler.shutdown(wait=True) \ No newline at end of file + scheduler.shutdown(wait=True) diff --git a/bazarr/update_db.py b/bazarr/update_db.py index 1b6d5297b..935f83eb6 100644 --- a/bazarr/update_db.py +++ b/bazarr/update_db.py @@ -1,14 +1,16 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 +from get_args import args + # Check if database exist -if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: +if os.path.exists(os.path.join(args.config_dir, 'db', 'bazarr.db')): # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - + # Execute tables modifications try: c.execute('alter table table_settings_providers add column "username" "text"') @@ -55,7 +57,6 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: except: pass - # Commit change to db db.commit() @@ -100,4 +101,4 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: if integration[13] is True: execute_now('update_movies') - db.close() \ No newline at end of file + db.close() diff --git a/bazarr/utils.py b/bazarr/utils.py index 10acfebdc..8d20bc1f6 100644 --- a/bazarr/utils.py +++ b/bazarr/utils.py @@ -1,30 +1,37 @@ -from get_argv import config_dir +# coding=utf-8 import os import sqlite3 import time +from get_args import args + + def history_log(action, sonarrSeriesId, sonarrEpisodeId, description): # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Get Sonarr API URL from database config table - history = c.execute('''INSERT INTO table_history(action, sonarrSeriesId, sonarrEpisodeId, timestamp, description) VALUES (?, ?, ?, ?, ?)''', (action, sonarrSeriesId, sonarrEpisodeId, time.time(), description)) + history = c.execute( + '''INSERT INTO table_history(action, sonarrSeriesId, sonarrEpisodeId, timestamp, description) VALUES (?, ?, ?, ?, ?)''', + (action, sonarrSeriesId, sonarrEpisodeId, time.time(), description)) # Commit changes to DB db.commit() - + # Close database connection db.close() def history_log_movie(action, radarrId, description): # Open database connection - db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() - history = c.execute('''INSERT INTO table_history_movie(action, radarrId, timestamp, description) VALUES (?, ?, ?, ?)''', (action, radarrId, time.time(), description)) + history = c.execute( + '''INSERT INTO table_history_movie(action, radarrId, timestamp, description) VALUES (?, ?, ?, ?)''', + (action, radarrId, time.time(), description)) # Commit changes to DB db.commit() diff --git a/views/menu.tpl b/views/menu.tpl index 997b1a452..bc79aba23 100644 --- a/views/menu.tpl +++ b/views/menu.tpl @@ -32,7 +32,7 @@ % monitored_only_query_string = "" %end - % conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + % conn = sqlite3.connect(os.path.join(config_dir, 'db', 'bazarr.db'), timeout=30) % 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() diff --git a/views/wanted.tpl b/views/wanted.tpl index c980f585e..ca27d110f 100644 --- a/views/wanted.tpl +++ b/views/wanted.tpl @@ -56,7 +56,7 @@ % monitored_only_query_string = "" %end - % conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) + % conn = sqlite3.connect(os.path.join(config_dir, 'db', 'bazarr.db'), timeout=30) % 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()