diff --git a/VERSION b/VERSION index 1c1b8d80..338b9d2a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.18.1-develop7 +1.18.1-develop8 diff --git a/docs/config/webhooks.md b/docs/config/webhooks.md index b9cdb3ba..6682d32a 100644 --- a/docs/config/webhooks.md +++ b/docs/config/webhooks.md @@ -19,10 +19,11 @@ webhooks: | Attribute | Global | Library | Collection | |:----------------------------------------|:-------:|:--------:|:----------:| -| [`error`](#error-notifications) | ✅ | ✅ | ❌ | +| [`error`](#error-notifications) | ✅ | ❌ | ❌ | | [`version`](#version-notifications) | ✅ | ❌ | ❌ | | [`run_start`](#run-start-notifications) | ✅ | ❌ | ❌ | | [`run_end`](#run-end-notifications) | ✅ | ❌ | ❌ | +| [`delete`](#delete-notifications) | ✅ | ❌ | ❌ | | [`changes`](#changes-notifications) | ✅ | ✅ | ✅ | * Each Attribute can be either a webhook url as a string or a comma-separated list of webhooks urls. @@ -127,6 +128,20 @@ The Run End notification will be sent at the end of every run with statistics. } ``` +## Delete Notifications + +The Delete Notification will be sent whenever a collection/playlist is deleted containing the following payload. + +### JSON Payload + +```yaml +{ + "message": str, // Status Message + "server_name": str, // Server Name + "library_name": str, // Library Name (Only if a Collection is deleted) +} +``` + ## Changes Notifications The Changes Notification will be sent after each collection/playlist containing the following payload if the collection/playlist has been created, has new items, or has had items removed. @@ -140,7 +155,6 @@ The Changes Notification will be sent after each collection/playlist containing "collection": str, // Collection Name only in payload for a collection "playlist": str, // Playlist Name only in payload for a playlist "created": bool, // Was the Collection/Playlist Created on this run - "deleted": bool, // Was the Collection/Playlist Deleted on this run "poster": str, // Base64 Encoded Collection/Playlist Poster if no poster_url is found "poster_url": str, // Collection/Playlist Poster URL if avaiable "background": str, // Base64 Encoded Collection/Playlist Background if no poster_url is found diff --git a/modules/builder.py b/modules/builder.py index 30b2c2b7..db48a600 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -41,8 +41,8 @@ string_details = ["sort_title", "content_rating", "name_mapping"] ignored_details = [ "smart_filter", "smart_label", "smart_url", "run_again", "schedule", "sync_mode", "template", "variables", "test", "suppress_overlays", "delete_not_scheduled", "tmdb_person", "build_collection", "collection_order", "builder_level", "overlay", - "validate_builders", "libraries", "sync_to_users", "collection_name", "playlist_name", "name", "blank_collection", - "allowed_library_types", "delete_playlist", "ignore_blank_results", "only_run_on_create" + "validate_builders", "libraries", "sync_to_users", "exclude_users", "collection_name", "playlist_name", "name", + "blank_collection", "allowed_library_types", "delete_playlist", "ignore_blank_results", "only_run_on_create" ] details = [ "ignore_ids", "ignore_imdb_ids", "server_preroll", "changes_webhooks", "collection_filtering", "collection_mode", "limit", "url_theme", @@ -162,7 +162,7 @@ parts_collection_valid = [ "url_theme", "file_theme", "item_label", "default_percent" ] + episode_parts_only + summary_details + poster_details + background_details + string_details playlist_attributes = [ - "filters", "name_mapping", "show_filtered", "show_missing", "save_report", + "filters", "name_mapping", "show_filtered", "show_missing", "save_report", "allowed_library_types", "missing_only_released", "only_filter_missing", "delete_below_minimum", "ignore_ids", "ignore_imdb_ids", "server_preroll", "changes_webhooks", "minimum_items", "cache_builders", "default_percent" ] + custom_sort_builders + summary_details + poster_details + radarr_details + sonarr_details @@ -2876,7 +2876,6 @@ class CollectionBuilder: poster_url=self.collection_poster.location if self.collection_poster and self.collection_poster.is_url else None, background_url=self.collection_background.location if self.collection_background and self.collection_background.is_url else None, created=self.created, - deleted=self.deleted, additions=self.notification_additions, removals=self.notification_removals, radarr=self.added_to_radarr, diff --git a/modules/config.py b/modules/config.py index 8dc0ef06..2af5da5e 100644 --- a/modules/config.py +++ b/modules/config.py @@ -423,7 +423,8 @@ class ConfigFile: "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) + "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: @@ -694,7 +695,6 @@ class ConfigFile: params["ignore_ids"].extend([i for i in self.general["ignore_ids"] if i not in params["ignore_ids"]]) params["ignore_imdb_ids"] = check_for_attribute(lib, "ignore_imdb_ids", parent="settings", var_type="list", default_is_none=True, do_print=False, save=False) params["ignore_imdb_ids"].extend([i for i in self.general["ignore_imdb_ids"] if i not in params["ignore_imdb_ids"]]) - params["error_webhooks"] = check_for_attribute(lib, "error", parent="webhooks", var_type="list", default=self.webhooks["error"], do_print=False, save=False, default_is_none=True) params["changes_webhooks"] = check_for_attribute(lib, "changes", parent="webhooks", var_type="list", default=self.webhooks["changes"], do_print=False, save=False, default_is_none=True) params["report_path"] = None if lib and "report_path" in lib and lib["report_path"]: @@ -952,7 +952,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, {"error_webhooks": library.error_webhooks}, library=library, notifiarr=self.NotifiarrFactory) + library.Webhooks = Webhooks(self, {}, library=library, notifiarr=self.NotifiarrFactory) library.Overlays = Overlays(self, library) logger.info("") @@ -986,6 +986,13 @@ class ConfigFile: logger.stacktrace() logger.error(f"Webhooks Error: {e}") + def notify_delete(self, message, server=None, library=None): + try: + self.Webhooks.delete_webhooks(message, server=server, library=library) + except Failed as e: + logger.stacktrace() + logger.error(f"Webhooks Error: {e}") + def get_html(self, url, headers=None, params=None): return html.fromstring(self.get(url, headers=headers, params=params).content) diff --git a/modules/library.py b/modules/library.py index 24fbbdab..828e58f2 100644 --- a/modules/library.py +++ b/modules/library.py @@ -100,7 +100,6 @@ class Library(ABC): self.metadata_backup = params["metadata_backup"] self.genre_mapper = params["genre_mapper"] self.content_rating_mapper = params["content_rating_mapper"] - self.error_webhooks = params["error_webhooks"] self.changes_webhooks = params["changes_webhooks"] self.split_duplicates = params["split_duplicates"] # TODO: Here or just in Plex? self.clean_bundles = params["plex"]["clean_bundles"] # TODO: Here or just in Plex? @@ -214,6 +213,10 @@ class Library(ABC): def notify(self, text, collection=None, critical=True): pass + @abstractmethod + def notify_delete(self, message): + pass + @abstractmethod def _upload_image(self, item, image): pass diff --git a/modules/plex.py b/modules/plex.py index 0b211e51..1326dbb9 100644 --- a/modules/plex.py +++ b/modules/plex.py @@ -477,6 +477,9 @@ class Plex(Library): def notify(self, text, collection=None, critical=True): self.config.notify(text, server=self.PlexServer.friendlyName, library=self.name, collection=collection, critical=critical) + def notify_delete(self, message): + self.config.notify_delete(message, server=self.PlexServer.friendlyName, library=self.name) + def set_server_preroll(self, preroll): self.PlexServer.settings.get('cinemaTrailersPrerollID').set(preroll) self.PlexServer.settings.save() diff --git a/modules/webhooks.py b/modules/webhooks.py index e8536242..de88d519 100644 --- a/modules/webhooks.py +++ b/modules/webhooks.py @@ -11,6 +11,7 @@ class Webhooks: self.version_webhooks = system_webhooks["version"] if "version" in system_webhooks else [] self.run_start_webhooks = system_webhooks["run_start"] if "run_start" in system_webhooks else [] self.run_end_webhooks = system_webhooks["run_end"] if "run_end" in system_webhooks else [] + self.delete_webhooks = system_webhooks["delete"] if "delete" in system_webhooks else [] self.library = library self.notifiarr = notifiarr @@ -105,7 +106,14 @@ class Webhooks: if playlist: json["playlist"] = str(playlist) self._request(self.error_webhooks, json) - def collection_hooks(self, webhooks, collection, poster_url=None, background_url=None, created=False, deleted=False, + def delete_hooks(self, message, server=None, library=None): + if self.delete_webhooks: + json = {"message": message} + if server: json["server_name"] = str(server) + if library: json["library_name"] = str(library) + self._request(self.delete_webhooks, json) + + def collection_hooks(self, webhooks, collection, poster_url=None, background_url=None, created=False, additions=None, removals=None, radarr=None, sonarr=None, playlist=False): if self.library: thumb = None @@ -119,7 +127,6 @@ class Webhooks: "library_name": self.library.name, "playlist" if playlist else "collection": collection.title, "created": created, - "deleted": deleted, "poster": thumb, "background": art, "poster_url": poster_url, diff --git a/plex_meta_manager.py b/plex_meta_manager.py index f8eb6fce..95821908 100644 --- a/plex_meta_manager.py +++ b/plex_meta_manager.py @@ -724,6 +724,7 @@ def run_collection(config, library, metadata, requested_collections): except NotScheduled as e: logger.info(e) if str(e).endswith("and was deleted"): + library.notify_delete(e) library.stats["deleted"] += 1 library.status[str(mapping_name)]["status"] = "Deleted Not Scheduled" elif str(e).startswith("Skipped because allowed_library_types"): @@ -903,11 +904,13 @@ def run_playlists(config): except Deleted as e: logger.info(e) status[mapping_name]["status"] = "Deleted" + config.notify_delete(e) except NotScheduled as e: logger.info(e) if str(e).endswith("and was deleted"): stats["deleted"] += 1 status[mapping_name]["status"] = "Deleted Not Scheduled" + config.notify_delete(e) else: status[mapping_name]["status"] = "Not Scheduled" except Failed as e: