mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-10 06:54:21 +00:00
gotify api
This commit is contained in:
parent
56961ccca1
commit
459710d8e6
11 changed files with 232 additions and 10 deletions
|
@ -105,6 +105,9 @@ mdblist:
|
|||
cache_expiration: 60
|
||||
notifiarr:
|
||||
apikey: ####################################
|
||||
gotify:
|
||||
url: http://192.168.1.12:80
|
||||
apikey: ####################################
|
||||
anidb: # Not required for AniDB builders unless you want mature content
|
||||
username: ######
|
||||
password: ######
|
||||
|
|
31
docs/config/gotify.md
Normal file
31
docs/config/gotify.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Gotify Attributes
|
||||
|
||||
Configuring [Gotify](https://gotify.net/) is optional but can allow you to send the [webhooks](webhooks.md)
|
||||
straight to gotify..
|
||||
|
||||
A `gotify` mapping is in the root of the config file.
|
||||
|
||||
Below is a `gotify` mapping example and the full set of attributes:
|
||||
|
||||
```yaml
|
||||
gotify:
|
||||
url: ####################################
|
||||
apikey: ####################################
|
||||
```
|
||||
|
||||
| Attribute | Allowed Values | Required |
|
||||
|:----------|:-----------------------------------------|:------------------------------------------:|
|
||||
| `url` | Gotify Server Url | :fontawesome-solid-circle-check:{ .green } |
|
||||
| `apikey` | Gotify Application API Key | :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.
|
||||
|
||||
```yaml
|
||||
webhooks:
|
||||
error: gotify
|
||||
version: gotify
|
||||
run_start: gotify
|
||||
run_end: gotify
|
||||
changes: gotify
|
||||
```
|
|
@ -24,6 +24,7 @@ requirements for setup that can be found by clicking the links within the table.
|
|||
| [`tautulli`](tautulli.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`omdb`](omdb.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`notifiarr`](notifiarr.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`gotify`](gotify.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`anidb`](anidb.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`radarr`](radarr.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
| [`sonarr`](sonarr.md) | :fontawesome-solid-circle-xmark:{ .red } |
|
||||
|
|
|
@ -27,7 +27,7 @@ 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) just add `notifiarr` to a webhook instead of the webhook url.
|
||||
* To send notifications to [Notifiarr](notifiarr.md) or [Gotify](gotify.md) just add `notifiarr` or `gotify` to a webhook instead of the webhook url.
|
||||
|
||||
## Error Notifications
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
"notifiarr": {
|
||||
"$ref": "#/definitions/notifiarr-api"
|
||||
},
|
||||
"gotify": {
|
||||
"$ref": "#/definitions/gotify-api"
|
||||
},
|
||||
"anidb": {
|
||||
"$ref": "#/definitions/anidb-api"
|
||||
},
|
||||
|
@ -253,6 +256,24 @@
|
|||
],
|
||||
"title": "notifiarr"
|
||||
},
|
||||
"gotify-api": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"apikey": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url",
|
||||
"apikey"
|
||||
|
||||
],
|
||||
"title": "gotify"
|
||||
},
|
||||
"anidb-api": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
@ -902,7 +923,7 @@
|
|||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^(?!plex|tmdb|tautulli|webhooks|omdb|mdblist|notifiarr|anidb|radarr|sonarr|trakt|mal).+$": {
|
||||
"^(?!plex|tmdb|tautulli|webhooks|omdb|mdblist|notifiarr|gotify|anidb|radarr|sonarr|trakt|mal).+$": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"metadata_files": {
|
||||
|
|
|
@ -472,6 +472,9 @@ mdblist:
|
|||
cache_expiration: 60
|
||||
notifiarr:
|
||||
apikey: this-is-a-placeholder-string
|
||||
gotify:
|
||||
url: http://192.168.1.12:80
|
||||
apikey: 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
|
||||
|
|
|
@ -177,6 +177,7 @@ nav:
|
|||
- Radarr: config/radarr.md
|
||||
- Sonarr: config/sonarr.md
|
||||
- Notifiarr: config/notifiarr.md
|
||||
- Gotify: config/gotify.md
|
||||
- Tautulli: config/tautulli.md
|
||||
- Github: config/github.md
|
||||
- MdbList: config/mdblist.md
|
||||
|
|
|
@ -15,6 +15,7 @@ from modules.letterboxd import Letterboxd
|
|||
from modules.mal import MyAnimeList
|
||||
from modules.meta import PlaylistFile
|
||||
from modules.notifiarr import Notifiarr
|
||||
from modules.gotify import Gotify
|
||||
from modules.omdb import OMDb
|
||||
from modules.overlays import Overlays
|
||||
from modules.plex import Plex
|
||||
|
@ -286,6 +287,7 @@ class ConfigFile:
|
|||
if "omdb" in self.data: self.data["omdb"] = self.data.pop("omdb")
|
||||
if "mdblist" in self.data: self.data["mdblist"] = self.data.pop("mdblist")
|
||||
if "notifiarr" in self.data: self.data["notifiarr"] = self.data.pop("notifiarr")
|
||||
if "gotify" in self.data: self.data["gotify"] = self.data.pop("gotify")
|
||||
if "anidb" in self.data: self.data["anidb"] = self.data.pop("anidb")
|
||||
if "radarr" in self.data:
|
||||
if "monitor" in self.data["radarr"] and isinstance(self.data["radarr"]["monitor"], bool):
|
||||
|
@ -543,6 +545,42 @@ class ConfigFile:
|
|||
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)})
|
||||
except Failed as e:
|
||||
if str(e).endswith("is blank"):
|
||||
logger.warning(e)
|
||||
else:
|
||||
logger.stacktrace()
|
||||
logger.error(e)
|
||||
logger.info(f"Gotify Connection {'Failed' if self.GotifyFactory is None else 'Successful'}")
|
||||
else:
|
||||
logger.info("gotify 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.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]):
|
||||
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()
|
||||
|
||||
try:
|
||||
self.TMDb = None
|
||||
if "tmdb" in self.data:
|
||||
|
@ -1173,7 +1211,7 @@ class ConfigFile:
|
|||
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)
|
||||
library.Webhooks = Webhooks(self, {}, library=library, notifiarr=self.NotifiarrFactory or self.GotifyFactory,)
|
||||
library.Overlays = Overlays(self, library)
|
||||
|
||||
logger.info("")
|
||||
|
|
42
modules/gotify.py
Normal file
42
modules/gotify.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
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)
|
||||
try:
|
||||
self.request(path="message")
|
||||
except JSONDecodeError:
|
||||
raise Failed("Gotify Error: Invalid JSON response received")
|
||||
|
||||
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)
|
||||
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
|
|
@ -17,6 +17,7 @@ class Library(ABC):
|
|||
self.Operations = Operations(config, self)
|
||||
self.Overlays = None
|
||||
self.Notifiarr = None
|
||||
self.Gotify = None
|
||||
self.collections = []
|
||||
self.collection_names = []
|
||||
self.metadatas = []
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from json import JSONDecodeError
|
||||
from json import JSONDecodeError, dumps
|
||||
from modules import util
|
||||
from modules.util import Failed, YAML
|
||||
|
||||
|
@ -24,10 +24,14 @@ class Webhooks:
|
|||
for webhook in list(set(webhooks)):
|
||||
response = None
|
||||
logger.trace(f"Webhook: {webhook}")
|
||||
if webhook == "notifiarr":
|
||||
if webhook == "notifiarr" or webhook == "gotify":
|
||||
if self.notifiarr:
|
||||
for x in range(6):
|
||||
response = self.notifiarr.notification(json)
|
||||
if webhook == "gotify":
|
||||
json = self.gotify(json)
|
||||
response = self.notifiarr.notification(json)
|
||||
else:
|
||||
response = self.notifiarr.notification(json)
|
||||
if response.status_code < 500:
|
||||
break
|
||||
else:
|
||||
|
@ -40,16 +44,17 @@ class Webhooks:
|
|||
try:
|
||||
response_json = response.json()
|
||||
logger.trace(f"Response: {response_json}")
|
||||
if webhook == "notifiarr" and self.notifiarr and response.status_code == 400:
|
||||
if (webhook == "notifiarr" or webhook == "gotify") and self.notifiarr and response.status_code == 400:
|
||||
def remove_from_config(text, hook_cat):
|
||||
if response_json["details"]["response"] == text:
|
||||
yaml = YAML(self.config.config_path)
|
||||
changed = False
|
||||
if hook_cat in yaml.data and yaml.data["webhooks"][hook_cat]:
|
||||
if isinstance(yaml.data["webhooks"][hook_cat], list) and "notifiarr" in yaml.data["webhooks"][hook_cat]:
|
||||
if isinstance(yaml.data["webhooks"][hook_cat], list) and ("notifiarr" in yaml.data["webhooks"][hook_cat] or "gotify" in yaml.data["webhooks"][hook_cat]):
|
||||
changed = True
|
||||
yaml.data["webhooks"][hook_cat].pop("notifiarr")
|
||||
elif yaml.data["webhooks"][hook_cat] == "notifiarr":
|
||||
yaml.data["webhooks"][hook_cat].pop("gotify")
|
||||
elif yaml.data["webhooks"][hook_cat] == "notifiarr" or yaml.data["webhooks"][hook_cat] == "gotify":
|
||||
changed = True
|
||||
yaml.data["webhooks"][hook_cat] = None
|
||||
if changed:
|
||||
|
@ -62,7 +67,7 @@ class Webhooks:
|
|||
remove_from_config("PMM start/complete trigger is not enabled", "run_end")
|
||||
remove_from_config("PMM app updates trigger is not enabled", "version")
|
||||
if "result" in response_json and response_json["result"] == "error" and "details" in response_json and "response" in response_json["details"]:
|
||||
raise Failed(f"Notifiarr Error: {response_json['details']['response']}")
|
||||
raise Failed(f"Notifiarr/Gotify Error: {response_json['details']['response']}")
|
||||
if response.status_code >= 400 or ("result" in response_json and response_json["result"] == "error"):
|
||||
raise Failed(f"({response.status_code} [{response.reason}]) {response_json}")
|
||||
except JSONDecodeError:
|
||||
|
@ -326,3 +331,79 @@ class Webhooks:
|
|||
fields.append(field)
|
||||
new_json["embeds"][0]["fields"] = fields
|
||||
return new_json
|
||||
|
||||
|
||||
def gotify(self, json: dict):
|
||||
message = ""
|
||||
if json.get("event") == "run_end":
|
||||
title = "Run Completed"
|
||||
message = [
|
||||
[("Start Time", json["start_time"]), ("End Time", json["end_time"]), ("Run Time", json["run_time"])],
|
||||
[("Collections", None)],
|
||||
[
|
||||
("Created", json["collections_created"] if json["collections_created"] else "0"),
|
||||
("Modified", json["collections_modified"] if json["collections_modified"] else "0"),
|
||||
("Deleted", json["collections_deleted"] if json["collections_deleted"] else "0")
|
||||
]
|
||||
]
|
||||
message = f"Start Time: {json['start_time']}\nEnd Time: {json['end_time']}\nRun Time: {json['run_time']}\nCollections Created: {json['collections_created']}\nCollections Modified: {json['collections_modified']}\nCollections Deleted: {json['collections_deleted']}"
|
||||
if json.get("added_to_radarr"):
|
||||
message = message + (f"{json['added_to_radarr']} Movies Added To Radarr\n", None)
|
||||
if json.get("added_to_sonarr"):
|
||||
message = message + (f"{json['added_to_sonarr']} Series Added To Sonarr\n", None)
|
||||
elif json.get("event") == "run_start":
|
||||
title = "Run Started"
|
||||
message = json["start_time"]
|
||||
elif json.get("event") == "version":
|
||||
title = "New Version Available"
|
||||
message = [
|
||||
[("Current", json["current"]), ("Latest", json["latest"])],
|
||||
[("New Commits", json["notes"])]
|
||||
]
|
||||
message = f"Current : {json['current']}\nLatest: {json['latest']}\nNew Commits: {json['notes']}"
|
||||
else:
|
||||
message1 = ""
|
||||
text = ""
|
||||
if "server_name" in json:
|
||||
message1 = message1 + f"Server: {json['server_name']}\n"
|
||||
if "library_name" in json:
|
||||
message1 = message1 + f"Library: {json['library_name']}\n"
|
||||
if "collection" in json:
|
||||
text = "Collection"
|
||||
message1 = message1 + f"Collection: {json['collection']}\n"
|
||||
elif "playlist" in json:
|
||||
text = "Playlist"
|
||||
message1 = message1 + f"Playlist: {json['playlist']}\n"
|
||||
if message1:
|
||||
message1 = message1 + "\n"
|
||||
if json["event"] == "delete":
|
||||
title = json["message"]
|
||||
elif "error" in json:
|
||||
title = f"{'Critical ' if json['critical'] else ''}Error"
|
||||
message = message + f"Error Message: {json['error']}\n"
|
||||
else:
|
||||
title = f"{text} {'Created' if json['created'] else 'Modified'}"
|
||||
|
||||
def get_field_text(items_list):
|
||||
field_text = ""
|
||||
for i, item in enumerate(items_list, 1):
|
||||
field_text += f"\n{i}. {item['title']}"
|
||||
return field_text
|
||||
|
||||
if json["additions"]:
|
||||
message = message + f"Items Added: { get_field_text(json['additions'])}\n"
|
||||
if json["removals"]:
|
||||
message = message + f"Items Removed: { get_field_text(json['removals'])}\n"
|
||||
|
||||
gotify_json = {
|
||||
"message": "",
|
||||
"priority": 1,
|
||||
"title": ""
|
||||
}
|
||||
if message:
|
||||
gotify_json["message"] = message
|
||||
|
||||
if title:
|
||||
gotify_json["title"] = title
|
||||
|
||||
return gotify_json
|
||||
|
|
Loading…
Reference in a new issue