Home Assistant Unofficial Reference 2024.12.1
flash_briefings.py
Go to the documentation of this file.
1 """Support for Alexa skill service end point."""
2 
3 import hmac
4 from http import HTTPStatus
5 import logging
6 import uuid
7 
8 from aiohttp.web_response import StreamResponse
9 
10 from homeassistant.components import http
11 from homeassistant.const import CONF_PASSWORD
12 from homeassistant.core import HomeAssistant, callback
13 from homeassistant.helpers import template
14 from homeassistant.helpers.typing import ConfigType
15 import homeassistant.util.dt as dt_util
16 
17 from .const import (
18  API_PASSWORD,
19  ATTR_MAIN_TEXT,
20  ATTR_REDIRECTION_URL,
21  ATTR_STREAM_URL,
22  ATTR_TITLE_TEXT,
23  ATTR_UID,
24  ATTR_UPDATE_DATE,
25  CONF_AUDIO,
26  CONF_DISPLAY_URL,
27  CONF_TEXT,
28  CONF_TITLE,
29  CONF_UID,
30  DATE_FORMAT,
31 )
32 
33 _LOGGER = logging.getLogger(__name__)
34 
35 FLASH_BRIEFINGS_API_ENDPOINT = "/api/alexa/flash_briefings/{briefing_id}"
36 
37 
38 @callback
39 def async_setup(hass: HomeAssistant, flash_briefing_config: ConfigType) -> None:
40  """Activate Alexa component."""
41  hass.http.register_view(AlexaFlashBriefingView(hass, flash_briefing_config))
42 
43 
44 class AlexaFlashBriefingView(http.HomeAssistantView):
45  """Handle Alexa Flash Briefing skill requests."""
46 
47  url = FLASH_BRIEFINGS_API_ENDPOINT
48  requires_auth = False
49  name = "api:alexa:flash_briefings"
50 
51  def __init__(self, hass: HomeAssistant, flash_briefings: ConfigType) -> None:
52  """Initialize Alexa view."""
53  super().__init__()
54  self.flash_briefingsflash_briefings = flash_briefings
55 
56  @callback
57  def get(
58  self, request: http.HomeAssistantRequest, briefing_id: str
59  ) -> StreamResponse | tuple[bytes, HTTPStatus]:
60  """Handle Alexa Flash Briefing request."""
61  _LOGGER.debug("Received Alexa flash briefing request for: %s", briefing_id)
62 
63  if request.query.get(API_PASSWORD) is None:
64  err = "No password provided for Alexa flash briefing: %s"
65  _LOGGER.error(err, briefing_id)
66  return b"", HTTPStatus.UNAUTHORIZED
67 
68  if not hmac.compare_digest(
69  request.query[API_PASSWORD].encode("utf-8"),
70  self.flash_briefingsflash_briefings[CONF_PASSWORD].encode("utf-8"),
71  ):
72  err = "Wrong password for Alexa flash briefing: %s"
73  _LOGGER.error(err, briefing_id)
74  return b"", HTTPStatus.UNAUTHORIZED
75 
76  if not isinstance(self.flash_briefingsflash_briefings.get(briefing_id), list):
77  err = "No configured Alexa flash briefing was found for: %s"
78  _LOGGER.error(err, briefing_id)
79  return b"", HTTPStatus.NOT_FOUND
80 
81  briefing = []
82 
83  for item in self.flash_briefingsflash_briefings.get(briefing_id, []):
84  output = {}
85  if item.get(CONF_TITLE) is not None:
86  if isinstance(item.get(CONF_TITLE), template.Template):
87  output[ATTR_TITLE_TEXT] = item[CONF_TITLE].async_render(
88  parse_result=False
89  )
90  else:
91  output[ATTR_TITLE_TEXT] = item.get(CONF_TITLE)
92 
93  if item.get(CONF_TEXT) is not None:
94  if isinstance(item.get(CONF_TEXT), template.Template):
95  output[ATTR_MAIN_TEXT] = item[CONF_TEXT].async_render(
96  parse_result=False
97  )
98  else:
99  output[ATTR_MAIN_TEXT] = item.get(CONF_TEXT)
100 
101  if (uid := item.get(CONF_UID)) is None:
102  uid = str(uuid.uuid4())
103  output[ATTR_UID] = uid
104 
105  if item.get(CONF_AUDIO) is not None:
106  if isinstance(item.get(CONF_AUDIO), template.Template):
107  output[ATTR_STREAM_URL] = item[CONF_AUDIO].async_render(
108  parse_result=False
109  )
110  else:
111  output[ATTR_STREAM_URL] = item.get(CONF_AUDIO)
112 
113  if item.get(CONF_DISPLAY_URL) is not None:
114  if isinstance(item.get(CONF_DISPLAY_URL), template.Template):
115  output[ATTR_REDIRECTION_URL] = item[CONF_DISPLAY_URL].async_render(
116  parse_result=False
117  )
118  else:
119  output[ATTR_REDIRECTION_URL] = item.get(CONF_DISPLAY_URL)
120 
121  output[ATTR_UPDATE_DATE] = dt_util.utcnow().strftime(DATE_FORMAT)
122 
123  briefing.append(output)
124 
125  return self.json(briefing)
None __init__(self, HomeAssistant hass, ConfigType flash_briefings)
StreamResponse|tuple[bytes, HTTPStatus] get(self, http.HomeAssistantRequest request, str briefing_id)
None async_setup(HomeAssistant hass, ConfigType flash_briefing_config)