"Trying to match album %s on provider %s", db_album.name, provider.name
)
match_found = False
- searchstr = f"{db_album.artist.name} {db_album.name}"
- if db_album.version:
- searchstr += " " + db_album.version
- search_result = await self.search(searchstr, provider.id)
+ search_result = await self.search(db_album.name, provider.id)
for search_result_item in search_result:
if not search_result_item.available:
continue
# 100% match, we can simply update the db with additional provider ids
await self.update_db_item(db_album.item_id, prov_album)
match_found = True
- # while we're here, also match the artist
- if db_album.artist.provider == ProviderType.DATABASE:
- await self.mass.music.artists.update_db_item(
- db_album.artist.item_id, prov_album.artist
- )
return match_found
# try to find match on all providers
ref_track = await self.mass.music.tracks.get(
ref_track.item_id, ref_track.provider
)
- searchstr = f"{db_artist.name} {ref_track.name}"
search_results = await self.mass.music.tracks.search(
- searchstr, provider.type
+ ref_track.name, provider.type
)
for search_result_item in search_results:
if not compare_track(search_result_item, ref_track):
for ref_album in artist_albums:
if ref_album.album_type == AlbumType.COMPILATION:
continue
- searchstr = f"{db_artist.name} {ref_album.name}"
search_result = await self.mass.music.albums.search(
- searchstr, provider.type
+ ref_album.name, provider.type
)
for search_result_item in search_result:
# artist must match 100%
result = []
# searching the filesystem is slow and unreliable,
# instead we make some (slow) freaking queries to the db ;-)
- if " - " in search_query:
- artist, title = search_query.split(" - ", 1)
- else:
- artist = None
- title = search_query
+ params = {"name": f"%{search_query}%", "prov_type": f"%{self.type.value}%"}
if media_types is None or MediaType.TRACK in media_types:
- query = f"SELECT * FROM tracks WHERE name LIKE '%{title}%'"
- query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
- if artist:
- query += f" AND artists LIKE '%{artist}%'"
- tracks = await self.mass.music.tracks.get_db_items(query)
+ query = "SELECT * FROM tracks WHERE name LIKE :name AND provider_ids LIKE :prov_type"
+ tracks = await self.mass.music.tracks.get_db_items(query, params)
result += tracks
if media_types is None or MediaType.ALBUM in media_types:
- query = f"SELECT * FROM albums WHERE name LIKE '%{title}%'"
- query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
- if artist:
- query += f" AND artist LIKE '%{artist}%'"
- albums = await self.mass.music.albums.get_db_items(query)
+ query = "SELECT * FROM albums WHERE name LIKE :name AND provider_ids LIKE :prov_type"
+ albums = await self.mass.music.albums.get_db_items(query, params)
result += albums
if media_types is None or MediaType.ARTIST in media_types:
- query = f"SELECT * FROM artists WHERE name LIKE '%{title}%'"
- query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
- artists = await self.mass.music.artists.get_db_items(query)
+ query = "SELECT * FROM artists WHERE name LIKE :name AND provider_ids LIKE :prov_type"
+ artists = await self.mass.music.artists.get_db_items(query, params)
result += artists
if media_types is None or MediaType.PLAYLIST in media_types:
- query = f"SELECT * FROM playlists WHERE name LIKE '%{title}%'"
- query += f" AND provider_ids LIKE '%\"{self.type.value}\"%'"
- playlists = await self.mass.music.playlists.get_db_items(query)
+ query = "SELECT * FROM playlists WHERE name LIKE :name AND provider_ids LIKE :prov_type"
+ playlists = await self.mass.music.playlists.get_db_items(query, params)
result += playlists
return result
import asyncio
from typing import List, Optional, Union
-from music_assistant.helpers.compare import (
- compare_artists,
- compare_strings,
- compare_track,
-)
+from music_assistant.helpers.compare import compare_artists, compare_track
from music_assistant.helpers.database import TABLE_TRACKS
from music_assistant.helpers.json import json_serializer
from music_assistant.models.enums import EventType, MediaType, ProviderType
"""Return all versions of a track we can find on all providers."""
track = await self.get(item_id, provider, provider_id)
prov_types = {item.type for item in self.mass.music.providers}
- first_artist = next(iter(track.artists))
- search_query = f"{first_artist.name} {track.name}"
return [
prov_item
for prov_items in await asyncio.gather(
- *[self.search(search_query, prov_type) for prov_type in prov_types]
+ *[self.search(track.name, prov_type) for prov_type in prov_types]
)
for prov_item in prov_items
if compare_artists(prov_item.artists, track.artists)
"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 = f"{db_track_artist.name} {db_track.name}"
- if db_track.version:
- searchstr += " " + db_track.version
- search_result = await self.search(searchstr, provider.type)
- for search_result_item in search_result:
- 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.update_db_item(db_track.item_id, search_result_item)
- # while we're here, also match the artist
- if db_track_artist.provider == ProviderType.DATABASE:
- for artist in search_result_item.artists:
- if not compare_strings(
- db_track_artist.name, artist.name
- ):
- continue
- prov_artist = (
- await self.mass.music.artists.get_provider_item(
- artist.item_id, artist.provider
- )
- )
- await self.mass.music.artists.update_db_item(
- db_track_artist.item_id, prov_artist
- )
+ search_result = await self.search(db_track.name, provider.type)
+ for search_result_item in search_result:
+ 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.update_db_item(db_track.item_id, search_result_item)
if not match_found:
self.logger.debug(
return await _db.fetch_all(sql_query, match)
async def get_rows_from_query(
- self, query: str, db: Optional[Db] = None
+ self, query: str, params: Optional[dict] = None, db: Optional[Db] = None
) -> List[Mapping]:
"""Get all rows for given custom query."""
async with self.get_db(db) as _db:
- return await _db.fetch_all(query)
+ return await _db.fetch_all(query, params)
async def search(
self, table: str, search: str, column: str = "name", db: Optional[Db] = None
) -> List[Mapping]:
"""Search table by column."""
async with self.get_db(db) as _db:
- sql_query = f'SELECT * FROM {table} WHERE {column} LIKE "{search}"'
- return await _db.fetch_all(sql_query)
+ sql_query = f"SELECT * FROM {table} WHERE {column} LIKE :search"
+ params = {"search": f"%{search}%"}
+ return await _db.fetch_all(sql_query, params)
async def get_row(
self, table: str, match: Dict[str, Any] = None, db: Optional[Db] = None
return None, None
async def get_db_items(
- self, custom_query: Optional[str] = None, db: Optional[Db] = None
+ self,
+ query: Optional[str] = None,
+ query_params: Optional[dict] = None,
+ db: Optional[Db] = None,
) -> List[ItemCls]:
"""Fetch all records from database."""
- if custom_query is not None:
- func = self.mass.database.get_rows_from_query(custom_query, db=db)
+ if query is not None:
+ func = self.mass.database.get_rows_from_query(query, query_params, db=db)
else:
func = self.mass.database.get_rows(self.db_table, db=db)
return [self.item_cls.from_db_row(db_row) for db_row in await func]