Coverage for custom_components/supernotify/transports/sms.py: 89%

35 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-21 23:31 +0000

1import logging 

2from typing import Any 

3 

4from homeassistant.components.notify.const import ATTR_DATA, ATTR_TARGET 

5 

6from custom_components.supernotify 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.envelope import Envelope 

15from custom_components.supernotify.model import MessageOnlyPolicy, TransportConfig 

16from custom_components.supernotify.transport import ( 

17 Transport, 

18) 

19 

20RE_VALID_PHONE = r"^(\+\d{1,3})?\s?\(?\d{1,4}\)?[\s.-]?\d{3}[\s.-]?\d{4}$" 

21 

22_LOGGER = logging.getLogger(__name__) 

23 

24 

25class SMSTransport(Transport): 

26 name = TRANSPORT_SMS 

27 MAX_MESSAGE_LENGTH = 158 

28 

29 def __init__(self, *args: Any, **kwargs: Any) -> None: 

30 super().__init__(*args, **kwargs) 

31 

32 @property 

33 def default_config(self) -> TransportConfig: 

34 config = TransportConfig() 

35 config.delivery_defaults.options = { 

36 OPTION_SIMPLIFY_TEXT: True, 

37 OPTION_STRIP_URLS: False, 

38 OPTION_MESSAGE_USAGE: MessageOnlyPolicy.COMBINE_TITLE, 

39 OPTION_TARGET_CATEGORIES: [ATTR_PHONE], 

40 } 

41 return config 

42 

43 def validate_action(self, action: str | None) -> bool: 

44 """Override in subclass if transport has fixed action or doesn't require one""" 

45 return action is not None 

46 

47 async def deliver(self, envelope: Envelope) -> bool: 

48 _LOGGER.debug("SUPERNOTIFY notify_sms: %s", envelope.delivery_name) 

49 

50 data: dict[str, Any] = envelope.data or {} 

51 mobile_numbers = envelope.target.phone or [] 

52 

53 if not envelope.message: 

54 _LOGGER.warning("SUPERNOTIFY notify_sms: No message to send") 

55 return False 

56 

57 message: str = envelope.message or "" 

58 if len(message) > self.MAX_MESSAGE_LENGTH: 

59 _LOGGER.debug( 

60 "SUPERNOTIFY notify_sms: Message too long (%d characters), truncating to %d characters", 

61 len(message), 

62 self.MAX_MESSAGE_LENGTH, 

63 ) 

64 

65 action_data = {"message": message[: self.MAX_MESSAGE_LENGTH], ATTR_TARGET: mobile_numbers} 

66 if data and data.get("data"): 

67 action_data[ATTR_DATA] = data.get("data", {}) 

68 

69 return await self.call_action(envelope, action_data=action_data)