-
-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apprise Integration #2796
Apprise Integration #2796
Changes from 8 commits
f8129e2
1b04ecb
43847c3
e39d44a
5efb9df
cc97db6
6cff4ce
bd882fe
82d1b23
a34ef89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# Main requirements | ||
# Note that not all sub-dependencies are listed, but only ones we know could cause trouble | ||
apprise==1.7.2 | ||
sabctools==8.1.0 | ||
cheetah3==3.2.6.post1 | ||
cffi==1.16.0 | ||
|
@@ -54,7 +55,29 @@ notify2==0.3.1; sys_platform != 'win32' and sys_platform != 'darwin' | |
# Uncomment line below or manually install after installing requirements. | ||
# pygobject>=3.10.2; sys_platform != 'win32' and sys_platform != 'darwin' | ||
|
||
# PyYAML does not have binary packages for Mac Users | ||
PyYAML==6.0.1 --no-binary=PyYAML; sys_platform == 'darwin' | ||
PyYAML==6.0.1; sys_platform != 'darwin' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can remove this special |
||
|
||
# Apprise Requirements | ||
requests==2.31.0 | ||
requests-oauthlib==1.3.1 | ||
Safihre marked this conversation as resolved.
Show resolved
Hide resolved
|
||
markdown==3.5.2 | ||
paho-mqtt==1.6.1 | ||
|
||
# Requests Requirements | ||
charset_normalizer==3.3.2 | ||
idna==3.6 | ||
urllib3==2.2.0 | ||
certifi==2024.2.2 | ||
oauthlib==3.2.2 | ||
PyJWT==2.8.0 | ||
blinker==1.7.0 | ||
|
||
# Markdown Requirements | ||
importlib-metadata==7.0.1 | ||
|
||
# Optional support for system power management on *nix. | ||
# Requires libdbus-1-dev to be installed. | ||
# Uncomment line below or manually install after installing requirements. | ||
# dbus-python; sys_platform != 'win32' and sys_platform != 'darwin' | ||
# dbus-python; sys_platform != 'win32' and sys_platform != 'darwin' |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,8 @@ | |
import http.client | ||
import json | ||
from threading import Thread | ||
from typing import Optional, Dict | ||
from typing import Optional, Dict, Union | ||
import apprise | ||
Safihre marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import sabnzbd | ||
import sabnzbd.cfg | ||
|
@@ -115,6 +116,25 @@ def get_prio(notification_type: str, section: str) -> int: | |
return -1000 | ||
|
||
|
||
def get_target(notification_type: str, section: str) -> Union[str, bool, None]: | ||
"""Check target of `notification_type` in `section` if enabled is set""" | ||
try: | ||
if sabnzbd.config.get_config(section, "%s_target_%s_enable" % (section, notification_type))() > 0: | ||
result = sabnzbd.config.get_config(section, "%s_target_%s" % (section, notification_type))().strip() | ||
if result: | ||
return result | ||
|
||
else: | ||
# Use Default | ||
return True | ||
|
||
except TypeError: | ||
logging.debug("Incorrect Notify option %s:%s_target_%s", section, section, notification_type) | ||
return None | ||
|
||
return False | ||
|
||
|
||
def check_cat(section: str, job_cat: str, keyword: Optional[str] = None) -> bool: | ||
"""Check if `job_cat` is enabled in `section`. | ||
* = All, if no other categories selected. | ||
|
@@ -165,6 +185,11 @@ def send_notification( | |
if sabnzbd.cfg.pushbullet_apikey() and check_classes(notification_type, "pushbullet"): | ||
Thread(target=send_pushbullet, args=(title, msg, notification_type)).start() | ||
|
||
# Apprise | ||
if sabnzbd.cfg.apprise_enable() and check_cat("apprise", job_cat): | ||
if sabnzbd.cfg.apprise_urls() and check_classes(notification_type, "apprise"): | ||
Thread(target=send_apprise, args=(title, msg, notification_type)).start() | ||
|
||
# Notification script. | ||
if sabnzbd.cfg.nscript_enable() and check_cat("nscript", job_cat): | ||
if sabnzbd.cfg.nscript_script(): | ||
|
@@ -265,6 +290,91 @@ def send_prowl(title, msg, notification_type, force=False, test=None): | |
return "" | ||
|
||
|
||
def send_apprise(title, msg, notification_type, force=False, test=None): | ||
"""send apprise message""" | ||
logging.debug("Sending Apprise notification") | ||
if test: | ||
urls = test.get("apprise_urls") | ||
else: | ||
urls = sabnzbd.cfg.apprise_urls() | ||
|
||
# Notification mapper | ||
n_map = { | ||
# Startup/Shutdown | ||
"startup": apprise.common.NotifyType.INFO, | ||
# Pause/Resume | ||
"pause_resume": apprise.common.NotifyType.INFO, | ||
# Added NZB | ||
"download": apprise.common.NotifyType.INFO, | ||
# Post-processing started | ||
"pp": apprise.common.NotifyType.INFO, | ||
# Job finished | ||
"complete": apprise.common.NotifyType.SUCCESS, | ||
# Job failed | ||
"failed": apprise.common.NotifyType.FAILURE, | ||
# Warning | ||
"warning": apprise.common.NotifyType.WARNING, | ||
# Error | ||
"error": apprise.common.NotifyType.FAILURE, | ||
# Disk full | ||
"disk_full": apprise.common.NotifyType.WARNING, | ||
# Queue finished | ||
"queue_done": apprise.common.NotifyType.INFO, | ||
# User logged in | ||
"new_login": apprise.common.NotifyType.INFO, | ||
# Other Messages | ||
"other": apprise.common.NotifyType.INFO, | ||
} | ||
|
||
# Prepare our Asset Object | ||
asset = apprise.AppriseAsset( | ||
app_id="SABnzbd", | ||
app_desc="SABnzbd Notification", | ||
app_url="https://sabnzbd.org/", | ||
image_path_mask=os.path.join(os.path.dirname(__file__), "apprise", "apprise-{TYPE}.png"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should have any images in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want me to hardcode This was why i originally stored the images here and then cross-referenced them here via both web and locally (it's now i do it with apprise, so it's just 1 directory to manage - link. At the end of the day, to truly get the best use of Apprise, you need some images stored locally. If you want, i can just not set a mask over-ride at all, and you'll use the ones that ship with Apprise instead of some custom SABnzbd ones i rigged up quickly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can fix this one up when all the code is fine, we have some constants to handle this :) |
||
image_url_mask="https://raw.githubusercontent.com/sabnzbd/sabnzbd.github.io/master/images/icons/apprise/{TYPE}.png", | ||
image_url_logo="https://raw.githubusercontent.com/sabnzbd/sabnzbd.github.io/master/images/icons/" | ||
"apple-touch-icon-180x180-precomposed.png", | ||
) | ||
|
||
# Initialize our Apprise Instance | ||
apobj = apprise.Apprise(asset=asset) | ||
|
||
if not test: | ||
# Get a list of tags that are set to use the common list | ||
if target := get_target(notification_type, "apprise"): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah sorry I missed that about the empty string! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no worries; it makes a bit more sense now.. True - use Default, otherwise string means there are URLs to load. |
||
if target is True: | ||
# Use default list | ||
apobj.add(urls) | ||
|
||
else: # Target is string of URLs to over-ride with | ||
# Store our URL and assign our key | ||
if not apobj.add(target): | ||
logging.warning( | ||
"Key: %s - %s", notification_type, T("One or more Apprise URLs could not be loaded.") | ||
) | ||
|
||
else: | ||
# Nothing to notify | ||
return "" | ||
|
||
else: | ||
# Use default list | ||
apobj.add(urls) | ||
|
||
try: | ||
# The below notifies anything added to our list | ||
if not apobj.notify(body=msg, title=title, notify_type=n_map[notification_type], body_format="text"): | ||
return T("Failed to send one or more Apprise Notifications") | ||
|
||
except: | ||
logging.warning(T("Failed to send Apprise message")) | ||
logging.info("Traceback: ", exc_info=True) | ||
return T("Failed to send Apprise message") | ||
|
||
return "" | ||
|
||
|
||
def send_pushover(title, msg, notification_type, force=False, test=None): | ||
"""Send message to pushover""" | ||
logging.debug("Sending Pushover notification") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -671,6 +671,16 @@ | |
"explain-pushbullet_apikey": TT("Your personal Pushbullet API key (required)"), #: Pushbullet settings | ||
"opt-pushbullet_device": TT("Device"), #: Pushbullet settings | ||
"explain-pushbullet_device": TT("Device to which message should be sent"), #: Pushbullet settings | ||
"section-Apprise": TT("Apprise"), #: Header for Apprise notification section | ||
"opt-apprise_enable": TT("Enable Apprise notifications"), #: Apprise settings | ||
"explain-apprise_enable": TT("Send notifications using Apprise URLs"), #: Apprise settings | ||
"opt-apprise_urls": TT("Default Apprise URLs"), #: Apprise settings | ||
"explain-apprise_urls": TT("Use a comma and/or space to identify more then one URL"), #: Apprise settings | ||
"explain-apprise_extra_urls": TT( | ||
"Optionally override the default URL(s) for specific cases. To disable a notification for a specific category:" | ||
" simply enable it below, but do not provide it a URL to trigger off of. Alternatively, use comma and/or " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this. What can users do here? And how is it different from unchecking a notification-type? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the same thing. You can drop this if you like. Was just trying to make it clear that anything specified in the individual entries overrides the default (does not stack with it) |
||
"space to identify more then one Apprise URL overide." | ||
), #: Apprise settings | ||
"section-NScript": TT("Notification Script"), #: Header for Notification Script notification section | ||
"opt-nscript_enable": TT("Enable notification script"), #: Notification Script settings | ||
"opt-nscript_script": TT("Script"), #: Notification Script settings | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pyYAML is needed by Apprise. Zoggys advice to define these 2 entries was a really good one. I don't think we should remove it from the requirements.txt.
Also, the way it was gave every system that had the ability to leverage the binary package to do so yet still be compatible for the systems that couldn't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not removed, it's added a few lines down:
https://github.com/sabnzbd/sabnzbd/pull/2796/files#diff-4d7c51b1efe9043e44439a949dfd92e5827321b34082903477fd04876edb7552R55
But without the special
darwin
stuff, as this is handled already here:https://github.com/sabnzbd/sabnzbd/pull/2796/files#diff-ec12760430cbac327a0a49aff7d95b2803a24a5d066c654f37a78f9177fdf36aR108