Coverage for custom_components/supernotify/transports/sms.py: 100%
37 statements
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-01 15:06 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2026-04-01 15:06 +0000
1import logging
2from typing import TYPE_CHECKING, Any
4from homeassistant.components.notify.const import ATTR_DATA, ATTR_TARGET
6from custom_components.supernotify.const import (
7 ATTR_PHONE,
8 OPTION_MESSAGE_USAGE,
9 OPTION_SIMPLIFY_TEXT,
10 OPTION_STRIP_URLS,
11 OPTION_TARGET_CATEGORIES,
12 TRANSPORT_SMS,
13)
14from custom_components.supernotify.model import DebugTrace, MessageOnlyPolicy, TransportConfig, TransportFeature
15from custom_components.supernotify.transport import (
16 Transport,
17)
19if TYPE_CHECKING:
20 from custom_components.supernotify.envelope import Envelope
22RE_VALID_PHONE = r"^(\+\d{1,3})?\s?\(?\d{1,4}\)?[\s.-]?\d{3}[\s.-]?\d{4}$"
24_LOGGER = logging.getLogger(__name__)
27class SMSTransport(Transport):
28 name = TRANSPORT_SMS
29 MAX_MESSAGE_LENGTH = 158
31 def __init__(self, *args: Any, **kwargs: Any) -> None:
32 super().__init__(*args, **kwargs)
34 @property
35 def supported_features(self) -> TransportFeature:
36 return TransportFeature.MESSAGE | TransportFeature.TITLE
38 @property
39 def default_config(self) -> TransportConfig:
40 config = TransportConfig()
41 config.delivery_defaults.options = {
42 OPTION_SIMPLIFY_TEXT: True,
43 OPTION_STRIP_URLS: False,
44 OPTION_MESSAGE_USAGE: MessageOnlyPolicy.COMBINE_TITLE,
45 OPTION_TARGET_CATEGORIES: [ATTR_PHONE],
46 }
47 return config
49 def validate_action(self, action: str | None) -> bool:
50 """Override in subclass if transport has fixed action or doesn't require one"""
51 return action is not None
53 async def deliver(self, envelope: Envelope, debug_trace: DebugTrace | None = None) -> bool: # noqa: ARG002
54 _LOGGER.debug("SUPERNOTIFY notify_sms: %s", envelope.delivery_name)
56 data: dict[str, Any] = envelope.data or {}
57 mobile_numbers = envelope.target.phone or []
59 if not envelope.message:
60 _LOGGER.warning("SUPERNOTIFY notify_sms: No message to send")
61 return False
63 message: str = envelope.message or ""
64 if len(message) > self.MAX_MESSAGE_LENGTH:
65 _LOGGER.debug(
66 "SUPERNOTIFY notify_sms: Message too long (%d characters), truncating to %d characters",
67 len(message),
68 self.MAX_MESSAGE_LENGTH,
69 )
71 action_data = {"message": message[: self.MAX_MESSAGE_LENGTH], ATTR_TARGET: mobile_numbers}
72 if data and data.get("data"):
73 action_data[ATTR_DATA] = data.get("data", {})
75 return await self.call_action(envelope, action_data=action_data)