fix passing kwargs to add functions in the media controllers
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 3 Aug 2023 08:17:02 +0000 (10:17 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 3 Aug 2023 08:21:30 +0000 (10:21 +0200)
music_assistant/server/controllers/media/albums.py
music_assistant/server/controllers/media/artists.py
music_assistant/server/controllers/media/base.py
music_assistant/server/controllers/media/radio.py
music_assistant/server/controllers/media/tracks.py
music_assistant/server/models/music_provider.py

index dd4b86481a3d9dedd5ab631797caff8a7b0a6021..e16b9a27d1311ffc2e4231b4428513a8352d17cc 100644 (file)
@@ -4,7 +4,7 @@ from __future__ import annotations
 import asyncio
 import contextlib
 from random import choice, random
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING
 
 from music_assistant.common.helpers.datetime import utc_timestamp
 from music_assistant.common.helpers.json import serialize_to_json
@@ -65,7 +65,6 @@ class AlbumsController(MediaControllerBase[Album]):
         lazy: bool = True,
         details: Album | ItemMapping = None,
         add_to_library: bool = False,
-        **kwargs: dict[str, Any],
     ) -> Album:
         """Return (full) details for a single media item."""
         album = await super().get(
@@ -75,7 +74,6 @@ class AlbumsController(MediaControllerBase[Album]):
             lazy=lazy,
             details=details,
             add_to_library=add_to_library,
-            **kwargs,
         )
         # append full artist details to full album item
         album.artists = [
@@ -85,7 +83,6 @@ class AlbumsController(MediaControllerBase[Album]):
                 lazy=lazy,
                 details=item,
                 add_to_library=add_to_library,
-                **kwargs,
             )
             for item in album.artists
         ]
@@ -95,25 +92,13 @@ class AlbumsController(MediaControllerBase[Album]):
         self,
         item: Album,
         metadata_lookup: bool = True,
-        add_album_tracks: bool = True,
-        **kwargs: dict[str, Any],  # noqa: ARG002
+        add_album_tracks: bool = False,
     ) -> Album:
         """Add album to library and return the database item."""
         if not isinstance(item, Album):
             raise InvalidDataError("Not a valid Album object (ItemMapping can not be added to db)")
         if not item.provider_mappings:
             raise InvalidDataError("Album is missing provider mapping(s)")
-        # resolve any ItemMapping artists
-        item.artists = [
-            await self.mass.music.artists.get_provider_item(
-                artist.item_id, artist.provider, fallback=artist
-            )
-            if isinstance(artist, ItemMapping)
-            else artist
-            for artist in item.artists
-        ]
-        if not item.artists:
-            raise InvalidDataError("Album is missing artist(s)")
         # grab additional metadata
         if not metadata_lookup:
             await self.mass.metadata.get_album_metadata(item)
@@ -131,9 +116,7 @@ class AlbumsController(MediaControllerBase[Album]):
                 for track in await self._get_provider_album_tracks(item.item_id, item.provider):
                     track.album = library_item
                     tg.create_task(
-                        self.mass.music.tracks.add_item_to_library(
-                            track, metadata_lookup=metadata_lookup
-                        )
+                        self.mass.music.tracks.add_item_to_library(track, metadata_lookup=False)
                     )
         self.mass.signal_event(
             EventType.MEDIA_ITEM_ADDED,
index 7890f01aa4560de2874f9d3a46b15dd579d79ce2..7393a00c95f9274e9289eb1542d2be0c2dc1aaa9 100644 (file)
@@ -59,7 +59,6 @@ class ArtistsController(MediaControllerBase[Artist]):
         self,
         item: Artist | ItemMapping,
         metadata_lookup: bool = True,
-        **kwargs: dict[str, Any],  # noqa: ARG002
     ) -> Artist:
         """Add artist to library and return the database item."""
         if isinstance(item, ItemMapping):
index 4f1e66a80dc1da8ad96930308f7034d5b0e6771b..54345cd356d3f4e2c3c8572b03dd566aee981a01 100644 (file)
@@ -46,7 +46,7 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
         self.logger = logging.getLogger(f"{ROOT_LOGGER_NAME}.music.{self.media_type.value}")
 
     @abstractmethod
-    async def add_item_to_library(self, item: ItemCls, **kwargs: dict[str, Any]) -> ItemCls:
+    async def add_item_to_library(self, item: ItemCls, metadata_lookup: bool = True) -> ItemCls:
         """Add item to library and return the database item."""
         raise NotImplementedError
 
@@ -153,7 +153,6 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
         lazy: bool = True,
         details: ItemCls = None,
         add_to_library: bool = False,
-        **kwargs: dict[str, Any],
     ) -> ItemCls:
         """Return (full) details for a single media item."""
         if provider_instance_id_or_domain == "database":
@@ -203,9 +202,7 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
         # only if we really need to wait for the result (e.g. to prevent race conditions),
         # we can set lazy to false and we await the job to complete.
         task_id = f"add_{self.media_type.value}.{details.provider}.{details.item_id}"
-        add_task = self.mass.create_task(
-            self.add_item_to_library, item=details, task_id=task_id, **kwargs
-        )
+        add_task = self.mass.create_task(self.add_item_to_library, item=details, task_id=task_id)
         if not lazy:
             await add_task
             return add_task.result()
@@ -684,17 +681,17 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
             return ItemMapping.from_item(db_artist)
 
         # try to request the full item
+        artist = await self.mass.music.artists.get_provider_item(
+            artist.item_id, artist.provider, fallback=artist
+        )
         with suppress(MediaNotFoundError, AssertionError, InvalidDataError):
             db_artist = await self.mass.music.artists.add_item_to_library(
                 artist, metadata_lookup=False
             )
             return ItemMapping.from_item(db_artist)
         # fallback to just the provider item
-        artist = await self.mass.music.artists.get_provider_item(
-            artist.item_id, artist.provider, fallback=artist
-        )
+        # this can happen for unavailable items
         if isinstance(artist, ItemMapping):
-            # this can happen for unavailable items
             return artist
         return ItemMapping.from_item(artist)
 
index e3531844a63a86e2ad240505b5be4b3a78e7c490..5180c772438cd26770bd781e8762a7eaf592dfc8 100644 (file)
@@ -2,7 +2,6 @@
 from __future__ import annotations
 
 import asyncio
-from typing import Any
 
 from music_assistant.common.helpers.datetime import utc_timestamp
 from music_assistant.common.helpers.json import serialize_to_json
@@ -63,9 +62,7 @@ class RadioController(MediaControllerBase[Radio]):
         # return the aggregated result
         return all_versions.values()
 
-    async def add_item_to_library(
-        self, item: Radio, metadata_lookup: bool = True, **kwargs: dict[str, Any]  # noqa: ARG002
-    ) -> Radio:
+    async def add_item_to_library(self, item: Radio, metadata_lookup: bool = True) -> Radio:
         """Add radio to library and return the new database item."""
         if not isinstance(item, Radio):
             raise InvalidDataError("Not a valid Radio object (ItemMapping can not be added to db)")
index e3d7174c86be166a5d75da16e31149fdd62e006f..a5d8a8f91e552df421dbf5275082ec2ab649338e 100644 (file)
@@ -3,7 +3,7 @@ from __future__ import annotations
 
 import asyncio
 import urllib.parse
-from typing import Any
+from contextlib import suppress
 
 from music_assistant.common.helpers.datetime import utc_timestamp
 from music_assistant.common.helpers.json import serialize_to_json
@@ -64,7 +64,6 @@ class TracksController(MediaControllerBase[Track]):
         details: Track = None,
         album_uri: str | None = None,
         add_to_library: bool = False,
-        **kwargs: dict[str, Any],
     ) -> Track:
         """Return (full) details for a single media item."""
         track = await super().get(
@@ -74,7 +73,6 @@ class TracksController(MediaControllerBase[Track]):
             lazy=lazy,
             details=details,
             add_to_library=add_to_library,
-            **kwargs,
         )
         # append full album details to full track item
         try:
@@ -87,7 +85,6 @@ class TracksController(MediaControllerBase[Track]):
                     lazy=lazy,
                     details=None if isinstance(track.album, ItemMapping) else track.album,
                     add_to_library=add_to_library,
-                    **kwargs,
                 )
             elif provider_instance_id_or_domain == "library":
                 # grab the first album this track is attached to
@@ -117,15 +114,12 @@ class TracksController(MediaControllerBase[Track]):
                     lazy=lazy,
                     details=None if isinstance(artist, ItemMapping) else artist,
                     add_to_library=add_to_library,
-                    **kwargs,
                 )
             )
         track.artists = full_artists
         return track
 
-    async def add_item_to_library(
-        self, item: Track, metadata_lookup: bool = True, **kwargs: dict[str, Any]  # noqa: ARG002
-    ) -> Track:
+    async def add_item_to_library(self, item: Track, metadata_lookup: bool = True) -> Track:
         """Add track to library and return the new database item."""
         if not isinstance(item, Track):
             raise InvalidDataError("Not a valid Track object (ItemMapping can not be added to db)")
@@ -133,35 +127,6 @@ class TracksController(MediaControllerBase[Track]):
             raise InvalidDataError("Track is missing artist(s)")
         if not item.provider_mappings:
             raise InvalidDataError("Track is missing provider mapping(s)")
-        # resolve any ItemMapping artists
-        item.artists = [
-            await self.mass.music.artists.get_provider_item(
-                artist.item_id, artist.provider, fallback=artist
-            )
-            if isinstance(artist, ItemMapping)
-            else artist
-            for artist in item.artists
-        ]
-        # resolve ItemMapping album
-        if isinstance(item.album, ItemMapping):
-            item.album = await self.mass.music.albums.get_provider_item(
-                item.album.item_id, item.album.provider, fallback=item.album
-            )
-            if isinstance(item.album, ItemMapping):
-                self.logger.warning(
-                    "Unable to resolve Album for track %s, "
-                    "track will be added to the library without album",
-                    item.uri,
-                )
-        if item.album and not isinstance(item.album, ItemMapping):
-            item.album.artists = [
-                await self.mass.music.artists.get_provider_item(
-                    artist.item_id, artist.provider, fallback=artist
-                )
-                if isinstance(artist, ItemMapping)
-                else artist
-                for artist in item.album.artists
-            ]
         # grab additional metadata
         if not metadata_lookup:
             await self.mass.metadata.get_track_metadata(item)
@@ -442,18 +407,31 @@ class TracksController(MediaControllerBase[Track]):
 
     async def _set_track_album(self, db_id: int, album: Album, disc_number: int, track_number: int):
         """Store AlbumTrack info."""
+        db_album = None
         if album.provider == "library":
             db_album = album
+        elif existing := await self.mass.music.artists.get_library_item_by_prov_id(
+            album.item_id, album.provider
+        ):
+            db_album = existing
         else:
-            db_album = await self.mass.music.albums.get(
-                item_id=album.item_id,
-                provider_instance_id_or_domain=album.provider,
-                lazy=False,
-                details=album,
-                add_to_library=True,
-                metadata_lookup=False,
-                add_album_tracks=False,
+            # not an existing album, we need to fetch and add it
+            if isinstance(album, ItemMapping):
+                album = await self.mass.music.albums.get_provider_item(
+                    album.item_id, album.provider, fallback=album
+                )
+            with suppress(MediaNotFoundError, AssertionError, InvalidDataError):
+                db_album = await self.mass.music.albums.add_item_to_library(
+                    album, metadata_lookup=False, add_album_tracks=False
+                )
+
+        if not db_album:
+            self.logger.warning(
+                "Unable to resolve Album for track %s, "
+                "track will be added to the library without album",
+                album.uri,
             )
+            return
         album_mapping = {"track_id": db_id, "album_id": int(db_album.item_id)}
         if db_row := await self.mass.music.database.get_row(DB_TABLE_ALBUM_TRACKS, album_mapping):
             # update existing
index c7f4949724be324a27bfc77ca90fb191dd71739e..aa7e6177d540434ed29da4f1b2cf302efa02f966 100644 (file)
@@ -420,9 +420,13 @@ class MusicProvider(Provider):
                         # create full db item
                         # note that we skip the metadata lookup purely to speed up the sync
                         # the additional metadata is then lazy retrieved afterwards
+
                         prov_item.favorite = True
+                        extra_kwargs = (
+                            {"add_album_tracks": True} if media_type == MediaType.ALBUM else {}
+                        )
                         library_item = await controller.add_item_to_library(
-                            prov_item, metadata_lookup=False
+                            prov_item, metadata_lookup=False, **extra_kwargs
                         )
                     elif (
                         library_item.metadata.checksum and prov_item.metadata.checksum