async def search_artist_by_album(self, artistname, albumname=None, album_upc=None): """Retrieve musicbrainz artist id by providing the artist name and albumname or upc.""" for searchartist in [ re.sub(LUCENE_SPECIAL, r"\\\1", artistname), get_compare_string(artistname), ]: if album_upc: endpoint = "release" params = {"query": "barcode:%s" % album_upc} else: searchalbum = re.sub(LUCENE_SPECIAL, r"\\\1", albumname) endpoint = "release" params = { "query": 'artist:"%s" AND release:"%s"' % (searchartist, searchalbum) } result = await self.get_data(endpoint, params) if result and "releases" in result: for strictness in [True, False]: for item in result["releases"]: if album_upc or compare_strings( item["title"], albumname, strictness ): for artist in item["artist-credit"]: if compare_strings( artist["artist"]["name"], artistname, strictness ): return artist["artist"]["id"] for alias in artist.get("aliases", []): if compare_strings( alias["name"], artistname, strictness ): return artist["id"] return ""
async def search_artist_by_track(self, artistname, trackname=None, track_isrc=None): """Retrieve artist id by providing the artist name and trackname or track isrc.""" endpoint = "recording" searchartist = re.sub(LUCENE_SPECIAL, r"\\\1", artistname) # searchartist = searchartist.replace('/','').replace('\\','').replace('-', '') if track_isrc: endpoint = "isrc/%s" % track_isrc params = {"inc": "artist-credits"} else: searchtrack = re.sub(LUCENE_SPECIAL, r"\\\1", trackname) endpoint = "recording" params = {"query": '"%s" AND artist:"%s"' % (searchtrack, searchartist)} result = await self.get_data(endpoint, params) if result and "recordings" in result: for strictness in [True, False]: for item in result["recordings"]: if track_isrc or compare_strings( item["title"], trackname, strictness ): for artist in item["artist-credit"]: if compare_strings( artist["artist"]["name"], artistname, strictness ): return artist["artist"]["id"] for alias in artist.get("aliases", []): if compare_strings( alias["name"], artistname, strictness ): return artist["id"] return ""
async def _match_prov_artist(self, db_artist: Artist, provider: MusicProvider): """Try to find matching artists on given provider for the provided (database) artist.""" LOGGER.debug("Trying to match artist %s on provider %s", db_artist.name, provider.name) # try to get a match with some reference tracks of this artist for ref_track in await self.get_artist_toptracks( db_artist.item_id, db_artist.provider): # make sure we have a full track if isinstance(ref_track.album, ItemMapping): ref_track = await self.get_track(ref_track.item_id, ref_track.provider) searchstr = "%s %s" % (db_artist.name, ref_track.name) search_results = await self.search_provider(searchstr, provider.id, [MediaType.Track], limit=25) for search_result_item in search_results.tracks: if compare_track(search_result_item, ref_track): # get matching artist from track for search_item_artist in search_result_item.artists: if compare_strings(db_artist.name, search_item_artist.name): # 100% album match # get full artist details so we have all metadata prov_artist = await self._get_provider_artist( search_item_artist.item_id, search_item_artist.provider) await self.mass.database.update_artist( db_artist.item_id, prov_artist) return True # try to get a match with some reference albums of this artist artist_albums = await self.get_artist_albums(db_artist.item_id, db_artist.provider) for ref_album in artist_albums: if ref_album.album_type == AlbumType.Compilation: continue searchstr = "%s %s" % (db_artist.name, ref_album.name) search_result = await self.search_provider(searchstr, provider.id, [MediaType.Album], limit=25) for search_result_item in search_result.albums: # artist must match 100% if not compare_strings(db_artist.name, search_result_item.artist.name): continue if compare_album(search_result_item, ref_album): # 100% album match # get full artist details so we have all metadata prov_artist = await self._get_provider_artist( search_result_item.artist.item_id, search_result_item.artist.provider, ) await self.mass.database.update_artist( db_artist.item_id, prov_artist) return True return False
def new_cast_status(self, cast_status) -> None: """Handle updates of the cast status.""" self.cast_status = cast_status self._is_speaker_group = ( self._cast_info.is_audio_group and self._chromecast.mz_controller and self._chromecast.mz_controller.members and compare_strings( self._chromecast.mz_controller.members[0], self.player_id)) self.update_state()
async def match_track(self, db_track: Track): """ Try to find matching track on all providers for the provided (database) track_id. This is used to link objects of different providers/qualities together. """ assert (db_track.provider == "database" ), "Matching only supported for database items!" if isinstance(db_track.album, ItemMapping): # matching only works if we have a full track object db_track = await self.mass.database.get_track(db_track.item_id) for provider in self.mass.get_providers(ProviderType.MUSIC_PROVIDER): if MediaType.Track not in provider.supported_mediatypes: continue LOGGER.debug("Trying to match track %s on provider %s", db_track.name, provider.name) match_found = False for db_track_artist in db_track.artists: if match_found: break searchstr = "%s %s" % (db_track_artist.name, db_track.name) if db_track.version: searchstr += " " + db_track.version search_result = await self.search_provider(searchstr, provider.id, [MediaType.Track], limit=25) for search_result_item in search_result.tracks: if not search_result_item.available: continue if compare_track(search_result_item, db_track): # 100% match, we can simply update the db with additional provider ids match_found = True await self.mass.database.update_track( db_track.item_id, search_result_item) # while we're here, also match the artist if db_track_artist.provider == "database": for artist in search_result_item.artists: if not compare_strings(db_track_artist.name, artist.name): continue prov_artist = await self._get_provider_artist( artist.item_id, artist.provider) await self.mass.database.update_artist( db_track_artist.item_id, prov_artist) if not match_found: LOGGER.debug( "Could not find match for Track %s on provider %s", db_track.name, provider.name, )
async def get_album_versions(self, item_id: str, provider_id: str) -> Set[Album]: """Return all versions of an album we can find on all providers.""" album = await self.get_album(item_id, provider_id) provider_ids = { item.id for item in self.mass.get_providers(ProviderType.MUSIC_PROVIDER) } search_query = f"{album.artist.name} {album.name}" return { prov_item for prov_items in await asyncio.gather(*[ self.search_provider(search_query, prov_id, [MediaType.Album], 25) for prov_id in provider_ids ]) for prov_item in prov_items.albums if compare_strings(prov_item.artist.name, album.artist.name) }