move voice states to global
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use revolt_database::{
|
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,
|
MemberCompositeKey, Presence, RelationshipStatus,
|
||||||
};
|
};
|
||||||
use revolt_models::v0;
|
use revolt_models::v0;
|
||||||
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
|
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
|
||||||
use revolt_presence::filter_online;
|
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};
|
use super::state::{Cache, State};
|
||||||
|
|
||||||
@@ -127,11 +127,18 @@ impl State {
|
|||||||
// Filter server channels by permission.
|
// Filter server channels by permission.
|
||||||
let channels = self.cache.filter_accessible_channels(db, channels).await;
|
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.
|
// Append known user IDs from DMs.
|
||||||
for channel in &channels {
|
for channel in &channels {
|
||||||
match channel {
|
match channel {
|
||||||
Channel::DirectMessage { recipients, .. } | Channel::Group { recipients, .. } => {
|
Channel::DirectMessage { id, recipients, .. } | Channel::Group { id, recipients, .. } => {
|
||||||
user_ids.extend(&mut recipients.clone().into_iter());
|
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());
|
self.insert_subscription(channel.id().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut conn = get_connection().await.unwrap();
|
for server in &servers {
|
||||||
let mut new_servers = Vec::with_capacity(servers.len());
|
|
||||||
|
|
||||||
for server in servers {
|
|
||||||
let mut voice_states = vec![];
|
|
||||||
|
|
||||||
for channel in &server.channels {
|
for channel in &server.channels {
|
||||||
let members = conn.smembers::<_, Vec<String>>(format!("vc-members-{channel}")).await.unwrap();
|
if let Ok(Some(voice_state)) = self.fetch_voice_state(&mut conn, channel).await {
|
||||||
|
voice_states.push(voice_state)
|
||||||
if !members.is_empty() {
|
|
||||||
voice_states.push(ChannelVoiceState {
|
|
||||||
id: channel.clone(),
|
|
||||||
participants: members.into_iter().map(|id| UserVoiceState { id }).collect()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_servers.push(ReadyServer { server: server.into(), voice_states })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EventV1::Ready {
|
Ok(EventV1::Ready {
|
||||||
users,
|
users,
|
||||||
servers: new_servers,
|
servers: servers.into_iter().map(Into::into).collect(),
|
||||||
channels: channels.into_iter().map(Into::into).collect(),
|
channels: channels.into_iter().map(Into::into).collect(),
|
||||||
members: members.into_iter().map(Into::into).collect(),
|
members: members.into_iter().map(Into::into).collect(),
|
||||||
emojis: emojis.into_iter().map(Into::into).collect(),
|
emojis: emojis.into_iter().map(Into::into).collect(),
|
||||||
|
voice_states
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,4 +567,19 @@ impl State {
|
|||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fetch_voice_state(&self, conn: &mut Conn, channel: &str) -> Result<Option<v0::ChannelVoiceState>> {
|
||||||
|
let members = conn.smembers::<_, Vec<String>>(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ use authifier::AuthifierEvent;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use revolt_models::v0::{
|
use revolt_models::v0::{
|
||||||
AppendMessage, Channel, Emoji, FieldsChannel, FieldsMember, FieldsRole, FieldsServer,
|
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
|
||||||
FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember,
|
|
||||||
PartialMessage, PartialRole, PartialServer, PartialUser, PartialWebhook, Report, Server, User,
|
|
||||||
UserSettings, Webhook
|
|
||||||
};
|
};
|
||||||
use revolt_result::Error;
|
use revolt_result::Error;
|
||||||
|
|
||||||
@@ -39,25 +36,6 @@ pub enum ErrorEvent {
|
|||||||
APIError(Error),
|
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<UserVoiceState>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct ReadyServer {
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub server: Server,
|
|
||||||
pub voice_states: Vec<ChannelVoiceState>
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Protocol Events
|
/// Protocol Events
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
@@ -70,10 +48,11 @@ pub enum EventV1 {
|
|||||||
/// Basic data to cache
|
/// Basic data to cache
|
||||||
Ready {
|
Ready {
|
||||||
users: Vec<User>,
|
users: Vec<User>,
|
||||||
servers: Vec<ReadyServer>,
|
servers: Vec<Server>,
|
||||||
channels: Vec<Channel>,
|
channels: Vec<Channel>,
|
||||||
members: Vec<Member>,
|
members: Vec<Member>,
|
||||||
emojis: Vec<Emoji>,
|
emojis: Vec<Emoji>,
|
||||||
|
voice_states: Vec<ChannelVoiceState>
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Ping response
|
/// Ping response
|
||||||
@@ -248,7 +227,7 @@ pub enum EventV1 {
|
|||||||
/// Voice events
|
/// Voice events
|
||||||
VoiceChannelJoin {
|
VoiceChannelJoin {
|
||||||
id: String,
|
id: String,
|
||||||
user: String,
|
state: UserVoiceState,
|
||||||
},
|
},
|
||||||
VoiceChannelLeave {
|
VoiceChannelLeave {
|
||||||
id: String,
|
id: String,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::File;
|
use super::{File, UserVoiceState};
|
||||||
|
|
||||||
use revolt_permissions::{Override, OverrideField};
|
use revolt_permissions::{Override, OverrideField};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@@ -306,10 +306,18 @@ auto_derived!(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Voice server token response
|
/// Voice server token response
|
||||||
pub struct LegacyCreateVoiceUserResponse {
|
pub struct CreateVoiceUserResponse {
|
||||||
/// Token for authenticating with the voice server
|
/// 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<UserVoiceState>
|
||||||
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
|
|||||||
@@ -270,6 +270,13 @@ auto_derived!(
|
|||||||
/// Username and discriminator combo separated by #
|
/// Username and discriminator combo separated by #
|
||||||
pub username: String,
|
pub username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Voice State information for a user
|
||||||
|
pub struct UserVoiceState {
|
||||||
|
pub id: String
|
||||||
|
// TODO - muted, etc
|
||||||
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
pub trait CheckRelationship {
|
pub trait CheckRelationship {
|
||||||
|
|||||||
@@ -2,27 +2,19 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
use revolt_config::config;
|
use revolt_config::config;
|
||||||
use revolt_models::v0;
|
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_permissions::{calculate_channel_permissions, ChannelPermission};
|
||||||
use revolt_result::{create_error, Result};
|
use revolt_result::{create_error, Result};
|
||||||
|
|
||||||
use livekit_api::{access_token::{AccessToken, VideoGrants}, services::room::{CreateRoomOptions, RoomClient}};
|
use livekit_api::{access_token::{AccessToken, VideoGrants}, services::room::{CreateRoomOptions, RoomClient}};
|
||||||
use rocket::{serde::json::Json, State};
|
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
|
/// # Join Call
|
||||||
///
|
///
|
||||||
/// Asks the voice server for a token to join the call.
|
/// Asks the voice server for a token to join the call.
|
||||||
#[openapi(tag = "Voice")]
|
#[openapi(tag = "Voice")]
|
||||||
#[post("/<target>/join_call")]
|
#[post("/<target>/join_call")]
|
||||||
pub async fn call(db: &State<Database>, rooms: &State<RoomClient>, user: User, target: Reference) -> Result<Json<CreateVoiceUserResponse>> {
|
pub async fn call(db: &State<Database>, rooms: &State<RoomClient>, user: User, target: Reference) -> Result<Json<v0::CreateVoiceUserResponse>> {
|
||||||
let channel = target.as_channel(db).await?;
|
let channel = target.as_channel(db).await?;
|
||||||
|
|
||||||
let mut permissions = perms(db, &user).channel(&channel);
|
let mut permissions = perms(db, &user).channel(&channel);
|
||||||
@@ -71,5 +63,5 @@ pub async fn call(db: &State<Database>, rooms: &State<RoomClient>, user: User, t
|
|||||||
|
|
||||||
log::info!("created room {room:?}");
|
log::info!("created room {room:?}");
|
||||||
|
|
||||||
Ok(Json(CreateVoiceUserResponse { token }))
|
Ok(Json(v0::CreateVoiceUserResponse { token }))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::env;
|
|||||||
use redis_kiss::{get_connection, AsyncCommands};
|
use redis_kiss::{get_connection, AsyncCommands};
|
||||||
|
|
||||||
use revolt_database::events::client::EventV1;
|
use revolt_database::events::client::EventV1;
|
||||||
|
use revolt_models::v0::UserVoiceState;
|
||||||
use rocket::{build, post, routes, serde::json::Json, Config};
|
use rocket::{build, post, routes, serde::json::Json, Config};
|
||||||
use rocket_empty::EmptyResponse;
|
use rocket_empty::EmptyResponse;
|
||||||
use livekit_protocol::WebhookEvent;
|
use livekit_protocol::WebhookEvent;
|
||||||
@@ -47,9 +48,13 @@ async fn ingress(body: Json<WebhookEvent>) -> Result<EmptyResponse> {
|
|||||||
redis.sadd::<_, _, u64>(format!("vc-members-{}", channel_id), user_id).await.unwrap();
|
redis.sadd::<_, _, u64>(format!("vc-members-{}", channel_id), user_id).await.unwrap();
|
||||||
redis.set::<_, _, String>(format!("vc-{}", user_id), &channel_id).await.unwrap();
|
redis.set::<_, _, String>(format!("vc-{}", user_id), &channel_id).await.unwrap();
|
||||||
|
|
||||||
|
let voice_state = UserVoiceState {
|
||||||
|
id: user_id.clone()
|
||||||
|
};
|
||||||
|
|
||||||
EventV1::VoiceChannelJoin {
|
EventV1::VoiceChannelJoin {
|
||||||
id: channel_id.clone(),
|
id: channel_id.clone(),
|
||||||
user: user_id.clone()
|
state: voice_state
|
||||||
}
|
}
|
||||||
.p(channel_id.clone())
|
.p(channel_id.clone())
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in New Issue
Block a user