/
/
/
1"""Helper functions for the ABC Radio provider."""
2
3from typing import Any
4
5from music_assistant_models.enums import ImageType
6from music_assistant_models.media_items import MediaItemImage, ProviderMapping, Radio
7from music_assistant_models.streamdetails import StreamMetadata
8
9from .constants import ABC_RADIO_STATIONS
10
11
12def parse_radio(station_id: str, instance_id: str, provider_domain: str) -> Radio:
13 """
14 Create a Radio object from static station information.
15
16 :param station_id: A known ABC Radio station id; callers must validate.
17 :param instance_id: The provider instance id.
18 :param provider_domain: The provider domain string.
19 """
20 station = ABC_RADIO_STATIONS[station_id]
21 radio = Radio(
22 provider=instance_id,
23 item_id=station_id,
24 name=station["name"],
25 provider_mappings={
26 ProviderMapping(
27 item_id=station_id,
28 provider_domain=provider_domain,
29 provider_instance=instance_id,
30 available=True,
31 )
32 },
33 )
34 radio.metadata.description = station["description"]
35 radio.metadata.add_image(
36 MediaItemImage(
37 provider=instance_id,
38 type=ImageType.THUMB,
39 path=station["logo_url"],
40 remotely_accessible=True,
41 )
42 )
43 return radio
44
45
46def parse_now_playing(data: dict[str, Any]) -> StreamMetadata | None:
47 """
48 Parse a now-playing API response into StreamMetadata.
49
50 Returns None when no track is currently playing (e.g. talk programming).
51
52 :param data: JSON response from the ABC Radio now-playing API.
53 """
54 play: dict[str, Any] = data.get("now") or {}
55 recording: dict[str, Any] = play.get("recording") or {}
56 title = recording.get("title")
57 if not title:
58 return None
59
60 # Prefer the display artist ABC's own players use; the recording artist list
61 # contains separate performer/composer entries (e.g. for classical works).
62 artist = (play.get("summary") or {}).get("artist") or ", ".join(
63 name
64 for entry in recording.get("artists") or []
65 if entry.get("type") == "primary" and (name := entry.get("name"))
66 )
67
68 # The play-level release is not always populated; fall back to the
69 # first release attached to the recording.
70 releases: list[dict[str, Any]] = recording.get("releases") or []
71 release: dict[str, Any] = play.get("release") or (releases[0] if releases else {})
72 album = release.get("title")
73 if album and (year := release.get("release_year")):
74 album = f"{album} ({year})"
75
76 artwork: list[dict[str, Any]] = release.get("artwork") or []
77 image_url = artwork[0].get("url") if artwork else None
78
79 return StreamMetadata(
80 title=title,
81 artist=artist or None,
82 album=album,
83 image_url=image_url,
84 duration=recording.get("duration"),
85 )
86