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
alsoSkip: Optional[bool] = False
class ValidRadioTypeaheadRequest(BaseModel):
"""
- **query**: Typeahead query
"""
query: str
class ValidRadioQueueGetRequest(BaseModel):
"""
- **key**: API key (optional, needed if specifying a non-default limit)

View File

@ -7,7 +7,8 @@ import random
import asyncio
from . import radio_util
from .constructors import ValidRadioNextRequest, ValidRadioReshuffleRequest, ValidRadioQueueShiftRequest,\
ValidRadioQueueRemovalRequest, ValidRadioSongRequest, RadioException
ValidRadioQueueRemovalRequest, ValidRadioSongRequest,\
ValidRadioTypeaheadRequest, RadioException
from uuid import uuid4 as uuid
from typing import Optional
from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException
@ -30,6 +31,7 @@ class Radio(FastAPI):
self.endpoints: dict = {
"radio/np": self.radio_now_playing,
"radio/request": self.radio_request,
"radio/typeahead": self.radio_typeahead,
"radio/get_queue": self.radio_get_queue,
"radio/skip": self.radio_skip,
"radio/queue_shift": self.radio_queue_shift,
@ -290,3 +292,19 @@ class Radio(FastAPI):
return JSONResponse(content={
'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
from aiohttp import ClientSession, ClientTimeout
import aiosqlite as sqlite3
from typing import Union, Optional, LiteralString
from typing import Union, Optional, LiteralString, Iterable
from uuid import uuid4 as uuid
from .constructors import RadioException
@ -65,6 +65,22 @@ class RadioUtil:
"""
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,
artist: Optional[str] = None,
song: Optional[str] = None) -> bool:
@ -138,7 +154,8 @@ class RadioUtil:
"metal", "punk", "electronic", "nu metal", "EDM",\
"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",\
"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...