music-app/backend/app/services/shareplay.py
2026-07-03 01:06:35 +00:00

129 lines
4.2 KiB
Python

import uuid
from typing import Dict, List, Optional
from sqlalchemy.orm import Session
from ..models.shareplay import SharePlayRoom, SharePlayCue as SharePlayCueModel
from ..models.song import Song
class SharePlayManager:
def __init__(self):
self.rooms: Dict[str, Dict] = {}
self.connections: Dict[str, set] = {}
def create_room(self, db: Session, creator: str = "user") -> Dict:
room_id = str(uuid.uuid4())[:8]
room = SharePlayRoom(
id=room_id,
creator_user=creator,
active_connections=1,
)
db.add(room)
db.commit()
db.refresh(room)
self.rooms[room_id] = {
"song_id": None,
"position": 0,
"is_playing": False,
"shuffle": False,
"volume": 0.8,
}
self.connections[room_id] = set()
return {
"id": room_id,
"creator_user": creator,
"active_connections": 1,
}
def join_room(self, db: Session, room_id: str) -> Optional[Dict]:
room = db.query(SharePlayRoom).filter(SharePlayRoom.id == room_id).first()
if not room:
return None
room.active_connections += 1
db.commit()
if room_id not in self.rooms:
self.rooms[room_id] = {
"song_id": room.current_song_id,
"position": room.position_sec,
"is_playing": room.is_playing,
"shuffle": room.shuffle_mode,
"volume": 0.8,
}
return {
"id": room_id,
"active_connections": room.active_connections,
"state": self.rooms[room_id],
}
def leave_room(self, db: Session, room_id: str) -> bool:
room = db.query(SharePlayRoom).filter(SharePlayRoom.id == room_id).first()
if not room:
return False
room.active_connections = max(0, room.active_connections - 1)
db.commit()
if room.active_connections <= 0:
self.rooms.pop(room_id, None)
self.connections.pop(room_id, None)
return True
def get_state(self, room_id: str) -> Optional[Dict]:
return self.rooms.get(room_id)
def update_state(self, room_id: str, **kwargs) -> Optional[Dict]:
if room_id not in self.rooms:
return None
self.rooms[room_id].update(kwargs)
return self.rooms[room_id]
def get_cue(self, db: Session, room_id: str) -> List[Dict]:
cues = db.query(SharePlayCueModel).filter(SharePlayCueModel.room_id == room_id).order_by(SharePlayCueModel.position).all()
result = []
for cue in cues:
song = db.query(Song).filter(Song.id == cue.song_id).first()
if song:
result.append({
"song": {
"id": song.id,
"title": song.title,
"artist": song.artist,
"album": song.album,
"duration_sec": song.duration_sec,
},
"position": cue.position,
"added_by": cue.added_by,
})
return result
def add_to_cue(self, db: Session, room_id: str, song_id: str, added_by: str = "user") -> bool:
song = db.query(Song).filter(Song.id == song_id).first()
if not song:
return False
max_pos = db.query(SharePlayCueModel).filter(SharePlayCueModel.room_id == room_id).count()
cue = SharePlayCueModel(
id=str(uuid.uuid4()),
room_id=room_id,
song_id=song_id,
position=max_pos,
added_by=added_by,
)
db.add(cue)
db.commit()
return True
def next_cue(self, db: Session, room_id: str) -> Optional[str]:
cue = db.query(SharePlayCueModel).filter(SharePlayCueModel.room_id == room_id).order_by(SharePlayCueModel.position).first()
if cue:
db.delete(cue)
db.commit()
return cue.song_id
return None