From c21c2869f70b2aed1d33675a4e46b7358e3d719f Mon Sep 17 00:00:00 2001 From: Halali Date: Thu, 25 Oct 2018 12:06:33 +0200 Subject: [PATCH 01/41] Initial commit --- bazarr/logger.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ bazarr/main.py | 39 +------------------ views/logs.tpl | 14 ++++--- 3 files changed, 107 insertions(+), 43 deletions(-) create mode 100644 bazarr/logger.py diff --git a/bazarr/logger.py b/bazarr/logger.py new file mode 100644 index 000000000..d44cfdaf2 --- /dev/null +++ b/bazarr/logger.py @@ -0,0 +1,97 @@ +import os +import sys +import logging +import re + +from logging.handlers import TimedRotatingFileHandler +from get_argv import config_dir +from get_settings import get_general_settings + +log_level = get_general_settings()[4] +if log_level is None: + log_level = "INFO" + + +class OneLineExceptionFormatter(logging.Formatter): + def formatException(self, exc_info): + """ + Format an exception so that it prints on a single line. + """ + result = super(OneLineExceptionFormatter, self).formatException(exc_info) + return repr(result) # or format into one line however you want to + + def format(self, record): + s = super(OneLineExceptionFormatter, self).format(record) + if record.exc_text: + s = s.replace('\n', '') + '|' + return s + + +class NoExceptionFormatter(logging.Formatter): + def format(self, record): + record.exc_text = '' # ensure formatException gets called + return super(NoExceptionFormatter, self).format(record) + + def formatException(self, record): + return '' + + +def configure_logging(): + log = logging.getLogger() + log.handlers = [] + + global fh + fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, + backupCount=7) + f = OneLineExceptionFormatter('%(asctime)s|%(levelname)-8s|%(name)-32s|%(message)s|', + '%d/%m/%Y %H:%M:%S') + fh.setFormatter(f) + fh.addFilter(BlacklistFilter()) + logging.getLogger("enzyme").setLevel(logging.CRITICAL) + logging.getLogger("apscheduler").setLevel(logging.WARNING) + if log_level == 'debug': + logging.getLogger("subliminal").setLevel(logging.DEBUG) + else: + logging.getLogger("subliminal").setLevel(logging.CRITICAL) + logging.getLogger("guessit").setLevel(logging.WARNING) + logging.getLogger("rebulk").setLevel(logging.WARNING) + logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) + log.setLevel(log_level) + log.addHandler(fh) + + ch = logging.StreamHandler() + cf = NoExceptionFormatter('%(asctime)s - %(levelname)s :: %(message)s', + '%Y-%m-%d %H:%M:%S') + ch.setFormatter(cf) + ch.setLevel(logging.INFO) + log.addHandler(ch) + + +class BlacklistFilter(logging.Filter): + """ + Log filter for blacklisted tokens and passwords + """ + def __init__(self): + pass + + def filter(self, record): + try: + apikeys = re.findall(r'apikey(?:=|%3D)([a-zA-Z0-9]+)', record.msg) + for apikey in apikeys: + record.msg = record.msg.replace(apikey, 8 * '*' + apikey[-2:]) + + args = [] + for arg in record.args: + apikeys = re.findall(r'apikey(?:=|%3D)([a-zA-Z0-9]+)', arg) if isinstance(arg, basestring) else [] + for apikey in apikeys: + arg = arg.replace(apikey, 8 * '*' + apikey[-2:]) + args.append(arg) + record.args = tuple(args) + except: + pass + return True + + +def empty_log(): + fh.doRollover() + diff --git a/bazarr/main.py b/bazarr/main.py index 8d37e45e0..a922b5f9a 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -21,42 +21,7 @@ from update_db import * from get_settings import get_general_settings, get_proxy_settings import logging -from logging.handlers import TimedRotatingFileHandler - -log_level = get_general_settings()[4] -if log_level is None: - log_level = "INFO" - -class OneLineExceptionFormatter(logging.Formatter): - def formatException(self, exc_info): - """ - Format an exception so that it prints on a single line. - """ - result = super(OneLineExceptionFormatter, self).formatException(exc_info) - return repr(result) # or format into one line however you want to - - def format(self, record): - s = super(OneLineExceptionFormatter, self).format(record) - if record.exc_text: - s = s.replace('\n', '') + '|' - return s - -def configure_logging(): - global fh - fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, backupCount=7) - f = OneLineExceptionFormatter('%(asctime)s|%(levelname)s|%(message)s|', - '%d/%m/%Y %H:%M:%S') - fh.setFormatter(f) - logging.getLogger("enzyme").setLevel(logging.CRITICAL) - logging.getLogger("apscheduler").setLevel(logging.WARNING) - logging.getLogger("subliminal").setLevel(logging.CRITICAL) - logging.getLogger("guessit").setLevel(logging.WARNING) - logging.getLogger("rebulk").setLevel(logging.WARNING) - logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) - root = logging.getLogger() - root.setLevel(log_level) - root.addHandler(fh) - +from logger import configure_logging, empty_log configure_logging() import requests @@ -449,7 +414,7 @@ def emptylog(): authorize() ref = request.environ['HTTP_REFERER'] - fh.doRollover() + empty_log() logging.info('BAZARR Log file emptied') redirect(ref) diff --git a/views/logs.tpl b/views/logs.tpl index ea8fe473f..b8ec92f0a 100644 --- a/views/logs.tpl +++ b/views/logs.tpl @@ -34,25 +34,27 @@ %line = log.split('|') \\ %try: -{{line[2]}}\\ +{{line[3]}}\\ %except: \\ %end From 1b8efc890a4c7cfa8525e01692f890208badd801 Mon Sep 17 00:00:00 2001 From: Halali Date: Thu, 25 Oct 2018 13:56:02 +0200 Subject: [PATCH 02/41] Change debug logging level settings --- bazarr/logger.py | 9 +++++++-- bazarr/main.py | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bazarr/logger.py b/bazarr/logger.py index d44cfdaf2..9173fedd9 100644 --- a/bazarr/logger.py +++ b/bazarr/logger.py @@ -47,12 +47,17 @@ def configure_logging(): '%d/%m/%Y %H:%M:%S') fh.setFormatter(f) fh.addFilter(BlacklistFilter()) - logging.getLogger("enzyme").setLevel(logging.CRITICAL) - logging.getLogger("apscheduler").setLevel(logging.WARNING) + if log_level == 'debug': + logging.getLogger("apscheduler").setLevel(logging.DEBUG) logging.getLogger("subliminal").setLevel(logging.DEBUG) + logging.getLogger("git").setLevel(logging.DEBUG) + logging.getLogger("apprise").setLevel(logging.DEBUG) else: + logging.getLogger("apscheduler").setLevel(logging.WARNING) logging.getLogger("subliminal").setLevel(logging.CRITICAL) + + logging.getLogger("enzyme").setLevel(logging.CRITICAL) logging.getLogger("guessit").setLevel(logging.WARNING) logging.getLogger("rebulk").setLevel(logging.WARNING) logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) diff --git a/bazarr/main.py b/bazarr/main.py index a922b5f9a..ba8d62636 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -188,7 +188,7 @@ def restart(): except Exception as e: logging.error('BAZARR Cannot create bazarr.restart file.') else: - print 'Bazarr is being restarted...' + # print 'Bazarr is being restarted...' logging.info('Bazarr is being restarted...') restart_file.write('') restart_file.close() @@ -1895,7 +1895,7 @@ warnings.simplefilter("ignore", DeprecationWarning) server = CherryPyWSGIServer((str(ip), int(port)), app) try: logging.info('BAZARR is started and waiting for request on http://' + str(ip) + ':' + str(port) + str(base_url)) - print 'Bazarr is started and waiting for request on http://' + str(ip) + ':' + str(port) + str(base_url) + # print 'Bazarr is started and waiting for request on http://' + str(ip) + ':' + str(port) + str(base_url) server.start() except KeyboardInterrupt: shutdown() From 5ff8baa19cfc1ac7e426184931e22bb7a6884bef Mon Sep 17 00:00:00 2001 From: Halali Date: Tue, 30 Oct 2018 19:06:30 +0100 Subject: [PATCH 03/41] Change Log_level settings to Debug checkbox --- bazarr/get_settings.py | 12 ++++++------ bazarr/init.py | 7 +++++++ bazarr/logger.py | 19 ++++++++++++++----- bazarr/main.py | 10 +++++++--- views/settings.tpl | 20 +++++++++++--------- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/bazarr/get_settings.py b/bazarr/get_settings.py index ebe291686..038cbb583 100644 --- a/bazarr/get_settings.py +++ b/bazarr/get_settings.py @@ -39,10 +39,10 @@ def get_general_settings(): else: path_mappings = '[]' - if cfg.has_option('general', 'log_level'): - log_level = cfg.get('general', 'log_level') + if cfg.has_option('general', 'debug'): + debug = cfg.getboolean('general', 'debug') else: - log_level = 'INFO' + debug = False if cfg.has_option('general', 'branch'): branch = cfg.get('general', 'branch') @@ -154,7 +154,7 @@ def get_general_settings(): port = '6767' base_url = '/' path_mappings = '[]' - log_level = 'INFO' + debug = False branch = 'master' auto_update = True single_language = False @@ -177,7 +177,7 @@ 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, debug, 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(): @@ -450,7 +450,7 @@ ip = result[0] port = result[1] base_url = result[2] path_mappings = ast.literal_eval(result[3]) -log_level = result[4] +debug = result[4] branch = result[5] automatic = result[6] single_language = result[7] diff --git a/bazarr/init.py b/bazarr/init.py index 8078a48a1..633b9347b 100644 --- a/bazarr/init.py +++ b/bazarr/init.py @@ -66,6 +66,13 @@ if cfg.has_section('auth'): cfg.remove_option('auth', 'enabled') with open(config_file, 'w+') as configfile: cfg.write(configfile) + +if cfg.has_section('general'): + if cfg.has_option('general', 'log_level'): + cfg.remove_option('general', 'log_level') + cfg.set('general', 'debug', 'False') + with open(config_file, 'w+') as configfile: + cfg.write(configfile) from cork import Cork import time diff --git a/bazarr/logger.py b/bazarr/logger.py index 9173fedd9..c558d554f 100644 --- a/bazarr/logger.py +++ b/bazarr/logger.py @@ -7,10 +7,11 @@ from logging.handlers import TimedRotatingFileHandler from get_argv import config_dir from get_settings import get_general_settings -log_level = get_general_settings()[4] -if log_level is None: +debug = get_general_settings()[4] +if debug is False: log_level = "INFO" - +else: + log_level = "DEBUG" class OneLineExceptionFormatter(logging.Formatter): def formatException(self, exc_info): @@ -48,7 +49,7 @@ def configure_logging(): fh.setFormatter(f) fh.addFilter(BlacklistFilter()) - if log_level == 'debug': + if debug is True: logging.getLogger("apscheduler").setLevel(logging.DEBUG) logging.getLogger("subliminal").setLevel(logging.DEBUG) logging.getLogger("git").setLevel(logging.DEBUG) @@ -63,11 +64,19 @@ def configure_logging(): logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) log.setLevel(log_level) log.addHandler(fh) - + + # Console logging ch = logging.StreamHandler() cf = NoExceptionFormatter('%(asctime)s - %(levelname)s :: %(message)s', '%Y-%m-%d %H:%M:%S') ch.setFormatter(cf) + + logging.getLogger("apscheduler").setLevel(logging.WARNING) + logging.getLogger("subliminal").setLevel(logging.CRITICAL) + logging.getLogger("enzyme").setLevel(logging.CRITICAL) + logging.getLogger("guessit").setLevel(logging.WARNING) + logging.getLogger("rebulk").setLevel(logging.WARNING) + logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) ch.setLevel(logging.INFO) log.addHandler(ch) diff --git a/bazarr/main.py b/bazarr/main.py index ba8d62636..782748fc3 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1029,7 +1029,11 @@ def save_settings(): settings_general_baseurl = request.forms.get('settings_general_baseurl') if settings_general_baseurl.endswith('/') is False: settings_general_baseurl += '/' - settings_general_loglevel = request.forms.get('settings_general_loglevel') + settings_general_debug = request.forms.get('settings_general_debug') + if settings_general_debug is None: + settings_general_debug = 'False' + else: + settings_general_debug = 'True' settings_general_sourcepath = request.forms.getall('settings_general_sourcepath') settings_general_destpath = request.forms.getall('settings_general_destpath') settings_general_pathmapping = [] @@ -1092,7 +1096,7 @@ 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)) + after = (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_debug), 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() @@ -1104,7 +1108,7 @@ def save_settings(): cfg.set('general', 'port', text_type(settings_general_port)) cfg.set('general', 'base_url', text_type(settings_general_baseurl)) cfg.set('general', 'path_mappings', text_type(settings_general_pathmapping)) - cfg.set('general', 'log_level', text_type(settings_general_loglevel)) + cfg.set('general', 'debug', text_type(settings_general_debug)) cfg.set('general', 'branch', text_type(settings_general_branch)) cfg.set('general', 'auto_update', text_type(settings_general_automatic)) cfg.set('general', 'single_language', text_type(settings_general_single_language)) diff --git a/views/settings.tpl b/views/settings.tpl index b698ce56b..fac299492 100644 --- a/views/settings.tpl +++ b/views/settings.tpl @@ -135,17 +135,13 @@
- +
- +
+ + +
+
+
About
+
+
+
+
+ +
+
+
+
+ {{bazarr_version}} +
+
+
+
+
+
+ +
+
+
+
+ {{operation_system}} +
+
+
+
+ % from get_settings import get_general_settings + % if get_general_settings()[12]: +
+
+ +
+
+
+
+ {{sonarr_version}} +
+
+
+
+ % end + % if get_general_settings()[13]: +
+
+ +
+
+
+
+ {{radarr_version}} +
+
+
+
+ % end +
+
+ +
+
+
+
+ {{python_version}} +
+
+
+
+
+
+ +
+
+
+
+ {{config_dir}} +
+
+
+
+
+
+ +
+
+
+
+ {{bazarr_dir}} +
+
+
+
+
+
+
More info
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
%for release in releases: From 280b43711678966fa21994258acaa3fe758c9204 Mon Sep 17 00:00:00 2001 From: Halali Date: Fri, 2 Nov 2018 22:14:36 +0100 Subject: [PATCH 06/41] Add Logout to system tab --- views/system.tpl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/views/system.tpl b/views/system.tpl index b99903153..903074320 100644 --- a/views/system.tpl +++ b/views/system.tpl @@ -49,6 +49,10 @@
+ % from get_settings import get_auth_settings + % if get_auth_settings()[0] != 'None': +
+ % end
- %enabled_providers = [] %for provider in settings_providers: @@ -1205,7 +1205,7 @@
- %enabled_languages = [] %for language in settings_languages: @@ -1251,7 +1251,7 @@
- %if settings_general[7] is False: %else: @@ -1308,7 +1308,7 @@
- %if settings_general[7] is False: %else: diff --git a/views/wizard.tpl b/views/wizard.tpl index ca5e2f941..0ab7ecd0a 100644 --- a/views/wizard.tpl +++ b/views/wizard.tpl @@ -347,7 +347,7 @@
- %enabled_providers = [] %for provider in settings_providers: @@ -390,7 +390,7 @@
- %enabled_languages = [] %for language in settings_languages: @@ -436,7 +436,7 @@
- %if settings_general[7] is False: %else: @@ -493,7 +493,7 @@
- %if settings_general[7] is False: %else: From 675bacc78d9ccee10c1ce1dac4c43e43c9061cbe Mon Sep 17 00:00:00 2001 From: Halali Date: Sat, 3 Nov 2018 22:56:24 +0100 Subject: [PATCH 08/41] Add tooltips for scenename, filename and adaptive searching in episode and wanted episode --- bazarr/main.py | 4 ++-- views/episodes.tpl | 43 +++++++++++++++++++++++++++++++++--------- views/wantedseries.tpl | 27 ++++++++++++++++++++++---- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 8c6e18520..9a1f987c3 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -690,7 +690,7 @@ def episodes(no): 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, failedAttempts 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() @@ -986,7 +986,7 @@ 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, table_episodes.failedAttempts FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.missing_subtitles != '[]'" + monitored_only_query_string + " ORDER BY table_episodes._rowid_ DESC LIMIT ? OFFSET ?", (page_size, offset,)) 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) diff --git a/views/episodes.tpl b/views/episodes.tpl index 7314e3946..74d9f0947 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -51,7 +51,7 @@ padding-left: 2em; padding-right: 2em; padding-bottom: 1em; - overflow-x:auto; + overflow-x: auto; } .ui.basic.button:hover, .ui.basic.buttons .button:hover { background: transparent !important; @@ -165,6 +165,7 @@ Episode + Title Existing
subtitles Missing
subtitles @@ -182,7 +183,12 @@ %end {{episode[3]}} - {{episode[0]}} + + % if episode[8] is not None: + + % end + + {{episode[0]}} %if episode[4] is not None: % actual_languages = ast.literal_eval(episode[4]) @@ -208,7 +214,7 @@ %end - %try: + %try: %if episode[6] is not None: % missing_languages = ast.literal_eval(episode[6]) % missing_languages.sort() @@ -216,15 +222,34 @@ % missing_languages = None %end %if missing_languages is not None: + %from get_subtitle import search_active + %from get_settings import get_general_settings %for language in missing_languages: - - {{language}} - + %if episode[10] is not None and get_general_settings()[25]: + %for lang in ast.literal_eval(episode[10]): + %if language in lang: + %active = search_active(lang[1]) + %if active: + + {{language}} + + %else: + + {{language}} + + %end + %end + %end + %else: + + {{language}} + + %end - %end + %end %end - %except: - %pass + %except: + %pass %end diff --git a/views/wantedseries.tpl b/views/wantedseries.tpl index 8e1977632..53de62342 100644 --- a/views/wantedseries.tpl +++ b/views/wantedseries.tpl @@ -78,11 +78,30 @@ %missing_languages = ast.literal_eval(row[3]) %if missing_languages is not None: + %from get_subtitle import search_active + %from get_settings import get_general_settings %for language in missing_languages: - - {{language}} - - + %if row[9] is not None and get_general_settings()[25]: + %for lang in ast.literal_eval(row[9]): + %if language in lang: + %active = search_active(lang[1]) + %if active: + + {{language}} + + %else: + + {{language}} + + %end + %end + %end + %else: + + {{language}} + + %end + %end %end From 8c91494e647179252a04dc1f193a0d1549d555db Mon Sep 17 00:00:00 2001 From: morpheus65535 <5130500+morpheus65535@users.noreply.github.com> Date: Sun, 4 Nov 2018 22:17:21 -0500 Subject: [PATCH 09/41] Fix for missing path returned by Radarr #213 --- bazarr/get_movies.py | 69 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/bazarr/get_movies.py b/bazarr/get_movies.py index 24aa76497..fd3e3db13 100644 --- a/bazarr/get_movies.py +++ b/bazarr/get_movies.py @@ -50,41 +50,44 @@ def update_movies(): for movie in r.json(): if movie['hasFile'] is True: if 'movieFile' in movie: - try: - overview = unicode(movie['overview']) - except: - overview = "" - try: - poster_big = movie['images'][0]['url'] - poster = os.path.splitext(poster_big)[0] + '-500' + os.path.splitext(poster_big)[1] - except: - poster = "" - try: - fanart = movie['images'][1]['url'] - except: - fanart = "" + if movie['movieFile']['relativePath'] is not None: + try: + overview = unicode(movie['overview']) + except: + overview = "" + try: + poster_big = movie['images'][0]['url'] + poster = os.path.splitext(poster_big)[0] + '-500' + os.path.splitext(poster_big)[1] + except: + poster = "" + try: + fanart = movie['images'][1]['url'] + except: + fanart = "" - if 'sceneName' in movie['movieFile']: - sceneName = movie['movieFile']['sceneName'] - else: - sceneName = None - - # Add movies in radarr to current movies list - current_movies_radarr.append(unicode(movie['tmdbId'])) - - # Detect file separator - if movie['path'][0] == "/": - separator = "/" - else: - 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"])) - 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'])))) + if 'sceneName' in movie['movieFile']: + sceneName = movie['movieFile']['sceneName'] 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'])))) + sceneName = None + + # Add movies in radarr to current movies list + current_movies_radarr.append(unicode(movie['tmdbId'])) + + # Detect file separator + if movie['path'][0] == "/": + separator = "/" + else: + 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"])) + 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'])))) + 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'])))) + else: + logging.error('BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator + movie['movieFile']['relativePath']) # Update or insert movies in DB db = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) From e97e34bbd42814bbb8eb97ccd179ce09bdf714da Mon Sep 17 00:00:00 2001 From: morpheus65535 <5130500+morpheus65535@users.noreply.github.com> Date: Mon, 5 Nov 2018 06:30:50 -0500 Subject: [PATCH 10/41] Fix for missing path returned by Radarr #213 --- bazarr/get_movies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/get_movies.py b/bazarr/get_movies.py index fd3e3db13..4228eae1d 100644 --- a/bazarr/get_movies.py +++ b/bazarr/get_movies.py @@ -50,7 +50,7 @@ def update_movies(): for movie in r.json(): if movie['hasFile'] is True: if 'movieFile' in movie: - if movie['movieFile']['relativePath'] is not None: + if movie["path"] != None and movie['movieFile']['relativePath'] != None: try: overview = unicode(movie['overview']) except: From dd87c1bffeea32d82edc1047272e59632b773364 Mon Sep 17 00:00:00 2001 From: Halali Date: Mon, 5 Nov 2018 13:09:17 +0100 Subject: [PATCH 11/41] Fix code3b position in DB --- bazarr/create_db.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/create_db.sql b/bazarr/create_db.sql index 067cac174..dc2188e44 100644 --- a/bazarr/create_db.sql +++ b/bazarr/create_db.sql @@ -28,10 +28,10 @@ CREATE TABLE "table_settings_notifier" ( ); CREATE TABLE "table_settings_languages" ( `code3` TEXT NOT NULL UNIQUE, - `code3b` TEXT, `code2` TEXT, `name` TEXT NOT NULL, `enabled` INTEGER, + `code3b` TEXT, PRIMARY KEY(`code3`) ); CREATE TABLE "table_history" ( From 54b39bf4a4ab07e6425d0012661a769fbf22e602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20V=C3=A9zina?= <5130500+morpheus65535@users.noreply.github.com> Date: Tue, 6 Nov 2018 11:39:54 -0500 Subject: [PATCH 12/41] Remove bottle debug mode when not executed in pycharm. --- bazarr/main.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index ed698df59..73ac07d49 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -74,8 +74,11 @@ 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() +if "PYCHARM_HOSTED" in os.environ: + bottle.debug(True) + bottle.TEMPLATES.clear() +else: + bottle.ERROR_PAGE_TEMPLATE = bottle.ERROR_PAGE_TEMPLATE.replace('if DEBUG and', 'if') from cherrypy.wsgiserver import CherryPyWSGIServer From da505bf087daa9e25c9cbb13273e586da2be8867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20V=C3=A9zina?= <5130500+morpheus65535@users.noreply.github.com> Date: Tue, 6 Nov 2018 11:42:49 -0500 Subject: [PATCH 13/41] Version bump. --- bazarr/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/main.py b/bazarr/main.py index 73ac07d49..b9d2bdbbd 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -1,4 +1,4 @@ -bazarr_version = '0.6.7' +bazarr_version = '0.6.7.1' import gc gc.enable() From 3c271ec64e630f4307cad1a937a0d780458fafd1 Mon Sep 17 00:00:00 2001 From: morpheus65535 <5130500+morpheus65535@users.noreply.github.com> Date: Tue, 6 Nov 2018 17:52:09 -0500 Subject: [PATCH 14/41] Some tweak. --- bazarr/main.py | 2 +- views/episodes.tpl | 27 +++++++++++++-------------- views/historymovies.tpl | 6 +++--- views/historyseries.tpl | 6 +++--- views/movie.tpl | 3 +++ views/movies.tpl | 17 +++++++++++------ views/series.tpl | 6 +++--- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 9a1f987c3..c4662a56c 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -721,7 +721,7 @@ 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, sceneName 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() diff --git a/views/episodes.tpl b/views/episodes.tpl index 74d9f0947..b011d0559 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -102,8 +102,8 @@
- - + + <% subs_languages = ast.literal_eval(str(details[7])) subs_languages_list = [] @@ -113,7 +113,7 @@ end end %> - +

{{details[0]}}

{{details[1]}}

@@ -165,8 +165,7 @@ Episode - - Title + Title Existing
subtitles Missing
subtitles Manual
search @@ -177,18 +176,18 @@ %if episode[9] == 'True': - + %else: - + %end {{episode[3]}} - - % if episode[8] is not None: - - % end - - {{episode[0]}} + + % if episode[8] is not None: + + % end + {{episode[0]}} + %if episode[4] is not None: % actual_languages = ast.literal_eval(episode[4]) @@ -234,7 +233,7 @@ {{language}} %else: -
+ {{language}} %end diff --git a/views/historymovies.tpl b/views/historymovies.tpl index e25b537e7..a8b6c6f22 100644 --- a/views/historymovies.tpl +++ b/views/historymovies.tpl @@ -67,11 +67,11 @@ %if row[0] == 0: -
+
%elif row[0] == 1: -
+
%end @@ -80,7 +80,7 @@
{{row[1]}} -
+
{{pretty.date(int(row[2]))}}
diff --git a/views/historyseries.tpl b/views/historyseries.tpl index 0542f9ba2..e1c85ba19 100644 --- a/views/historyseries.tpl +++ b/views/historyseries.tpl @@ -69,11 +69,11 @@ %if row[0] == 0: -
+
%elif row[0] == 1: -
+
%end @@ -95,7 +95,7 @@ %end -
+
{{pretty.date(int(row[4]))}}
diff --git a/views/movie.tpl b/views/movie.tpl index a4afd0489..d32d27889 100644 --- a/views/movie.tpl +++ b/views/movie.tpl @@ -120,6 +120,9 @@

{{details[6]}}
{{details[8]}}
+ % if details[12] is not None: +
{{details[12]}}
+ % end

%for language in subs_languages_list: diff --git a/views/movies.tpl b/views/movies.tpl index 3a321fbb7..fb4391841 100644 --- a/views/movies.tpl +++ b/views/movies.tpl @@ -72,17 +72,22 @@ %if row[8] == "True": - + %else: - + %end - {{row[1]}} + + % if row[9] is not None: + + % end + {{row[1]}} + %if os.path.isfile(row[2]): - + %else: - + %end {{row[2]}} @@ -105,7 +110,7 @@ end end %> -

+
diff --git a/views/series.tpl b/views/series.tpl index ca680ceae..62330c5db 100644 --- a/views/series.tpl +++ b/views/series.tpl @@ -79,9 +79,9 @@ {{row[1]}} %if os.path.isdir(row[2]): - + %else: - + %end {{row[2]}} @@ -127,7 +127,7 @@ end end %> -
+
From 3f93493ba801a328a2bee3ea0297269c63e27cfb Mon Sep 17 00:00:00 2001 From: morpheus65535 <5130500+morpheus65535@users.noreply.github.com> Date: Wed, 7 Nov 2018 22:27:14 -0500 Subject: [PATCH 15/41] Fix for #174 --- bazarr/get_movies.py | 12 ++++++------ bazarr/main.py | 2 +- bazarr/update_db.py | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/bazarr/get_movies.py b/bazarr/get_movies.py index 4228eae1d..3ec306567 100644 --- a/bazarr/get_movies.py +++ b/bazarr/get_movies.py @@ -80,12 +80,12 @@ 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['sortTitle'],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'])),movie['sortTitle'])) 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'])),movie['sortTitle'])) else: logging.error('BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator + movie['movieFile']['relativePath']) @@ -93,14 +93,14 @@ def update_movies(): db = sqlite3.connect(os.path.join(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 = ?, sortTitle= ? 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, sortTitle) 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, sortTitle) VALUES (?,?,?,(SELECT languages FROM table_movies WHERE tmdbId = ?), '[]',(SELECT `hearing_impaired` FROM table_movies WHERE tmdbId = ?), ?, ?, ?, ?, ?, ?, ?, ?)''', movies_to_add) db.commit() db.close() diff --git a/bazarr/main.py b/bazarr/main.py index b9d2bdbbd..c62d94cea 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -724,7 +724,7 @@ 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 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() diff --git a/bazarr/update_db.py b/bazarr/update_db.py index 1b6d5297b..f9b55e808 100644 --- a/bazarr/update_db.py +++ b/bazarr/update_db.py @@ -34,6 +34,11 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: except: pass + try: + c.execute('alter table table_movies add column "sortTitle" "text"') + except: + pass + try: rows = c.execute('SELECT name FROM table_settings_notifier WHERE name = "Kodi/XBMC"').fetchall() if len(rows) == 0: From 1f25a9f48470aa07ace5a5d0456eec0e1f4bf2cf Mon Sep 17 00:00:00 2001 From: Halali Date: Thu, 8 Nov 2018 13:56:52 +0100 Subject: [PATCH 16/41] Add DEBUG icon to logs page --- views/logs.tpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/views/logs.tpl b/views/logs.tpl index ea8fe473f..16186c757 100644 --- a/views/logs.tpl +++ b/views/logs.tpl @@ -53,6 +53,8 @@ blue info circle icon \\ yellow warning circle icon \\ %elif line[1] == 'ERROR': red bug icon \\ +%elif line[1] == 'DEBUG': +bug icon \\ %end %except: %pass From c20236141fd0d7522e47791e503f693dd2796389 Mon Sep 17 00:00:00 2001 From: Halali Date: Thu, 8 Nov 2018 14:03:34 +0100 Subject: [PATCH 17/41] Add tooltips for scenename, filename and adaptive searching in movies and wanted movies --- bazarr/main.py | 4 ++-- views/movie.tpl | 23 ++++++++++++++++++++++- views/wantedmovies.tpl | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 6878f1ef8..8c33b04c9 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -830,7 +830,7 @@ def movie(no): 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, failedAttempts 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() @@ -1017,7 +1017,7 @@ 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, failedAttempts 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) diff --git a/views/movie.tpl b/views/movie.tpl index d32d27889..0edaf75ab 100644 --- a/views/movie.tpl +++ b/views/movie.tpl @@ -170,7 +170,8 @@ <% - missing_subs_languages = ast.literal_eval(str(details[11])) + missing_subs_languages = ast.literal_eval(details[11]) + from get_subtitle import search_active if missing_subs_languages is not None: %> @@ -182,12 +183,32 @@
<% for missing_subs_language in missing_subs_languages: + if details[14] is not None and get_general_settings()[25]: + for lang in ast.literal_eval(details[14]): + if missing_subs_language in lang: + if search_active(lang[1]): %> {{language_from_alpha2(str(missing_subs_language))}} + %else: + + {{language_from_alpha2(str(missing_subs_language))}} + + <% + end + end + end + else: + %> + + {{language_from_alpha2(str(missing_subs_language))}} + + + <% + end end end %> diff --git a/views/wantedmovies.tpl b/views/wantedmovies.tpl index 67299e07c..f459d1a0e 100644 --- a/views/wantedmovies.tpl +++ b/views/wantedmovies.tpl @@ -65,17 +65,41 @@ No missing movie subtitles. %end - %for row in rows: + %for row in rows: {{row[0]}} - %missing_languages = ast.literal_eval(row[1]) - %if missing_languages is not None: - %for language in missing_languages: - - {{language}} - - + <% + missing_languages = ast.literal_eval(row[1]) + if missing_languages is not None: + from get_subtitle import search_active + from get_settings import get_general_settings + for language in missing_languages: + if row[6] is not None and get_general_settings()[25]: + for lang in ast.literal_eval(row[6]): + if language in lang: + active = search_active(lang[1]) + if active: + %> + + {{language}} + + + %else: + + {{language}} + + + %end + %end + %end + %else: + + {{language}} + + + %end + %end %end From e1b9f0dd8d3ad84c3abff3b1b7047e6c41f3d268 Mon Sep 17 00:00:00 2001 From: Halali Date: Thu, 8 Nov 2018 14:04:45 +0100 Subject: [PATCH 18/41] Some tweak --- bazarr/main.py | 2 +- views/episodes.tpl | 33 +++++++++++++++++---------------- views/wantedseries.tpl | 27 ++++++++++++++++----------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 8c33b04c9..736fc7124 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -693,7 +693,7 @@ def episodes(no): 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, failedAttempts 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() diff --git a/views/episodes.tpl b/views/episodes.tpl index b011d0559..a349340e8 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -214,26 +214,27 @@ %try: - %if episode[6] is not None: - % missing_languages = ast.literal_eval(episode[6]) - % missing_languages.sort() - %else: - % missing_languages = None - %end - %if missing_languages is not None: - %from get_subtitle import search_active - %from get_settings import get_general_settings - %for language in missing_languages: - %if episode[10] is not None and get_general_settings()[25]: - %for lang in ast.literal_eval(episode[10]): - %if language in lang: - %active = search_active(lang[1]) - %if active: + <% + if episode[6] is not None: + missing_languages = ast.literal_eval(episode[6]) + missing_languages.sort() + else: + missing_languages = None + end + if missing_languages is not None: + from get_subtitle import search_active + from get_settings import get_general_settings + for language in missing_languages: + if episode[10] is not None and get_general_settings()[25]: + for lang in ast.literal_eval(episode[10]): + if language in lang: + if search_active(lang[1]): + %> {{language}} %else: - + {{language}} %end diff --git a/views/wantedseries.tpl b/views/wantedseries.tpl index 53de62342..a7931628b 100644 --- a/views/wantedseries.tpl +++ b/views/wantedseries.tpl @@ -76,23 +76,27 @@ {{row[2]}} - %missing_languages = ast.literal_eval(row[3]) - %if missing_languages is not None: - %from get_subtitle import search_active - %from get_settings import get_general_settings - %for language in missing_languages: - %if row[9] is not None and get_general_settings()[25]: - %for lang in ast.literal_eval(row[9]): - %if language in lang: - %active = search_active(lang[1]) - %if active: + <% + missing_languages = ast.literal_eval(row[3]) + if missing_languages is not None: + from get_subtitle import search_active + from get_settings import get_general_settings + for language in missing_languages: + if row[9] is not None and get_general_settings()[25]: + for lang in ast.literal_eval(row[9]): + if language in lang: + active = search_active(lang[1]) + if active: + %> {{language}} + %else: - + {{language}} + %end %end %end @@ -100,6 +104,7 @@ {{language}} + %end %end From 2f5f9bad3589f027f74c268fc96b947641a8ac38 Mon Sep 17 00:00:00 2001 From: Halali Date: Sat, 10 Nov 2018 14:36:12 +0100 Subject: [PATCH 19/41] Fix for episodes template --- bazarr/main.py | 2 +- views/episodes.tpl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bazarr/main.py b/bazarr/main.py index 736fc7124..8c33b04c9 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -693,7 +693,7 @@ def episodes(no): 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, failedAttempts 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() diff --git a/views/episodes.tpl b/views/episodes.tpl index a349340e8..dab968502 100644 --- a/views/episodes.tpl +++ b/views/episodes.tpl @@ -218,8 +218,6 @@ if episode[6] is not None: missing_languages = ast.literal_eval(episode[6]) missing_languages.sort() - else: - missing_languages = None end if missing_languages is not None: from get_subtitle import search_active @@ -233,10 +231,12 @@ {{language}} + %else: {{language}} + %end %end %end @@ -244,8 +244,8 @@ {{language}} + %end - %end %end %except: From ed50acd7ccb01d4ed4e819eed5ba4124fc77fc8d Mon Sep 17 00:00:00 2001 From: Halali Date: Sat, 10 Nov 2018 19:53:27 +0100 Subject: [PATCH 20/41] Add IP filtering for logging --- bazarr/logger.py | 81 ++++++++++++++++++++++++++++++++++++++---------- bazarr/main.py | 8 +++-- 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/bazarr/logger.py b/bazarr/logger.py index c558d554f..936a60375 100644 --- a/bazarr/logger.py +++ b/bazarr/logger.py @@ -7,6 +7,8 @@ from logging.handlers import TimedRotatingFileHandler from get_argv import config_dir from get_settings import get_general_settings +logger = logging.getLogger() + debug = get_general_settings()[4] if debug is False: log_level = "INFO" @@ -38,9 +40,21 @@ class NoExceptionFormatter(logging.Formatter): def configure_logging(): - log = logging.getLogger() - log.handlers = [] + logger.handlers = [] + logger.setLevel(log_level) + + # Console logging + ch = logging.StreamHandler() + cf = NoExceptionFormatter('%(asctime)-15s - %(name)-32s (%(thread)x) : %(levelname)s (%(module)s:%(lineno)d) ' + '- %(message)s') + ch.setFormatter(cf) + + ch.setLevel(log_level) + # ch.addFilter(MyFilter()) + logger.addHandler(ch) + + #File Logging global fh fh = TimedRotatingFileHandler(os.path.join(config_dir, 'log/bazarr.log'), when="midnight", interval=1, backupCount=7) @@ -48,6 +62,7 @@ def configure_logging(): '%d/%m/%Y %H:%M:%S') fh.setFormatter(f) fh.addFilter(BlacklistFilter()) + fh.addFilter(PublicIPFilter()) if debug is True: logging.getLogger("apscheduler").setLevel(logging.DEBUG) @@ -62,23 +77,18 @@ def configure_logging(): logging.getLogger("guessit").setLevel(logging.WARNING) logging.getLogger("rebulk").setLevel(logging.WARNING) logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) - log.setLevel(log_level) - log.addHandler(fh) + fh.setLevel(log_level) + logger.addHandler(fh) - # Console logging - ch = logging.StreamHandler() - cf = NoExceptionFormatter('%(asctime)s - %(levelname)s :: %(message)s', - '%Y-%m-%d %H:%M:%S') - ch.setFormatter(cf) + +class MyFilter(logging.Filter): + def __init__(self): + pass - logging.getLogger("apscheduler").setLevel(logging.WARNING) - logging.getLogger("subliminal").setLevel(logging.CRITICAL) - logging.getLogger("enzyme").setLevel(logging.CRITICAL) - logging.getLogger("guessit").setLevel(logging.WARNING) - logging.getLogger("rebulk").setLevel(logging.WARNING) - logging.getLogger("stevedore.extension").setLevel(logging.CRITICAL) - ch.setLevel(logging.INFO) - log.addHandler(ch) + def filter(self, record): + if record.name != 'root': + return False + return True class BlacklistFilter(logging.Filter): @@ -106,6 +116,43 @@ class BlacklistFilter(logging.Filter): return True +class PublicIPFilter(logging.Filter): + """ + Log filter for public IP addresses + """ + def __init__(self): + pass + + def filter(self, record): + try: + # Currently only checking for ipv4 addresses + ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', record.msg) + for ip in ipv4: + record.msg = record.msg.replace(ip, ip.partition('.')[0] + '.***.***.***') + + args = [] + for arg in record.args: + ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', arg) if isinstance(arg, basestring) else [] + for ip in ipv4: + arg = arg.replace(ip, ip.partition('.')[0] + '.***.***.***') + args.append(arg) + record.args = tuple(args) + except: + pass + + return True + + def empty_log(): fh.doRollover() + +def update_settings(debug): + if debug == 'False': + level = "INFO" + else: + level = "DEBUG" + print debug, level + logging.getLogger().setLevel(level) + for handler in logging.getLogger().handlers: + handler.setLevel(level) diff --git a/bazarr/main.py b/bazarr/main.py index 3bd1ef72d..4c0269b38 100644 --- a/bazarr/main.py +++ b/bazarr/main.py @@ -23,7 +23,7 @@ update_notifier() from get_settings import get_general_settings, get_proxy_settings import logging -from logger import configure_logging, empty_log +from logger import configure_logging, empty_log, update_settings configure_logging() import requests @@ -1100,8 +1100,8 @@ 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_debug), 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[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_pathmapping), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie)) from six import text_type cfg = ConfigParser() @@ -1129,6 +1129,8 @@ def save_settings(): cfg.set('general', 'use_embedded_subs', text_type(settings_general_embedded)) cfg.set('general', 'only_monitored', text_type(settings_general_only_monitored)) cfg.set('general', 'adaptive_searching', text_type(settings_general_adaptive_searching)) + + update_settings(settings_general_debug) if after != before: configured() From 3891ccdaf5e4654d2cd1a06411ac84c437ced99f Mon Sep 17 00:00:00 2001 From: Halali Date: Sat, 10 Nov 2018 20:02:02 +0100 Subject: [PATCH 21/41] Remove restart requirement icon from Debug setting --- bazarr/logger.py | 4 ++-- views/settings.tpl | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/bazarr/logger.py b/bazarr/logger.py index 936a60375..b1b7bcefc 100644 --- a/bazarr/logger.py +++ b/bazarr/logger.py @@ -153,6 +153,6 @@ def update_settings(debug): else: level = "DEBUG" print debug, level - logging.getLogger().setLevel(level) - for handler in logging.getLogger().handlers: + logger.setLevel(level) + for handler in logger.handlers: handler.setLevel(level) diff --git a/views/settings.tpl b/views/settings.tpl index cce1a4ef7..212b32dd9 100644 --- a/views/settings.tpl +++ b/views/settings.tpl @@ -146,12 +146,6 @@
- -