1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-14 23:28:42 +00:00

Move entity service registration to async_setup in ntfy integration (#162833)

This commit is contained in:
Manu
2026-02-12 16:42:15 +01:00
committed by GitHub
parent 29feccb190
commit 5839191c37
4 changed files with 129 additions and 94 deletions

View File

@@ -15,13 +15,24 @@ from aiontfy.exceptions import (
from homeassistant.const import CONF_TOKEN, CONF_URL, CONF_VERIFY_SSL, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
from .coordinator import NtfyConfigEntry, NtfyDataUpdateCoordinator
from .services import async_setup_services
_LOGGER = logging.getLogger(__name__)
PLATFORMS: list[Platform] = [Platform.EVENT, Platform.NOTIFY, Platform.SENSOR]
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the ntfy services."""
async_setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: NtfyConfigEntry) -> bool:

View File

@@ -12,97 +12,28 @@ from aiontfy.exceptions import (
NtfyHTTPError,
NtfyUnauthorizedAuthenticationError,
)
import voluptuous as vol
from yarl import URL
from homeassistant.components import camera, image
from homeassistant.components.media_source import async_resolve_media
from homeassistant.components.notify import (
ATTR_MESSAGE,
ATTR_TITLE,
NotifyEntity,
NotifyEntityDescription,
NotifyEntityFeature,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.selector import MediaSelector
from .const import DOMAIN
from .coordinator import NtfyConfigEntry
from .entity import NtfyBaseEntity
from .services import ATTR_ATTACH_FILE, ATTR_FILENAME, ATTR_SEQUENCE_ID
_LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 0
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"
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
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,
}
),
validate_filename,
)
SERVICE_CLEAR_DELETE_SCHEMA = cv.make_entity_service_schema(
{
vol.Required(ATTR_SEQUENCE_ID): cv.string,
}
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: NtfyConfigEntry,
@@ -115,29 +46,6 @@ async def async_setup_entry(
[NtfyNotifyEntity(config_entry, subentry)], config_subentry_id=subentry_id
)
platform = entity_platform.async_get_current_platform()
platform.async_register_entity_service(
SERVICE_PUBLISH,
SERVICE_PUBLISH_SCHEMA,
"publish",
description_placeholders={
"markdown_guide_url": "https://www.markdownguide.org/basic-syntax/",
"emoji_reference_url": "https://docs.ntfy.sh/emojis/",
},
)
platform.async_register_entity_service(
SERVICE_CLEAR,
SERVICE_CLEAR_DELETE_SCHEMA,
"clear",
)
platform.async_register_entity_service(
SERVICE_DELETE,
SERVICE_CLEAR_DELETE_SCHEMA,
"delete",
)
class NtfyNotifyEntity(NtfyBaseEntity, NotifyEntity):
"""Representation of a ntfy notification entity."""

View File

@@ -0,0 +1,116 @@
"""Service registration for ntfy integration."""
from datetime import timedelta
from typing import Any
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"
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
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,
}
),
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",
)

View File

@@ -15,7 +15,7 @@ from yarl import URL
from homeassistant.components import camera, image, media_source
from homeassistant.components.notify import ATTR_MESSAGE, ATTR_TITLE
from homeassistant.components.ntfy.const import DOMAIN
from homeassistant.components.ntfy.notify import (
from homeassistant.components.ntfy.services import (
ATTR_ATTACH,
ATTR_ATTACH_FILE,
ATTR_CALL,