use std::{collections::HashMap, sync::Arc}; use axum::extract::ws::{Message, WebSocket}; use dashmap::DashMap; use futures::{stream::SplitSink, SinkExt}; use once_cell::sync::Lazy; use tokio::sync::{Mutex, MutexGuard}; use uuid::Uuid; use crate::sources::MediaSource; #[derive(Clone)] pub struct RoomRef { room: Arc>, } impl RoomRef { fn new(room: Room) -> Self { RoomRef { room: Arc::new(Mutex::new(room)), } } pub async fn get(&self) -> MutexGuard { self.room.lock().await } pub async fn add_member(&self, member: Member) { let mut room = self.room.lock().await; room.members.insert(member.id, member); } pub async fn broadcast(&self, message: Message) { let mut room = self.room.lock().await; for member in room.members.values_mut() { member.send(message.clone()).await } } pub async fn list_chat_members(&self) -> Vec { let room = self.room.lock().await; room.members .values() .flat_map(|m| &m.chat_identity) .cloned() .collect() } } static ROOMS: Lazy> = Lazy::new(DashMap::new); pub async fn create_room(playlist: Vec) -> RoomRef { let id = Uuid::new_v4(); let room = Room { id, playlist, currently_playing: 0, members: HashMap::new(), }; let room_ref = RoomRef::new(room); ROOMS.insert(id, room_ref.clone()); room_ref } pub async fn find_room(id: Uuid) -> Option { ROOMS.get(&id).as_deref().cloned() } pub struct Room { pub id: Uuid, pub playlist: Vec, pub currently_playing: usize, pub members: HashMap, } #[derive(Clone)] pub struct ChatIdentity { pub nickname: String, pub color: String, } pub struct Member { pub id: Uuid, pub chat_identity: Option, pub connections: Vec>, } impl Member { pub async fn send(&mut self, message: Message) { for conn in self.connections.iter_mut() { let _ = conn.send(message.clone()).await; } } }