Skip to content

Commit

Permalink
[21] Fix Gotify PR
Browse files Browse the repository at this point in the history
  • Loading branch information
meisnate12 committed Jan 26, 2024
1 parent fe9d074 commit 33b92f2
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 142 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Updated python-dotenv requirement to 1.0.1

# New Features
Added `monitor_existing` to sonarr and radarr. To update the monitored status of items existing in plex to match the `monitor` declared.

Added [Gotify](https://gotify.net/) as a notification service. Thanks @krstn420 for the initial code.

# Updates
Added new [BoxOfficeMojo Builder](https://metamanager.wiki/en/latest/files/builders/mojo/) - credit to @nwithan8 for the suggestion and initial code submission
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.20.0-develop20
1.20.0-develop21
2 changes: 1 addition & 1 deletion config/config.yml.template
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ notifiarr:
apikey: ####################################
gotify:
url: http://192.168.1.12:80
apikey: ####################################
token: ####################################
anidb: # Not required for AniDB builders unless you want mature content
username: ######
password: ######
Expand Down
10 changes: 5 additions & 5 deletions docs/config/gotify.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ Below is a `gotify` mapping example and the full set of attributes:
```yaml
gotify:
url: ####################################
apikey: ####################################
token: ####################################
```
| Attribute | Allowed Values | Required |
|:----------|:-----------------------------------------|:------------------------------------------:|
| `url` | Gotify Server Url | :fontawesome-solid-circle-check:{ .green } |
| `apikey` | Gotify Application API Key | :fontawesome-solid-circle-check:{ .green } |
| Attribute | Allowed Values | Required |
|:----------|:-------------------------|:------------------------------------------:|
| `url` | Gotify Server Url | :fontawesome-solid-circle-check:{ .green } |
| `token` | Gotify Application Token | :fontawesome-solid-circle-check:{ .green } |

Once you have added the apikey your config.yml you have to add `gotify` to any [webhook](webhooks.md) to send that
notification to Gotify.
Expand Down
4 changes: 2 additions & 2 deletions docs/config/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ webhooks:
| [`changes`](#changes-notifications) | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |

* Each Attribute can be either a webhook url as a string or a comma-separated list of webhooks urls.
* To send notifications to [Notifiarr](notifiarr.md) or [Gotify](gotify.md) just add `notifiarr` or `gotify` to a webhook instead of the webhook url.
* To send notifications to [Notifiarr](notifiarr.md) just add `notifiarr` to a webhook instead of the webhook url.
* To send notifications to [Gotify](gotify.md) just add `gotify` to a webhook instead of the webhook url.

## Error Notifications

Expand Down Expand Up @@ -77,7 +78,6 @@ level the error occurs.
"error": str, // Error Message
"critical": bool, // Critical Error
"server_name": str, // Server Name
"library_name": str, // Library Name
"playlist": str // Playlist Name
}
```
Expand Down
4 changes: 2 additions & 2 deletions json-schema/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,13 @@
"url": {
"type": "string"
},
"apikey": {
"token": {
"type": "string"
}
},
"required": [
"url",
"apikey"
"token"

],
"title": "gotify"
Expand Down
2 changes: 1 addition & 1 deletion json-schema/prototype_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ notifiarr:
apikey: this-is-a-placeholder-string
gotify:
url: http://192.168.1.12:80
apikey: this-is-a-placeholder-string
token: this-is-a-placeholder-string
anidb: # Not required for AniDB builders unless you want mature content
username: this-is-a-placeholder-string
password: this-is-a-placeholder-string
Expand Down
30 changes: 6 additions & 24 deletions modules/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,32 +528,14 @@ def check_for_attribute(data, attribute, parent=None, test_list=None, default=No
else:
logger.info("notifiarr attribute not found")

self.webhooks = {
"error": check_for_attribute(self.data, "error", parent="webhooks", var_type="list", default_is_none=True),
"version": check_for_attribute(self.data, "version", parent="webhooks", var_type="list", default_is_none=True),
"run_start": check_for_attribute(self.data, "run_start", parent="webhooks", var_type="list", default_is_none=True),
"run_end": check_for_attribute(self.data, "run_end", parent="webhooks", var_type="list", default_is_none=True),
"changes": check_for_attribute(self.data, "changes", parent="webhooks", var_type="list", default_is_none=True),
"delete": check_for_attribute(self.data, "delete", parent="webhooks", var_type="list", default_is_none=True)
}
self.Webhooks = Webhooks(self, self.webhooks, notifiarr=self.NotifiarrFactory)
try:
self.Webhooks.start_time_hooks(self.start_time)
if self.version[0] != "Unknown" and self.latest_version[0] != "Unknown" and self.version[1] != self.latest_version[1] or (self.version[2] and self.version[2] < self.latest_version[2]):
self.Webhooks.version_hooks(self.version, self.latest_version)
except Failed as e:
logger.stacktrace()
logger.error(f"Webhooks Error: {e}")

logger.save_errors = True
logger.separator()

self.GotifyFactory = None
if "gotify" in self.data:
logger.info("Connecting to Gotify...")
try:
self.GotifyFactory = Gotify(self, {"url": check_for_attribute(self.data, "url", parent="gotify", throw=True),
"apikey": check_for_attribute(self.data, "apikey", parent="gotify", throw=True)})
self.GotifyFactory = Gotify(self, {
"url": check_for_attribute(self.data, "url", parent="gotify", throw=True),
"token": check_for_attribute(self.data, "token", parent="gotify", throw=True)
})
except Failed as e:
if str(e).endswith("is blank"):
logger.warning(e)
Expand All @@ -572,7 +554,7 @@ def check_for_attribute(data, attribute, parent=None, test_list=None, default=No
"changes": check_for_attribute(self.data, "changes", parent="webhooks", var_type="list", default_is_none=True),
"delete": check_for_attribute(self.data, "delete", parent="webhooks", var_type="list", default_is_none=True)
}
self.Webhooks = Webhooks(self, self.webhooks, notifiarr=self.GotifyFactory)
self.Webhooks = Webhooks(self, self.webhooks, notifiarr=self.NotifiarrFactory, gotify=self.GotifyFactory)
try:
self.Webhooks.start_time_hooks(self.start_time)
if self.version[0] != "Unknown" and self.latest_version[0] != "Unknown" and self.version[1] != self.latest_version[1] or (self.version[2] and self.version[2] < self.latest_version[2]):
Expand Down Expand Up @@ -1243,7 +1225,7 @@ def check_for_attribute(data, attribute, parent=None, test_list=None, default=No
logger.info("")
logger.info(f"{display_name} library's Tautulli Connection {'Failed' if library.Tautulli is None else 'Successful'}")

library.Webhooks = Webhooks(self, {}, library=library, notifiarr=self.NotifiarrFactory or self.GotifyFactory,)
library.Webhooks = Webhooks(self, {}, library=library, notifiarr=self.NotifiarrFactory, gotify=self.GotifyFactory)
library.Overlays = Overlays(self, library)

logger.info("")
Expand Down
107 changes: 82 additions & 25 deletions modules/gotify.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,99 @@
from json import JSONDecodeError
from modules import util
from modules.util import Failed
from retrying import retry

logger = util.logger

class Gotify:
def __init__(self, config, params):
self.config = config
self.apikey = params["apikey"]
self.url = params["url"]
logger.secret(self.apikey)
self.token = params["token"]
self.url = params["url"].rstrip("/")
logger.secret(self.url)
logger.secret(self.token)
try:
self.request(path="message")
except JSONDecodeError:
raise Failed("Gotify Error: Invalid JSON response received")
logger.info(f"Gotify Version: {self._request(path='version', post=False)['version']}")
except Exception:
logger.stacktrace()
raise Failed("Gotify Error: Invalid URL")

def notification(self, json):
return self.request(json=json)

@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_failed)
def request(self, json=None, path="message"):
if not json:
json = {
"message": "Well hello there.",
"priority": 1,
"title": "This is first contact"
}
response = self.config.post(f"{self.url}{path}?token={self.apikey}", json=json)
def _request(self, path="message", json=None, post=True):
if post:
response = self.config.post(f"{self.url}/{path}", headers={"X-Gotify-Key": self.token}, json=json)
else:
response = self.config.get(f"{self.url}/{path}")
try:
response_json = response.json()
except JSONDecodeError as e:
logger.error(response.content)
logger.debug(e)
raise e
if response.status_code >= 400 or ("result" in response_json and response_json["result"] == "error"):
logger.debug(f"Response: {response_json}")
raise Failed(f"({response.status_code} [{response.reason}]) {response_json}")
if not response_json["id"]:
raise Failed("Gotify Error: Invalid apikey")
return response
if response.status_code >= 400:
raise Failed(f"({response.status_code} [{response.reason}]) {response_json['errorDescription']}")
return response_json

def notification(self, json):
message = ""
if json["event"] == "run_end":
title = "Run Completed"
message = f"Start Time: {json['start_time']}\n" \
f"End Time: {json['end_time']}\n" \
f"Run Time: {json['run_time']}\n" \
f"Collections Created: {json['collections_created']}\n" \
f"Collections Modified: {json['collections_modified']}\n" \
f"Collections Deleted: {json['collections_deleted']}\n" \
f"Items Added: {json['items_added']}\n" \
f"Items Removed: {json['items_removed']}"
if json["added_to_radarr"]:
message += f"\n{json['added_to_radarr']} Movies Added To Radarr"
if json["added_to_sonarr"]:
message += f"\n{json['added_to_sonarr']} Movies Added To Sonarr"
elif json["event"] == "run_start":
title = "Run Started"
message = json["start_time"]
elif json["event"] == "version":
title = "New Version Available"
message = f"Current: {json['current']}\n" \
f"Latest: {json['latest']}\n" \
f"Notes: {json['notes']}"
elif json["event"] == "delete":
if "library_name" in json:
title = "Collection Deleted"
else:
title = "Playlist Deleted"
message = json["message"]
else:
new_line = "\n"
if "server_name" in json:
message += f"{new_line if message else ''}Server: {json['server_name']}"
if "library_name" in json:
message += f"{new_line if message else ''}Library: {json['library_name']}"
if "collection" in json:
message += f"{new_line if message else ''}Collection: {json['collection']}"
if "playlist" in json:
message += f"{new_line if message else ''}Playlist: {json['playlist']}"
if json["event"] == "error":
if "collection" in json:
title_name = "Collection"
elif "playlist" in json:
title_name = "Playlist"
elif "library_name" in json:
title_name = "Library"
else:
title_name = "Global"
title = f"{'Critical ' if json['critical'] else ''}{title_name} Error"
message += f"{new_line if message else ''}Error Message: {json['error']}"
else:
title = f"{'Collection' if 'collection' in json else 'Playlist'} {'Created' if json['created'] else 'Modified'}"
if json['radarr_adds']:
message += f"{new_line if message else ''}{len(json['radarr_adds'])} Radarr Additions:"
if json['sonarr_adds']:
message += f"{new_line if message else ''}{len(json['sonarr_adds'])} Sonarr Additions:"
message += f"{new_line if message else ''}{len(json['additions'])} Additions:"
for add_dict in json['additions']:
message += f"\n{add_dict['title']}"
message += f"{new_line if message else ''}{len(json['removals'])} Removals:"
for add_dict in json['removals']:
message += f"\n{add_dict['title']}"

self._request(json={"message": message, "title": title})
2 changes: 0 additions & 2 deletions modules/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ def __init__(self, config, params):
self.Webhooks = None
self.Operations = Operations(config, self)
self.Overlays = None
self.Notifiarr = None
self.Gotify = None
self.collections = []
self.collection_names = []
self.metadatas = []
Expand Down
Loading

0 comments on commit 33b92f2

Please sign in to comment.