diff --git a/bazarr/create_db.sql b/bazarr/create_db.sql index f878fc058..dc2188e44 100644 --- a/bazarr/create_db.sql +++ b/bazarr/create_db.sql @@ -20,12 +20,18 @@ CREATE TABLE "table_settings_providers" ( `password` "text", PRIMARY KEY(`name`) ); +CREATE TABLE "table_settings_notifier" ( + `name` TEXT, + `url` TEXT, + `enabled` INTEGER, + PRIMARY KEY(`name`) +); 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" ( diff --git a/bazarr/get_movies.py b/bazarr/get_movies.py index 24aa76497..3ec306567 100644 --- a/bazarr/get_movies.py +++ b/bazarr/get_movies.py @@ -50,54 +50,57 @@ 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 'sceneName' in movie['movieFile']: - sceneName = movie['movieFile']['sceneName'] - else: - sceneName = None + if movie["path"] != None and movie['movieFile']['relativePath'] != 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'])) + # 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 = "\\" + # 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 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['sortTitle'],movie["tmdbId"])) 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'])))) + 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'])),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'])),movie['sortTitle'])) + 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) 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/get_subtitle.py b/bazarr/get_subtitle.py index 4cc7354f7..b596b6ef6 100644 --- a/bazarr/get_subtitle.py +++ b/bazarr/get_subtitle.py @@ -96,70 +96,76 @@ def download_subtitle(path, language, hi, providers, providers_auth, sceneName, logging.debug('BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path) if len(subtitles_list) > 0: try: - best_subtitle = subtitles_list[0] - download_subtitles([best_subtitle], providers=providers, provider_configs=providers_auth) - logging.debug('BAZARR Subtitles file downloaded for this file:' + path) + 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) + 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).') + 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.") + 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(best_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 = scan_video(path) single = get_general_settings()[7] if single is True: - result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8') + result = save_subtitles(video, [subtitle], single=True, encoding='utf-8') else: - result = save_subtitles(video, [best_subtitle], encoding='utf-8') + result = save_subtitles(video, [subtitle], encoding='utf-8') except Exception as e: logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) pass else: - if len(result) > 0: - downloaded_provider = result[0].provider_name - downloaded_language = language_from_alpha3(result[0].language.alpha3) - downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) - downloaded_language_code3 = result[0].language.alpha3 - 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 - else: - 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) - try: - if os.name == 'nt': - 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) + downloaded_provider = result[0].provider_name + downloaded_language = language_from_alpha3(result[0].language.alpha3) + downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) + downloaded_language_code3 = result[0].language.alpha3 + 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 + else: + 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) + try: + if os.name == 'nt': + codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate - out, err = process.communicate() + out_codepage, err_codepage = codepage.communicate() + encoding = out_codepage.split(':')[-1].strip() - if os.name == 'nt': - out = out.decode(encoding) + process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # wait for the process to terminate + out, err = process.communicate() - except: - if out == "": - 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) + if os.name == 'nt': + out = out.decode(encoding) + + except: + if out == "": + 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') else: - if out == "": - 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) + logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out) - return message - else: - logging.error('BAZARR Tried to download best subtitles available for file: ' + path + ' but it had no content. Going to retry on next search.') - return None + return message else: + logging.debug('BAZARR No subtitles were found for this file: ' + path) return None logging.debug('BAZARR Ended searching subtitles for file: ' + path) @@ -265,8 +271,7 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a pass else: try: - best_subtitle = subtitle - download_subtitles([best_subtitle], providers=provider, provider_configs=providers_auth) + download_subtitles([subtitle], providers=provider, provider_configs=providers_auth) logging.debug('BAZARR Subtitles file downloaded for this file:' + path) except Exception as e: logging.exception('BAZARR Error downloading subtitles for this file ' + path) @@ -274,13 +279,13 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a else: single = get_general_settings()[7] try: - score = round(float(compute_score(best_subtitle, video, hearing_impaired=hi)) / type_of_score * 100, 2) + score = round(float(compute_score(subtitle, video, hearing_impaired=hi)) / type_of_score * 100, 2) if used_sceneName == True: video = scan_video(path) if single is True: - result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8') + result = save_subtitles(video, [subtitle], single=True, encoding='utf-8') else: - result = save_subtitles(video, [best_subtitle], encoding='utf-8') + result = save_subtitles(video, [subtitle], encoding='utf-8') except Exception as e: logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) return None @@ -323,7 +328,7 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a return message else: - logging.error('BAZARR Tried to manually download a subtitles for file: ' + path + ' but it had no content. Going to retry on next search.') + 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) diff --git a/bazarr/main.py b/bazarr/main.py index 782748fc3..3bd1ef72d 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() @@ -17,6 +17,8 @@ import signal import sqlite3 from init import * from update_db import * +from notifier import update_notifier +update_notifier() from get_settings import get_general_settings, get_proxy_settings @@ -37,8 +39,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 @@ -215,7 +220,7 @@ def wizard(): @route(base_url + 'save_wizard', method='POST') @custom_auth_basic(check_credentials) -def save_settings(): +def save_wizard(): authorize() conn = sqlite3.connect(os.path.join(config_dir, 'db/bazarr.db'), timeout=30) @@ -684,7 +689,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() @@ -1294,197 +1299,16 @@ def save_settings(): with open(config_file, 'wb') as f: cfg.write(f) - settings_notifier_Boxcar_enabled = request.forms.get('settings_notifier_Boxcar_enabled') - if settings_notifier_Boxcar_enabled == 'on': - settings_notifier_Boxcar_enabled = 1 - else: - settings_notifier_Boxcar_enabled = 0 - settings_notifier_Boxcar_url = request.forms.get('settings_notifier_Boxcar_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Boxcar'", (settings_notifier_Boxcar_enabled, settings_notifier_Boxcar_url)) - - settings_notifier_Faast_enabled = request.forms.get('settings_notifier_Faast_enabled') - if settings_notifier_Faast_enabled == 'on': - settings_notifier_Faast_enabled = 1 - else: - settings_notifier_Faast_enabled = 0 - settings_notifier_Faast_url = request.forms.get('settings_notifier_Faast_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Faast'", (settings_notifier_Faast_enabled, settings_notifier_Faast_url)) - - settings_notifier_Growl_enabled = request.forms.get('settings_notifier_Growl_enabled') - if settings_notifier_Growl_enabled == 'on': - settings_notifier_Growl_enabled = 1 - else: - settings_notifier_Growl_enabled = 0 - settings_notifier_Growl_url = request.forms.get('settings_notifier_Growl_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Growl'", (settings_notifier_Growl_enabled, settings_notifier_Growl_url)) - - settings_notifier_Join_enabled = request.forms.get('settings_notifier_Join_enabled') - if settings_notifier_Join_enabled == 'on': - settings_notifier_Join_enabled = 1 - else: - settings_notifier_Join_enabled = 0 - settings_notifier_Join_url = request.forms.get('settings_notifier_Join_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Join'", (settings_notifier_Join_enabled, settings_notifier_Join_url)) - - settings_notifier_KODI_enabled = request.forms.get('settings_notifier_KODI_enabled') - if settings_notifier_KODI_enabled == 'on': - settings_notifier_KODI_enabled = 1 - else: - settings_notifier_KODI_enabled = 0 - settings_notifier_KODI_url = request.forms.get('settings_notifier_KODI_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'KODI'", (settings_notifier_KODI_enabled, settings_notifier_KODI_url)) - - settings_notifier_Mattermost_enabled = request.forms.get('settings_notifier_Mattermost_enabled') - if settings_notifier_Mattermost_enabled == 'on': - settings_notifier_Mattermost_enabled = 1 - else: - settings_notifier_Mattermost_enabled = 0 - settings_notifier_Mattermost_url = request.forms.get('settings_notifier_Mattermost_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Mattermost'", (settings_notifier_Mattermost_enabled, settings_notifier_Mattermost_url)) - - settings_notifier_NMA_enabled = request.forms.get('settings_notifier_Notify My Android_enabled') - if settings_notifier_NMA_enabled == 'on': - settings_notifier_NMA_enabled = 1 - else: - settings_notifier_NMA_enabled = 0 - settings_notifier_NMA_url = request.forms.get('settings_notifier_Notify My Android_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Notify My Android'", (settings_notifier_NMA_enabled, settings_notifier_NMA_url)) - - settings_notifier_Prowl_enabled = request.forms.get('settings_notifier_Prowl_enabled') - if settings_notifier_Prowl_enabled == 'on': - settings_notifier_Prowl_enabled = 1 - else: - settings_notifier_Prowl_enabled = 0 - settings_notifier_Prowl_url = request.forms.get('settings_notifier_Prowl_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Prowl'", (settings_notifier_Prowl_enabled, settings_notifier_Prowl_url)) - - settings_notifier_Pushalot_enabled = request.forms.get('settings_notifier_Pushalot_enabled') - if settings_notifier_Pushalot_enabled == 'on': - settings_notifier_Pushalot_enabled = 1 - else: - settings_notifier_Pushalot_enabled = 0 - settings_notifier_Pushalot_url = request.forms.get('settings_notifier_Pushalot_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushalot'", (settings_notifier_Pushalot_enabled, settings_notifier_Pushalot_url)) - - settings_notifier_PushBullet_enabled = request.forms.get('settings_notifier_PushBullet_enabled') - if settings_notifier_PushBullet_enabled == 'on': - settings_notifier_PushBullet_enabled = 1 - else: - settings_notifier_PushBullet_enabled = 0 - settings_notifier_PushBullet_url = request.forms.get('settings_notifier_PushBullet_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'PushBullet'", (settings_notifier_PushBullet_enabled, settings_notifier_PushBullet_url)) - - settings_notifier_Pushjet_enabled = request.forms.get('settings_notifier_Pushjet_enabled') - if settings_notifier_Pushjet_enabled == 'on': - settings_notifier_Pushjet_enabled = 1 - else: - settings_notifier_Pushjet_enabled = 0 - settings_notifier_Pushjet_url = request.forms.get('settings_notifier_Pushjet_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushjet'", (settings_notifier_Pushjet_enabled, settings_notifier_Pushjet_url)) - - settings_notifier_Pushover_enabled = request.forms.get('settings_notifier_Pushover_enabled') - if settings_notifier_Pushover_enabled == 'on': - settings_notifier_Pushover_enabled = 1 - else: - settings_notifier_Pushover_enabled = 0 - settings_notifier_Pushover_url = request.forms.get('settings_notifier_Pushover_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushover'", (settings_notifier_Pushover_enabled, settings_notifier_Pushover_url)) - - settings_notifier_RocketChat_enabled = request.forms.get('settings_notifier_Rocket.Chat_enabled') - if settings_notifier_RocketChat_enabled == 'on': - settings_notifier_RocketChat_enabled = 1 - else: - settings_notifier_RocketChat_enabled = 0 - settings_notifier_RocketChat_url = request.forms.get('settings_notifier_Rocket.Chat_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Rocket.Chat'", (settings_notifier_RocketChat_enabled, settings_notifier_RocketChat_url)) - - settings_notifier_Slack_enabled = request.forms.get('settings_notifier_Slack_enabled') - if settings_notifier_Slack_enabled == 'on': - settings_notifier_Slack_enabled = 1 - else: - settings_notifier_Slack_enabled = 0 - settings_notifier_Slack_url = request.forms.get('settings_notifier_Slack_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Slack'", (settings_notifier_Slack_enabled, settings_notifier_Slack_url)) - - settings_notifier_SuperToasty_enabled = request.forms.get('settings_notifier_Super Toasty_enabled') - if settings_notifier_SuperToasty_enabled == 'on': - settings_notifier_SuperToasty_enabled = 1 - else: - settings_notifier_SuperToasty_enabled = 0 - settings_notifier_SuperToasty_url = request.forms.get('settings_notifier_Super Toasty_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Super Toasty'", (settings_notifier_SuperToasty_enabled, settings_notifier_SuperToasty_url)) - - settings_notifier_Telegram_enabled = request.forms.get('settings_notifier_Telegram_enabled') - if settings_notifier_Telegram_enabled == 'on': - settings_notifier_Telegram_enabled = 1 - else: - settings_notifier_Telegram_enabled = 0 - settings_notifier_Telegram_url = request.forms.get('settings_notifier_Telegram_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Telegram'", (settings_notifier_Telegram_enabled, settings_notifier_Telegram_url)) - - settings_notifier_Twitter_enabled = request.forms.get('settings_notifier_Twitter_enabled') - if settings_notifier_Twitter_enabled == 'on': - settings_notifier_Twitter_enabled = 1 - else: - settings_notifier_Twitter_enabled = 0 - settings_notifier_Twitter_url = request.forms.get('settings_notifier_Twitter_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Twitter'", (settings_notifier_Twitter_enabled, settings_notifier_Twitter_url)) - - settings_notifier_XBMC_enabled = request.forms.get('settings_notifier_XBMC_enabled') - if settings_notifier_XBMC_enabled == 'on': - settings_notifier_XBMC_enabled = 1 - else: - settings_notifier_XBMC_enabled = 0 - settings_notifier_XBMC_url = request.forms.get('settings_notifier_XBMC_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'XBMC'", (settings_notifier_XBMC_enabled, settings_notifier_XBMC_url)) - - settings_notifier_Discord_enabled = request.forms.get('settings_notifier_Discord_enabled') - if settings_notifier_Discord_enabled == 'on': - settings_notifier_Discord_enabled = 1 - else: - settings_notifier_Discord_enabled = 0 - settings_notifier_Discord_url = request.forms.get('settings_notifier_Discord_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Discord'", (settings_notifier_Discord_enabled, settings_notifier_Discord_url)) - - settings_notifier_E_Mail_enabled = request.forms.get('settings_notifier_E-Mail_enabled') - if settings_notifier_E_Mail_enabled == 'on': - settings_notifier_E_Mail_enabled = 1 - else: - settings_notifier_E_Mail_enabled = 0 - settings_notifier_E_Mail_url = request.forms.get('settings_notifier_E-Mail_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'E-Mail'", (settings_notifier_E_Mail_enabled, settings_notifier_E_Mail_url)) - - settings_notifier_Emby_enabled = request.forms.get('settings_notifier_Emby_enabled') - if settings_notifier_Emby_enabled == 'on': - settings_notifier_Emby_enabled = 1 - else: - settings_notifier_Emby_enabled = 0 - settings_notifier_Emby_url = request.forms.get('settings_notifier_Emby_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Emby'", (settings_notifier_Emby_enabled, settings_notifier_Emby_url)) - - settings_notifier_IFTTT_enabled = request.forms.get('settings_notifier_IFTTT_enabled') - if settings_notifier_IFTTT_enabled == 'on': - settings_notifier_IFTTT_enabled = 1 - else: - settings_notifier_IFTTT_enabled = 0 - settings_notifier_IFTTT_url = request.forms.get('settings_notifier_IFTTT_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'IFTTT'", (settings_notifier_IFTTT_enabled, settings_notifier_IFTTT_url)) - - settings_notifier_Stride_enabled = request.forms.get('settings_notifier_Stride_enabled') - if settings_notifier_Stride_enabled == 'on': - settings_notifier_Stride_enabled = 1 - else: - settings_notifier_Stride_enabled = 0 - settings_notifier_Stride_url = request.forms.get('settings_notifier_Stride_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Stride'", (settings_notifier_Stride_enabled, settings_notifier_Stride_url)) - - settings_notifier_Windows_enabled = request.forms.get('settings_notifier_Windows_enabled') - if settings_notifier_Windows_enabled == 'on': - settings_notifier_Windows_enabled = 1 - else: - settings_notifier_Windows_enabled = 0 - settings_notifier_Windows_url = request.forms.get('settings_notifier_Windows_url') - c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Windows'", (settings_notifier_Windows_enabled, settings_notifier_Windows_url)) + notifiers = c.execute("SELECT * FROM table_settings_notifier ORDER BY name").fetchall() + for notifier in notifiers: + enabled = request.forms.get('settings_notifier_' + notifier[0] + '_enabled') + if enabled == 'on': + enabled = 1 + else: + enabled = 0 + notifier_url = request.forms.get('settings_notifier_' + notifier[0] + '_url') + c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = ?", + (enabled, notifier_url, notifier[0])) conn.commit() c.close() diff --git a/bazarr/notifier.py b/bazarr/notifier.py index 6109e1fa7..52d7533c1 100644 --- a/bazarr/notifier.py +++ b/bazarr/notifier.py @@ -3,6 +3,41 @@ from get_argv import config_dir import apprise import os import sqlite3 +import logging + + +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) + c_db = conn_db.cursor() + notifiers_current = c_db.execute('SELECT name FROM table_settings_notifier').fetchall() + for x in results['schemas']: + if x['service_name'] not in str(notifiers_current): + notifiers_new.append(x['service_name']) + logging.debug('Adding new notifier agent: ' + x['service_name']) + 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) diff --git a/bazarr/update_db.py b/bazarr/update_db.py index 110b2219b..f9b55e808 100644 --- a/bazarr/update_db.py +++ b/bazarr/update_db.py @@ -29,43 +29,23 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: except: pass - try: - c.execute('CREATE TABLE `table_settings_notifier` (`name` TEXT, `url` TEXT, `enabled` INTEGER);') - except: - pass - else: - providers = ['Boxcar','Faast','Growl','Join','KODI','Mattermost','Notify My Android','Prowl','Pushalot','PushBullet','Pushjet','Pushover','Rocket.Chat','Slack','Super Toasty','Telegram','Twitter','XBMC'] - for provider in providers: - c.execute('INSERT INTO `table_settings_notifier` (name, enabled) VALUES (?, ?);', (provider,'0')) - try: c.execute('alter table table_shows add column "sortTitle" "text"') except: pass try: - c.execute('CREATE TABLE "table_movies" ( `tmdbId` TEXT NOT NULL UNIQUE, `title` TEXT NOT NULL, `path` TEXT NOT NULL UNIQUE, `languages` TEXT, `subtitles` TEXT, `missing_subtitles` TEXT, `hearing_impaired` TEXT, `radarrId` INTEGER NOT NULL UNIQUE, `overview` TEXT, `poster` TEXT, `fanart` TEXT, "audio_language" "text", `sceneName` TEXT, PRIMARY KEY(`tmdbId`) )') - except: - pass - - try: - c.execute('CREATE TABLE "table_history_movie" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `action` INTEGER NOT NULL, `radarrId` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `description` TEXT NOT NULL )') + c.execute('alter table table_movies add column "sortTitle" "text"') except: pass try: - c.execute('DELETE FROM table_settings_notifier WHERE rowid > 24') #Modify this if we add more notification provider - rows = c.execute('SELECT name FROM table_settings_notifier WHERE name = "Discord"').fetchall() + rows = c.execute('SELECT name FROM table_settings_notifier WHERE name = "Kodi/XBMC"').fetchall() if len(rows) == 0: - providers = ['Discord', 'E-Mail', 'Emby', 'IFTTT', 'Stride', 'Windows'] - for provider in providers: - c.execute('INSERT INTO `table_settings_notifier` (name, enabled) VALUES (?, ?);', (provider, '0')) - except: - pass - - try: - c.execute('CREATE TABLE `system` ( `configured` TEXT, `updated` TEXT)') - c.execute('INSERT INTO `system` (configured, updated) VALUES (?, ?);', ('0', '0')) + providers = [['KODI', 'Kodi/XBMC'], ['Windows', 'Windows Notification'], ['Super Toasty', 'Toasty'], + ['PushBullet', 'Pushbullet'], ['Mattermost', 'MatterMost']] + for provider_old, provider_new in providers: + c.execute('UPDATE table_settings_notifier SET name=? WHERE name=?', (provider_new, provider_old)) except: pass @@ -92,13 +72,13 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: else: from scheduler import execute_now from get_settings import get_general_settings + integration = get_general_settings() if integration[12] is True: execute_now('sync_episodes') if integration[13] is True: execute_now('update_movies') - try: c.execute('alter table table_episodes add column "monitored" TEXT') db.commit() @@ -107,6 +87,7 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: else: from scheduler import execute_now from get_settings import get_general_settings + integration = get_general_settings() if integration[12] is True: execute_now('sync_episodes') @@ -119,6 +100,7 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True: else: from scheduler import execute_now from get_settings import get_general_settings + integration = get_general_settings() if integration[13] is True: execute_now('update_movies') diff --git a/libs/apprise/Apprise.py b/libs/apprise/Apprise.py index 8512ea145..73adf6299 100644 --- a/libs/apprise/Apprise.py +++ b/libs/apprise/Apprise.py @@ -32,6 +32,7 @@ from .AppriseAsset import AppriseAsset from . import NotifyBase from . import plugins +from . import __version__ logger = logging.getLogger(__name__) @@ -54,6 +55,9 @@ def __load_matrix(): # Get our plugin plugin = getattr(plugins, entry) + if not hasattr(plugin, 'app_id'): # pragma: no branch + # Filter out non-notification modules + continue # Load protocol(s) if defined proto = getattr(plugin, 'protocol', None) @@ -277,6 +281,52 @@ class Apprise(object): return status + def details(self): + """ + Returns the details associated with the Apprise object + + """ + + # general object returned + response = { + # Defines the current version of Apprise + 'version': __version__, + # Lists all of the currently supported Notifications + 'schemas': [], + # Includes the configured asset details + 'asset': self.asset.details(), + } + + # to add it's mapping to our hash table + for entry in sorted(dir(plugins)): + + # Get our plugin + plugin = getattr(plugins, entry) + if not hasattr(plugin, 'app_id'): # pragma: no branch + # Filter out non-notification modules + continue + + # Standard protocol(s) should be None or a tuple + protocols = getattr(plugin, 'protocol', None) + if compat_is_basestring(protocols): + protocols = (protocols, ) + + # Secure protocol(s) should be None or a tuple + secure_protocols = getattr(plugin, 'secure_protocol', None) + if compat_is_basestring(secure_protocols): + secure_protocols = (secure_protocols, ) + + # Build our response object + response['schemas'].append({ + 'service_name': getattr(plugin, 'service_name', None), + 'service_url': getattr(plugin, 'service_url', None), + 'setup_url': getattr(plugin, 'setup_url', None), + 'protocols': protocols, + 'secure_protocols': secure_protocols, + }) + + return response + def __len__(self): """ Returns the number of servers loaded diff --git a/libs/apprise/AppriseAsset.py b/libs/apprise/AppriseAsset.py index 5bbba2a9b..ee845f726 100644 --- a/libs/apprise/AppriseAsset.py +++ b/libs/apprise/AppriseAsset.py @@ -62,12 +62,13 @@ class AppriseAsset(object): # Image URL Mask image_url_mask = \ - 'http://nuxref.com/apprise/themes/{THEME}/' \ - 'apprise-{TYPE}-{XY}{EXTENSION}' + 'https://github.com/caronc/apprise/raw/master/apprise/assets/' \ + 'themes/{THEME}/apprise-{TYPE}-{XY}{EXTENSION}' # Application Logo image_url_logo = \ - 'http://nuxref.com/apprise/themes/{THEME}/apprise-logo.png' + 'https://github.com/caronc/apprise/raw/master/apprise/assets/' \ + 'themes/{THEME}/apprise-logo.png' # Image Path Mask image_path_mask = abspath(join( @@ -216,6 +217,21 @@ class AppriseAsset(object): return None + def details(self): + """ + Returns the details associated with the AppriseAsset object + + """ + return { + 'app_id': self.app_id, + 'app_desc': self.app_desc, + 'default_extension': self.default_extension, + 'theme': self.theme, + 'image_path_mask': self.image_url_mask, + 'image_url_mask': self.image_url_mask, + 'image_url_logo': self.image_url_logo, + } + @staticmethod def hex_to_rgb(value): """ diff --git a/libs/apprise/plugins/NotifyBase.py b/libs/apprise/plugins/NotifyBase.py index 9f0284999..0a8a3687b 100644 --- a/libs/apprise/plugins/NotifyBase.py +++ b/libs/apprise/plugins/NotifyBase.py @@ -34,7 +34,6 @@ except ImportError: from ..utils import parse_url from ..utils import parse_bool from ..utils import is_hostname -from ..common import NOTIFY_IMAGE_SIZES from ..common import NOTIFY_TYPES from ..common import NotifyFormat from ..common import NOTIFY_FORMATS @@ -70,7 +69,8 @@ PATHSPLIT_LIST_DELIM = re.compile(r'[ \t\r\n,\\/]+') # Regular expression retrieved from: # http://www.regular-expressions.info/email.html IS_EMAIL_RE = re.compile( - r"(?P[a-z0-9$%+=_~-]+" + r"((?P