Coverage for custom_components/supernotify/transports/alexa_media_player.py: 91%

33 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 

5from homeassistant.const import ATTR_ENTITY_ID 

6 

7from custom_components.supernotify import ( 

8 OPTION_MESSAGE_USAGE, 

9 OPTION_SIMPLIFY_TEXT, 

10 OPTION_STRIP_URLS, 

11 OPTION_TARGET_CATEGORIES, 

12 OPTION_TARGET_INCLUDE_RE, 

13 OPTION_UNIQUE_TARGETS, 

14 TRANSPORT_ALEXA_MEDIA_PLAYER, 

15) 

16from custom_components.supernotify.envelope import Envelope 

17from custom_components.supernotify.model import MessageOnlyPolicy, TargetRequired, TransportConfig 

18from custom_components.supernotify.transport import ( 

19 Transport, 

20) 

21 

22RE_VALID_ALEXA = r"media_player\.[A-Za-z0-9_]+" 

23 

24_LOGGER = logging.getLogger(__name__) 

25 

26 

27class AlexaMediaPlayerTransport(Transport): 

28 """Notify via Amazon Alexa announcements 

29 

30 options: 

31 message_usage: standard | use_title | combine_title 

32 

33 """ 

34 

35 name = TRANSPORT_ALEXA_MEDIA_PLAYER 

36 

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

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

39 

40 @property 

41 def default_config(self) -> TransportConfig: 

42 config = TransportConfig() 

43 config.delivery_defaults.action = "notify.alexa_media" 

44 config.delivery_defaults.target_required = TargetRequired.ALWAYS 

45 config.delivery_defaults.options = { 

46 OPTION_SIMPLIFY_TEXT: True, 

47 OPTION_STRIP_URLS: True, 

48 OPTION_MESSAGE_USAGE: MessageOnlyPolicy.STANDARD, 

49 OPTION_UNIQUE_TARGETS: True, 

50 OPTION_TARGET_CATEGORIES: [ATTR_ENTITY_ID], 

51 OPTION_TARGET_INCLUDE_RE: [RE_VALID_ALEXA], 

52 } 

53 return config 

54 

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

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

57 return action is not None 

58 

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

60 _LOGGER.debug("SUPERNOTIFY notify_alexa_media %s", envelope.message) 

61 

62 media_players = envelope.target.entity_ids or [] 

63 

64 if not media_players: 

65 _LOGGER.debug("SUPERNOTIFY skipping alexa media player, no targets") 

66 return False 

67 

68 action_data: dict[str, Any] = {"message": envelope.message, ATTR_DATA: {"type": "announce"}, ATTR_TARGET: media_players} 

69 # alexa media player expects a non-std list as target, so don't use notify target arg (which expects dict) 

70 if envelope.data and envelope.data.get("data"): 

71 action_data[ATTR_DATA].update(envelope.data.get("data")) 

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