forked from jmug/stoatchat
initial livekit support
fix up code undo changes to compose file add back .env.example
This commit is contained in:
@@ -69,3 +69,4 @@ emoji_size = 500000
|
||||
[sentry]
|
||||
api = ""
|
||||
events = ""
|
||||
voice_ingress = ""
|
||||
@@ -44,8 +44,7 @@ pub struct Hosts {
|
||||
pub events: String,
|
||||
pub autumn: String,
|
||||
pub january: String,
|
||||
pub voso_legacy: String,
|
||||
pub voso_legacy_ws: String,
|
||||
pub livekit: String
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
@@ -94,6 +93,13 @@ pub struct ApiWorkers {
|
||||
pub max_concurrent_connections: usize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct ApiLiveKit {
|
||||
pub url: String,
|
||||
pub key: String,
|
||||
pub secret: String
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct Api {
|
||||
pub registration: ApiRegistration,
|
||||
@@ -102,6 +108,7 @@ pub struct Api {
|
||||
pub fcm: ApiFcm,
|
||||
pub security: ApiSecurity,
|
||||
pub workers: ApiWorkers,
|
||||
pub livekit: ApiLiveKit,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
@@ -144,6 +151,7 @@ pub struct Features {
|
||||
pub struct Sentry {
|
||||
pub api: String,
|
||||
pub events: String,
|
||||
pub voice_ingress: String
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
||||
@@ -22,7 +22,7 @@ pub enum DatabaseInfo {
|
||||
}
|
||||
|
||||
/// Database
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Database {
|
||||
/// Mock database
|
||||
Reference(ReferenceDb),
|
||||
@@ -35,7 +35,7 @@ impl DatabaseInfo {
|
||||
#[async_recursion]
|
||||
pub async fn connect(self) -> Result<Database, String> {
|
||||
let config = config().await;
|
||||
|
||||
println!("{config:?}");
|
||||
Ok(match self {
|
||||
DatabaseInfo::Auto => {
|
||||
if std::env::var("TEST_DB").is_ok() {
|
||||
|
||||
@@ -12,6 +12,7 @@ use serde::Serialize;
|
||||
database_derived!(
|
||||
#[cfg(feature = "mongodb")]
|
||||
/// MongoDB implementation
|
||||
#[derive(Debug)]
|
||||
pub struct MongoDb(pub ::mongodb::Client, pub String);
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
|
||||
database_derived!(
|
||||
/// Reference implementation
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ReferenceDb {
|
||||
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
||||
pub channels: Arc<Mutex<HashMap<String, Channel>>>,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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,
|
||||
UserSettings, Webhook
|
||||
};
|
||||
use revolt_result::Error;
|
||||
|
||||
@@ -39,6 +39,25 @@ 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<UserVoiceState>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ReadyServer {
|
||||
#[serde(flatten)]
|
||||
pub server: Server,
|
||||
pub voice_states: Vec<ChannelVoiceState>
|
||||
}
|
||||
|
||||
/// Protocol Events
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
@@ -51,7 +70,7 @@ pub enum EventV1 {
|
||||
/// Basic data to cache
|
||||
Ready {
|
||||
users: Vec<User>,
|
||||
servers: Vec<Server>,
|
||||
servers: Vec<ReadyServer>,
|
||||
channels: Vec<Channel>,
|
||||
members: Vec<Member>,
|
||||
emojis: Vec<Emoji>,
|
||||
@@ -225,6 +244,16 @@ pub enum EventV1 {
|
||||
|
||||
/// Auth events
|
||||
Auth(AuthifierEvent),
|
||||
|
||||
/// Voice events
|
||||
VoiceChannelJoin {
|
||||
id: String,
|
||||
user: String,
|
||||
},
|
||||
VoiceChannelLeave {
|
||||
id: String,
|
||||
user: String,
|
||||
}
|
||||
}
|
||||
|
||||
impl EventV1 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use revolt_config::config;
|
||||
use revolt_models::v0::{self, MessageAuthor};
|
||||
use revolt_models::v0::{self, MessageAuthor, VoiceInformation};
|
||||
use revolt_permissions::OverrideField;
|
||||
use revolt_result::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -103,6 +103,10 @@ auto_derived!(
|
||||
/// Whether this channel is marked as not safe for work
|
||||
#[serde(skip_serializing_if = "crate::if_false", default)]
|
||||
nsfw: bool,
|
||||
|
||||
/// Voice Information for when this channel is also a voice channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
voice: Option<VoiceInformation>
|
||||
},
|
||||
/// Voice channel belonging to a server
|
||||
VoiceChannel {
|
||||
@@ -219,6 +223,7 @@ impl Channel {
|
||||
default_permissions: None,
|
||||
role_permissions: HashMap::new(),
|
||||
nsfw: data.nsfw.unwrap_or(false),
|
||||
voice: data.voice
|
||||
},
|
||||
v0::LegacyServerChannelType::Voice => Channel::VoiceChannel {
|
||||
id: id.clone(),
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::{events::client::EventV1, Database, File, RatelimitEvent};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::seq::SliceRandom;
|
||||
use redis_kiss::{get_connection, AsyncCommands};
|
||||
use revolt_config::config;
|
||||
use revolt_models::v0;
|
||||
use revolt_presence::filter_online;
|
||||
@@ -567,6 +568,15 @@ impl User {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets current voice channel
|
||||
pub async fn current_voice_channel(&self) -> Result<Option<String>> {
|
||||
let mut conn = get_connection().await.map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
conn.get::<_, Option<String>>(format!("vc-{}", &self.id))
|
||||
.await
|
||||
.map_err(|_| create_error!(InternalError))
|
||||
}
|
||||
|
||||
/// Update user data
|
||||
pub async fn update<'a>(
|
||||
&mut self,
|
||||
|
||||
@@ -186,6 +186,7 @@ impl From<crate::Channel> for Channel {
|
||||
default_permissions,
|
||||
role_permissions,
|
||||
nsfw,
|
||||
voice
|
||||
} => Channel::TextChannel {
|
||||
id,
|
||||
server,
|
||||
@@ -196,6 +197,7 @@ impl From<crate::Channel> for Channel {
|
||||
default_permissions,
|
||||
role_permissions,
|
||||
nsfw,
|
||||
voice
|
||||
},
|
||||
crate::Channel::VoiceChannel {
|
||||
id,
|
||||
@@ -266,6 +268,7 @@ impl From<Channel> for crate::Channel {
|
||||
default_permissions,
|
||||
role_permissions,
|
||||
nsfw,
|
||||
voice
|
||||
} => crate::Channel::TextChannel {
|
||||
id,
|
||||
server,
|
||||
@@ -276,6 +279,7 @@ impl From<Channel> for crate::Channel {
|
||||
default_permissions,
|
||||
role_permissions,
|
||||
nsfw,
|
||||
voice
|
||||
},
|
||||
Channel::VoiceChannel {
|
||||
id,
|
||||
|
||||
@@ -107,8 +107,12 @@ auto_derived!(
|
||||
serde(skip_serializing_if = "crate::if_false", default)
|
||||
)]
|
||||
nsfw: bool,
|
||||
|
||||
/// Voice Information for when this channel is also a voice channel
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
voice: Option<VoiceInformation>
|
||||
},
|
||||
/// Voice channel belonging to a server
|
||||
/// DEPRECATED (use TextChannel { voice }): Voice channel belonging to a server
|
||||
VoiceChannel {
|
||||
/// Unique Id
|
||||
#[cfg_attr(feature = "serde", serde(rename = "_id"))]
|
||||
@@ -147,6 +151,15 @@ auto_derived!(
|
||||
},
|
||||
}
|
||||
|
||||
/// Voice information for a channel
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(feature = "validator", derive(validator::Validate))]
|
||||
pub struct VoiceInformation {
|
||||
/// Maximium amount of users allowed in the voice channel at once
|
||||
#[cfg_attr(feature = "validator", validate(range(min = 1)))]
|
||||
pub max_users: Option<u32>
|
||||
}
|
||||
|
||||
/// Partial representation of a channel
|
||||
#[derive(Default)]
|
||||
pub struct PartialChannel {
|
||||
@@ -260,6 +273,10 @@ auto_derived!(
|
||||
/// Whether this channel is age restricted
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nsfw: Option<bool>,
|
||||
|
||||
/// Voice Information for when this channel is also a voice channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub voice: Option<VoiceInformation>
|
||||
}
|
||||
|
||||
/// New default permissions
|
||||
|
||||
@@ -130,8 +130,9 @@ pub enum ErrorType {
|
||||
error: String,
|
||||
},
|
||||
|
||||
// ? Legacy errors
|
||||
VosoUnavailable,
|
||||
// ? Voice errors
|
||||
LiveKitUnavailable,
|
||||
AlreadyInVoiceChannel
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
||||
@@ -71,10 +71,12 @@ impl<'r> Responder<'r, 'static> for Error {
|
||||
ErrorType::InvalidProperty => Status::BadRequest,
|
||||
ErrorType::InvalidSession => Status::Unauthorized,
|
||||
ErrorType::DuplicateNonce => Status::Conflict,
|
||||
ErrorType::VosoUnavailable => Status::BadRequest,
|
||||
ErrorType::NotFound => Status::NotFound,
|
||||
ErrorType::NoEffect => Status::Ok,
|
||||
ErrorType::FailedValidation { .. } => Status::BadRequest,
|
||||
|
||||
ErrorType::LiveKitUnavailable => Status::BadRequest,
|
||||
ErrorType::AlreadyInVoiceChannel => Status::BadRequest,
|
||||
};
|
||||
|
||||
// Serialize the error data structure into JSON.
|
||||
|
||||
Reference in New Issue
Block a user