cleanup
This commit is contained in:
@ -7,7 +7,8 @@ import urllib.parse
|
||||
import regex
|
||||
import aiosqlite as sqlite3
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from typing import LiteralString, Optional, Callable
|
||||
from fastapi.responses import JSONResponse
|
||||
from typing import LiteralString, Optional, Union
|
||||
from regex import Pattern
|
||||
from .constructors import ValidTypeAheadRequest, ValidLyricRequest
|
||||
from lyric_search.constructors import LyricsResult
|
||||
@ -15,13 +16,18 @@ from lyric_search.sources import aggregate
|
||||
from lyric_search import notifier
|
||||
|
||||
class CacheUtils:
|
||||
"""Lyrics Cache DB Utils"""
|
||||
"""
|
||||
Lyrics Cache DB Utils
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
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: str | None = None) -> list[dict]:
|
||||
"""Check s against artists stored - for typeahead"""
|
||||
async def check_typeahead(self, s: str,
|
||||
pre_query: Optional[str] = None) -> list[dict]:
|
||||
"""
|
||||
Check s against artists stored - for typeahead
|
||||
"""
|
||||
async with sqlite3.connect(self.lyrics_db_path,
|
||||
timeout=2) as db_conn:
|
||||
db_conn.row_factory = sqlite3.Row
|
||||
@ -36,9 +42,12 @@ class CacheUtils:
|
||||
|
||||
|
||||
class LyricSearch(FastAPI):
|
||||
"""Lyric Search Endpoint"""
|
||||
def __init__(self, app: FastAPI, util, constants): # pylint: disable=super-init-not-called
|
||||
self.app = app
|
||||
"""
|
||||
Lyric Search Endpoint
|
||||
"""
|
||||
def __init__(self, app: FastAPI,
|
||||
util, constants) -> None: # pylint: disable=super-init-not-called
|
||||
self.app: FastAPI = app
|
||||
self.util = util
|
||||
self.constants = constants
|
||||
self.cache_utils = CacheUtils()
|
||||
@ -70,36 +79,39 @@ class LyricSearch(FastAPI):
|
||||
_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) -> list[str]|dict:
|
||||
"""Artist Type Ahead Handler"""
|
||||
async def artist_typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse:
|
||||
"""
|
||||
Artist Type Ahead Handler
|
||||
"""
|
||||
if not isinstance(data.query, str) or len(data.query) < 2:
|
||||
return {
|
||||
return JSONResponse(status_code=500, content={
|
||||
'err': True,
|
||||
'errorText': 'Invalid request',
|
||||
}
|
||||
})
|
||||
query: str = data.query
|
||||
typeahead_result: list[dict] = await self.cache_utils.check_typeahead(query)
|
||||
typeahead_list: list[str] = [str(r.get('artist')) for r in typeahead_result]
|
||||
return typeahead_list
|
||||
return JSONResponse(content=typeahead_list)
|
||||
|
||||
async def song_typeahead_handler(self, data: ValidTypeAheadRequest) -> list[str]|dict:
|
||||
"""Song Type Ahead Handler"""
|
||||
async def song_typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse:
|
||||
"""
|
||||
Song Type Ahead Handler
|
||||
"""
|
||||
if not isinstance(data.pre_query, str)\
|
||||
or not isinstance(data.query, str|None):
|
||||
return {
|
||||
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.get('song')) for r in typeahead_result]
|
||||
return typeahead_list
|
||||
return JSONResponse(content=typeahead_list)
|
||||
|
||||
async def lyric_search_handler(self, data: ValidLyricRequest) -> dict:
|
||||
async def lyric_search_handler(self, data: ValidLyricRequest) -> JSONResponse:
|
||||
"""
|
||||
Search for lyrics
|
||||
|
||||
- **a**: artist
|
||||
- **s**: song
|
||||
- **t**: track (artist and song combined) [used only if a & s are not used]
|
||||
@ -109,26 +121,23 @@ class LyricSearch(FastAPI):
|
||||
- **src**: the script/utility which initiated the request
|
||||
- **excluded_sources**: sources to exclude [optional, default: none]
|
||||
"""
|
||||
|
||||
if (not data.a or not data.s) and not data.t or not data.src:
|
||||
raise HTTPException(detail="Invalid request", status_code=500)
|
||||
|
||||
if data.src.upper() not in self.acceptable_request_sources:
|
||||
await self.notifier.send(f"ERROR @ {__file__.rsplit("/", maxsplit=1)[-1]}",
|
||||
f"Unknown request source: {data.src}")
|
||||
return {
|
||||
return JSONResponse(status_code=500, content={
|
||||
'err': True,
|
||||
'errorText': f'Unknown request source: {data.src}',
|
||||
}
|
||||
})
|
||||
|
||||
if not data.t:
|
||||
search_artist: Optional[str] = data.a
|
||||
search_song: Optional[str] = data.s
|
||||
else:
|
||||
t_split = data.t.split(" - ", maxsplit=1)
|
||||
search_artist = t_split[0]
|
||||
search_song = t_split[1]
|
||||
|
||||
t_split: tuple = tuple(data.t.split(" - ", maxsplit=1))
|
||||
(search_artist, search_song) = t_split
|
||||
|
||||
if search_artist and search_song:
|
||||
search_artist = str(self.constants.DOUBLE_SPACE_REGEX.sub(" ", search_artist.strip()))
|
||||
@ -137,21 +146,21 @@ class LyricSearch(FastAPI):
|
||||
search_song = urllib.parse.unquote(search_song)
|
||||
|
||||
if not isinstance(search_artist, str) or not isinstance(search_song, str):
|
||||
return {
|
||||
return JSONResponse(status_code=500, content={
|
||||
'err': True,
|
||||
'errorText': 'Invalid request',
|
||||
}
|
||||
})
|
||||
|
||||
excluded_sources: Optional[list] = data.excluded_sources
|
||||
aggregate_search = aggregate.Aggregate(exclude_methods=excluded_sources)
|
||||
plain_lyrics: bool = not data.lrc
|
||||
result: Optional[LyricsResult|dict] = await aggregate_search.search(search_artist, search_song, plain_lyrics)
|
||||
result: Optional[Union[LyricsResult, dict]] = await aggregate_search.search(search_artist, search_song, plain_lyrics)
|
||||
|
||||
if not result:
|
||||
return {
|
||||
return JSONResponse(content={
|
||||
'err': True,
|
||||
'errorText': 'Sources exhausted, lyrics not located.',
|
||||
}
|
||||
})
|
||||
|
||||
result = vars(result)
|
||||
|
||||
@ -167,9 +176,11 @@ class LyricSearch(FastAPI):
|
||||
break
|
||||
|
||||
if not seeked_found_line:
|
||||
return {
|
||||
return JSONResponse(status_code=500, content={
|
||||
'err': True,
|
||||
'errorText': 'Seek (a.k.a. subsearch) failed.',
|
||||
'failed_seek': True,
|
||||
}
|
||||
})
|
||||
result['lyrics'] = " / ".join(lyric_lines[seeked_found_line:])
|
||||
|
||||
result['confidence'] = int(result.get('confidence', 0))
|
||||
@ -188,4 +199,4 @@ class LyricSearch(FastAPI):
|
||||
if not data.extra:
|
||||
result.pop('src')
|
||||
|
||||
return result
|
||||
return JSONResponse(content=result)
|
Reference in New Issue
Block a user