From ca883b2974969f0c59d415f21aba85432d80897f Mon Sep 17 00:00:00 2001 From: codey Date: Tue, 8 Apr 2025 20:15:32 -0400 Subject: [PATCH] typeahead/various --- endpoints/constructors.py | 1 - endpoints/lyric_search.py | 75 +++++++++++++++------------------------ endpoints/radio.py | 2 +- utils/radio_util.py | 8 ++--- 4 files changed, 34 insertions(+), 52 deletions(-) diff --git a/endpoints/constructors.py b/endpoints/constructors.py index 920fea4..88fc85a 100644 --- a/endpoints/constructors.py +++ b/endpoints/constructors.py @@ -195,7 +195,6 @@ class ValidTypeAheadRequest(BaseModel): """ - **query**: query string """ - pre_query: Optional[str] = None query: str """ diff --git a/endpoints/lyric_search.py b/endpoints/lyric_search.py index 599c861..9e89027 100644 --- a/endpoints/lyric_search.py +++ b/endpoints/lyric_search.py @@ -5,7 +5,7 @@ import regex import aiosqlite as sqlite3 from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse -from typing import LiteralString, Optional, Union +from typing import LiteralString, Optional, Union, Iterable from regex import Pattern from .constructors import ValidTypeAheadRequest, ValidLyricRequest from lyric_search.constructors import LyricsResult @@ -20,22 +20,23 @@ class CacheUtils: self.lyrics_db_path: LiteralString = os.path.join("/usr/local/share", "sqlite_dbs", "cached_lyrics.db") - async def check_typeahead(self, s: str, - pre_query: Optional[str] = None) -> list[dict]: - """ - Check s against artists stored - for typeahead - """ + async def check_typeahead(self, query: str) -> Optional[list[str]]: + """Lyric Search Typeahead DB Handler""" + if not query: + return None async with sqlite3.connect(self.lyrics_db_path, - timeout=2) as db_conn: - db_conn.row_factory = sqlite3.Row - if not pre_query: - query: str = "SELECT distinct(artist) FROM lyrics WHERE artist LIKE ? LIMIT 15" - query_params: tuple = (f"%{s}%",) - else: - query = "SELECT distinct(song) FROM lyrics WHERE artist LIKE ? AND song LIKE ? LIMIT 15" - query_params = (f"%{pre_query}%", f"%{s}%",) - async with await db_conn.execute(query, query_params) as db_cursor: - return await db_cursor.fetchall() + timeout=1) as _db: + _db.row_factory = sqlite3.Row + db_query: str = """SELECT DISTINCT(LOWER(TRIM(artist) || " - " || TRIM(song))),\ + (TRIM(artist) || " - " || TRIM(song)) as ret FROM lyrics WHERE\ + ret LIKE ? LIMIT 100""" + db_params: tuple[str] = (f"%%%{query}%%%",) + async with _db.execute(db_query, db_params) as _cursor: + result: Iterable[sqlite3.Row] = await _cursor.fetchall() + out_result = [ + str(r['ret']) for r in result + ] + return out_result class LyricSearch(FastAPI): @@ -52,8 +53,7 @@ class LyricSearch(FastAPI): self.endpoints: dict = { - "typeahead/artist": self.artist_typeahead_handler, - "typeahead/song": self.song_typeahead_handler, + "typeahead/lyrics": self.typeahead_handler, "lyric_search": self.lyric_search_handler, # Preserving old endpoint path temporarily "lyric/search": self.lyric_search_handler, } @@ -71,39 +71,22 @@ class LyricSearch(FastAPI): for endpoint, handler in self.endpoints.items(): _schema_include = endpoint in ["lyric/search"] app.add_api_route(f"/{endpoint}", handler, methods=["POST"], include_in_schema=_schema_include) - - async def artist_typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse: + + async def typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse: """ - Artist Type Ahead Handler - - **query**: The query + Lyric search typeahead handler + - **query**: Typeahead query """ - if not isinstance(data.query, str) or len(data.query) < 2: + if not isinstance(data.query, str): return JSONResponse(status_code=500, content={ 'err': True, - 'errorText': 'Invalid request', + 'errorText': 'Invalid request.', }) - query: str = data.query - typeahead_result: list[dict] = await self.cache_utils.check_typeahead(query) - typeahead_list: list[str] = [str(r['artist']) for r in typeahead_result] - return JSONResponse(content=typeahead_list) - - async def song_typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse: - """ - Song Type Ahead Handler - - **query**: The query - - **pre_query**: The pre-query (artist) - """ - if not isinstance(data.pre_query, str)\ - or not isinstance(data.query, str): - return JSONResponse(status_code=500, content={ - 'err': True, - 'errorText': 'Invalid request', - }) - pre_query: str = data.pre_query - query: str = data.query - typeahead_result: list[dict] = await self.cache_utils.check_typeahead(query, pre_query) - typeahead_list: list[str] = [str(r['song']) for r in typeahead_result] - return JSONResponse(content=typeahead_list) + typeahead: Optional[list[str]] = await self.cache_utils.check_typeahead(data.query) + if not typeahead: + return JSONResponse(content=[]) + return JSONResponse(content=typeahead) + async def lyric_search_handler(self, data: ValidLyricRequest) -> JSONResponse: """ diff --git a/endpoints/radio.py b/endpoints/radio.py index 9dd8453..b7582af 100644 --- a/endpoints/radio.py +++ b/endpoints/radio.py @@ -300,7 +300,7 @@ class Radio(FastAPI): async def radio_typeahead(self, data: ValidRadioTypeaheadRequest, request: Request) -> JSONResponse: """ - Radio typehead handler + Radio typeahead handler - **query**: Typeahead query """ if not isinstance(data.query, str): diff --git a/utils/radio_util.py b/utils/radio_util.py index 688ff0a..bbe7d4f 100644 --- a/utils/radio_util.py +++ b/utils/radio_util.py @@ -186,15 +186,15 @@ class RadioUtil: LIMITED TO ONE/SMALL SUBSET OF GENRES """ - db_query = 'SELECT distinct(artist || " - " || song) AS artistdashsong, id, artist, song, album, genre, file_path, duration FROM tracks\ - WHERE genre LIKE "%edm%" OR artist LIKE "%sullivan king%" OR artist LIKE "%kai wachi%" OR artist LIKE "%kayzo%" ORDER BY RANDOM()' #ORDER BY artist DESC, album ASC, song ASC' + # db_query = 'SELECT distinct(artist || " - " || song) AS artistdashsong, id, artist, song, album, genre, file_path, duration FROM tracks\ + # WHERE genre LIKE "%edm%" OR artist LIKE "%sullivan king%" OR artist LIKE "%kai wachi%" OR artist LIKE "%kayzo%" ORDER BY RANDOM()' #ORDER BY artist DESC, album ASC, song ASC' """ LIMITED TO ONE/SOME ARTISTS... """ - # db_query = 'SELECT distinct(artist || " - " || song) AS artistdashsong, id, artist, song, album, genre, file_path, duration FROM tracks\ - # WHERE (artist LIKE "%a scent like wolves%" OR artist LIKE "%bad wolves%" or artist LIKE "%oceans%" OR artist LIKE "%oh,%" OR artist LIKE "%august%" OR artist LIKE "%periphery%") AND (NOT song LIKE "%%stripped%%" AND NOT song LIKE "%(2022)%" AND NOT song LIKE "%(live%%" AND NOT song LIKE "%%acoustic%%" AND NOT song LIKE "%%instrumental%%" AND NOT song LIKE "%%remix%%" AND NOT song LIKE "%%reimagined%%" AND NOT song LIKE "%%alternative%%" AND NOT song LIKE "%%unzipped%%") GROUP BY artistdashsong ORDER BY RANDOM()'# ORDER BY album ASC, id ASC' + db_query = 'SELECT distinct(artist || " - " || song) AS artistdashsong, id, artist, song, album, genre, file_path, duration FROM tracks\ + WHERE (artist LIKE "%chunk! no, %" OR artist LIKE "woe,%" OR artist LIKE "%woe is%") AND (NOT song LIKE "%%stripped%%" AND NOT song LIKE "%(2022)%" AND NOT song LIKE "%(live%%" AND NOT song LIKE "%%acoustic%%" AND NOT song LIKE "%%instrumental%%" AND NOT song LIKE "%%remix%%" AND NOT song LIKE "%%reimagined%%" AND NOT song LIKE "%%alternative%%" AND NOT song LIKE "%%unzipped%%") GROUP BY artistdashsong ORDER BY RANDOM()'# ORDER BY album ASC, id ASC' async with sqlite3.connect(self.active_playlist_path, timeout=2) as db_conn: