diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py index 8d2906d1..dbd0cccf 100644 --- a/plexpy/notifiers.py +++ b/plexpy/notifiers.py @@ -96,7 +96,8 @@ AGENT_IDS = {'growl': 0, 'plexmobileapp': 26, 'lunasea': 27, 'microsoftteams': 28, - 'gotify': 29 + 'gotify': 29, + 'ntfy': 30 } DEFAULT_CUSTOM_CONDITIONS = [{'parameter': '', 'operator': '', 'value': [], 'type': None}] @@ -198,6 +199,12 @@ def available_notification_agents(): 'class': MQTT, 'action_types': ('all',) }, + {'label': 'ntfy', + 'name': 'ntfy', + 'id': AGENT_IDS['ntfy'], + 'class': NTFY, + 'action_types': ('all',) + }, {'label': 'Plex Home Theater', 'name': 'plex', 'id': AGENT_IDS['plex'], @@ -2592,6 +2599,187 @@ class MQTT(Notifier): return config_option +class NTFY(Notifier): + """ + ntfy notifications + """ + NAME = 'ntfy' + _DEFAULT_CONFIG = {'host': '', + 'access_token': '', + 'topic': '', + 'priority': 'default', + 'incl_subject': 1, + 'incl_description': 1, + 'incl_poster': 0, + 'incl_url': 0, + 'incl_pmslink': 0, + 'movie_provider': '', + 'tv_provider': '', + 'music_provider': '' + } + + def agent_notify(self, subject='', body='', action='', **kwargs): + method = "POST" + url = f"{self.config['host']}/{self.config['topic']}" + params = {} + data = body + headers = { + 'Priority': self.config['priority'], + 'Authorization': f'Bearer {self.config["access_token"]}', + 'Icon': 'https://tautulli.com/images/favicon.ico' + } + + # Add optional subject + if self.config['incl_subject']: + headers['Title'] = subject + + # Add optional parameters (dependent on notification type + metadata extraction) + if kwargs.get('parameters', {}).get('media_type'): + # Grab formatted metadata + pretty_metadata = PrettyMetadata(kwargs['parameters']) + + # Add optional description + if self.config['incl_description']: + description = pretty_metadata.get_description() + if description: + data = f"{data}\n\n{description}" + + # Add optional poster + if self.config['incl_poster']: + method = "PUT" # Need to use PUT instead of POST to send attachments + image_file_name, image_content, image_file_type = pretty_metadata.get_image() + + if image_file_name and image_content: + # Image data will take up "data", message content needs to shift to the "message" query parameter + params['message'] = data + data = image_content + headers['Filename'] = image_file_name + else: + # Fallback to default Tautulli media type poster + # Can keep message content in "data" payload and just add a header for the attachment + poster_url = pretty_metadata.get_poster_url() + headers['Attach'] = poster_url + + # Add optional links (actions) + actions = [] + + if self.config['incl_url']: + if pretty_metadata.media_type == 'movie': + provider = self.config['movie_provider'] + elif pretty_metadata.media_type in ('show', 'season', 'episode'): + provider = self.config['tv_provider'] + elif pretty_metadata.media_type in ('artist', 'album', 'track'): + provider = self.config['music_provider'] + else: + provider = None + + provider_name = pretty_metadata.get_provider_name(provider) + provider_link = pretty_metadata.get_provider_link(provider) + actions.append(f"view, View on {provider_name}, {provider_link}, clear=true") + + if self.config['incl_pmslink']: + plex_url = pretty_metadata.get_plex_url() + actions.append(f"view, View on Plex, {plex_url}, clear=true") + + if actions: + headers['Actions'] = ';'.join(actions) + + return self.make_request(url=url, method=method, headers=headers, params=params, data=data) + + def _return_config_options(self): + config_option = [{'label': 'ntfy Host Address', + 'value': self.config['host'], + 'name': 'ntfy_host', + 'description': 'Host running ntfy (e.g. http://localhost:80).', + 'input_type': 'text' + }, + {'label': 'ntfy Access Token', + 'value': self.config['access_token'], + 'name': 'ntfy_access_token', + 'description': 'Your ntfy access token.', + 'input_type': 'token' + }, + {'label': 'ntfy Topic', + 'value': self.config['topic'], + 'name': 'ntfy_topic', + 'description': 'The topic to publish notifications to.', + 'input_type': 'text' + }, + {'label': 'Priority', + 'value': self.config['priority'], + 'name': 'ntfy_priority', + 'description': 'Set the notification priority.', + 'input_type': 'select', + 'select_options': { + 'min': 1, + 'low': 2, + 'default': 3, + 'high': 4, + 'max': 5 + } + }, + {'label': 'Include Subject Line', + 'value': self.config['incl_subject'], + 'name': 'ntfy_incl_subject', + 'description': 'Include a subject line in the notification.', + 'input_type': 'checkbox' + }, + {'label': 'Include Poster Image', + 'value': self.config['incl_poster'], + 'name': 'ntfy_incl_poster', + 'description': 'Include a poster of the media item in the notification.', + 'input_type': 'checkbox' + }, + {'label': 'Include Summary', + 'value': self.config['incl_description'], + 'name': 'ntfy_incl_description', + 'description': 'Include a summary of the media item in the notification.', + 'input_type': 'checkbox' + }, + {'label': 'Include Link to Metadata Provider', + 'value': self.config['incl_url'], + 'name': 'ntfy_incl_url', + 'description': 'Include a link to the media item on the metadata provider in the notification.', + 'input_type': 'checkbox' + }, + {'label': 'Include Link to Plex Web', + 'value': self.config['incl_pmslink'], + 'name': 'ntfy_incl_pmslink', + 'description': 'Include a link to the media item in Plex Web in the notification.', + 'input_type': 'checkbox' + }, + {'label': 'Movie Link Source', + 'value': self.config['movie_provider'], + 'name': 'ntfy_movie_provider', + 'description': 'Select the source for movie links in the notification. Leave blank to disable.
' + 'Note: Metadata Lookups ' + 'may need to be enabled under the 3rd Party APIs settings tab.', + 'input_type': 'select', + 'select_options': PrettyMetadata().get_movie_providers() + }, + {'label': 'TV Show Link Source', + 'value': self.config['tv_provider'], + 'name': 'ntfy_tv_provider', + 'description': 'Select the source for TV show links in the notification. Leave blank to disable.
' + 'Note: Metadata Lookups ' + 'may need to be enabled under the 3rd Party APIs settings tab.', + 'input_type': 'select', + 'select_options': PrettyMetadata().get_tv_providers() + }, + {'label': 'Music Link Source', + 'value': self.config['music_provider'], + 'name': 'ntfy_music_provider', + 'description': 'Select the source for music links in the notification. Leave blank to disable.
' + 'Note: Metadata Lookups ' + 'may need to be enabled under the 3rd Party APIs settings tab.', + 'input_type': 'select', + 'select_options': PrettyMetadata().get_music_providers() + } + ] + + return config_option + + class OSX(Notifier): """ macOS notifications