Home Assistant Unofficial Reference 2024.12.1
event.py
Go to the documentation of this file.
1 """Event entities for RSS/Atom feeds."""
2 
3 from __future__ import annotations
4 
5 import html
6 import logging
7 
8 from feedparser import FeedParserDict
9 
10 from homeassistant.components.event import EventEntity
11 from homeassistant.core import HomeAssistant, callback
12 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
13 from homeassistant.helpers.entity_platform import AddEntitiesCallback
14 from homeassistant.helpers.update_coordinator import CoordinatorEntity
15 
16 from . import FeedReaderConfigEntry
17 from .const import DOMAIN, EVENT_FEEDREADER
18 from .coordinator import FeedReaderCoordinator
19 
20 LOGGER = logging.getLogger(__name__)
21 
22 ATTR_CONTENT = "content"
23 ATTR_DESCRIPTION = "description"
24 ATTR_LINK = "link"
25 ATTR_TITLE = "title"
26 
27 
29  hass: HomeAssistant,
30  entry: FeedReaderConfigEntry,
31  async_add_entities: AddEntitiesCallback,
32 ) -> None:
33  """Set up event entities for feedreader."""
34  coordinator = entry.runtime_data
35 
36  async_add_entities([FeedReaderEvent(coordinator)])
37 
38 
39 class FeedReaderEvent(CoordinatorEntity[FeedReaderCoordinator], EventEntity):
40  """Representation of a feedreader event."""
41 
42  _attr_event_types = [EVENT_FEEDREADER]
43  _attr_name = None
44  _attr_has_entity_name = True
45  _unrecorded_attributes = frozenset(
46  {ATTR_CONTENT, ATTR_DESCRIPTION, ATTR_TITLE, ATTR_LINK}
47  )
48  coordinator: FeedReaderCoordinator
49 
50  def __init__(self, coordinator: FeedReaderCoordinator) -> None:
51  """Initialize the feedreader event."""
52  super().__init__(coordinator)
53  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.entry_id}_latest_feed"
54  self._attr_translation_key_attr_translation_key = "latest_feed"
55  self._attr_device_info_attr_device_info = DeviceInfo(
56  identifiers={(DOMAIN, coordinator.config_entry.entry_id)},
57  name=coordinator.config_entry.title,
58  configuration_url=coordinator.url,
59  manufacturer=coordinator.feed_author,
60  sw_version=coordinator.feed_version,
61  entry_type=DeviceEntryType.SERVICE,
62  )
63 
64  async def async_added_to_hass(self) -> None:
65  """Entity added to hass."""
66  await super().async_added_to_hass()
67  self.async_on_removeasync_on_remove(
68  self.coordinator.async_add_listener(self._async_handle_update_async_handle_update)
69  )
70 
71  @callback
72  def _async_handle_update(self) -> None:
73  if (data := self.coordinator.data) is None or not data:
74  return
75 
76  # RSS feeds are normally sorted reverse chronologically by published date
77  # so we always take the first entry in list, since we only care about the latest entry
78  feed_data: FeedParserDict = data[0]
79 
80  if description := feed_data.get("description"):
81  description = html.unescape(description)
82 
83  if title := feed_data.get("title"):
84  title = html.unescape(title)
85 
86  if content := feed_data.get("content"):
87  if isinstance(content, list) and isinstance(content[0], dict):
88  content = content[0].get("value")
89  content = html.unescape(content)
90 
91  self._trigger_event_trigger_event(
92  EVENT_FEEDREADER,
93  {
94  ATTR_DESCRIPTION: description,
95  ATTR_TITLE: title,
96  ATTR_LINK: feed_data.get("link"),
97  ATTR_CONTENT: content,
98  },
99  )
100  self.async_write_ha_stateasync_write_ha_state()
None _trigger_event(self, str event_type, dict[str, Any]|None event_attributes=None)
Definition: __init__.py:148
None __init__(self, FeedReaderCoordinator coordinator)
Definition: event.py:50
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
Callable[[], None] async_add_listener(self, CALLBACK_TYPE update_callback, Any context=None)
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, FeedReaderConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: event.py:32