radio typeahead

This commit is contained in:
codey 2025-02-16 13:54:28 -05:00
parent b24176b12f
commit 3567e750fa
3 changed files with 46 additions and 4 deletions

View File

@ -218,6 +218,13 @@ class ValidRadioSongRequest(BaseModel):
artistsong: Optional[str] = None artistsong: Optional[str] = None
alsoSkip: Optional[bool] = False alsoSkip: Optional[bool] = False
class ValidRadioTypeaheadRequest(BaseModel):
"""
- **query**: Typeahead query
"""
query: str
class ValidRadioQueueGetRequest(BaseModel): class ValidRadioQueueGetRequest(BaseModel):
""" """
- **key**: API key (optional, needed if specifying a non-default limit) - **key**: API key (optional, needed if specifying a non-default limit)

View File

@ -7,7 +7,8 @@ import random
import asyncio import asyncio
from . import radio_util from . import radio_util
from .constructors import ValidRadioNextRequest, ValidRadioReshuffleRequest, ValidRadioQueueShiftRequest,\ from .constructors import ValidRadioNextRequest, ValidRadioReshuffleRequest, ValidRadioQueueShiftRequest,\
ValidRadioQueueRemovalRequest, ValidRadioSongRequest, RadioException ValidRadioQueueRemovalRequest, ValidRadioSongRequest,\
ValidRadioTypeaheadRequest, RadioException
from uuid import uuid4 as uuid from uuid import uuid4 as uuid
from typing import Optional from typing import Optional
from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException
@ -30,6 +31,7 @@ class Radio(FastAPI):
self.endpoints: dict = { self.endpoints: dict = {
"radio/np": self.radio_now_playing, "radio/np": self.radio_now_playing,
"radio/request": self.radio_request, "radio/request": self.radio_request,
"radio/typeahead": self.radio_typeahead,
"radio/get_queue": self.radio_get_queue, "radio/get_queue": self.radio_get_queue,
"radio/skip": self.radio_skip, "radio/skip": self.radio_skip,
"radio/queue_shift": self.radio_queue_shift, "radio/queue_shift": self.radio_queue_shift,
@ -290,3 +292,19 @@ class Radio(FastAPI):
return JSONResponse(content={ return JSONResponse(content={
'result': search 'result': search
}) })
async def radio_typeahead(self, data: ValidRadioTypeaheadRequest,
request: Request) -> JSONResponse:
"""
Radio typehead handler
- **query**: Typeahead query
"""
if not isinstance(data.query, str):
return JSONResponse(status_code=500, content={
'err': True,
'errorText': 'Invalid request.',
})
typeahead = await self.radio_util.trackdb_typeahead(data.query)
if not typeahead:
return JSONResponse(content=[])
return JSONResponse(content=typeahead)

View File

@ -14,7 +14,7 @@ import os
import gpt import gpt
from aiohttp import ClientSession, ClientTimeout from aiohttp import ClientSession, ClientTimeout
import aiosqlite as sqlite3 import aiosqlite as sqlite3
from typing import Union, Optional, LiteralString from typing import Union, Optional, LiteralString, Iterable
from uuid import uuid4 as uuid from uuid import uuid4 as uuid
from .constructors import RadioException from .constructors import RadioException
@ -65,6 +65,22 @@ class RadioUtil:
""" """
return str(datetime.timedelta(seconds=s)).split(".", maxsplit=1)[0] return str(datetime.timedelta(seconds=s)).split(".", maxsplit=1)[0]
async def trackdb_typeahead(self, query: str) -> Optional[list[str]]:
if not query:
return None
async with sqlite3.connect(self.active_playlist_path,
timeout=1) as _db:
_db.row_factory = sqlite3.Row
db_query: str = 'SELECT (artist || " - " || song) as artistsong FROM tracks WHERE\
artistsong LIKE ? LIMIT 15'
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['artistsong']) for r in result
]
return out_result
async def search_playlist(self, artistsong: Optional[str] = None, async def search_playlist(self, artistsong: Optional[str] = None,
artist: Optional[str] = None, artist: Optional[str] = None,
song: Optional[str] = None) -> bool: song: Optional[str] = None) -> bool:
@ -138,7 +154,8 @@ class RadioUtil:
"metal", "punk", "electronic", "nu metal", "EDM",\ "metal", "punk", "electronic", "nu metal", "EDM",\
"post-hardcore", "pop rock", "experimental", "post-punk", "death metal", "electronicore", "hard rock", "psychedelic rock",\ "post-hardcore", "pop rock", "experimental", "post-punk", "death metal", "electronicore", "hard rock", "psychedelic rock",\
"grunge", "house", "dubstep", "hardcore", "hair metal", "horror punk", "folk punk", "breakcore",\ "grunge", "house", "dubstep", "hardcore", "hair metal", "horror punk", "folk punk", "breakcore",\
"post-rock", "deathcore", "hardcore punk", "synthwave", "trap") GROUP BY artistdashsong ORDER BY RANDOM()' "post-rock", "deathcore", "hardcore punk", "synthwave",\
"trap", "indie pop") GROUP BY artistdashsong ORDER BY RANDOM()'
""" """
LIMITED TO ONE ARTIST... LIMITED TO ONE ARTIST...