Home Assistant Unofficial Reference 2024.12.1
calendar.py
Go to the documentation of this file.
1 """Calendar platform for a Epic Games Store."""
2 
3 from __future__ import annotations
4 
5 from collections import namedtuple
6 from datetime import datetime
7 from typing import Any
8 
9 from homeassistant.components.calendar import CalendarEntity, CalendarEvent
10 from homeassistant.config_entries import ConfigEntry
11 from homeassistant.core import HomeAssistant
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 .const import DOMAIN, CalendarType
17 from .coordinator import EGSCalendarUpdateCoordinator
18 
19 DateRange = namedtuple("DateRange", ["start", "end"]) # noqa: PYI024
20 
21 
23  hass: HomeAssistant,
24  entry: ConfigEntry,
25  async_add_entities: AddEntitiesCallback,
26 ) -> None:
27  """Set up the local calendar platform."""
28  coordinator: EGSCalendarUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
29 
30  entities = [
31  EGSCalendar(coordinator, entry.entry_id, CalendarType.FREE),
32  EGSCalendar(coordinator, entry.entry_id, CalendarType.DISCOUNT),
33  ]
34  async_add_entities(entities)
35 
36 
37 class EGSCalendar(CoordinatorEntity[EGSCalendarUpdateCoordinator], CalendarEntity):
38  """A calendar entity by Epic Games Store."""
39 
40  _attr_has_entity_name = True
41 
42  def __init__(
43  self,
44  coordinator: EGSCalendarUpdateCoordinator,
45  config_entry_id: str,
46  cal_type: CalendarType,
47  ) -> None:
48  """Initialize EGSCalendar."""
49  super().__init__(coordinator)
50  self._cal_type_cal_type = cal_type
51  self._attr_translation_key_attr_translation_key = f"{cal_type}_games"
52  self._attr_unique_id_attr_unique_id = f"{config_entry_id}-{cal_type}"
53  self._attr_device_info_attr_device_info = DeviceInfo(
54  entry_type=DeviceEntryType.SERVICE,
55  identifiers={(DOMAIN, config_entry_id)},
56  manufacturer="Epic Games Store",
57  name="Epic Games Store",
58  )
59 
60  @property
61  def event(self) -> CalendarEvent | None:
62  """Return the next upcoming event."""
63  if event := self.coordinator.data[self._cal_type_cal_type]:
64  return _get_calendar_event(event[0])
65  return None
66 
67  async def async_get_events(
68  self, hass: HomeAssistant, start_date: datetime, end_date: datetime
69  ) -> list[CalendarEvent]:
70  """Get all events in a specific time frame."""
71  events = filter(
72  lambda game: _are_date_range_overlapping(
73  DateRange(start=game["discount_start_at"], end=game["discount_end_at"]),
74  DateRange(start=start_date, end=end_date),
75  ),
76  self.coordinator.data[self._cal_type_cal_type],
77  )
78  return [_get_calendar_event(event) for event in events]
79 
80 
81 def _get_calendar_event(event: dict[str, Any]) -> CalendarEvent:
82  """Return a CalendarEvent from an API event."""
83  return CalendarEvent(
84  summary=event["title"],
85  start=event["discount_start_at"],
86  end=event["discount_end_at"],
87  description=f"{event['description']}\n\n{event['url']}",
88  )
89 
90 
91 def _are_date_range_overlapping(range1: DateRange, range2: DateRange) -> bool:
92  """Return a CalendarEvent from an API event."""
93  latest_start = max(range1.start, range2.start)
94  earliest_end = min(range1.end, range2.end)
95  delta = (earliest_end - latest_start).days + 1
96  overlap = max(0, delta)
97  return overlap > 0
None __init__(self, EGSCalendarUpdateCoordinator coordinator, str config_entry_id, CalendarType cal_type)
Definition: calendar.py:47
list[CalendarEvent] async_get_events(self, HomeAssistant hass, datetime start_date, datetime end_date)
Definition: calendar.py:69
bool _are_date_range_overlapping(DateRange range1, DateRange range2)
Definition: calendar.py:91
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: calendar.py:26
CalendarEvent _get_calendar_event(dict[str, Any] event)
Definition: calendar.py:81