Source code for flexget.components.notify.notifiers.pushover

import datetime

from loguru import logger
from requests.exceptions import RequestException

from flexget import plugin
from flexget.config_schema import one_or_more
from flexget.event import event
from flexget.plugin import PluginWarning
from flexget.utils.requests import Session as RequestSession
from flexget.utils.requests import TimedLimiter

plugin_name = 'pushover'
logger = logger.bind(name=plugin_name)

PUSHOVER_URL = 'https://api.pushover.net/1/messages.json'

requests = RequestSession(max_retries=3)
requests.add_domain_limiter(TimedLimiter('pushover.net', '5 seconds'))


[docs] class PushoverNotifier: """Send a Pushover notification. Example:: notify: entries: via: - pushover: user_key: <USER_KEY> (can also be a list of userkeys) token: <TOKEN> [device: <DEVICE_STRING>] [priority: <PRIORITY>] [url: <URL>] [url_title: <URL_TITLE>] [sound: <SOUND>] [retry]: <RETRY>] [expire]: <EXPIRE>] [callback]: <CALLBACK>] [html]: <HTML>] """ schema = { 'type': 'object', 'properties': { 'user_key': one_or_more({'type': 'string'}), 'api_key': {'type': 'string', 'default': 'aPwSHwkLcNaavShxktBpgJH4bRWc3m'}, 'device': one_or_more({'type': 'string'}), 'priority': { 'oneOf': [{'type': 'number', 'minimum': -2, 'maximum': 2}, {'type': 'string'}] }, 'url': {'type': 'string'}, 'url_title': {'type': 'string'}, 'sound': {'type': 'string'}, 'retry': {'type': 'integer', 'minimum': 30}, 'expire': {'type': 'integer', 'maximum': 86400}, 'callback': {'type': 'string'}, 'html': {'type': 'boolean'}, }, 'required': ['user_key'], 'additionalProperties': False, }
[docs] def notify(self, title, message, config): """Send a Pushover notification. :param str title: the message's title :param str message: the message to send :param dict config: The pushover config """ notification = { 'token': config.get('api_key'), 'message': message, 'title': title, 'device': config.get('device'), 'priority': config.get('priority'), 'url': config.get('url'), 'url_title': config.get('url_title'), 'sound': config.get('sound'), 'retry': config.get('retry'), 'expire': config.get('expire'), 'callback': config.get('callback'), } # HTML parsing mode if config.get('html'): notification['html'] = 1 # Support multiple devices if isinstance(notification['device'], list): notification['device'] = ','.join(notification['device']) # Special case, verify certain fields exists if priority is 2 priority = config.get('priority') expire = config.get('expire') retry = config.get('retry') if priority == 2 and not all([expire, retry]): logger.warning( 'Priority set to 2 but fields "expire" and "retry" are not both present.Lowering priority to 1' ) notification['priority'] = 1 if not isinstance(config['user_key'], list): config['user_key'] = [config['user_key']] for user in config['user_key']: notification['user'] = user try: response = requests.post(PUSHOVER_URL, data=notification) except RequestException as e: if e.response is not None: if e.response.status_code == 429: app_reset = e.response.headers.get('X-Limit-App-Reset') if app_reset: reset_time = datetime.datetime.fromtimestamp(int(app_reset)).strftime( '%Y-%m-%d %H:%M:%S' ) error_message = ( f'Monthly pushover message limit reached. Next reset: {reset_time}' ) else: error_message = e.response.json()['errors'][0] else: error_message = str(e) raise PluginWarning(error_message) reset_time = datetime.datetime.fromtimestamp( int(response.headers['X-Limit-App-Reset']) ).strftime('%Y-%m-%d %H:%M:%S') remaining = response.headers['X-Limit-App-Remaining'] logger.debug( 'Pushover notification sent. Notifications remaining until next reset: {}. Next reset at: {}', remaining, reset_time, )
[docs] @event('plugin.register') def register_plugin(): plugin.register(PushoverNotifier, plugin_name, api_ver=2, interfaces=['notifiers'])