1from loguru import logger 2from requests.exceptions import RequestException 3 4from flexget import plugin 5from flexget.event import event 6from flexget.plugin import PluginWarning 7from flexget.utils.requests import Session as RequestSession 8 9requests = RequestSession(max_retries=3) 10 11plugin_name = 'slack' 12 13logger = logger.bind(name=plugin_name) 14 15 16class SlackNotifier: 17 """ 18 Example: 19 20 notify: 21 entries: 22 via: 23 - slack: 24 web_hook_url: <string> 25 [channel: <string>] (override channel, use "@username" or "#channel") 26 [username: <string>] (override username) 27 [icon_emoji: <string>] (override emoji icon) 28 [icon_url: <string>] (override emoji icon) 29 [attachments: <array>[<object>]] (override attachments) 30 31 """ 32 33 schema = { 34 'type': 'object', 35 'properties': { 36 'web_hook_url': {'type': 'string', 'format': 'uri'}, 37 'username': {'type': 'string', 'default': 'Flexget'}, 38 'icon_url': {'type': 'string', 'format': 'uri'}, 39 'icon_emoji': {'type': 'string'}, 40 'channel': {'type': 'string'}, 41 'unfurl_links': {'type': 'boolean'}, 42 'message': {'type': 'string'}, 43 'attachments': { 44 'type': 'array', 45 'items': { 46 'type': 'object', 47 'properties': { 48 'title': {'type': 'string'}, 49 'author_name': {'type': 'string'}, 50 'author_link': {'type': 'string'}, 51 'author_icon': {'type': 'string'}, 52 'title_link': {'type': 'string'}, 53 'image_url': {'type': 'string'}, 54 'thumb_url': {'type': 'string'}, 55 'footer': {'type': 'string'}, 56 'footer_icon': {'type': 'string'}, 57 'ts': {'type': 'number'}, 58 'fallback': {'type': 'string'}, 59 'text': {'type': 'string'}, 60 'pretext': {'type': 'string'}, 61 'color': {'type': 'string'}, 62 'fields': { 63 'type': 'array', 64 'minItems': 1, 65 'items': { 66 'type': 'object', 67 'properties': { 68 'title': {'type': 'string'}, 69 'value': {'type': 'string'}, 70 'short': {'type': 'boolean'}, 71 }, 72 'required': ['title'], 73 'additionalProperties': False, 74 }, 75 }, 76 'actions': { 77 'type': 'array', 78 'minItems': 1, 79 'items': { 80 'type': 'object', 81 'properties': { 82 'name': {'type': 'string'}, 83 'text': {'type': 'string'}, 84 'type': {'type': 'string'}, 85 'value': {'type': 'string'}, 86 }, 87 'required': ['name', 'text', 'type', 'value'], 88 'additionalProperties': False, 89 }, 90 }, 91 'callback_id': {'type': 'string'}, 92 }, 93 'required': ['fallback'], 94 'dependencies': {'actions': ['callback_id']}, 95 'additionalProperties': False, 96 }, 97 }, 98 }, 99 'not': {'required': ['icon_emoji', 'icon_url']}, 100 'error_not': 'Can only use one of \'icon_emoji\' or \'icon_url\'', 101 'required': ['web_hook_url'], 102 'additionalProperties': False, 103 } 104 105 def notify(self, title, message, config): 106 """ 107 Send a Slack notification 108 """ 109 notification = { 110 'text': message, 111 'username': config.get('username'), 112 'channel': config.get('channel'), 113 'attachments': config.get('attachments'), 114 } 115 if config.get('icon_emoji'): 116 notification['icon_emoji'] = ':%s:' % config['icon_emoji'].strip(':') 117 if config.get('icon_url'): 118 notification['icon_url'] = config['icon_url'] 119 120 try: 121 requests.post(config['web_hook_url'], json=notification) 122 except RequestException as e: 123 raise PluginWarning(e.args[0]) 124 125 126@event('plugin.register') 127def register_plugin(): 128 plugin.register(SlackNotifier, plugin_name, api_ver=2, interfaces=['notifiers']) 129