Merge branch 'development' into logging

pull/249/head
Halali 6 years ago
commit cb1ea10add

@ -20,12 +20,18 @@ CREATE TABLE "table_settings_providers" (
`password` "text", `password` "text",
PRIMARY KEY(`name`) PRIMARY KEY(`name`)
); );
CREATE TABLE "table_settings_notifier" (
`name` TEXT,
`url` TEXT,
`enabled` INTEGER,
PRIMARY KEY(`name`)
);
CREATE TABLE "table_settings_languages" ( CREATE TABLE "table_settings_languages" (
`code3` TEXT NOT NULL UNIQUE, `code3` TEXT NOT NULL UNIQUE,
`code3b` TEXT,
`code2` TEXT, `code2` TEXT,
`name` TEXT NOT NULL, `name` TEXT NOT NULL,
`enabled` INTEGER, `enabled` INTEGER,
`code3b` TEXT,
PRIMARY KEY(`code3`) PRIMARY KEY(`code3`)
); );
CREATE TABLE "table_history" ( CREATE TABLE "table_history" (

@ -50,54 +50,57 @@ def update_movies():
for movie in r.json(): for movie in r.json():
if movie['hasFile'] is True: if movie['hasFile'] is True:
if 'movieFile' in movie: if 'movieFile' in movie:
try: if movie["path"] != None and movie['movieFile']['relativePath'] != None:
overview = unicode(movie['overview']) try:
except: overview = unicode(movie['overview'])
overview = "" except:
try: overview = ""
poster_big = movie['images'][0]['url'] try:
poster = os.path.splitext(poster_big)[0] + '-500' + os.path.splitext(poster_big)[1] poster_big = movie['images'][0]['url']
except: poster = os.path.splitext(poster_big)[0] + '-500' + os.path.splitext(poster_big)[1]
poster = "" except:
try: poster = ""
fanart = movie['images'][1]['url'] try:
except: fanart = movie['images'][1]['url']
fanart = "" except:
fanart = ""
if 'sceneName' in movie['movieFile']:
sceneName = movie['movieFile']['sceneName'] if 'sceneName' in movie['movieFile']:
else: sceneName = movie['movieFile']['sceneName']
sceneName = None else:
sceneName = None
# Add movies in radarr to current movies list # Add movies in radarr to current movies list
current_movies_radarr.append(unicode(movie['tmdbId'])) current_movies_radarr.append(unicode(movie['tmdbId']))
# Detect file separator # Detect file separator
if movie['path'][0] == "/": if movie['path'][0] == "/":
separator = "/" separator = "/"
else: else:
separator = "\\" separator = "\\"
if unicode(movie['tmdbId']) in current_movies_db_list: 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']))))
else: 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 # 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(config_dir, 'db/bazarr.db'), timeout=30)
c = db.cursor() 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() db.commit()
if movie_default_enabled is True: 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() db.commit()
else: 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.commit()
db.close() db.close()

@ -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) logging.debug('BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path)
if len(subtitles_list) > 0: if len(subtitles_list) > 0:
try: try:
best_subtitle = subtitles_list[0] pdownload_result = False
download_subtitles([best_subtitle], providers=providers, provider_configs=providers_auth) for subtitle in subtitles_list:
logging.debug('BAZARR Subtitles file downloaded for this file:' + path) 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: except Exception as e:
logging.exception('BAZARR Error downloading subtitles for this file ' + path) logging.exception('BAZARR Error downloading subtitles for this file ' + path)
return None return None
else: else:
try: 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: if used_sceneName == True:
video = scan_video(path) video = scan_video(path)
single = get_general_settings()[7] single = get_general_settings()[7]
if single is True: 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: else:
result = save_subtitles(video, [best_subtitle], encoding='utf-8') result = save_subtitles(video, [subtitle], encoding='utf-8')
except Exception as e: except Exception as e:
logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path)
pass pass
else: else:
if len(result) > 0: downloaded_provider = result[0].provider_name
downloaded_provider = result[0].provider_name downloaded_language = language_from_alpha3(result[0].language.alpha3)
downloaded_language = language_from_alpha3(result[0].language.alpha3) downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3)
downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3) downloaded_language_code3 = result[0].language.alpha3
downloaded_language_code3 = result[0].language.alpha3 downloaded_path = get_subtitle_path(path, language=language_set)
downloaded_path = get_subtitle_path(path, language=language_set) logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path)
logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) if used_sceneName == True:
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:
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:
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:
try: if os.name == 'nt':
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)
# wait for the process to terminate # 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': process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out = out.decode(encoding) # wait for the process to terminate
out, err = process.communicate()
except: if os.name == 'nt':
if out == "": out = out.decode(encoding)
logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution')
else: except:
logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out) 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: else:
if out == "": logging.info('BAZARR Post-processing result for file ' + path + ' : ' + 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)
return message 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
else: else:
logging.debug('BAZARR No subtitles were found for this file: ' + path)
return None return None
logging.debug('BAZARR Ended searching subtitles for file: ' + path) 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 pass
else: else:
try: try:
best_subtitle = subtitle download_subtitles([subtitle], providers=provider, provider_configs=providers_auth)
download_subtitles([best_subtitle], providers=provider, provider_configs=providers_auth)
logging.debug('BAZARR Subtitles file downloaded for this file:' + path) logging.debug('BAZARR Subtitles file downloaded for this file:' + path)
except Exception as e: except Exception as e:
logging.exception('BAZARR Error downloading subtitles for this file ' + path) 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: else:
single = get_general_settings()[7] single = get_general_settings()[7]
try: 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: if used_sceneName == True:
video = scan_video(path) video = scan_video(path)
if single is True: 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: else:
result = save_subtitles(video, [best_subtitle], encoding='utf-8') result = save_subtitles(video, [subtitle], encoding='utf-8')
except Exception as e: except Exception as e:
logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path) logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path)
return None return None
@ -323,7 +328,7 @@ def manual_download_subtitle(path, language, hi, subtitle, provider, providers_a
return message return message
else: 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 return None
logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path) logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path)

@ -1,4 +1,4 @@
bazarr_version = '0.6.7' bazarr_version = '0.6.7.1'
import gc import gc
gc.enable() gc.enable()
@ -17,6 +17,8 @@ import signal
import sqlite3 import sqlite3
from init import * from init import *
from update_db import * from update_db import *
from notifier import update_notifier
update_notifier()
from get_settings import get_general_settings, get_proxy_settings 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 from bottle import route, run, template, static_file, request, redirect, response, HTTPError, app, hook
import bottle import bottle
bottle.TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(__file__), '../views/')) bottle.TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(__file__), '../views/'))
bottle.debug(True) if "PYCHARM_HOSTED" in os.environ:
bottle.TEMPLATES.clear() 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 cherrypy.wsgiserver import CherryPyWSGIServer
@ -215,7 +220,7 @@ def wizard():
@route(base_url + 'save_wizard', method='POST') @route(base_url + 'save_wizard', method='POST')
@custom_auth_basic(check_credentials) @custom_auth_basic(check_credentials)
def save_settings(): def save_wizard():
authorize() authorize()
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)
@ -684,7 +689,7 @@ def movies():
offset = (int(page) - 1) * page_size offset = (int(page) - 1) * page_size
max_page = int(math.ceil(missing_count / (page_size + 0.0))) 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() data = c.fetchall()
c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1") c.execute("SELECT code2, name FROM table_settings_languages WHERE enabled = 1")
languages = c.fetchall() languages = c.fetchall()
@ -1294,197 +1299,16 @@ def save_settings():
with open(config_file, 'wb') as f: with open(config_file, 'wb') as f:
cfg.write(f) cfg.write(f)
settings_notifier_Boxcar_enabled = request.forms.get('settings_notifier_Boxcar_enabled') notifiers = c.execute("SELECT * FROM table_settings_notifier ORDER BY name").fetchall()
if settings_notifier_Boxcar_enabled == 'on': for notifier in notifiers:
settings_notifier_Boxcar_enabled = 1 enabled = request.forms.get('settings_notifier_' + notifier[0] + '_enabled')
else: if enabled == 'on':
settings_notifier_Boxcar_enabled = 0 enabled = 1
settings_notifier_Boxcar_url = request.forms.get('settings_notifier_Boxcar_url') else:
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Boxcar'", (settings_notifier_Boxcar_enabled, settings_notifier_Boxcar_url)) enabled = 0
notifier_url = request.forms.get('settings_notifier_' + notifier[0] + '_url')
settings_notifier_Faast_enabled = request.forms.get('settings_notifier_Faast_enabled') c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = ?",
if settings_notifier_Faast_enabled == 'on': (enabled, notifier_url, notifier[0]))
settings_notifier_Faast_enabled = 1
else:
settings_notifier_Faast_enabled = 0
settings_notifier_Faast_url = request.forms.get('settings_notifier_Faast_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Faast'", (settings_notifier_Faast_enabled, settings_notifier_Faast_url))
settings_notifier_Growl_enabled = request.forms.get('settings_notifier_Growl_enabled')
if settings_notifier_Growl_enabled == 'on':
settings_notifier_Growl_enabled = 1
else:
settings_notifier_Growl_enabled = 0
settings_notifier_Growl_url = request.forms.get('settings_notifier_Growl_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Growl'", (settings_notifier_Growl_enabled, settings_notifier_Growl_url))
settings_notifier_Join_enabled = request.forms.get('settings_notifier_Join_enabled')
if settings_notifier_Join_enabled == 'on':
settings_notifier_Join_enabled = 1
else:
settings_notifier_Join_enabled = 0
settings_notifier_Join_url = request.forms.get('settings_notifier_Join_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Join'", (settings_notifier_Join_enabled, settings_notifier_Join_url))
settings_notifier_KODI_enabled = request.forms.get('settings_notifier_KODI_enabled')
if settings_notifier_KODI_enabled == 'on':
settings_notifier_KODI_enabled = 1
else:
settings_notifier_KODI_enabled = 0
settings_notifier_KODI_url = request.forms.get('settings_notifier_KODI_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'KODI'", (settings_notifier_KODI_enabled, settings_notifier_KODI_url))
settings_notifier_Mattermost_enabled = request.forms.get('settings_notifier_Mattermost_enabled')
if settings_notifier_Mattermost_enabled == 'on':
settings_notifier_Mattermost_enabled = 1
else:
settings_notifier_Mattermost_enabled = 0
settings_notifier_Mattermost_url = request.forms.get('settings_notifier_Mattermost_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Mattermost'", (settings_notifier_Mattermost_enabled, settings_notifier_Mattermost_url))
settings_notifier_NMA_enabled = request.forms.get('settings_notifier_Notify My Android_enabled')
if settings_notifier_NMA_enabled == 'on':
settings_notifier_NMA_enabled = 1
else:
settings_notifier_NMA_enabled = 0
settings_notifier_NMA_url = request.forms.get('settings_notifier_Notify My Android_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Notify My Android'", (settings_notifier_NMA_enabled, settings_notifier_NMA_url))
settings_notifier_Prowl_enabled = request.forms.get('settings_notifier_Prowl_enabled')
if settings_notifier_Prowl_enabled == 'on':
settings_notifier_Prowl_enabled = 1
else:
settings_notifier_Prowl_enabled = 0
settings_notifier_Prowl_url = request.forms.get('settings_notifier_Prowl_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Prowl'", (settings_notifier_Prowl_enabled, settings_notifier_Prowl_url))
settings_notifier_Pushalot_enabled = request.forms.get('settings_notifier_Pushalot_enabled')
if settings_notifier_Pushalot_enabled == 'on':
settings_notifier_Pushalot_enabled = 1
else:
settings_notifier_Pushalot_enabled = 0
settings_notifier_Pushalot_url = request.forms.get('settings_notifier_Pushalot_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushalot'", (settings_notifier_Pushalot_enabled, settings_notifier_Pushalot_url))
settings_notifier_PushBullet_enabled = request.forms.get('settings_notifier_PushBullet_enabled')
if settings_notifier_PushBullet_enabled == 'on':
settings_notifier_PushBullet_enabled = 1
else:
settings_notifier_PushBullet_enabled = 0
settings_notifier_PushBullet_url = request.forms.get('settings_notifier_PushBullet_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'PushBullet'", (settings_notifier_PushBullet_enabled, settings_notifier_PushBullet_url))
settings_notifier_Pushjet_enabled = request.forms.get('settings_notifier_Pushjet_enabled')
if settings_notifier_Pushjet_enabled == 'on':
settings_notifier_Pushjet_enabled = 1
else:
settings_notifier_Pushjet_enabled = 0
settings_notifier_Pushjet_url = request.forms.get('settings_notifier_Pushjet_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushjet'", (settings_notifier_Pushjet_enabled, settings_notifier_Pushjet_url))
settings_notifier_Pushover_enabled = request.forms.get('settings_notifier_Pushover_enabled')
if settings_notifier_Pushover_enabled == 'on':
settings_notifier_Pushover_enabled = 1
else:
settings_notifier_Pushover_enabled = 0
settings_notifier_Pushover_url = request.forms.get('settings_notifier_Pushover_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Pushover'", (settings_notifier_Pushover_enabled, settings_notifier_Pushover_url))
settings_notifier_RocketChat_enabled = request.forms.get('settings_notifier_Rocket.Chat_enabled')
if settings_notifier_RocketChat_enabled == 'on':
settings_notifier_RocketChat_enabled = 1
else:
settings_notifier_RocketChat_enabled = 0
settings_notifier_RocketChat_url = request.forms.get('settings_notifier_Rocket.Chat_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Rocket.Chat'", (settings_notifier_RocketChat_enabled, settings_notifier_RocketChat_url))
settings_notifier_Slack_enabled = request.forms.get('settings_notifier_Slack_enabled')
if settings_notifier_Slack_enabled == 'on':
settings_notifier_Slack_enabled = 1
else:
settings_notifier_Slack_enabled = 0
settings_notifier_Slack_url = request.forms.get('settings_notifier_Slack_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Slack'", (settings_notifier_Slack_enabled, settings_notifier_Slack_url))
settings_notifier_SuperToasty_enabled = request.forms.get('settings_notifier_Super Toasty_enabled')
if settings_notifier_SuperToasty_enabled == 'on':
settings_notifier_SuperToasty_enabled = 1
else:
settings_notifier_SuperToasty_enabled = 0
settings_notifier_SuperToasty_url = request.forms.get('settings_notifier_Super Toasty_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Super Toasty'", (settings_notifier_SuperToasty_enabled, settings_notifier_SuperToasty_url))
settings_notifier_Telegram_enabled = request.forms.get('settings_notifier_Telegram_enabled')
if settings_notifier_Telegram_enabled == 'on':
settings_notifier_Telegram_enabled = 1
else:
settings_notifier_Telegram_enabled = 0
settings_notifier_Telegram_url = request.forms.get('settings_notifier_Telegram_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Telegram'", (settings_notifier_Telegram_enabled, settings_notifier_Telegram_url))
settings_notifier_Twitter_enabled = request.forms.get('settings_notifier_Twitter_enabled')
if settings_notifier_Twitter_enabled == 'on':
settings_notifier_Twitter_enabled = 1
else:
settings_notifier_Twitter_enabled = 0
settings_notifier_Twitter_url = request.forms.get('settings_notifier_Twitter_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Twitter'", (settings_notifier_Twitter_enabled, settings_notifier_Twitter_url))
settings_notifier_XBMC_enabled = request.forms.get('settings_notifier_XBMC_enabled')
if settings_notifier_XBMC_enabled == 'on':
settings_notifier_XBMC_enabled = 1
else:
settings_notifier_XBMC_enabled = 0
settings_notifier_XBMC_url = request.forms.get('settings_notifier_XBMC_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'XBMC'", (settings_notifier_XBMC_enabled, settings_notifier_XBMC_url))
settings_notifier_Discord_enabled = request.forms.get('settings_notifier_Discord_enabled')
if settings_notifier_Discord_enabled == 'on':
settings_notifier_Discord_enabled = 1
else:
settings_notifier_Discord_enabled = 0
settings_notifier_Discord_url = request.forms.get('settings_notifier_Discord_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Discord'", (settings_notifier_Discord_enabled, settings_notifier_Discord_url))
settings_notifier_E_Mail_enabled = request.forms.get('settings_notifier_E-Mail_enabled')
if settings_notifier_E_Mail_enabled == 'on':
settings_notifier_E_Mail_enabled = 1
else:
settings_notifier_E_Mail_enabled = 0
settings_notifier_E_Mail_url = request.forms.get('settings_notifier_E-Mail_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'E-Mail'", (settings_notifier_E_Mail_enabled, settings_notifier_E_Mail_url))
settings_notifier_Emby_enabled = request.forms.get('settings_notifier_Emby_enabled')
if settings_notifier_Emby_enabled == 'on':
settings_notifier_Emby_enabled = 1
else:
settings_notifier_Emby_enabled = 0
settings_notifier_Emby_url = request.forms.get('settings_notifier_Emby_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Emby'", (settings_notifier_Emby_enabled, settings_notifier_Emby_url))
settings_notifier_IFTTT_enabled = request.forms.get('settings_notifier_IFTTT_enabled')
if settings_notifier_IFTTT_enabled == 'on':
settings_notifier_IFTTT_enabled = 1
else:
settings_notifier_IFTTT_enabled = 0
settings_notifier_IFTTT_url = request.forms.get('settings_notifier_IFTTT_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'IFTTT'", (settings_notifier_IFTTT_enabled, settings_notifier_IFTTT_url))
settings_notifier_Stride_enabled = request.forms.get('settings_notifier_Stride_enabled')
if settings_notifier_Stride_enabled == 'on':
settings_notifier_Stride_enabled = 1
else:
settings_notifier_Stride_enabled = 0
settings_notifier_Stride_url = request.forms.get('settings_notifier_Stride_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Stride'", (settings_notifier_Stride_enabled, settings_notifier_Stride_url))
settings_notifier_Windows_enabled = request.forms.get('settings_notifier_Windows_enabled')
if settings_notifier_Windows_enabled == 'on':
settings_notifier_Windows_enabled = 1
else:
settings_notifier_Windows_enabled = 0
settings_notifier_Windows_url = request.forms.get('settings_notifier_Windows_url')
c.execute("UPDATE table_settings_notifier SET enabled = ?, url = ? WHERE name = 'Windows'", (settings_notifier_Windows_enabled, settings_notifier_Windows_url))
conn.commit() conn.commit()
c.close() c.close()

@ -3,6 +3,41 @@ from get_argv import config_dir
import apprise import apprise
import os import os
import sqlite3 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(): 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(config_dir, 'db/bazarr.db'), timeout=30)

@ -29,43 +29,23 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True:
except: except:
pass 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: try:
c.execute('alter table table_shows add column "sortTitle" "text"') c.execute('alter table table_shows add column "sortTitle" "text"')
except: except:
pass pass
try: 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`) )') c.execute('alter table table_movies add column "sortTitle" "text"')
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 )')
except: except:
pass pass
try: 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 = "Kodi/XBMC"').fetchall()
rows = c.execute('SELECT name FROM table_settings_notifier WHERE name = "Discord"').fetchall()
if len(rows) == 0: if len(rows) == 0:
providers = ['Discord', 'E-Mail', 'Emby', 'IFTTT', 'Stride', 'Windows'] providers = [['KODI', 'Kodi/XBMC'], ['Windows', 'Windows Notification'], ['Super Toasty', 'Toasty'],
for provider in providers: ['PushBullet', 'Pushbullet'], ['Mattermost', 'MatterMost']]
c.execute('INSERT INTO `table_settings_notifier` (name, enabled) VALUES (?, ?);', (provider, '0')) for provider_old, provider_new in providers:
except: c.execute('UPDATE table_settings_notifier SET name=? WHERE name=?', (provider_new, provider_old))
pass
try:
c.execute('CREATE TABLE `system` ( `configured` TEXT, `updated` TEXT)')
c.execute('INSERT INTO `system` (configured, updated) VALUES (?, ?);', ('0', '0'))
except: except:
pass pass
@ -92,13 +72,13 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True:
else: else:
from scheduler import execute_now from scheduler import execute_now
from get_settings import get_general_settings from get_settings import get_general_settings
integration = get_general_settings() integration = get_general_settings()
if integration[12] is True: if integration[12] is True:
execute_now('sync_episodes') execute_now('sync_episodes')
if integration[13] is True: if integration[13] is True:
execute_now('update_movies') execute_now('update_movies')
try: try:
c.execute('alter table table_episodes add column "monitored" TEXT') c.execute('alter table table_episodes add column "monitored" TEXT')
db.commit() db.commit()
@ -107,6 +87,7 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True:
else: else:
from scheduler import execute_now from scheduler import execute_now
from get_settings import get_general_settings from get_settings import get_general_settings
integration = get_general_settings() integration = get_general_settings()
if integration[12] is True: if integration[12] is True:
execute_now('sync_episodes') execute_now('sync_episodes')
@ -119,6 +100,7 @@ if os.path.exists(os.path.join(config_dir, 'db/bazarr.db')) == True:
else: else:
from scheduler import execute_now from scheduler import execute_now
from get_settings import get_general_settings from get_settings import get_general_settings
integration = get_general_settings() integration = get_general_settings()
if integration[13] is True: if integration[13] is True:
execute_now('update_movies') execute_now('update_movies')

@ -32,6 +32,7 @@ from .AppriseAsset import AppriseAsset
from . import NotifyBase from . import NotifyBase
from . import plugins from . import plugins
from . import __version__
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -54,6 +55,9 @@ def __load_matrix():
# Get our plugin # Get our plugin
plugin = getattr(plugins, entry) plugin = getattr(plugins, entry)
if not hasattr(plugin, 'app_id'): # pragma: no branch
# Filter out non-notification modules
continue
# Load protocol(s) if defined # Load protocol(s) if defined
proto = getattr(plugin, 'protocol', None) proto = getattr(plugin, 'protocol', None)
@ -277,6 +281,52 @@ class Apprise(object):
return status 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): def __len__(self):
""" """
Returns the number of servers loaded Returns the number of servers loaded

@ -62,12 +62,13 @@ class AppriseAsset(object):
# Image URL Mask # Image URL Mask
image_url_mask = \ image_url_mask = \
'http://nuxref.com/apprise/themes/{THEME}/' \ 'https://github.com/caronc/apprise/raw/master/apprise/assets/' \
'apprise-{TYPE}-{XY}{EXTENSION}' 'themes/{THEME}/apprise-{TYPE}-{XY}{EXTENSION}'
# Application Logo # Application Logo
image_url_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
image_path_mask = abspath(join( image_path_mask = abspath(join(
@ -216,6 +217,21 @@ class AppriseAsset(object):
return None 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 @staticmethod
def hex_to_rgb(value): def hex_to_rgb(value):
""" """

@ -34,7 +34,6 @@ except ImportError:
from ..utils import parse_url from ..utils import parse_url
from ..utils import parse_bool from ..utils import parse_bool
from ..utils import is_hostname from ..utils import is_hostname
from ..common import NOTIFY_IMAGE_SIZES
from ..common import NOTIFY_TYPES from ..common import NOTIFY_TYPES
from ..common import NotifyFormat from ..common import NotifyFormat
from ..common import NOTIFY_FORMATS from ..common import NOTIFY_FORMATS
@ -70,7 +69,8 @@ PATHSPLIT_LIST_DELIM = re.compile(r'[ \t\r\n,\\/]+')
# Regular expression retrieved from: # Regular expression retrieved from:
# http://www.regular-expressions.info/email.html # http://www.regular-expressions.info/email.html
IS_EMAIL_RE = re.compile( IS_EMAIL_RE = re.compile(
r"(?P<userid>[a-z0-9$%+=_~-]+" r"((?P<label>[^+]+)\+)?"
r"(?P<userid>[a-z0-9$%=_~-]+"
r"(?:\.[a-z0-9$%+=_~-]+)" r"(?:\.[a-z0-9$%+=_~-]+)"
r"*)@(?P<domain>(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+" r"*)@(?P<domain>(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+"
r"[a-z0-9](?:[a-z0-9-]*" r"[a-z0-9](?:[a-z0-9-]*"
@ -84,16 +84,25 @@ class NotifyBase(object):
This is the base class for all notification services This is the base class for all notification services
""" """
# The default descriptive name associated with the Notification
service_name = None
# The services URL
service_url = None
# The default simple (insecure) protocol # The default simple (insecure) protocol
# all inheriting entries must provide their protocol lookup # all inheriting entries must provide their protocol lookup
# protocol:// (in this example they would specify 'protocol') # protocol:// (in this example they would specify 'protocol')
protocol = '' protocol = None
# The default secure protocol # The default secure protocol
# all inheriting entries must provide their protocol lookup # all inheriting entries must provide their protocol lookup
# protocols:// (in this example they would specify 'protocols') # protocols:// (in this example they would specify 'protocols')
# This value can be the same as the defined protocol. # This value can be the same as the defined protocol.
secure_protocol = '' secure_protocol = None
# A URL that takes you to the setup/help of the specific protocol
setup_url = None
# Most Servers do not like more then 1 request per 5 seconds, so 5.5 gives # Most Servers do not like more then 1 request per 5 seconds, so 5.5 gives
# us a safe play range... # us a safe play range...

@ -63,9 +63,18 @@ class NotifyBoxcar(NotifyBase):
A wrapper for Boxcar Notifications A wrapper for Boxcar Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Boxcar'
# The services URL
service_url = 'https://boxcar.io/'
# All boxcar notifications are secure # All boxcar notifications are secure
secure_protocol = 'boxcar' secure_protocol = 'boxcar'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_boxcar'
# Boxcar URL # Boxcar URL
notify_url = 'https://boxcar-api.io/api/push/' notify_url = 'https://boxcar-api.io/api/push/'

@ -49,10 +49,18 @@ class NotifyDiscord(NotifyBase):
A wrapper to Discord Notifications A wrapper to Discord Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Discord'
# The services URL
service_url = 'https://discordapp.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'discord' secure_protocol = 'discord'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_discored'
# Discord Webhook # Discord Webhook
notify_url = 'https://discordapp.com/api/webhooks' notify_url = 'https://discordapp.com/api/webhooks'

@ -47,7 +47,7 @@ WEBBASE_LOOKUP_TABLE = (
# Google GMail # Google GMail
( (
'Google Mail', 'Google Mail',
re.compile(r'^(?P<id>[^@]+)@(?P<domain>gmail\.com)$', re.I), re.compile(r'^((?P<label>[^+]+)\+)?(?P<id>[^@]+)@(?P<domain>gmail\.com)$', re.I),
{ {
'port': 587, 'port': 587,
'smtp_host': 'smtp.gmail.com', 'smtp_host': 'smtp.gmail.com',
@ -59,7 +59,7 @@ WEBBASE_LOOKUP_TABLE = (
# Pronto Mail # Pronto Mail
( (
'Pronto Mail', 'Pronto Mail',
re.compile(r'^(?P<id>[^@]+)@(?P<domain>prontomail\.com)$', re.I), re.compile(r'^((?P<label>[^+]+)\+)?(?P<id>[^@]+)@(?P<domain>prontomail\.com)$', re.I),
{ {
'port': 465, 'port': 465,
'smtp_host': 'secure.emailsrvr.com', 'smtp_host': 'secure.emailsrvr.com',
@ -71,7 +71,7 @@ WEBBASE_LOOKUP_TABLE = (
# Microsoft Hotmail # Microsoft Hotmail
( (
'Microsoft Hotmail', 'Microsoft Hotmail',
re.compile(r'^(?P<id>[^@]+)@(?P<domain>(hotmail|live)\.com)$', re.I), re.compile(r'^((?P<label>[^+]+)\+)?(?P<id>[^@]+)@(?P<domain>(hotmail|live)\.com)$', re.I),
{ {
'port': 587, 'port': 587,
'smtp_host': 'smtp.live.com', 'smtp_host': 'smtp.live.com',
@ -83,7 +83,7 @@ WEBBASE_LOOKUP_TABLE = (
# Yahoo Mail # Yahoo Mail
( (
'Yahoo Mail', 'Yahoo Mail',
re.compile(r'^(?P<id>[^@]+)@(?P<domain>yahoo\.(ca|com))$', re.I), re.compile(r'^((?P<label>[^+]+)\+)?(?P<id>[^@]+)@(?P<domain>yahoo\.(ca|com))$', re.I),
{ {
'port': 465, 'port': 465,
'smtp_host': 'smtp.mail.yahoo.com', 'smtp_host': 'smtp.mail.yahoo.com',
@ -95,7 +95,7 @@ WEBBASE_LOOKUP_TABLE = (
# Catch All # Catch All
( (
'Custom', 'Custom',
re.compile(r'^(?P<id>[^@]+)@(?P<domain>.+)$', re.I), re.compile(r'^((?P<label>[^+]+)\+)?(?P<id>[^@]+)@(?P<domain>.+)$', re.I),
{ {
# Setting smtp_host to None is a way of # Setting smtp_host to None is a way of
# auto-detecting it based on other parameters # auto-detecting it based on other parameters
@ -113,12 +113,18 @@ class NotifyEmail(NotifyBase):
""" """
# The default descriptive name associated with the Notification
service_name = 'E-Mail'
# The default simple (insecure) protocol # The default simple (insecure) protocol
protocol = 'mailto' protocol = 'mailto'
# The default secure protocol # The default secure protocol
secure_protocol = 'mailtos' secure_protocol = 'mailtos'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_email'
# Default Non-Encryption Port # Default Non-Encryption Port
default_port = 25 default_port = 25

@ -37,6 +37,11 @@ class NotifyEmby(NotifyBase):
""" """
A wrapper for Emby Notifications A wrapper for Emby Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Emby'
# The services URL
service_url = 'https://emby.media/'
# The default protocol # The default protocol
protocol = 'emby' protocol = 'emby'
@ -44,6 +49,9 @@ class NotifyEmby(NotifyBase):
# The default secure protocol # The default secure protocol
secure_protocol = 'embys' secure_protocol = 'embys'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_emby'
# Emby uses the http protocol with JSON requests # Emby uses the http protocol with JSON requests
emby_default_port = 8096 emby_default_port = 8096

@ -28,9 +28,18 @@ class NotifyFaast(NotifyBase):
A wrapper for Faast Notifications A wrapper for Faast Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Faast'
# The services URL
service_url = 'http://www.faast.io/'
# The default protocol (this is secure for faast) # The default protocol (this is secure for faast)
protocol = 'faast' protocol = 'faast'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_faast'
# Faast uses the http protocol with JSON requests # Faast uses the http protocol with JSON requests
notify_url = 'https://www.appnotifications.com/account/notifications.json' notify_url = 'https://www.appnotifications.com/account/notifications.json'

@ -50,9 +50,18 @@ class NotifyGrowl(NotifyBase):
""" """
# The default descriptive name associated with the Notification
service_name = 'Growl'
# The services URL
service_url = 'http://growl.info/'
# The default protocol # The default protocol
protocol = 'growl' protocol = 'growl'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_growl'
# Default Growl Port # Default Growl Port
default_port = 23053 default_port = 23053

@ -43,6 +43,18 @@ class NotifyIFTTT(NotifyBase):
""" """
# The default descriptive name associated with the Notification
service_name = 'IFTTT'
# The services URL
service_url = 'https://ifttt.com/'
# The default protocol
protocol = 'ifttt'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_ifttt'
# Even though you'll add 'Ingredients' as {{ Value1 }} to your Applets, # Even though you'll add 'Ingredients' as {{ Value1 }} to your Applets,
# you must use their lowercase value in the HTTP POST. # you must use their lowercase value in the HTTP POST.
ifttt_default_key_prefix = 'value' ifttt_default_key_prefix = 'value'
@ -65,9 +77,6 @@ class NotifyIFTTT(NotifyBase):
# value1, value2, and value3). # value1, value2, and value3).
ifttt_default_type_key = 'value3' ifttt_default_type_key = 'value3'
# The default protocol
protocol = 'ifttt'
# IFTTT uses the http protocol with JSON requests # IFTTT uses the http protocol with JSON requests
notify_url = 'https://maker.ifttt.com/trigger/{event}/with/key/{apikey}' notify_url = 'https://maker.ifttt.com/trigger/{event}/with/key/{apikey}'

@ -30,12 +30,18 @@ class NotifyJSON(NotifyBase):
A wrapper for JSON Notifications A wrapper for JSON Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'JSON'
# The default protocol # The default protocol
protocol = 'json' protocol = 'json'
# The default secure protocol # The default secure protocol
secure_protocol = 'jsons' secure_protocol = 'jsons'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_Custom_JSON'
# Allows the user to specify the NotifyImageSize object # Allows the user to specify the NotifyImageSize object
image_size = NotifyImageSize.XY_128 image_size = NotifyImageSize.XY_128

@ -64,9 +64,18 @@ class NotifyJoin(NotifyBase):
A wrapper for Join Notifications A wrapper for Join Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Join'
# The services URL
service_url = 'https://joaoapps.com/join/'
# The default protocol # The default protocol
protocol = 'join' protocol = 'join'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_join'
# Join uses the http protocol with JSON requests # Join uses the http protocol with JSON requests
notify_url = \ notify_url = \
'https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush' 'https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush'

@ -37,12 +37,21 @@ class NotifyMatterMost(NotifyBase):
A wrapper for MatterMost Notifications A wrapper for MatterMost Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'MatterMost'
# The services URL
service_url = 'https://mattermost.com/'
# The default protocol # The default protocol
protocol = 'mmost' protocol = 'mmost'
# The default secure protocol # The default secure protocol
secure_protocol = 'mmosts' secure_protocol = 'mmosts'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_mattermost'
# The default Mattermost port # The default Mattermost port
default_port = 8065 default_port = 8065

@ -59,9 +59,18 @@ class NotifyProwl(NotifyBase):
A wrapper for Prowl Notifications A wrapper for Prowl Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Prowl'
# The services URL
service_url = 'https://www.prowlapp.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'prowl' secure_protocol = 'prowl'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_prowl'
# Prowl uses the http protocol with JSON requests # Prowl uses the http protocol with JSON requests
notify_url = 'https://api.prowlapp.com/publicapi/add' notify_url = 'https://api.prowlapp.com/publicapi/add'

@ -45,9 +45,18 @@ class NotifyPushBullet(NotifyBase):
A wrapper for PushBullet Notifications A wrapper for PushBullet Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Pushbullet'
# The services URL
service_url = 'https://www.pushbullet.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'pbul' secure_protocol = 'pbul'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_pushbullet'
# PushBullet uses the http protocol with JSON requests # PushBullet uses the http protocol with JSON requests
notify_url = 'https://api.pushbullet.com/v2/pushes' notify_url = 'https://api.pushbullet.com/v2/pushes'

@ -40,9 +40,18 @@ class NotifyPushalot(NotifyBase):
A wrapper for Pushalot Notifications A wrapper for Pushalot Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Pushalot'
# The services URL
service_url = 'https://pushalot.com/'
# The default protocol is always secured # The default protocol is always secured
secure_protocol = 'palot' secure_protocol = 'palot'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_pushalot'
# Pushalot uses the http protocol with JSON requests # Pushalot uses the http protocol with JSON requests
notify_url = 'https://pushalot.com/api/sendmessage' notify_url = 'https://pushalot.com/api/sendmessage'

@ -32,12 +32,21 @@ class NotifyPushjet(NotifyBase):
A wrapper for Pushjet Notifications A wrapper for Pushjet Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Pushjet'
# The services URL
service_url = 'https://pushjet.io/'
# The default protocol # The default protocol
protocol = 'pjet' protocol = 'pjet'
# The default secure protocol # The default secure protocol
secure_protocol = 'pjets' secure_protocol = 'pjets'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_pushjet'
def __init__(self, **kwargs): def __init__(self, **kwargs):
""" """
Initialize Pushjet Object Initialize Pushjet Object

@ -68,9 +68,18 @@ class NotifyPushover(NotifyBase):
A wrapper for Pushover Notifications A wrapper for Pushover Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Pushover'
# The services URL
service_url = 'https://pushover.net/'
# All pushover requests are secure # All pushover requests are secure
secure_protocol = 'pover' secure_protocol = 'pover'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_pushover'
# Pushover uses the http protocol with JSON requests # Pushover uses the http protocol with JSON requests
notify_url = 'https://api.pushover.net/1/messages.json' notify_url = 'https://api.pushover.net/1/messages.json'

@ -44,12 +44,21 @@ class NotifyRocketChat(NotifyBase):
A wrapper for Notify Rocket.Chat Notifications A wrapper for Notify Rocket.Chat Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Rocket.Chat'
# The services URL
service_url = 'https://rocket.chat/'
# The default protocol # The default protocol
protocol = 'rocket' protocol = 'rocket'
# The default secure protocol # The default secure protocol
secure_protocol = 'rockets' secure_protocol = 'rockets'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_rocketchat'
# Defines the maximum allowable characters in the title # Defines the maximum allowable characters in the title
title_maxlen = 200 title_maxlen = 200

@ -71,9 +71,18 @@ class NotifySlack(NotifyBase):
A wrapper for Slack Notifications A wrapper for Slack Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Slack'
# The services URL
service_url = 'https://slack.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'slack' secure_protocol = 'slack'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_slack'
# Slack uses the http protocol with JSON requests # Slack uses the http protocol with JSON requests
notify_url = 'https://hooks.slack.com/services' notify_url = 'https://hooks.slack.com/services'

@ -61,10 +61,18 @@ class NotifyStride(NotifyBase):
A wrapper to Stride Notifications A wrapper to Stride Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Stride'
# The services URL
service_url = 'https://www.stride.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'stride' secure_protocol = 'stride'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_stride'
# Stride Webhook # Stride Webhook
notify_url = 'https://api.atlassian.com/site/{cloud_id}/' \ notify_url = 'https://api.atlassian.com/site/{cloud_id}/' \
'conversation/{convo_id}/message' 'conversation/{convo_id}/message'

@ -81,10 +81,18 @@ class NotifyTelegram(NotifyBase):
""" """
A wrapper for Telegram Notifications A wrapper for Telegram Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Telegram'
# The services URL
service_url = 'https://telegram.org/'
# The default secure protocol # The default secure protocol
secure_protocol = 'tgram' secure_protocol = 'tgram'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_telegram'
# Telegram uses the http protocol with JSON requests # Telegram uses the http protocol with JSON requests
notify_url = 'https://api.telegram.org/bot' notify_url = 'https://api.telegram.org/bot'

@ -34,9 +34,18 @@ class NotifyToasty(NotifyBase):
A wrapper for Toasty Notifications A wrapper for Toasty Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Toasty'
# The services URL
service_url = 'http://supertoasty.com/'
# The default protocol # The default protocol
protocol = 'toasty' protocol = 'toasty'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_toasty'
# Toasty uses the http protocol with JSON requests # Toasty uses the http protocol with JSON requests
notify_url = 'http://api.supertoasty.com/notify/' notify_url = 'http://api.supertoasty.com/notify/'

@ -26,9 +26,18 @@ class NotifyTwitter(NotifyBase):
""" """
# The default descriptive name associated with the Notification
service_name = 'Twitter'
# The services URL
service_url = 'https://twitter.com/'
# The default secure protocol # The default secure protocol
secure_protocol = 'tweet' secure_protocol = 'tweet'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_twitter'
# The maximum allowable characters allowed in the body per message # The maximum allowable characters allowed in the body per message
# This is used during a Private DM Message Size (not Public Tweets # This is used during a Private DM Message Size (not Public Tweets
# which are limited to 240 characters) # which are limited to 240 characters)

@ -47,9 +47,15 @@ class NotifyWindows(NotifyBase):
A wrapper for local Windows Notifications A wrapper for local Windows Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Windows Notification'
# The default protocol # The default protocol
protocol = 'windows' protocol = 'windows'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_windows'
# Allows the user to specify the NotifyImageSize object # Allows the user to specify the NotifyImageSize object
image_size = NotifyImageSize.XY_128 image_size = NotifyImageSize.XY_128

@ -31,12 +31,21 @@ class NotifyXBMC(NotifyBase):
A wrapper for XBMC/KODI Notifications A wrapper for XBMC/KODI Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'Kodi/XBMC'
# The services URL
service_url = 'http://kodi.tv/'
# The default protocols # The default protocols
protocol = ('xbmc', 'kodi') protocol = ('xbmc', 'kodi')
# The default secure protocols # The default secure protocols
secure_protocol = ('xbmc', 'kodis') secure_protocol = ('xbmc', 'kodis')
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_kodi'
# XBMC uses the http protocol with JSON requests # XBMC uses the http protocol with JSON requests
xbmc_default_port = 8080 xbmc_default_port = 8080

@ -30,12 +30,18 @@ class NotifyXML(NotifyBase):
A wrapper for XML Notifications A wrapper for XML Notifications
""" """
# The default descriptive name associated with the Notification
service_name = 'XML'
# The default protocol # The default protocol
protocol = 'xml' protocol = 'xml'
# The default secure protocol # The default secure protocol
secure_protocol = 'xmls' secure_protocol = 'xmls'
# A URL that takes you to the setup/help of the specific protocol
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_Custom_XML'
# Allows the user to specify the NotifyImageSize object # Allows the user to specify the NotifyImageSize object
image_size = NotifyImageSize.XY_128 image_size = NotifyImageSize.XY_128

@ -1,4 +1,4 @@
apprise=0.0.9 apprise=0.5.2
apscheduler=3.5.1 apscheduler=3.5.1
babelfish=0.5.5 babelfish=0.5.5
backports.functools-lru-cache=1.5 backports.functools-lru-cache=1.5
@ -6,12 +6,11 @@ Beaker=1.10.0
bottle=0.12.13 bottle=0.12.13
bottle-fdsend=0.1.1 bottle-fdsend=0.1.1
chardet=3.0.4 chardet=3.0.4
cherrypy=8.9.1 <-- Never update
configparser=3.5.0 configparser=3.5.0
dogpile.cache=0.6.5 dogpile.cache=0.6.5
enzyme=0.4.1 enzyme=0.4.1
gitpython=2.1.9 gitpython=2.1.9
guessit=3.0.0 guessit=2.1.4
langdetect=1.0.7 langdetect=1.0.7
py-pretty=1 py-pretty=1
pycountry=18.2.23 pycountry=18.2.23

@ -41,6 +41,12 @@
.fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; } .fast.backward, .backward, .forward, .fast.forward { pointer-events: auto; }
.fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; } .fast.backward.disabled, .backward.disabled, .forward.disabled, .fast.forward.disabled { pointer-events: none; }
.ui.progress:last-child {margin: 0 0 0em !important;} .ui.progress:last-child {margin: 0 0 0em !important;}
.ui.progress .bar>.progress {
right: auto;
left: .5em;
color: rgba(0, 0, 0, 0.60);
}
</style> </style>
</head> </head>
<body> <body>

@ -33,6 +33,9 @@
opacity: 0.45 !important; opacity: 0.45 !important;
pointer-events: none !important; pointer-events: none !important;
} }
[data-tooltip]:after {
z-index: 2;
}
</style> </style>
</head> </head>
<body> <body>

@ -40,7 +40,10 @@
width: 640px; width: 640px;
height: 480px; height: 480px;
margin: 20px; margin: 20px;
} }
[data-tooltip]:after {
z-index: 2;
}
</style> </style>
</head> </head>
<body> <body>

Loading…
Cancel
Save