1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-17 15:44:52 +01:00
Files
core/homeassistant/components/ntfy/services.py

182 lines
5.3 KiB
Python

"""Service registration for ntfy integration."""
from datetime import timedelta
from typing import Any
from aiontfy import BroadcastAction, CopyAction, HttpAction, ViewAction
import voluptuous as vol
from yarl import URL
from homeassistant.components.notify import (
ATTR_MESSAGE,
ATTR_TITLE,
DOMAIN as NOTIFY_DOMAIN,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, service
from homeassistant.helpers.selector import MediaSelector
from .const import DOMAIN
SERVICE_PUBLISH = "publish"
SERVICE_CLEAR = "clear"
SERVICE_DELETE = "delete"
ATTR_ATTACH = "attach"
ATTR_CALL = "call"
ATTR_CLICK = "click"
ATTR_DELAY = "delay"
ATTR_EMAIL = "email"
ATTR_ICON = "icon"
ATTR_MARKDOWN = "markdown"
ATTR_PRIORITY = "priority"
ATTR_TAGS = "tags"
ATTR_SEQUENCE_ID = "sequence_id"
ATTR_ATTACH_FILE = "attach_file"
ATTR_FILENAME = "filename"
GRP_ATTACHMENT = "attachment"
MSG_ATTACHMENT = "Only one attachment source is allowed: URL or local file"
ATTR_ACTIONS = "actions"
ATTR_ACTION = "action"
ATTR_VIEW = "view"
ATTR_BROADCAST = "broadcast"
ATTR_HTTP = "http"
ATTR_LABEL = "label"
ATTR_URL = "url"
ATTR_CLEAR = "clear"
ATTR_INTENT = "intent"
ATTR_EXTRAS = "extras"
ATTR_METHOD = "method"
ATTR_HEADERS = "headers"
ATTR_BODY = "body"
ATTR_VALUE = "value"
ATTR_COPY = "copy"
ACTIONS_MAP = {
ATTR_VIEW: ViewAction,
ATTR_BROADCAST: BroadcastAction,
ATTR_HTTP: HttpAction,
ATTR_COPY: CopyAction,
}
MAX_ACTIONS_ALLOWED = 3 # ntfy only supports up to 3 actions per notification
def validate_filename(params: dict[str, Any]) -> dict[str, Any]:
"""Validate filename."""
if ATTR_FILENAME in params and not (
ATTR_ATTACH_FILE in params or ATTR_ATTACH in params
):
raise vol.Invalid("Filename only allowed when attachment is provided")
return params
ACTION_SCHEMA = vol.Schema(
{
vol.Required(ATTR_LABEL): cv.string,
vol.Optional(ATTR_CLEAR, default=False): cv.boolean,
}
)
VIEW_SCHEMA = ACTION_SCHEMA.extend(
{
vol.Required(ATTR_ACTION): vol.Equal("view"),
vol.Required(ATTR_URL): vol.All(vol.Url(), vol.Coerce(URL)),
}
)
BROADCAST_SCHEMA = ACTION_SCHEMA.extend(
{
vol.Required(ATTR_ACTION): vol.Equal("broadcast"),
vol.Optional(ATTR_INTENT): cv.string,
vol.Optional(ATTR_EXTRAS): dict[str, str],
}
)
HTTP_SCHEMA = VIEW_SCHEMA.extend(
{
vol.Required(ATTR_ACTION): vol.Equal("http"),
vol.Optional(ATTR_METHOD): cv.string,
vol.Optional(ATTR_HEADERS): dict[str, str],
vol.Optional(ATTR_BODY): cv.string,
}
)
COPY_SCHEMA = ACTION_SCHEMA.extend(
{
vol.Required(ATTR_ACTION): vol.Equal("copy"),
vol.Required(ATTR_VALUE): cv.string,
}
)
SERVICE_PUBLISH_SCHEMA = vol.All(
cv.make_entity_service_schema(
{
vol.Optional(ATTR_TITLE): cv.string,
vol.Optional(ATTR_MESSAGE): cv.string,
vol.Optional(ATTR_MARKDOWN): cv.boolean,
vol.Optional(ATTR_TAGS): vol.All(cv.ensure_list, [str]),
vol.Optional(ATTR_PRIORITY): vol.All(vol.Coerce(int), vol.Range(1, 5)),
vol.Optional(ATTR_CLICK): vol.All(vol.Url(), vol.Coerce(URL)),
vol.Optional(ATTR_DELAY): vol.All(
cv.time_period,
vol.Range(min=timedelta(seconds=10), max=timedelta(days=3)),
),
vol.Optional(ATTR_EMAIL): vol.Email(),
vol.Optional(ATTR_CALL): cv.string,
vol.Optional(ATTR_ICON): vol.All(vol.Url(), vol.Coerce(URL)),
vol.Optional(ATTR_SEQUENCE_ID): cv.string,
vol.Exclusive(ATTR_ATTACH, GRP_ATTACHMENT, MSG_ATTACHMENT): vol.All(
vol.Url(), vol.Coerce(URL)
),
vol.Exclusive(
ATTR_ATTACH_FILE, GRP_ATTACHMENT, MSG_ATTACHMENT
): MediaSelector({"accept": ["*/*"]}),
vol.Optional(ATTR_FILENAME): cv.string,
vol.Optional(ATTR_ACTIONS): vol.All(
cv.ensure_list,
vol.Length(
max=MAX_ACTIONS_ALLOWED,
msg="Too many actions defined. A maximum of 3 is supported",
),
[vol.Any(VIEW_SCHEMA, BROADCAST_SCHEMA, HTTP_SCHEMA, COPY_SCHEMA)],
),
}
),
validate_filename,
)
SERVICE_CLEAR_DELETE_SCHEMA = cv.make_entity_service_schema(
{
vol.Required(ATTR_SEQUENCE_ID): cv.string,
}
)
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Set up services for ntfy integration."""
service.async_register_platform_entity_service(
hass,
DOMAIN,
SERVICE_PUBLISH,
entity_domain=NOTIFY_DOMAIN,
schema=SERVICE_PUBLISH_SCHEMA,
description_placeholders={
"markdown_guide_url": "https://www.markdownguide.org/basic-syntax/",
"emoji_reference_url": "https://docs.ntfy.sh/emojis/",
},
func="publish",
)
service.async_register_platform_entity_service(
hass,
DOMAIN,
SERVICE_CLEAR,
entity_domain=NOTIFY_DOMAIN,
schema=SERVICE_CLEAR_DELETE_SCHEMA,
func="clear",
)
service.async_register_platform_entity_service(
hass,
DOMAIN,
SERVICE_DELETE,
entity_domain=NOTIFY_DOMAIN,
schema=SERVICE_CLEAR_DELETE_SCHEMA,
func="delete",
)