/
/
/
1"""The default (library-backed) recommendation rows."""
2
3from __future__ import annotations
4
5from enum import StrEnum
6from typing import TYPE_CHECKING
7
8from music_assistant_models.enums import MediaType
9from music_assistant_models.media_items import RecommendationFolder, UniqueList
10
11if TYPE_CHECKING:
12 from collections.abc import Sequence
13
14 from music_assistant_models.media_items import BrowseFolder, ItemMapping, MediaItemType
15
16 from music_assistant.mass import MusicAssistant
17
18
19class LibraryRowID(StrEnum):
20 """The item_ids of the built-in library recommendation rows."""
21
22 IN_PROGRESS = "in_progress"
23 RECENTLY_PLAYED = "recently_played"
24 RECENTLY_ADDED_TRACKS = "recently_added_tracks"
25 RECENTLY_ADDED_ALBUMS = "recently_added_albums"
26 RANDOM_ARTISTS = "random_artists"
27 RANDOM_ALBUMS = "random_albums"
28 RECENT_FAVORITE_TRACKS = "recent_favorite_tracks"
29 FAVORITE_PLAYLISTS = "favorite_playlists"
30 FAVORITE_RADIO = "favorite_radio"
31 RECENT_ARTISTS = "recent_artists"
32 RECENT_TRACKS = "recent_tracks"
33
34
35def library_rows() -> list[RecommendationFolder]:
36 """Return the built-in library recommendation rows, without items."""
37 return [
38 _folder(LibraryRowID.IN_PROGRESS, "In progress", "in_progress_items", "mdi-motion-play"),
39 _folder(
40 LibraryRowID.RECENTLY_PLAYED, "Recently played", "recently_played", "mdi-motion-play"
41 ),
42 _folder(
43 LibraryRowID.RECENTLY_ADDED_TRACKS,
44 "Recently added tracks",
45 "recently_added_tracks",
46 "mdi-music-note-plus",
47 ),
48 _folder(
49 LibraryRowID.RECENTLY_ADDED_ALBUMS,
50 "Recently added albums",
51 "recently_added_albums",
52 "mdi-album",
53 ),
54 _folder(
55 LibraryRowID.RANDOM_ARTISTS,
56 "Random artists",
57 "random_artists",
58 "mdi-account-music",
59 False,
60 ),
61 _folder(LibraryRowID.RANDOM_ALBUMS, "Random albums", "random_albums", "mdi-album", False),
62 _folder(
63 LibraryRowID.RECENT_FAVORITE_TRACKS,
64 "Recently favorited tracks",
65 "recent_favorite_tracks",
66 "mdi-file-music",
67 ),
68 _folder(
69 LibraryRowID.FAVORITE_PLAYLISTS,
70 "Favorite playlists",
71 "favorite_playlists",
72 "mdi-playlist-music",
73 ),
74 _folder(
75 LibraryRowID.FAVORITE_RADIO,
76 "Favorite Radio stations",
77 "favorite_radio_stations",
78 "mdi-access-point",
79 ),
80 _folder(
81 LibraryRowID.RECENT_ARTISTS,
82 "Recent artists",
83 "recent_artists",
84 "mdi-account-music",
85 False,
86 ),
87 _folder(
88 LibraryRowID.RECENT_TRACKS, "Recent tracks", "recent_tracks", "mdi-music-note", False
89 ),
90 ]
91
92
93async def library_items(
94 mass: MusicAssistant, item_id: str
95) -> UniqueList[MediaItemType | ItemMapping | BrowseFolder]:
96 """Return the items for one built-in library row (empty for an unknown item_id)."""
97 items: Sequence[MediaItemType | ItemMapping | BrowseFolder]
98 match item_id:
99 case LibraryRowID.IN_PROGRESS:
100 items = await mass.music.in_progress_items(limit=10)
101 case LibraryRowID.RECENTLY_PLAYED:
102 items = await mass.music.recently_played(
103 limit=10,
104 media_types=[
105 MediaType.ALBUM,
106 MediaType.TRACK,
107 MediaType.PLAYLIST,
108 MediaType.ARTIST,
109 MediaType.GENRE,
110 ],
111 user_initiated_only=True,
112 always_include_media_types=[MediaType.PODCAST, MediaType.AUDIOBOOK],
113 )
114 case LibraryRowID.RECENTLY_ADDED_TRACKS:
115 items = await mass.music.tracks.library_items(limit=10, order_by="timestamp_added_desc")
116 case LibraryRowID.RECENTLY_ADDED_ALBUMS:
117 items = await mass.music.albums.library_items(limit=10, order_by="timestamp_added_desc")
118 case LibraryRowID.RANDOM_ARTISTS:
119 items = await mass.music.artists.library_items(limit=10, order_by="random_play_count")
120 case LibraryRowID.RANDOM_ALBUMS:
121 items = await mass.music.albums.library_items(limit=10, order_by="random_play_count")
122 case LibraryRowID.RECENT_FAVORITE_TRACKS:
123 items = await mass.music.tracks.library_items(
124 favorite=True, limit=10, order_by="timestamp_modified_desc"
125 )
126 case LibraryRowID.FAVORITE_PLAYLISTS:
127 items = await mass.music.playlists.library_items(
128 favorite=True, limit=10, order_by="random"
129 )
130 case LibraryRowID.FAVORITE_RADIO:
131 items = await mass.music.radio.library_items(
132 favorite=True, limit=10, order_by="play_count_desc"
133 )
134 case LibraryRowID.RECENT_ARTISTS:
135 items = await mass.music.recently_played(
136 limit=10, media_types=[MediaType.ARTIST], user_initiated_only=False
137 )
138 case LibraryRowID.RECENT_TRACKS:
139 items = await mass.music.recently_played(
140 limit=10, media_types=[MediaType.TRACK], user_initiated_only=False
141 )
142 case _:
143 items = []
144 return UniqueList(items)
145
146
147def _folder(
148 item_id: LibraryRowID,
149 name: str,
150 translation_key: str,
151 icon: str,
152 enabled_by_default: bool = True,
153) -> RecommendationFolder:
154 return RecommendationFolder(
155 item_id=item_id.value,
156 provider="library",
157 name=name,
158 translation_key=translation_key,
159 icon=icon,
160 enabled_by_default=enabled_by_default,
161 )
162