Fix: Consequently use instance id vs domain
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 17 Jan 2025 15:26:59 +0000 (16:26 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 17 Jan 2025 15:26:59 +0000 (16:26 +0100)
Use lookup key to automatically select instance id vs domain to define generic URI/provider

15 files changed:
music_assistant/providers/apple_music/__init__.py
music_assistant/providers/audiobookshelf/__init__.py
music_assistant/providers/deezer/__init__.py
music_assistant/providers/ibroadcast/__init__.py
music_assistant/providers/jellyfin/__init__.py
music_assistant/providers/plex/__init__.py
music_assistant/providers/podcastfeed/__init__.py
music_assistant/providers/qobuz/__init__.py
music_assistant/providers/siriusxm/__init__.py
music_assistant/providers/soundcloud/__init__.py
music_assistant/providers/spotify/__init__.py
music_assistant/providers/test/__init__.py
music_assistant/providers/tidal/__init__.py
music_assistant/providers/tunein/__init__.py
music_assistant/providers/ytmusic/__init__.py

index 1c1d5cbde85adb8bdbb38a2a1dbcbe2df2f6e264..f39bec991ec3e5dabd902f4757644ce10fba2be1 100644 (file)
@@ -364,7 +364,7 @@ class AppleMusicProvider(MusicProvider):
         key_id = base64.b64decode(uri.split(",")[1])
         return StreamDetails(
             item_id=item_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=ContentType.UNKNOWN,
             ),
@@ -392,7 +392,7 @@ class AppleMusicProvider(MusicProvider):
             # No more details available other than the id, return an ItemMapping
             return ItemMapping(
                 media_type=MediaType.ARTIST,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 item_id=artist_id,
                 name=artist_id,
             )
@@ -443,7 +443,7 @@ class AppleMusicProvider(MusicProvider):
             # No more details available other than the id, return an ItemMapping
             return ItemMapping(
                 media_type=MediaType.ALBUM,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 item_id=album_id,
                 name=album_id,
             )
@@ -474,7 +474,7 @@ class AppleMusicProvider(MusicProvider):
             album.artists = [
                 ItemMapping(
                     media_type=MediaType.ARTIST,
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     item_id=artist_name,
                     name=artist_name,
                 )
@@ -556,7 +556,7 @@ class AppleMusicProvider(MusicProvider):
                 ItemMapping(
                     media_type=MediaType.ARTIST,
                     item_id=artist_name,
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     name=artist_name,
                 )
             ]
@@ -584,9 +584,10 @@ class AppleMusicProvider(MusicProvider):
         """Parse Apple Music playlist object to generic layout."""
         attributes = playlist_obj["attributes"]
         playlist_id = attributes["playParams"].get("globalId") or playlist_obj["id"]
+        is_editable = attributes.get("canEdit", False)
         playlist = Playlist(
             item_id=playlist_id,
-            provider=self.domain,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=attributes["name"],
             owner=attributes.get("curatorName", "me"),
             provider_mappings={
@@ -597,6 +598,7 @@ class AppleMusicProvider(MusicProvider):
                     url=attributes.get("url"),
                 )
             },
+            is_editable=is_editable,
         )
         if artwork := attributes.get("artwork"):
             url = artwork["url"]
@@ -612,7 +614,6 @@ class AppleMusicProvider(MusicProvider):
             ]
         if description := attributes.get("description"):
             playlist.metadata.description = description.get("standard")
-        playlist.is_editable = attributes.get("canEdit", False)
         if checksum := attributes.get("lastModifiedDate"):
             playlist.cache_checksum = checksum
         return playlist
index 29cc3f2607c7d275b688e94ff06af168b263c237..8b5592843c14466cff6cd1283fb5b758c2491aa9 100644 (file)
@@ -164,7 +164,7 @@ class Audiobookshelf(MusicProvider):
             item_id=abs_podcast.id_,
             name=title,
             publisher=abs_podcast.media.metadata.author,
-            provider=self.domain,
+            provider=self.lookup_key,
             total_episodes=abs_podcast.media.num_episodes,
             provider_mappings={
                 ProviderMapping(
@@ -214,13 +214,13 @@ class Audiobookshelf(MusicProvider):
                 position = fallback_episode_cnt
         mass_episode = PodcastEpisode(
             item_id=episode_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=episode.title,
             duration=int(episode.duration),
             position=position,
             podcast=ItemMapping(
                 item_id=prov_podcast_id,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=episode.title,
                 media_type=MediaType.PODCAST,
             ),
@@ -292,7 +292,7 @@ class Audiobookshelf(MusicProvider):
     async def _parse_audiobook(self, abs_audiobook: ABSAudioBook) -> Audiobook:
         mass_audiobook = Audiobook(
             item_id=abs_audiobook.id_,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=abs_audiobook.media.metadata.title,
             duration=int(abs_audiobook.media.duration),
             provider_mappings={
@@ -378,7 +378,7 @@ class Audiobookshelf(MusicProvider):
         # audiobookshelf returns information of stream, so we should be able
         # to lift unknown at some point.
         return StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=audiobook_id,
             audio_format=AudioFormat(
                 content_type=ContentType.UNKNOWN,
@@ -404,7 +404,7 @@ class Audiobookshelf(MusicProvider):
         media_url = abs_episode.audio_track.content_url
         full_url = f"{base_url}{media_url}?token={token}"
         return StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=podcast_id,
             audio_format=AudioFormat(
                 content_type=ContentType.UNKNOWN,
@@ -453,7 +453,7 @@ class Audiobookshelf(MusicProvider):
                 BrowseFolder(
                     item_id=library.id_,
                     name=library.name,
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     path=f"{self.instance_id}://{item_path}/{library.id_}",
                 )
             )
@@ -486,7 +486,7 @@ class Audiobookshelf(MusicProvider):
             return ItemMapping(
                 media_type=media_type,
                 item_id=item.id_,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=title,
                 image=image,
             )
index 057c4fd5f4938f777c55401e3a558b8d780cfca7..994c14b8fb57135cd8b314d1f23c3e23a88c0ca0 100644 (file)
@@ -435,7 +435,7 @@ class DeezerProvider(MusicProvider):
         url = url_details["sources"][0]["url"]
         return StreamDetails(
             item_id=item_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=ContentType.try_parse(url_details["format"].split("_")[0])
             ),
@@ -553,7 +553,7 @@ class DeezerProvider(MusicProvider):
         """Parse the deezer-python artist to a Music Assistant artist."""
         return Artist(
             item_id=str(artist.id),
-            provider=self.domain,
+            provider=self.lookup_key,
             name=artist.name,
             media_type=MediaType.ARTIST,
             provider_mappings={
@@ -572,13 +572,13 @@ class DeezerProvider(MusicProvider):
         return Album(
             album_type=AlbumType(album.type),
             item_id=str(album.id),
-            provider=self.domain,
+            provider=self.lookup_key,
             name=album.title,
             artists=[
                 ItemMapping(
                     media_type=MediaType.ARTIST,
                     item_id=str(album.artist.id),
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     name=album.artist.name,
                 )
             ],
@@ -597,9 +597,10 @@ class DeezerProvider(MusicProvider):
     def parse_playlist(self, playlist: deezer.Playlist) -> Playlist:
         """Parse the deezer-python playlist to a Music Assistant playlist."""
         creator = self.get_playlist_creator(playlist)
+        is_editable = creator.id == self.user.id
         return Playlist(
             item_id=str(playlist.id),
-            provider=self.domain,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=playlist.title,
             media_type=MediaType.PLAYLIST,
             provider_mappings={
@@ -620,7 +621,7 @@ class DeezerProvider(MusicProvider):
                     )
                 ],
             ),
-            is_editable=creator.id == self.user.id,
+            is_editable=is_editable,
             owner=creator.name,
             cache_checksum=playlist.checksum,
         )
@@ -637,7 +638,7 @@ class DeezerProvider(MusicProvider):
             artist = ItemMapping(
                 media_type=MediaType.ARTIST,
                 item_id=str(getattr(track.artist, "id", f"deezer-{track.artist.name}")),
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=track.artist.name,
             )
         else:
@@ -646,7 +647,7 @@ class DeezerProvider(MusicProvider):
             album = ItemMapping(
                 media_type=MediaType.ALBUM,
                 item_id=str(track.album.id),
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=track.album.title,
             )
         else:
@@ -654,7 +655,7 @@ class DeezerProvider(MusicProvider):
 
         item = Track(
             item_id=str(track.id),
-            provider=self.domain,
+            provider=self.lookup_key,
             name=track.title,
             sort_name=self.get_short_title(track),
             duration=track.duration,
index 65f11cf3a321cbeeabc48360a80753b21e9ae072..6954326eee776f9d38c7e4ba34e775520bb390a9 100644 (file)
@@ -200,7 +200,7 @@ class IBroadcastProvider(MusicProvider):
         return ItemMapping(
             media_type=media_type,
             item_id=key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=name,
         )
 
@@ -241,7 +241,7 @@ class IBroadcastProvider(MusicProvider):
         url = await self._client.get_full_stream_url(int(item_id), "music-assistant")
 
         return StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=item_id,
             audio_format=AudioFormat(
                 content_type=ContentType.UNKNOWN,
@@ -268,7 +268,7 @@ class IBroadcastProvider(MusicProvider):
         artist = Artist(
             item_id=artist_id,
             name=artist_obj["name"],
-            provider=self.domain,
+            provider=self.lookup_key,
             provider_mappings={
                 ProviderMapping(
                     item_id=artist_id,
@@ -285,7 +285,7 @@ class IBroadcastProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=await self._client.get_artist_artwork_url(artist_id),
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=True,
                     )
                 ]
@@ -298,7 +298,7 @@ class IBroadcastProvider(MusicProvider):
         name, version = parse_title_and_version(album_obj["name"])
         album = Album(
             item_id=album_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=name,
             year=album_obj["year"],
             version=version,
@@ -316,7 +316,7 @@ class IBroadcastProvider(MusicProvider):
             artist = Artist(
                 item_id=VARIOUS_ARTISTS_MBID,
                 name=VARIOUS_ARTISTS_NAME,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 provider_mappings={
                     ProviderMapping(
                         item_id=VARIOUS_ARTISTS_MBID,
@@ -350,7 +350,7 @@ class IBroadcastProvider(MusicProvider):
         return MediaItemImage(
             type=ImageType.THUMB,
             path=url,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             remotely_accessible=True,
         )
 
@@ -358,7 +358,7 @@ class IBroadcastProvider(MusicProvider):
         """Parse an iBroadcast track object to a Track model object."""
         track = Track(
             item_id=track_obj["track_id"],
-            provider=self.domain,
+            provider=self.lookup_key,
             name=track_obj["title"],
             provider_mappings={
                 ProviderMapping(
@@ -432,7 +432,7 @@ class IBroadcastProvider(MusicProvider):
         playlist_id = str(playlist_obj["playlist_id"])
         playlist = Playlist(
             item_id=playlist_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=playlist_obj["name"],
             provider_mappings={
                 ProviderMapping(
index 687507bfc1e560b10a40a35f94879f37ca4f04c6..e5f934bde7bc8a29b53854cce521032bcfecc809 100644 (file)
@@ -372,7 +372,7 @@ class JellyfinProvider(MusicProvider):
             artist = Artist(
                 item_id=UNKNOWN_ARTIST_MAPPING.item_id,
                 name=UNKNOWN_ARTIST_MAPPING.name,
-                provider=self.domain,
+                provider=self.lookup_key,
                 provider_mappings={
                     ProviderMapping(
                         item_id=UNKNOWN_ARTIST_MAPPING.item_id,
@@ -460,7 +460,7 @@ class JellyfinProvider(MusicProvider):
             content_type = ContentType.try_parse(mimetype) if mimetype else ContentType.UNKNOWN
         return StreamDetails(
             item_id=jellyfin_track[ITEM_KEY_ID],
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=content_type,
                 channels=jellyfin_track[ITEM_KEY_MEDIA_STREAMS][0][ITEM_KEY_MEDIA_CHANNELS],
index cb28fb77528c59073d5fed7a1fbd15f013fe8db7..e6ce7cc5635cd0c95292a571a624c7752ea3b12c 100644 (file)
@@ -433,14 +433,14 @@ class PlexProvider(MusicProvider):
         return ItemMapping(
             media_type=media_type,
             item_id=key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=name,
             version=version,
         )
 
     async def _get_or_create_artist_by_name(self, artist_name: str) -> Artist | ItemMapping:
         if library_items := await self.mass.music.artists._get_library_items_by_query(
-            search=artist_name, provider=self.instance_id
+            search=artist_name, provider=self.lookup_key
         ):
             return ItemMapping.from_item(library_items[0])
 
@@ -448,7 +448,7 @@ class PlexProvider(MusicProvider):
         return Artist(
             item_id=artist_id,
             name=artist_name or UNKNOWN_ARTIST,
-            provider=self.domain,
+            provider=self.lookup_key,
             provider_mappings={
                 ProviderMapping(
                     item_id=str(artist_id),
@@ -540,7 +540,7 @@ class PlexProvider(MusicProvider):
         album_id = plex_album.key
         album = Album(
             item_id=album_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=plex_album.title or "[Unknown]",
             provider_mappings={
                 ProviderMapping(
@@ -566,7 +566,7 @@ class PlexProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=thumb,
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=False,
                     )
                 ]
@@ -592,7 +592,7 @@ class PlexProvider(MusicProvider):
         artist = Artist(
             item_id=artist_id,
             name=plex_artist.title or UNKNOWN_ARTIST,
-            provider=self.domain,
+            provider=self.lookup_key,
             provider_mappings={
                 ProviderMapping(
                     item_id=str(artist_id),
@@ -610,7 +610,7 @@ class PlexProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=thumb,
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=False,
                     )
                 ]
@@ -621,7 +621,7 @@ class PlexProvider(MusicProvider):
         """Parse a Plex Playlist response to a Playlist object."""
         playlist = Playlist(
             item_id=plex_playlist.key,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=plex_playlist.title or "[Unknown]",
             provider_mappings={
                 ProviderMapping(
@@ -640,7 +640,7 @@ class PlexProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=thumb,
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=False,
                     )
                 ]
@@ -660,7 +660,7 @@ class PlexProvider(MusicProvider):
             content = None
         track = Track(
             item_id=plex_track.key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=plex_track.title or "[Unknown]",
             provider_mappings={
                 ProviderMapping(
@@ -711,7 +711,7 @@ class PlexProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=thumb,
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=False,
                     )
                 ]
@@ -909,7 +909,7 @@ class PlexProvider(MusicProvider):
 
         stream_details = StreamDetails(
             item_id=plex_track.key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=content_type,
                 channels=media.audioChannels,
index 1483724ddaf612d4bd9b69478a84033352b5642e..374ff18733ac4d3c703e500dec9fdf9253700273 100644 (file)
@@ -172,7 +172,7 @@ class PodcastMusicprovider(MusicProvider):
         for episode in self.parsed["episodes"]:
             if item_id == episode["guid"]:
                 return StreamDetails(
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     item_id=item_id,
                     audio_format=AudioFormat(
                         # hard coded to unknown, so ffmpeg figures out
@@ -189,7 +189,7 @@ class PodcastMusicprovider(MusicProvider):
         podcast = Podcast(
             item_id=self.podcast_id,
             name=self.parsed["title"],
-            provider=self.domain,
+            provider=self.lookup_key,
             uri=self.parsed["link"],
             total_episodes=len(self.parsed["episodes"]),
             provider_mappings={
@@ -224,13 +224,13 @@ class PodcastMusicprovider(MusicProvider):
         item_id = episode_obj["guid"]
         episode = PodcastEpisode(
             item_id=item_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=name,
             duration=episode_obj["total_time"],
             position=episode_obj.get("number", fallback_position),
             podcast=ItemMapping(
                 item_id=self.podcast_id,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=self.parsed["title"],
                 media_type=MediaType.PODCAST,
             ),
index 6207f9db1d221d56e4d6ecb1d9021e4c62301b73..848138bade244b1a7ba000a29a4e31dddb58f9ac 100644 (file)
@@ -432,7 +432,7 @@ class QobuzProvider(MusicProvider):
         self.mass.create_task(self._report_playback_started(streamdata))
         return StreamDetails(
             item_id=str(item_id),
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=content_type,
                 sample_rate=int(streamdata["sampling_rate"] * 1000),
@@ -670,9 +670,13 @@ class QobuzProvider(MusicProvider):
 
     def _parse_playlist(self, playlist_obj):
         """Parse qobuz playlist object to generic layout."""
+        is_editable = (
+            playlist_obj["owner"]["id"] == self._user_auth_info["user"]["id"]
+            or playlist_obj["is_collaborative"]
+        )
         playlist = Playlist(
             item_id=str(playlist_obj["id"]),
-            provider=self.domain,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=playlist_obj["name"],
             owner=playlist_obj["owner"]["name"],
             provider_mappings={
@@ -683,10 +687,7 @@ class QobuzProvider(MusicProvider):
                     url=f'https://open.qobuz.com/playlist/{playlist_obj["id"]}',
                 )
             },
-        )
-        playlist.is_editable = (
-            playlist_obj["owner"]["id"] == self._user_auth_info["user"]["id"]
-            or playlist_obj["is_collaborative"]
+            is_editable=is_editable,
         )
         if img := self.__get_image(playlist_obj):
             playlist.metadata.images = [
index b8784caaf8c69947c9793f10769dc4b22c44a0f1..74fa2baab8e65dd1c7a5b7b5fa4edd9567ae95d3 100644 (file)
@@ -232,7 +232,7 @@ class SiriusXMProvider(MusicProvider):
         # See `_channel_updated` for where this is handled.
         self._current_stream_details = StreamDetails(
             item_id=item_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=ContentType.AAC,
             ),
@@ -287,7 +287,7 @@ class SiriusXMProvider(MusicProvider):
 
     def _parse_radio(self, channel: XMChannel) -> Radio:
         radio = Radio(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=channel.id,
             name=channel.name,
             provider_mappings={
@@ -309,7 +309,7 @@ class SiriusXMProvider(MusicProvider):
         if icon is not None:
             images.append(
                 MediaItemImage(
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     type=ImageType.THUMB,
                     path=icon,
                     remotely_accessible=True,
@@ -317,7 +317,7 @@ class SiriusXMProvider(MusicProvider):
             )
             images.append(
                 MediaItemImage(
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     type=ImageType.LOGO,
                     path=icon,
                     remotely_accessible=True,
@@ -327,7 +327,7 @@ class SiriusXMProvider(MusicProvider):
         if banner is not None:
             images.append(
                 MediaItemImage(
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     type=ImageType.BANNER,
                     path=banner,
                     remotely_accessible=True,
@@ -335,7 +335,7 @@ class SiriusXMProvider(MusicProvider):
             )
             images.append(
                 MediaItemImage(
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     type=ImageType.LANDSCAPE,
                     path=banner,
                     remotely_accessible=True,
index 3e260ef859e4f8e33adb69ece5337fedf03dfc7c..c0ea43552475baf1504094c4e2c4478657795ae9 100644 (file)
@@ -309,7 +309,7 @@ class SoundcloudMusicProvider(MusicProvider):
         """Return the content details for the given track when it will be streamed."""
         url: str = await self._soundcloud.get_stream_url(track_id=item_id)
         return StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=item_id,
             # let ffmpeg work out the details itself as
             # soundcloud uses a mix of different content types and streaming methods
index fe4ef2c1f9d1d907550e70a1fd2ecbaf6f0581e2..1c99a2811f00e69b2acbf25dd6cb0fe59fb0a722 100644 (file)
@@ -381,7 +381,7 @@ class SpotifyProvider(MusicProvider):
     async def _get_liked_songs_playlist(self) -> Playlist:
         liked_songs = Playlist(
             item_id=self._get_liked_songs_playlist_id(),
-            provider=self.domain,
+            provider=self.lookup_key,
             name=f'Liked Songs {self._sp_user["display_name"]}',  # TODO to be translated
             owner=self._sp_user["display_name"],
             provider_mappings={
@@ -400,7 +400,7 @@ class SpotifyProvider(MusicProvider):
             MediaItemImage(
                 type=ImageType.THUMB,
                 path="https://misc.scdn.co/liked-songs/liked-songs-64.png",
-                provider=self.domain,
+                provider=self.lookup_key,
                 remotely_accessible=True,
             )
         ]
@@ -552,7 +552,7 @@ class SpotifyProvider(MusicProvider):
         """Return the content details for the given track when it will be streamed."""
         return StreamDetails(
             item_id=item_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=ContentType.OGG,
             ),
@@ -627,7 +627,7 @@ class SpotifyProvider(MusicProvider):
         """Parse spotify artist object to generic layout."""
         artist = Artist(
             item_id=artist_obj["id"],
-            provider=self.domain,
+            provider=self.lookup_key,
             name=artist_obj["name"] or artist_obj["id"],
             provider_mappings={
                 ProviderMapping(
@@ -648,7 +648,7 @@ class SpotifyProvider(MusicProvider):
                         MediaItemImage(
                             type=ImageType.THUMB,
                             path=img_url,
-                            provider=self.instance_id,
+                            provider=self.lookup_key,
                             remotely_accessible=True,
                         )
                     ]
@@ -660,7 +660,7 @@ class SpotifyProvider(MusicProvider):
         name, version = parse_title_and_version(album_obj["name"])
         album = Album(
             item_id=album_obj["id"],
-            provider=self.domain,
+            provider=self.lookup_key,
             name=name,
             version=version,
             provider_mappings={
@@ -693,7 +693,7 @@ class SpotifyProvider(MusicProvider):
                 MediaItemImage(
                     type=ImageType.THUMB,
                     path=album_obj["images"][0]["url"],
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     remotely_accessible=True,
                 )
             ]
@@ -716,7 +716,7 @@ class SpotifyProvider(MusicProvider):
         name, version = parse_title_and_version(track_obj["name"])
         track = Track(
             item_id=track_obj["id"],
-            provider=self.domain,
+            provider=self.lookup_key,
             name=name,
             version=version,
             duration=track_obj["duration_ms"] / 1000,
@@ -758,7 +758,7 @@ class SpotifyProvider(MusicProvider):
                     MediaItemImage(
                         type=ImageType.THUMB,
                         path=track_obj["album"]["images"][0]["url"],
-                        provider=self.instance_id,
+                        provider=self.lookup_key,
                         remotely_accessible=True,
                     )
                 ]
@@ -772,9 +772,12 @@ class SpotifyProvider(MusicProvider):
 
     def _parse_playlist(self, playlist_obj):
         """Parse spotify playlist object to generic layout."""
+        is_editable = (
+            playlist_obj["owner"]["id"] == self._sp_user["id"] or playlist_obj["collaborative"]
+        )
         playlist = Playlist(
             item_id=playlist_obj["id"],
-            provider=self.domain,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=playlist_obj["name"],
             owner=playlist_obj["owner"]["display_name"],
             provider_mappings={
@@ -785,16 +788,14 @@ class SpotifyProvider(MusicProvider):
                     url=playlist_obj["external_urls"]["spotify"],
                 )
             },
-        )
-        playlist.is_editable = (
-            playlist_obj["owner"]["id"] == self._sp_user["id"] or playlist_obj["collaborative"]
+            is_editable=is_editable,
         )
         if playlist_obj.get("images"):
             playlist.metadata.images = [
                 MediaItemImage(
                     type=ImageType.THUMB,
                     path=playlist_obj["images"][0]["url"],
-                    provider=self.instance_id,
+                    provider=self.lookup_key,
                     remotely_accessible=True,
                 )
             ]
index c061769bfc995531b75c74ae38293e12ca60b173..b1653db5c32a4ea6b4a6dc71774895c17337f5c2 100644 (file)
@@ -156,7 +156,7 @@ class TestProvider(MusicProvider):
         artist_idx, album_idx, track_idx = prov_track_id.split("_", 3)
         return Track(
             item_id=prov_track_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test Track {artist_idx} - {album_idx} - {track_idx}",
             duration=60,
             artists=UniqueList([await self.get_artist(artist_idx)]),
@@ -177,7 +177,7 @@ class TestProvider(MusicProvider):
         """Get full artist details by id."""
         return Artist(
             item_id=prov_artist_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test Artist {prov_artist_id}",
             metadata=MediaItemMetadata(images=UniqueList([DEFAULT_THUMB, DEFAULT_FANART])),
             provider_mappings={
@@ -194,7 +194,7 @@ class TestProvider(MusicProvider):
         artist_idx, album_idx = prov_album_id.split("_", 2)
         return Album(
             item_id=prov_album_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test Album {album_idx}",
             artists=UniqueList([await self.get_artist(artist_idx)]),
             provider_mappings={
@@ -211,7 +211,7 @@ class TestProvider(MusicProvider):
         """Get full podcast details by id."""
         return Podcast(
             item_id=prov_podcast_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test Podcast {prov_podcast_id}",
             metadata=MediaItemMetadata(images=UniqueList([DEFAULT_THUMB])),
             provider_mappings={
@@ -228,7 +228,7 @@ class TestProvider(MusicProvider):
         """Get full audiobook details by id."""
         return Audiobook(
             item_id=prov_audiobook_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test Audiobook {prov_audiobook_id}",
             metadata=MediaItemMetadata(
                 images=UniqueList([DEFAULT_THUMB]),
@@ -314,12 +314,12 @@ class TestProvider(MusicProvider):
         podcast_id, episode_idx = prov_episode_id.split("_", 2)
         return PodcastEpisode(
             item_id=prov_episode_id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=f"Test PodcastEpisode {podcast_id}-{episode_idx}",
             duration=60,
             podcast=ItemMapping(
                 item_id=podcast_id,
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 name=f"Test Podcast {podcast_id}",
                 media_type=MediaType.PODCAST,
                 image=DEFAULT_THUMB,
@@ -343,7 +343,7 @@ class TestProvider(MusicProvider):
     ) -> StreamDetails:
         """Get streamdetails for a track/radio."""
         return StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=item_id,
             audio_format=AudioFormat(
                 content_type=ContentType.OGG,
index 8dac82e168bbb0b0fa213706a83de1bc31e2b90b..3db94ca390edbf0b34d051e24958aac9804ec449 100644 (file)
@@ -584,7 +584,7 @@ class TidalProvider(MusicProvider):
 
         return StreamDetails(
             item_id=track.id,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             audio_format=AudioFormat(
                 content_type=ContentType.try_parse(manifest.codecs),
                 sample_rate=manifest.sample_rate,
@@ -643,7 +643,7 @@ class TidalProvider(MusicProvider):
         return ItemMapping(
             media_type=media_type,
             item_id=key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=name,
         )
 
@@ -713,7 +713,7 @@ class TidalProvider(MusicProvider):
         artist_id = artist_obj.id
         artist = Artist(
             item_id=str(artist_id),
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=artist_obj.name,
             provider_mappings={
                 ProviderMapping(
@@ -750,7 +750,7 @@ class TidalProvider(MusicProvider):
         album_id = album_obj.id
         album = Album(
             item_id=str(album_id),
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=name,
             version=version,
             provider_mappings={
@@ -813,7 +813,7 @@ class TidalProvider(MusicProvider):
         track_id = str(track_obj.id)
         track = Track(
             item_id=str(track_id),
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=track_obj.name,
             version=version,
             duration=track_obj.duration,
@@ -871,9 +871,10 @@ class TidalProvider(MusicProvider):
         playlist_id = playlist_obj.id
         creator_id = playlist_obj.creator.id if playlist_obj.creator else None
         creator_name = playlist_obj.creator.name if playlist_obj.creator else "Tidal"
+        is_editable = bool(creator_id and str(creator_id) == self._tidal_user_id)
         playlist = Playlist(
             item_id=str(playlist_id),
-            provider=self.instance_id,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=playlist_obj.name,
             owner=creator_name,
             provider_mappings={
@@ -884,9 +885,8 @@ class TidalProvider(MusicProvider):
                     url=f"{BROWSE_URL}/playlist/{playlist_id}",
                 )
             },
+            is_editable=is_editable,
         )
-        is_editable = bool(creator_id and str(creator_id) == self._tidal_user_id)
-        playlist.is_editable = is_editable
         # metadata
         playlist.cache_checksum = str(playlist_obj.last_updated)
         playlist.metadata.popularity = playlist_obj.popularity
index 2ba94ce59932dd53f8d3fff6e06d8c35451a7925..ea3168e54c2ceb578d8f4e94710dd102fbe637f6 100644 (file)
@@ -245,7 +245,7 @@ class TuneInProvider(MusicProvider):
         if item_id.startswith("http"):
             # custom url
             return StreamDetails(
-                provider=self.instance_id,
+                provider=self.lookup_key,
                 item_id=item_id,
                 audio_format=AudioFormat(
                     content_type=ContentType.UNKNOWN,
@@ -264,7 +264,7 @@ class TuneInProvider(MusicProvider):
             if media_type and stream["media_type"] != media_type:
                 continue
             return StreamDetails(
-                provider=self.domain,
+                provider=self.lookup_key,
                 item_id=item_id,
                 # set contenttype to unknown so ffmpeg can auto detect it
                 audio_format=AudioFormat(content_type=ContentType.UNKNOWN),
index 2ce8097960c6d28d1a515c4540063c07b7a00f22..374cad8607209e069b86311bcebda011228ac3a1 100644 (file)
@@ -501,7 +501,7 @@ class YoutubeMusicProvider(MusicProvider):
         stream_format = await self._get_stream_format(item_id=item_id)
         self.logger.debug("Found stream_format: %s for song %s", stream_format["format"], item_id)
         stream_details = StreamDetails(
-            provider=self.instance_id,
+            provider=self.lookup_key,
             item_id=item_id,
             audio_format=AudioFormat(
                 content_type=ContentType.try_parse(stream_format["audio_ext"]),
@@ -572,7 +572,7 @@ class YoutubeMusicProvider(MusicProvider):
         album = Album(
             item_id=album_id,
             name=name,
-            provider=self.domain,
+            provider=self.lookup_key,
             provider_mappings={
                 ProviderMapping(
                     item_id=str(album_id),
@@ -625,7 +625,7 @@ class YoutubeMusicProvider(MusicProvider):
         artist = Artist(
             item_id=artist_id,
             name=artist_obj["name"],
-            provider=self.domain,
+            provider=self.lookup_key,
             provider_mappings={
                 ProviderMapping(
                     item_id=str(artist_id),
@@ -645,6 +645,7 @@ class YoutubeMusicProvider(MusicProvider):
         """Parse a YT Playlist response to a Playlist object."""
         playlist_id = playlist_obj["id"]
         playlist_name = playlist_obj["title"]
+        is_editable = playlist_obj.get("privacy") and playlist_obj.get("privacy") == "PRIVATE"
         # Playlist ID's are not unique across instances for lists like 'Likes', 'Supermix', etc.
         # So suffix with the instance id to make them unique
         if playlist_id in YT_PERSONAL_PLAYLISTS:
@@ -652,7 +653,7 @@ class YoutubeMusicProvider(MusicProvider):
             playlist_name = f"{playlist_name} ({self.name})"
         playlist = Playlist(
             item_id=playlist_id,
-            provider=self.domain,
+            provider=self.instance_id if is_editable else self.lookup_key,
             name=playlist_name,
             provider_mappings={
                 ProviderMapping(
@@ -662,15 +663,13 @@ class YoutubeMusicProvider(MusicProvider):
                     url=f"{YTM_DOMAIN}/playlist?list={playlist_id}",
                 )
             },
+            is_editable=is_editable,
         )
         if "description" in playlist_obj:
             playlist.metadata.description = playlist_obj["description"]
         if playlist_obj.get("thumbnails"):
             playlist.metadata.images = self._parse_thumbnails(playlist_obj["thumbnails"])
-        is_editable = False
-        if playlist_obj.get("privacy") and playlist_obj.get("privacy") == "PRIVATE":
-            is_editable = True
-        playlist.is_editable = is_editable
+
         if authors := playlist_obj.get("author"):
             if isinstance(authors, str):
                 playlist.owner = authors
@@ -691,7 +690,7 @@ class YoutubeMusicProvider(MusicProvider):
         track_id = str(track_obj["videoId"])
         track = Track(
             item_id=track_id,
-            provider=self.domain,
+            provider=self.lookup_key,
             name=track_obj["title"],
             provider_mappings={
                 ProviderMapping(
@@ -770,7 +769,7 @@ class YoutubeMusicProvider(MusicProvider):
         return ItemMapping(
             media_type=media_type,
             item_id=key,
-            provider=self.instance_id,
+            provider=self.lookup_key,
             name=name,
         )