/
/
/
1"""Model/base for a Metadata Provider implementation."""
2
3from __future__ import annotations
4
5from typing import TYPE_CHECKING
6
7from music_assistant_models.enums import ProviderFeature
8from music_assistant_models.media_items import UniqueList
9
10from .provider import Provider
11
12if TYPE_CHECKING:
13 from music_assistant_models.media_items import (
14 Album,
15 Artist,
16 BrowseFolder,
17 ItemMapping,
18 MediaItemMetadata,
19 MediaItemType,
20 Playlist,
21 RecommendationFolder,
22 Track,
23 )
24
25
26class MetadataProvider(Provider):
27 """
28 Base representation of a Metadata Provider (controller).
29
30 Metadata Provider implementations should inherit from this base model.
31 """
32
33 @property
34 def priority(self) -> int:
35 """Priority for this provider (lower = more preferred)."""
36 return 50
37
38 async def get_artist_metadata(self, artist: Artist) -> MediaItemMetadata | None:
39 """Retrieve metadata for an artist on this Metadata provider."""
40 if ProviderFeature.ARTIST_METADATA in self.supported_features:
41 raise NotImplementedError
42 return None
43
44 async def get_album_metadata(self, album: Album) -> MediaItemMetadata | None:
45 """Retrieve metadata for an album on this Metadata provider."""
46 if ProviderFeature.ALBUM_METADATA in self.supported_features:
47 raise NotImplementedError
48 return None
49
50 async def get_track_metadata(self, track: Track) -> MediaItemMetadata | None:
51 """Retrieve metadata for a track on this Metadata provider."""
52 if ProviderFeature.TRACK_METADATA in self.supported_features:
53 raise NotImplementedError
54 return None
55
56 async def get_playlist_metadata(self, playlist: Playlist) -> MediaItemMetadata | None:
57 """Retrieve metadata for a playlist on this Metadata provider."""
58 if ProviderFeature.PLAYLIST_METADATA in self.supported_features:
59 raise NotImplementedError
60 return None
61
62 async def get_similar_tracks(self, track: Track, limit: int = 25) -> list[Track]:
63 """
64 Retrieve a list of similar tracks for the given track.
65
66 Will only be called if ProviderFeature.SIMILAR_TRACKS is declared.
67
68 :param track: The reference track.
69 :param limit: Maximum number of similar tracks to return.
70 """
71 if ProviderFeature.SIMILAR_TRACKS in self.supported_features:
72 raise NotImplementedError
73 return []
74
75 async def get_similar_artists(self, artist: Artist, limit: int = 25) -> list[Artist]:
76 """
77 Retrieve a list of similar artists for the given artist.
78
79 Will only be called if ProviderFeature.SIMILAR_ARTISTS is declared.
80
81 :param artist: The reference artist.
82 :param limit: Maximum number of similar artists to return.
83 """
84 if ProviderFeature.SIMILAR_ARTISTS in self.supported_features:
85 raise NotImplementedError
86 return []
87
88 async def get_recommendations(self) -> list[RecommendationFolder]:
89 """
90 Get this provider's available recommendation rows, without items.
91
92 Must be fast: return static or cached row descriptors only, without
93 live backend calls. The items for a row are fetched separately
94 through get_recommendation_items.
95
96 Will only be called if ProviderFeature.RECOMMENDATIONS is declared.
97 """
98 if ProviderFeature.RECOMMENDATIONS in self.supported_features:
99 raise NotImplementedError
100 return []
101
102 async def get_recommendation_items(
103 self, item_id: str
104 ) -> UniqueList[MediaItemType | ItemMapping | BrowseFolder]:
105 """
106 Get the items for a single recommendation row.
107
108 Live backend fetches belong here. Will only be called if
109 ProviderFeature.RECOMMENDATIONS is declared.
110
111 :param item_id: The item_id of the row, as returned by get_recommendations.
112 """
113 if ProviderFeature.RECOMMENDATIONS in self.supported_features:
114 raise NotImplementedError
115 return UniqueList()
116
117 async def get_artist_toptracks(self, artist: Artist, limit: int = 25) -> list[Track]:
118 """
119 Retrieve a list of top tracks for the given artist.
120
121 Will only be called if ProviderFeature.ARTIST_TOPTRACKS is declared.
122
123 :param artist: The reference artist.
124 :param limit: Maximum number of top tracks to return.
125 """
126 if ProviderFeature.ARTIST_TOPTRACKS in self.supported_features:
127 raise NotImplementedError
128 return []
129
130 async def get_artist_topalbums(self, artist: Artist, limit: int = 25) -> list[Album]:
131 """
132 Retrieve a list of top albums for the given artist.
133
134 Will only be called if ProviderFeature.ARTIST_TOPALBUMS is declared.
135
136 :param artist: The reference artist.
137 :param limit: Maximum number of top albums to return.
138 """
139 if ProviderFeature.ARTIST_TOPALBUMS in self.supported_features:
140 raise NotImplementedError
141 return []
142
143 async def resolve_image(self, path: str) -> str | bytes:
144 """
145 Resolve an image from an image path.
146
147 This either returns (a generator to get) raw bytes of the image or
148 a string with an http(s) URL or local path that is accessible from the server.
149 """
150 return path
151