Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """DataUpdateCoordinator for the LastFM integration."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 from datetime import timedelta
7 
8 from pylast import LastFMNetwork, PyLastError, Track
9 
10 from homeassistant.config_entries import ConfigEntry
11 from homeassistant.const import CONF_API_KEY
12 from homeassistant.core import HomeAssistant
13 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
14 
15 from .const import CONF_USERS, DOMAIN, LOGGER
16 
17 
18 def format_track(track: Track | None) -> str | None:
19  """Format the track."""
20  if track is None:
21  return None
22  return f"{track.artist} - {track.title}"
23 
24 
25 @dataclass
27  """Data holder for LastFM data."""
28 
29  play_count: int
30  image: str
31  now_playing: str | None
32  top_track: str | None
33  last_track: str | None
34 
35 
36 class LastFMDataUpdateCoordinator(DataUpdateCoordinator[dict[str, LastFMUserData]]):
37  """A LastFM Data Update Coordinator."""
38 
39  config_entry: ConfigEntry
40  _client: LastFMNetwork
41 
42  def __init__(self, hass: HomeAssistant) -> None:
43  """Initialize the LastFM data coordinator."""
44  super().__init__(
45  hass,
46  LOGGER,
47  name=DOMAIN,
48  update_interval=timedelta(seconds=30),
49  )
50  self._client_client = LastFMNetwork(api_key=self.config_entryconfig_entry.options[CONF_API_KEY])
51 
52  async def _async_update_data(self) -> dict[str, LastFMUserData]:
53  res = {}
54  for username in self.config_entryconfig_entry.options[CONF_USERS]:
55  data = await self.hasshass.async_add_executor_job(self._get_user_data_get_user_data, username)
56  if data is not None:
57  res[username] = data
58  if not res:
59  raise UpdateFailed
60  return res
61 
62  def _get_user_data(self, username: str) -> LastFMUserData | None:
63  user = self._client_client.get_user(username)
64  try:
65  play_count = user.get_playcount()
66  image = user.get_image()
67  now_playing = format_track(user.get_now_playing())
68  top_tracks = user.get_top_tracks(limit=1)
69  last_tracks = user.get_recent_tracks(limit=1)
70  except PyLastError as exc:
71  if self.last_update_successlast_update_success:
72  LOGGER.error("LastFM update for %s failed: %r", username, exc)
73  return None
74  top_track = None
75  if len(top_tracks) > 0:
76  top_track = format_track(top_tracks[0].item)
77  last_track = None
78  if len(last_tracks) > 0:
79  last_track = format_track(last_tracks[0].track)
80  return LastFMUserData(
81  play_count,
82  image,
83  now_playing,
84  top_track,
85  last_track,
86  )
str|None format_track(Track|None track)
Definition: coordinator.py:18