if track := await self._parse_track(entry.path, checksum):
# process album
if track.album:
- await self.mass.music.albums.add_db_item(track.album, db=db)
+ db_album = await self.mass.music.albums.add_db_item(
+ track.album, db=db
+ )
+ if not db_album.in_library:
+ await self.mass.music.albums.set_db_library(
+ db_album.item_id, True, db=db
+ )
# process (album)artist
if track.album.artist:
- await self.mass.music.artists.add_db_item(
+ db_artist = await self.mass.music.artists.add_db_item(
track.album.artist, db=db
)
+ if not db_artist.in_library:
+ await self.mass.music.artists.set_db_library(
+ db_artist.item_id, True, db=db
+ )
# add/update track to db
- await self.mass.music.tracks.add_db_item(track, db=db)
+ db_track = await self.mass.music.tracks.add_db_item(
+ track, db=db
+ )
+ if not db_track.in_library:
+ await self.mass.music.tracks.set_db_library(
+ db_track.item_id, True, db=db
+ )
elif playlist := await self._parse_playlist(entry.path, checksum):
# add/update] playlist to db
await self.mass.music.playlists.add_db_item(playlist, db=db)
raise MediaNotFoundError(f"Artist not found: {prov_artist_id}")
# TODO: adjust to json query instead of text search
query = f"SELECT * FROM albums WHERE artist LIKE '%\"{db_artist.item_id}\"%'"
- query += f" AND provider_ids like '%\"{self.type.value}\"%'"
+ query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
return await self.mass.music.albums.get_db_items(query)
async def get_artist_toptracks(self, prov_artist_id: str) -> List[Track]:
raise MediaNotFoundError(f"Artist not found: {prov_artist_id}")
# TODO: adjust to json query instead of text search
query = f"SELECT * FROM tracks WHERE artists LIKE '%\"{db_artist.item_id}\"%'"
- query += f" AND provider_ids like '%\"{self.type.value}\"%'"
+ query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
return await self.mass.music.tracks.get_db_items(query)
async def library_add(self, *args, **kwargs) -> bool:
if tags.title:
track_title = tags.title
else:
-
ext = track_path.split(".")[-1]
track_title = track_path.split(os.sep)[-1]
track_title = track_title.replace(f".{ext}", "").replace("_", " ")
"""Run library sync for this provider."""
# this reference implementation can be overridden with provider specific approach
# this logic is aimed at streaming/online providers,
- # which all have more or less the same structure.
+ # which all have more or less the same structure.
# filesystem implementation(s) just override this.
async with self.mass.database.get_db() as db:
for media_type in self.supported_mediatypes:
controller = self.mass.music.get_controller(media_type)
# create a set of all previous and current db id's
+ # note we only store the items in the prev_ids list that are
+ # unique to this provider to avoid getting into a mess where
+ # for example an item still exists on disk (in case of file provider)
+ # and no longer favorite on streaming provider.
+ # Bottomline this means that we don't do a full 2 way sync if multiple
+ # providers are attached to the same media item.
prev_ids = set()
for db_item in await controller.library():
+ prov_types = {x.prov_type for x in db_item.provider_ids}
+ if len(prov_types) > 1:
+ continue
for prov_id in db_item.provider_ids:
if prov_id.prov_id == self.id:
prev_ids.add(db_item.item_id)