Coverage for custom_components/supernotify/methods/sms.py: 82%

39 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-10-26 08:54 +0000

1import logging 

2import re 

3from typing import Any 

4 

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

6from homeassistant.const import CONF_DEFAULT 

7 

8from custom_components.supernotify import ( 

9 CONF_OPTIONS, 

10 CONF_PHONE_NUMBER, 

11 METHOD_SMS, 

12 MessageOnlyPolicy, 

13) 

14from custom_components.supernotify.delivery_method import ( 

15 OPTION_MESSAGE_USAGE, 

16 OPTION_SIMPLIFY_TEXT, 

17 OPTION_STRIP_URLS, 

18 DeliveryMethod, 

19) 

20from custom_components.supernotify.envelope import Envelope 

21 

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

23 

24_LOGGER = logging.getLogger(__name__) 

25 

26 

27class SMSDeliveryMethod(DeliveryMethod): 

28 method = METHOD_SMS 

29 MAX_MESSAGE_LENGTH = 158 

30 

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

32 kwargs.setdefault(CONF_DEFAULT, {}) 

33 kwargs[CONF_DEFAULT].setdefault(CONF_OPTIONS, {}) 

34 kwargs[CONF_DEFAULT][CONF_OPTIONS].setdefault(OPTION_SIMPLIFY_TEXT, True) 

35 kwargs[CONF_DEFAULT][CONF_OPTIONS].setdefault(OPTION_STRIP_URLS, False) 

36 kwargs[CONF_DEFAULT][CONF_OPTIONS].setdefault(OPTION_MESSAGE_USAGE, MessageOnlyPolicy.COMBINE_TITLE) 

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

38 

39 def select_target(self, target: str) -> bool: 

40 return re.fullmatch(RE_VALID_PHONE, target) is not None 

41 

42 def recipient_target(self, recipient: dict[str, Any]) -> list[str]: 

43 phone = recipient.get(CONF_PHONE_NUMBER) 

44 return [phone] if phone else [] 

45 

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

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

48 

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

50 mobile_numbers = envelope.targets or [] 

51 

52 if not envelope.message: 

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

54 return False 

55 

56 message: str = envelope.message or "" 

57 if len(message) > self.MAX_MESSAGE_LENGTH: 

58 _LOGGER.debug( 

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

60 len(message), 

61 self.MAX_MESSAGE_LENGTH, 

62 ) 

63 

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

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

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

67 

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