From ae87bc0b67e5b55f8b18d9500fb180060afb81ba Mon Sep 17 00:00:00 2001 From: Zomatree Date: Tue, 9 Apr 2024 22:36:48 +0100 Subject: [PATCH] move voice states to global --- crates/bonfire/src/events/impl.rs | 51 +++++++++++-------- crates/core/database/src/events/client.rs | 29 ++--------- crates/core/models/src/v0/channels.rs | 14 +++-- crates/core/models/src/v0/users.rs | 7 +++ .../delta/src/routes/channels/voice_join.rs | 14 ++--- crates/voice-ingress/src/main.rs | 7 ++- 6 files changed, 62 insertions(+), 60 deletions(-) diff --git a/crates/bonfire/src/events/impl.rs b/crates/bonfire/src/events/impl.rs index d5ed027d..b7e90082 100644 --- a/crates/bonfire/src/events/impl.rs +++ b/crates/bonfire/src/events/impl.rs @@ -1,15 +1,15 @@ use std::collections::HashSet; use revolt_database::{ - events::client::{ChannelVoiceState, EventV1, ReadyServer, UserVoiceState}, util::permissions::DatabasePermissionQuery, Channel, Database, Member, + events::client::EventV1, util::permissions::DatabasePermissionQuery, Channel, Database, Member, MemberCompositeKey, Presence, RelationshipStatus, }; use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_presence::filter_online; -use revolt_result::Result; +use revolt_result::{create_error, Result}; -use redis_kiss::{get_connection, AsyncCommands}; +use redis_kiss::{get_connection, AsyncCommands, Conn}; use super::state::{Cache, State}; @@ -127,11 +127,18 @@ impl State { // Filter server channels by permission. let channels = self.cache.filter_accessible_channels(db, channels).await; + let mut voice_states = Vec::new(); + let mut conn = get_connection().await.unwrap(); + // Append known user IDs from DMs. for channel in &channels { match channel { - Channel::DirectMessage { recipients, .. } | Channel::Group { recipients, .. } => { + Channel::DirectMessage { id, recipients, .. } | Channel::Group { id, recipients, .. } => { user_ids.extend(&mut recipients.clone().into_iter()); + + if let Ok(Some(voice_state)) = self.fetch_voice_state(&mut conn, id).await { + voice_states.push(voice_state) + } } _ => {} } @@ -199,32 +206,21 @@ impl State { self.insert_subscription(channel.id().to_string()); } - let mut conn = get_connection().await.unwrap(); - let mut new_servers = Vec::with_capacity(servers.len()); - - for server in servers { - let mut voice_states = vec![]; - + for server in &servers { for channel in &server.channels { - let members = conn.smembers::<_, Vec>(format!("vc-members-{channel}")).await.unwrap(); - - if !members.is_empty() { - voice_states.push(ChannelVoiceState { - id: channel.clone(), - participants: members.into_iter().map(|id| UserVoiceState { id }).collect() - }) + if let Ok(Some(voice_state)) = self.fetch_voice_state(&mut conn, channel).await { + voice_states.push(voice_state) } } - - new_servers.push(ReadyServer { server: server.into(), voice_states }) } Ok(EventV1::Ready { users, - servers: new_servers, + servers: servers.into_iter().map(Into::into).collect(), channels: channels.into_iter().map(Into::into).collect(), members: members.into_iter().map(Into::into).collect(), emojis: emojis.into_iter().map(Into::into).collect(), + voice_states }) } @@ -571,4 +567,19 @@ impl State { true } + + async fn fetch_voice_state(&self, conn: &mut Conn, channel: &str) -> Result> { + let members = conn.smembers::<_, Vec>(format!("vc-members-{channel}")) + .await + .map_err(|_| create_error!(InternalError))?; + + if !members.is_empty() { + Ok(Some(v0::ChannelVoiceState { + id: channel.to_string(), + participants: members.into_iter().map(|id| v0::UserVoiceState { id }).collect() + })) + } else { + Ok(None) + } + } } diff --git a/crates/core/database/src/events/client.rs b/crates/core/database/src/events/client.rs index 04fb7f1b..feab64d4 100644 --- a/crates/core/database/src/events/client.rs +++ b/crates/core/database/src/events/client.rs @@ -2,10 +2,7 @@ use authifier::AuthifierEvent; use serde::{Deserialize, Serialize}; use revolt_models::v0::{ - AppendMessage, Channel, Emoji, FieldsChannel, FieldsMember, FieldsRole, FieldsServer, - FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember, - PartialMessage, PartialRole, PartialServer, PartialUser, PartialWebhook, Report, Server, User, - UserSettings, Webhook + AppendMessage, Channel, ChannelVoiceState, Emoji, FieldsChannel, FieldsMember, FieldsRole, FieldsServer, FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember, PartialMessage, PartialRole, PartialServer, PartialUser, PartialWebhook, Report, Server, User, UserSettings, UserVoiceState, Webhook }; use revolt_result::Error; @@ -39,25 +36,6 @@ pub enum ErrorEvent { APIError(Error), } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct UserVoiceState { - pub id: String - // TODO - muted, etc -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ChannelVoiceState { - pub id: String, - pub participants: Vec -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ReadyServer { - #[serde(flatten)] - pub server: Server, - pub voice_states: Vec -} - /// Protocol Events #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(tag = "type")] @@ -70,10 +48,11 @@ pub enum EventV1 { /// Basic data to cache Ready { users: Vec, - servers: Vec, + servers: Vec, channels: Vec, members: Vec, emojis: Vec, + voice_states: Vec }, /// Ping response @@ -248,7 +227,7 @@ pub enum EventV1 { /// Voice events VoiceChannelJoin { id: String, - user: String, + state: UserVoiceState, }, VoiceChannelLeave { id: String, diff --git a/crates/core/models/src/v0/channels.rs b/crates/core/models/src/v0/channels.rs index f30c7533..fd88f093 100644 --- a/crates/core/models/src/v0/channels.rs +++ b/crates/core/models/src/v0/channels.rs @@ -1,4 +1,4 @@ -use super::File; +use super::{File, UserVoiceState}; use revolt_permissions::{Override, OverrideField}; use std::collections::{HashMap, HashSet}; @@ -306,10 +306,18 @@ auto_derived!( } /// Voice server token response - pub struct LegacyCreateVoiceUserResponse { + pub struct CreateVoiceUserResponse { /// Token for authenticating with the voice server - token: String, + pub token: String, } + + /// Voice state for a channel + pub struct ChannelVoiceState { + pub id: String, + /// The states of the users who are connected to the channel + pub participants: Vec + } + ); impl Channel { diff --git a/crates/core/models/src/v0/users.rs b/crates/core/models/src/v0/users.rs index 1966e35c..1e6c4fff 100644 --- a/crates/core/models/src/v0/users.rs +++ b/crates/core/models/src/v0/users.rs @@ -270,6 +270,13 @@ auto_derived!( /// Username and discriminator combo separated by # pub username: String, } + + /// Voice State information for a user + pub struct UserVoiceState { + pub id: String + // TODO - muted, etc + } + ); pub trait CheckRelationship { diff --git a/crates/delta/src/routes/channels/voice_join.rs b/crates/delta/src/routes/channels/voice_join.rs index 7b252ced..e6afd62b 100644 --- a/crates/delta/src/routes/channels/voice_join.rs +++ b/crates/delta/src/routes/channels/voice_join.rs @@ -2,27 +2,19 @@ use std::borrow::Cow; use revolt_config::config; use revolt_models::v0; -use revolt_database::{events::client::EventV1, util::{permissions::perms, reference::Reference}, Channel, Database, User}; +use revolt_database::{util::{permissions::perms, reference::Reference}, Channel, Database, User}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; use livekit_api::{access_token::{AccessToken, VideoGrants}, services::room::{CreateRoomOptions, RoomClient}}; use rocket::{serde::json::Json, State}; -use serde::{Deserialize, Serialize}; - -/// # Voice Server Token Response -#[derive(Serialize, Deserialize, JsonSchema)] -pub struct CreateVoiceUserResponse { - /// Token for authenticating with the voice server - token: String, -} /// # Join Call /// /// Asks the voice server for a token to join the call. #[openapi(tag = "Voice")] #[post("//join_call")] -pub async fn call(db: &State, rooms: &State, user: User, target: Reference) -> Result> { +pub async fn call(db: &State, rooms: &State, user: User, target: Reference) -> Result> { let channel = target.as_channel(db).await?; let mut permissions = perms(db, &user).channel(&channel); @@ -71,5 +63,5 @@ pub async fn call(db: &State, rooms: &State, user: User, t log::info!("created room {room:?}"); - Ok(Json(CreateVoiceUserResponse { token })) + Ok(Json(v0::CreateVoiceUserResponse { token })) } diff --git a/crates/voice-ingress/src/main.rs b/crates/voice-ingress/src/main.rs index 43edde5c..6fc6c0d1 100644 --- a/crates/voice-ingress/src/main.rs +++ b/crates/voice-ingress/src/main.rs @@ -3,6 +3,7 @@ use std::env; use redis_kiss::{get_connection, AsyncCommands}; use revolt_database::events::client::EventV1; +use revolt_models::v0::UserVoiceState; use rocket::{build, post, routes, serde::json::Json, Config}; use rocket_empty::EmptyResponse; use livekit_protocol::WebhookEvent; @@ -47,9 +48,13 @@ async fn ingress(body: Json) -> Result { redis.sadd::<_, _, u64>(format!("vc-members-{}", channel_id), user_id).await.unwrap(); redis.set::<_, _, String>(format!("vc-{}", user_id), &channel_id).await.unwrap(); + let voice_state = UserVoiceState { + id: user_id.clone() + }; + EventV1::VoiceChannelJoin { id: channel_id.clone(), - user: user_id.clone() + state: voice_state } .p(channel_id.clone()) .await