From 3076fc5f25af55c8ddd058f49889aa495a7b1630 Mon Sep 17 00:00:00 2001 From: Alexey Kustov Date: Fri, 5 Jun 2020 23:26:56 +0400 Subject: [PATCH] Add notify_events notify integration (#36049) * Add new notify_events notification component * Fix manifest * Formatting fix * Black formatting + CODEOWNERS * Fix requirements_all.txt * Flake8 warning fix * Isort fixes * Update notify-events library requirement version * Replace Exception to more suitable and update lib version * Reformat integration according to "0007-integration-config-yaml-structure.md" * Update homeassistant/components/notify_events/manifest.json Co-authored-by: Martin Hjelmare * Fix manifest + remove async * Black formatting Co-authored-by: Martin Hjelmare --- .coveragerc | 1 + CODEOWNERS | 1 + .../components/notify_events/__init__.py | 20 +++ .../components/notify_events/const.py | 3 + .../components/notify_events/manifest.json | 7 + .../components/notify_events/notify.py | 120 ++++++++++++++++++ requirements_all.txt | 3 + 7 files changed, 155 insertions(+) create mode 100644 homeassistant/components/notify_events/__init__.py create mode 100644 homeassistant/components/notify_events/const.py create mode 100644 homeassistant/components/notify_events/manifest.json create mode 100644 homeassistant/components/notify_events/notify.py diff --git a/.coveragerc b/.coveragerc index 169d865ef39..d7ee4145ef4 100644 --- a/.coveragerc +++ b/.coveragerc @@ -538,6 +538,7 @@ omit = homeassistant/components/notion/sensor.py homeassistant/components/noaa_tides/sensor.py homeassistant/components/norway_air/air_quality.py + homeassistant/components/notify_events/notify.py homeassistant/components/nsw_fuel_station/sensor.py homeassistant/components/nuimo_controller/* homeassistant/components/nuki/lock.py diff --git a/CODEOWNERS b/CODEOWNERS index 82e3e388026..4364916934a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -274,6 +274,7 @@ homeassistant/components/nissan_leaf/* @filcole homeassistant/components/nmbs/* @thibmaek homeassistant/components/no_ip/* @fabaff homeassistant/components/notify/* @home-assistant/core +homeassistant/components/notify_events/* @matrozov @papajojo homeassistant/components/notion/* @bachya homeassistant/components/nsw_fuel_station/* @nickw444 homeassistant/components/nsw_rural_fire_service_feed/* @exxamalte diff --git a/homeassistant/components/notify_events/__init__.py b/homeassistant/components/notify_events/__init__.py new file mode 100644 index 00000000000..98702f75cba --- /dev/null +++ b/homeassistant/components/notify_events/__init__.py @@ -0,0 +1,20 @@ +"""The notify_events component.""" +import voluptuous as vol + +from homeassistant.const import CONF_TOKEN +from homeassistant.helpers import discovery +import homeassistant.helpers.config_validation as cv + +from .const import DOMAIN + +CONFIG_SCHEMA = vol.Schema( + {DOMAIN: vol.Schema({vol.Required(CONF_TOKEN): cv.string})}, extra=vol.ALLOW_EXTRA +) + + +def setup(hass, config): + """Set up the notify_events component.""" + + hass.data[DOMAIN] = config[DOMAIN] + discovery.load_platform(hass, "notify", DOMAIN, {}, config) + return True diff --git a/homeassistant/components/notify_events/const.py b/homeassistant/components/notify_events/const.py new file mode 100644 index 00000000000..811e0fca5f5 --- /dev/null +++ b/homeassistant/components/notify_events/const.py @@ -0,0 +1,3 @@ +"""Const for notify_events.""" + +DOMAIN = "notify_events" diff --git a/homeassistant/components/notify_events/manifest.json b/homeassistant/components/notify_events/manifest.json new file mode 100644 index 00000000000..9f0055e0164 --- /dev/null +++ b/homeassistant/components/notify_events/manifest.json @@ -0,0 +1,7 @@ +{ + "domain": "notify_events", + "name": "Notify.Events", + "documentation": "https://www.home-assistant.io/integrations/notify_events", + "codeowners": ["@matrozov", "@papajojo"], + "requirements": ["notify-events==1.0.4"] +} diff --git a/homeassistant/components/notify_events/notify.py b/homeassistant/components/notify_events/notify.py new file mode 100644 index 00000000000..23df01a128b --- /dev/null +++ b/homeassistant/components/notify_events/notify.py @@ -0,0 +1,120 @@ +"""Notify.Events platform for notify component.""" +import logging +import os.path + +from notify_events import Message + +from homeassistant.components.notify import ( + ATTR_DATA, + ATTR_TITLE, + BaseNotificationService, +) +from homeassistant.const import CONF_TOKEN + +from .const import DOMAIN + +ATTR_LEVEL = "level" +ATTR_PRIORITY = "priority" + +ATTR_FILES = "files" +ATTR_IMAGES = "images" + +ATTR_FILE_URL = "url" +ATTR_FILE_PATH = "path" +ATTR_FILE_CONTENT = "content" +ATTR_FILE_NAME = "name" +ATTR_FILE_MIME_TYPE = "mime_type" + +ATTR_FILE_KIND_FILE = "file" +ATTR_FILE_KIND_IMAGE = "image" + +_LOGGER = logging.getLogger(__name__) + + +def get_service(hass, config, discovery_info=None): + """Get the Notify.Events notification service.""" + return NotifyEventsNotificationService(hass.data[DOMAIN][CONF_TOKEN]) + + +class NotifyEventsNotificationService(BaseNotificationService): + """Implement the notification service for Notify.Events.""" + + def __init__(self, token): + """Initialize the service.""" + self.token = token + + def file_exists(self, filename) -> bool: + """Check if a file exists on disk and is in authorized path.""" + if not self.hass.config.is_allowed_path(filename): + return False + return os.path.isfile(filename) + + def attach_file(self, msg: Message, item: dict, kind: str = ATTR_FILE_KIND_FILE): + """Append a file or image to message.""" + file_name = None + mime_type = None + + if ATTR_FILE_NAME in item: + file_name = item[ATTR_FILE_NAME] + + if ATTR_FILE_MIME_TYPE in item: + mime_type = item[ATTR_FILE_MIME_TYPE] + + if ATTR_FILE_URL in item: + if kind == ATTR_FILE_KIND_IMAGE: + msg.add_image_from_url(item[ATTR_FILE_URL], file_name, mime_type) + else: + msg.add_file_from_url(item[ATTR_FILE_URL], file_name, mime_type) + elif ATTR_FILE_CONTENT in item: + if kind == ATTR_FILE_KIND_IMAGE: + msg.add_image_from_content( + item[ATTR_FILE_CONTENT], file_name, mime_type + ) + else: + msg.add_file_from_content(item[ATTR_FILE_CONTENT], file_name, mime_type) + elif ATTR_FILE_PATH in item: + file_exists = self.file_exists(item[ATTR_FILE_PATH]) + + if file_exists: + if kind == ATTR_FILE_KIND_IMAGE: + msg.add_image(item[ATTR_FILE_PATH], file_name, mime_type) + else: + msg.add_file(item[ATTR_FILE_PATH], file_name, mime_type) + else: + _LOGGER.error("File does not exist: %s", item[ATTR_FILE_PATH]) + + def prepare_message(self, message, data) -> Message: + """Prepare a message to send.""" + msg = Message(message) + + if ATTR_TITLE in data: + msg.set_title(data[ATTR_TITLE]) + + if ATTR_LEVEL in data: + try: + msg.set_level(data[ATTR_LEVEL]) + except ValueError as error: + _LOGGER.warning("Setting level error: %s", error) + + if ATTR_PRIORITY in data: + try: + msg.set_priority(data[ATTR_PRIORITY]) + except ValueError as error: + _LOGGER.warning("Setting priority error: %s", error) + + if ATTR_IMAGES in data: + for image in data[ATTR_IMAGES]: + self.attach_file(msg, image, ATTR_FILE_KIND_IMAGE) + + if ATTR_FILES in data: + for file in data[ATTR_FILES]: + self.attach_file(msg, file) + + return msg + + def send_message(self, message, **kwargs): + """Send a message.""" + data = kwargs.get(ATTR_DATA) or {} + + msg = self.prepare_message(message, data) + msg.send(self.token) diff --git a/requirements_all.txt b/requirements_all.txt index 5251f534717..1f9e369ba45 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -963,6 +963,9 @@ niko-home-control==0.2.1 # homeassistant.components.nilu niluclient==0.1.2 +# homeassistant.components.notify_events +notify-events==1.0.4 + # homeassistant.components.nederlandse_spoorwegen nsapi==3.0.4