diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py
index d8e4fd7c..f1b90bdf 100644
--- a/plexpy/notifiers.py
+++ b/plexpy/notifiers.py
@@ -107,7 +107,8 @@ AGENT_IDS = {'growl': 0,
'zapier': 24,
'webhook': 25,
'plexmobileapp': 26,
- 'lunasea': 27
+ 'lunasea': 27,
+ 'microsoftteams': 28
}
DEFAULT_CUSTOM_CONDITIONS = [{'parameter': '', 'operator': '', 'value': ''}]
@@ -186,6 +187,12 @@ def available_notification_agents():
'class': LUNASEA,
'action_types': ('all',)
},
+ {'label': 'Microsoft Teams',
+ 'name': 'microsoftteams',
+ 'id': AGENT_IDS['microsoftteams'],
+ 'class': MICROSOFTTEAMS,
+ 'action_types': ('all',)
+ },
{'label': 'MQTT',
'name': 'mqtt',
'id': AGENT_IDS['mqtt'],
@@ -1994,6 +2001,218 @@ class LUNASEA(Notifier):
return config_option
+class MICROSOFTTEAMS(Notifier):
+ """
+ Microsoft Teams Notifications
+ """
+ NAME = 'Microsoft Teams'
+ _DEFAULT_CONFIG = {'hook': '',
+ 'incl_subject': 1,
+ 'incl_card': 0,
+ 'incl_description': 1,
+ 'incl_pmslink': 0,
+ 'poster_size': 2,
+ 'movie_provider': '',
+ 'tv_provider': '',
+ 'music_provider': ''
+ }
+
+ def agent_notify(self, subject='', body='', action='', **kwargs):
+ data = {
+ 'type': 'message'
+ }
+ attachment = {
+ 'contentType': 'application/vnd.microsoft.card.adaptive'
+ }
+ content = {
+ '$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
+ 'type': 'AdaptiveCard',
+ 'version': '1.4',
+ }
+
+ card = []
+
+ if self.config['incl_subject']:
+ card.append({
+ 'type': 'TextBlock',
+ 'size': 'Large',
+ 'weight': 'Bolder',
+ 'text': subject
+ })
+ card.append({
+ 'type': 'TextBlock',
+ 'text': body,
+ 'wrap': True
+ })
+
+ if self.config['incl_card'] and kwargs.get('parameters', {}).get('media_type'):
+ # Grab formatted metadata
+ pretty_metadata = PrettyMetadata(kwargs['parameters'])
+
+ 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
+
+ poster_url = pretty_metadata.get_poster_url()
+ provider_name = pretty_metadata.get_provider_name(provider)
+ provider_link = pretty_metadata.get_provider_link(provider)
+ title = pretty_metadata.get_title('\u00B7')
+ description = pretty_metadata.get_description()
+ plex_url = pretty_metadata.get_plex_url()
+
+ columns = []
+
+ if poster_url and self.config['poster_size']:
+ columns.append({
+ 'type': 'Column',
+ 'width': 'auto',
+ 'items': [
+ {
+ 'type': 'Image',
+ 'url': poster_url,
+ 'altText': title,
+ 'size': 'Large',
+ 'height': '{}px'.format(self.config['poster_size'] * 75)
+ }
+ ]
+ })
+ columns.append({
+ 'type': 'Column',
+ 'width': 'stretch',
+ 'items': []
+ })
+
+ columns[-1]['items'].append({
+ 'type': 'TextBlock',
+ 'weight': 'Bolder',
+ 'text': title,
+ 'wrap': True
+ })
+ if self.config['incl_description']:
+ columns[-1]['items'].append({
+ 'type': 'TextBlock',
+ 'text': description,
+ 'size': 'Small',
+ 'spacing': 'Small',
+ 'wrap': True
+ })
+
+ card.append({
+ 'type': 'ColumnSet',
+ 'padding': 'Default',
+ 'spacing': 'Large',
+ 'columns': columns
+ })
+
+ actions = []
+
+ if provider_link:
+ actions.append({
+ 'type': 'Action.OpenUrl',
+ 'title': 'View on {}'.format(provider_name),
+ 'url': provider_link
+ })
+ if self.config['incl_pmslink']:
+ actions.append({
+ 'type': 'Action.OpenUrl',
+ 'title': 'View on Plex',
+ 'url': plex_url
+ })
+
+ if actions:
+ card.append({
+ 'type': 'ActionSet',
+ 'actions': actions
+ })
+
+ content['body'] = card
+ attachment['content'] = content
+ data['attachments'] = [attachment]
+
+ headers = {'Content-type': 'application/json'}
+
+ return self.make_request(self.config['hook'], headers=headers, json=data)
+
+ def _return_config_options(self):
+ config_option = [{'label': 'Teams Webhook URL',
+ 'value': self.config['hook'],
+ 'name': 'microsoftteams_hook',
+ 'description': 'Your Microsoft Teams incoming webhook URL.',
+ 'input_type': 'token'
+ },
+ {'label': 'Include Subject Line',
+ 'value': self.config['incl_subject'],
+ 'name': 'microsoftteams_incl_subject',
+ 'description': 'Include the subject line with the notifications.',
+ 'input_type': 'checkbox'
+ },
+ {'label': 'Include Rich Metadata Info',
+ 'value': self.config['incl_card'],
+ 'name': 'microsoftteams_incl_card',
+ 'description': 'Include an info card with a poster and metadata with the notifications.
'
+ 'Note: Image Hosting '
+ 'must be enabled under the 3rd Party APIs settings tab.',
+ 'input_type': 'checkbox'
+ },
+ {'label': 'Include Plot Summaries',
+ 'value': self.config['incl_description'],
+ 'name': 'microsoftteams_incl_description',
+ 'description': 'Include a plot summary for movies and TV shows on the info card.',
+ 'input_type': 'checkbox'
+ },
+ {'label': 'Include Link to Plex Web',
+ 'value': self.config['incl_pmslink'],
+ 'name': 'microsoftteams_incl_pmslink',
+ 'description': 'Include a second link to the media in Plex Web on the info card.',
+ 'input_type': 'checkbox'
+ },
+ {'label': 'Poster Size',
+ 'value': self.config['poster_size'],
+ 'name': 'microsoftteams_poster_size',
+ 'description': 'Select the size of the poster on the info card.',
+ 'input_type': 'select',
+ 'select_options': {
+ 0: 'None',
+ 1: 'Small',
+ 2: 'Medium',
+ 3: 'Large'}
+ },
+ {'label': 'Movie Link Source',
+ 'value': self.config['movie_provider'],
+ 'name': 'microsoftteams_movie_provider',
+ 'description': 'Select the source for movie links on the info cards. 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': 'microsoftteams_tv_provider',
+ 'description': 'Select the source for tv show links on the info cards. 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': 'microsoftteams_music_provider',
+ 'description': 'Select the source for music links on the info cards. Leave blank to disable.',
+ 'input_type': 'select',
+ 'select_options': PrettyMetadata().get_music_providers()
+ }
+ ]
+
+ return config_option
+
+
class MQTT(Notifier):
"""
MQTT notifications