radio changes/progress
This commit is contained in:
@ -6,12 +6,14 @@ import traceback
|
||||
import os
|
||||
import aiosqlite as sqlite3
|
||||
import time
|
||||
import random
|
||||
import asyncio
|
||||
import regex
|
||||
import music_tag
|
||||
from . import radio_util
|
||||
from uuid import uuid4 as uuid
|
||||
from pydantic import BaseModel
|
||||
from fastapi import FastAPI, Request, Response, HTTPException
|
||||
from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException
|
||||
from fastapi.responses import RedirectResponse
|
||||
from aiohttp import ClientSession, ClientTimeout
|
||||
|
||||
@ -39,16 +41,45 @@ class ValidRadioSongRequest(BaseModel):
|
||||
class ValidRadioNextRequest(BaseModel):
|
||||
"""
|
||||
- **key**: API Key
|
||||
- **skipTo**: UUID to skip to [optional]
|
||||
"""
|
||||
key: str
|
||||
skipTo: str|None = None
|
||||
|
||||
class ValidRadioReshuffleRequest(ValidRadioNextRequest):
|
||||
"""
|
||||
- **key**: API Key
|
||||
"""
|
||||
|
||||
class ValidRadioQueueShiftRequest(BaseModel):
|
||||
"""
|
||||
- **key**: API Key
|
||||
- **uuid**: UUID to shift
|
||||
- **next**: Play next if true, immediately if false, default False
|
||||
"""
|
||||
key: str
|
||||
uuid: str
|
||||
next: bool = False
|
||||
|
||||
class ValidRadioQueueRemovalRequest(BaseModel):
|
||||
"""
|
||||
- **key**: API Key
|
||||
- **uuid**: UUID to remove
|
||||
"""
|
||||
key: str
|
||||
uuid: str
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Radio(FastAPI):
|
||||
"""Radio Endpoints"""
|
||||
def __init__(self, app: FastAPI, my_util, constants, glob_state): # pylint: disable=super-init-not-called
|
||||
def __init__(self, app: FastAPI, my_util, constants, glob_state) -> None: # pylint: disable=super-init-not-called
|
||||
self.app = app
|
||||
self.util = my_util
|
||||
self.constants = constants
|
||||
self.radio_util = radio_util.RadioUtil(self.constants)
|
||||
self.glob_state = glob_state
|
||||
self.ls_uri = "http://10.10.10.101:29000"
|
||||
self.sqlite_exts: list[str] = ['/home/singer/api/solibs/spellfix1.cpython-311-x86_64-linux-gnu.so']
|
||||
@ -70,6 +101,9 @@ class Radio(FastAPI):
|
||||
"radio/request": self.radio_request,
|
||||
"radio/get_queue": self.radio_get_queue,
|
||||
"radio/skip": self.radio_skip,
|
||||
"radio/queue_shift": self.radio_queue_shift,
|
||||
"radio/reshuffle": self.radio_reshuffle,
|
||||
"radio/queue_remove": self.radio_queue_remove,
|
||||
# "widget/sqlite": self.homepage_sqlite_widget,
|
||||
# "widget/lyrics": self.homepage_lyrics_widget,
|
||||
# "widget/radio": self.homepage_radio_widget,
|
||||
@ -88,7 +122,7 @@ class Radio(FastAPI):
|
||||
asyncio.get_event_loop().run_until_complete(self.load_playlist())
|
||||
|
||||
|
||||
async def get_queue_item_by_uuid(self, uuid: str) -> tuple[int, dict] | None:
|
||||
def get_queue_item_by_uuid(self, uuid: str) -> tuple[int, dict] | None:
|
||||
"""
|
||||
Get queue item by UUID
|
||||
Args:
|
||||
@ -99,7 +133,7 @@ class Radio(FastAPI):
|
||||
for x, item in enumerate(self.active_playlist):
|
||||
if item.get('uuid') == uuid:
|
||||
return (x, item)
|
||||
return False
|
||||
return None
|
||||
|
||||
async def _ls_skip(self) -> bool:
|
||||
async with ClientSession() as session:
|
||||
@ -111,24 +145,40 @@ class Radio(FastAPI):
|
||||
|
||||
async def radio_skip(self, data: ValidRadioNextRequest, request: Request) -> bool:
|
||||
"""
|
||||
Skip to the next track in the queue
|
||||
Skip to the next track in the queue, or to uuid specified in skipTo if provided
|
||||
"""
|
||||
try:
|
||||
if not self.util.check_key(path=request.url.path, req_type=4, key=data.key):
|
||||
raise HTTPException(status_code=403, detail="Unauthorized")
|
||||
if data.skipTo:
|
||||
(x, _) = self.get_queue_item_by_uuid(data.skipTo)
|
||||
self.active_playlist = self.active_playlist[x:]
|
||||
if not self.active_playlist:
|
||||
await self.load_playlist()
|
||||
return await self._ls_skip()
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
async def radio_reshuffle(self, data: ValidRadioReshuffleRequest, request: Request) -> dict:
|
||||
"""
|
||||
Reshuffle the play queue
|
||||
"""
|
||||
if not self.util.check_key(path=request.url.path, req_type=4, key=data.key):
|
||||
raise HTTPException(status_code=403, detail="Unauthorized")
|
||||
|
||||
random.shuffle(self.active_playlist)
|
||||
return {
|
||||
'ok': True
|
||||
}
|
||||
|
||||
|
||||
async def radio_get_queue(self, request: Request, limit: int = 100) -> dict:
|
||||
async def radio_get_queue(self, request: Request, limit: int = 20_000) -> dict:
|
||||
"""
|
||||
Get current play queue, up to limit n [default: 100]
|
||||
Get current play queue, up to limit n [default: 20k]
|
||||
Args:
|
||||
limit (int): Number of results to return (default 100)
|
||||
limit (int): Number of results to return (default 20k)
|
||||
Returns:
|
||||
dict
|
||||
"""
|
||||
@ -146,6 +196,37 @@ class Radio(FastAPI):
|
||||
'items': queue_out
|
||||
}
|
||||
|
||||
async def radio_queue_shift(self, data: ValidRadioQueueShiftRequest, request: Request) -> dict:
|
||||
"""Shift position of a UUID within the queue [currently limited to playing next or immediately]"""
|
||||
if not self.util.check_key(path=request.url.path, req_type=4, key=data.key):
|
||||
raise HTTPException(status_code=403, detail="Unauthorized")
|
||||
|
||||
(x, item) = self.get_queue_item_by_uuid(data.uuid)
|
||||
self.active_playlist.pop(x)
|
||||
self.active_playlist.insert(0, item)
|
||||
if not data.next:
|
||||
await self._ls_skip()
|
||||
return {
|
||||
'ok': True,
|
||||
}
|
||||
|
||||
async def radio_queue_remove(self, data: ValidRadioQueueRemovalRequest, request: Request) -> dict:
|
||||
"""Remove an item from the current play queue"""
|
||||
if not self.util.check_key(path=request.url.path, req_type=4, key=data.key):
|
||||
raise HTTPException(status_code=403, detail="Unauthorized")
|
||||
|
||||
(x, found_item) = self.get_queue_item_by_uuid(data.uuid)
|
||||
if not found_item:
|
||||
return {
|
||||
'ok': False,
|
||||
'err': 'UUID not found in play queue',
|
||||
}
|
||||
self.active_playlist.pop(x)
|
||||
return {
|
||||
'ok': True,
|
||||
}
|
||||
|
||||
|
||||
async def search_playlist(self, artistsong: str|None = None, artist: str|None = None, song: str|None = None) -> bool:
|
||||
if artistsong and (artist or song):
|
||||
raise RadioException("Cannot search using combination provided")
|
||||
@ -250,7 +331,8 @@ class Radio(FastAPI):
|
||||
return ret_obj
|
||||
|
||||
|
||||
async def radio_get_next(self, data: ValidRadioNextRequest, request: Request) -> dict:
|
||||
async def radio_get_next(self, data: ValidRadioNextRequest, request: Request,
|
||||
background_tasks: BackgroundTasks) -> dict:
|
||||
"""
|
||||
Get next track
|
||||
Args:
|
||||
@ -285,6 +367,10 @@ class Radio(FastAPI):
|
||||
self.now_playing = next
|
||||
next['start'] = time_started
|
||||
next['end'] = time_ends
|
||||
try:
|
||||
background_tasks.add_task(self.radio_util.webhook_song_change, next)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return next
|
||||
else:
|
||||
return await self.radio_pop_track(request, recursion_type="not list: self.active_playlist")
|
||||
|
Reference in New Issue
Block a user