104 lines
3.5 KiB
Python
104 lines
3.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from starlette.websockets import WebSocket, WebSocketDisconnect
|
|
from sqlalchemy.orm import Session
|
|
from typing import Optional
|
|
from pydantic import BaseModel
|
|
from ..db.database import get_db
|
|
from ..models.shareplay import SharePlayRoom, SharePlayCue as SharePlayCueModel
|
|
from ..schemas.shareplay import SharePlayRoomResponse, SharePlayCommand, SharePlayCueResponse
|
|
from ..services.shareplay import SharePlayManager
|
|
|
|
|
|
class RoomIdRequest(BaseModel):
|
|
room_id: str
|
|
|
|
|
|
class ControlRequest(BaseModel):
|
|
room_id: str
|
|
type: str
|
|
payload: Optional[dict] = None
|
|
|
|
router = APIRouter(prefix="/api/shareplay", tags=["shareplay"])
|
|
manager = SharePlayManager()
|
|
|
|
|
|
@router.post("/create")
|
|
def create_room(db: Session = Depends(get_db)):
|
|
return manager.create_room(db, creator="user")
|
|
|
|
|
|
@router.post("/join")
|
|
def join_room(data: RoomIdRequest, db: Session = Depends(get_db)):
|
|
result = manager.join_room(db, data.room_id)
|
|
if not result:
|
|
raise HTTPException(status_code=404, detail="Room not found")
|
|
return result
|
|
|
|
|
|
@router.post("/leave")
|
|
def leave_room(data: RoomIdRequest, db: Session = Depends(get_db)):
|
|
success = manager.leave_room(db, data.room_id)
|
|
if not success:
|
|
raise HTTPException(status_code=404, detail="Room not found")
|
|
return {"message": "Left room"}
|
|
|
|
|
|
@router.get("/cue")
|
|
def get_cue(room_id: str, db: Session = Depends(get_db)):
|
|
items = manager.get_cue(db, room_id)
|
|
return SharePlayCueResponse(items=items, next_song=None)
|
|
|
|
|
|
@router.post("/cue")
|
|
def add_to_cue(room_id: str, song_id: str, db: Session = Depends(get_db)):
|
|
success = manager.add_to_cue(db, room_id, song_id)
|
|
if not success:
|
|
raise HTTPException(status_code=400, detail="Failed to add to cue")
|
|
return {"message": "Added to cue"}
|
|
|
|
|
|
@router.post("/control")
|
|
def send_control(data: ControlRequest, db: Session = Depends(get_db)):
|
|
state = manager.get_state(data.room_id)
|
|
if not state:
|
|
raise HTTPException(status_code=404, detail="Room not found")
|
|
|
|
if data.type == "play":
|
|
manager.update_state(data.room_id, is_playing=True)
|
|
elif data.type == "pause":
|
|
manager.update_state(data.room_id, is_playing=False)
|
|
elif data.type == "seek" and data.payload:
|
|
manager.update_state(data.room_id, position=data.payload.get("position", 0))
|
|
elif data.type == "shuffle":
|
|
current = manager.get_state(data.room_id)
|
|
manager.update_state(data.room_id, shuffle=not current.get("shuffle", False))
|
|
|
|
return {"message": f"Command '{data.type}' sent"}
|
|
|
|
|
|
# WebSocket endpoint
|
|
@router.websocket("/ws/{room_id}")
|
|
async def websocket_endpoint(websocket: WebSocket, room_id: str):
|
|
await websocket.accept()
|
|
|
|
state = manager.get_state(room_id)
|
|
if state:
|
|
await websocket.send_json({"type": "state", "data": state})
|
|
|
|
try:
|
|
while True:
|
|
data = await websocket.receive_text()
|
|
import json
|
|
message = json.loads(data)
|
|
|
|
if message.get("type") == "control":
|
|
cmd = message.get("payload", {})
|
|
state = manager.get_state(room_id)
|
|
if state and cmd.get("type") == "play":
|
|
manager.update_state(room_id, is_playing=True)
|
|
elif state and cmd.get("type") == "pause":
|
|
manager.update_state(room_id, is_playing=False)
|
|
|
|
await websocket.send_json({"type": "ack", "data": message})
|
|
except WebSocketDisconnect:
|
|
pass |