Merge branch 'main' into main

Signed-off-by: Tom <iamtomahawkx@gmail.com>
This commit is contained in:
Tom
2024-07-19 09:20:42 -07:00
committed by GitHub
5 changed files with 112 additions and 39 deletions

View File

@@ -1,5 +1,6 @@
use async_tungstenite::tungstenite::{handshake, Message}; use async_tungstenite::tungstenite::{handshake, Message};
use futures::channel::oneshot::Sender; use futures::channel::oneshot::Sender;
use revolt_database::events::client::ReadyPayloadFields;
use revolt_result::{create_error, Result}; use revolt_result::{create_error, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -83,6 +84,17 @@ impl ProtocolConfiguration {
pub fn get_protocol_format(&self) -> &ProtocolFormat { pub fn get_protocol_format(&self) -> &ProtocolFormat {
&self.format &self.format
} }
/// Get ready payload fields
pub fn get_ready_payload_fields(&self) -> Vec<ReadyPayloadFields> {
vec![
ReadyPayloadFields::Users,
ReadyPayloadFields::Servers,
ReadyPayloadFields::Channels,
ReadyPayloadFields::Members,
ReadyPayloadFields::Emoji,
]
}
} }
/// Object holding one side of a channel for receiving the parsed information /// Object holding one side of a channel for receiving the parsed information

View File

@@ -1,8 +1,9 @@
use std::collections::HashSet; use std::collections::HashSet;
use revolt_database::{ use revolt_database::{
events::client::EventV1, util::permissions::DatabasePermissionQuery, Channel, Database, Member, events::client::{EventV1, ReadyPayloadFields},
MemberCompositeKey, Presence, RelationshipStatus, util::permissions::DatabasePermissionQuery,
Channel, Database, Member, 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};
@@ -90,7 +91,11 @@ impl Cache {
/// State Manager /// State Manager
impl State { impl State {
/// Generate a Ready packet for the current user /// Generate a Ready packet for the current user
pub async fn generate_ready_payload(&mut self, db: &Database) -> Result<EventV1> { pub async fn generate_ready_payload(
&mut self,
db: &Database,
fields: Vec<ReadyPayloadFields>,
) -> Result<EventV1> {
let user = self.clone_user(); let user = self.clone_user();
self.cache.is_bot = user.bot.is_some(); self.cache.is_bot = user.bot.is_some();
@@ -150,14 +155,36 @@ impl State {
.await?; .await?;
// Fetch customisations. // Fetch customisations.
let emojis = db let emojis = if fields.contains(&ReadyPayloadFields::Emoji) {
.fetch_emoji_by_parent_ids( Some(
&servers db.fetch_emoji_by_parent_ids(
.iter() &servers
.map(|x| x.id.to_string()) .iter()
.collect::<Vec<String>>(), .map(|x| x.id.to_string())
.collect::<Vec<String>>(),
)
.await?,
) )
.await?; } else {
None
};
// Fetch user settings
let user_settings = if let Some(ReadyPayloadFields::UserSettings(keys)) = fields
.iter()
.find(|e| matches!(e, ReadyPayloadFields::UserSettings(_)))
{
Some(db.fetch_user_settings(&user.id, &keys).await?)
} else {
None
};
// Fetch channel unreads
let channel_unreads = if fields.contains(&ReadyPayloadFields::ChannelUnreads) {
Some(db.fetch_unreads(&user.id).await?)
} else {
None
};
// Copy data into local state cache. // Copy data into local state cache.
self.cache.users = users.iter().cloned().map(|x| (x.id.clone(), x)).collect(); self.cache.users = users.iter().cloned().map(|x| (x.id.clone(), x)).collect();
@@ -201,13 +228,31 @@ impl State {
for channel in &channels { for channel in &channels {
self.insert_subscription(channel.id().to_string()).await; self.insert_subscription(channel.id().to_string()).await;
} }
Ok(EventV1::Ready { Ok(EventV1::Ready {
users, users: if fields.contains(&ReadyPayloadFields::Users) {
servers: servers.into_iter().map(Into::into).collect(), Some(users)
channels: channels.into_iter().map(Into::into).collect(), } else {
members: members.into_iter().map(Into::into).collect(), None
emojis: emojis.into_iter().map(Into::into).collect(), },
servers: if fields.contains(&ReadyPayloadFields::Servers) {
Some(servers.into_iter().map(Into::into).collect())
} else {
None
},
channels: if fields.contains(&ReadyPayloadFields::Channels) {
Some(channels.into_iter().map(Into::into).collect())
} else {
None
},
members: if fields.contains(&ReadyPayloadFields::Members) {
Some(members.into_iter().map(Into::into).collect())
} else {
None
},
emojis: emojis.map(|vec| vec.into_iter().map(Into::into).collect()),
user_settings,
channel_unreads: channel_unreads.map(|vec| vec.into_iter().map(Into::into).collect()),
}) })
} }

View File

@@ -106,7 +106,10 @@ pub async fn client(db: &'static Database, stream: TcpStream, addr: SocketAddr)
} }
// Download required data to local cache and send Ready payload. // Download required data to local cache and send Ready payload.
let ready_payload = match state.generate_ready_payload(db).await { let ready_payload = match state
.generate_ready_payload(db, config.get_ready_payload_fields())
.await
{
Ok(ready_payload) => ready_payload, Ok(ready_payload) => ready_payload,
Err(err) => { Err(err) => {
sentry::capture_error(&err); sentry::capture_error(&err);

View File

@@ -2,10 +2,10 @@ 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, ChannelUnread, Emoji, FieldsChannel, FieldsMember, FieldsRole,
FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialMember, FieldsServer, FieldsUser, FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel,
PartialMessage, PartialRole, PartialServer, PartialUser, PartialWebhook, RemovalIntention, PartialMember, PartialMessage, PartialRole, PartialServer, PartialUser, PartialWebhook,
Report, Server, User, UserSettings, Webhook, RemovalIntention, Report, Server, User, UserSettings, Webhook,
}; };
use revolt_result::Error; use revolt_result::Error;
@@ -39,6 +39,19 @@ pub enum ErrorEvent {
APIError(Error), APIError(Error),
} }
/// Fields provided in Ready payload
#[derive(PartialEq)]
pub enum ReadyPayloadFields {
Users,
Servers,
Channels,
Members,
Emoji,
UserSettings(Vec<String>),
ChannelUnreads,
}
/// Protocol Events /// Protocol Events
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")] #[serde(tag = "type")]
@@ -52,11 +65,21 @@ pub enum EventV1 {
Logout, Logout,
/// Basic data to cache /// Basic data to cache
Ready { Ready {
users: Vec<User>, #[serde(skip_serializing_if = "Option::is_none")]
servers: Vec<Server>, users: Option<Vec<User>>,
channels: Vec<Channel>, #[serde(skip_serializing_if = "Option::is_none")]
members: Vec<Member>, servers: Option<Vec<Server>>,
emojis: Vec<Emoji>, #[serde(skip_serializing_if = "Option::is_none")]
channels: Option<Vec<Channel>>,
#[serde(skip_serializing_if = "Option::is_none")]
members: Option<Vec<Member>>,
#[serde(skip_serializing_if = "Option::is_none")]
emojis: Option<Vec<Emoji>>,
#[serde(skip_serializing_if = "Option::is_none")]
user_settings: Option<UserSettings>,
#[serde(skip_serializing_if = "Option::is_none")]
channel_unreads: Option<Vec<ChannelUnread>>,
}, },
/// Ping response /// Ping response

View File

@@ -1024,6 +1024,8 @@ impl crate::User {
} }
/// Convert user object into user model assuming mutual connection /// Convert user object into user model assuming mutual connection
///
/// Relations will never be included, i.e. when we process ourselves
pub fn into_known<'a, P>(self, perspective: P, is_online: bool) -> User pub fn into_known<'a, P>(self, perspective: P, is_online: bool) -> User
where where
P: Into<Option<&'a crate::User>>, P: Into<Option<&'a crate::User>>,
@@ -1059,19 +1061,7 @@ impl crate::User {
discriminator: self.discriminator, discriminator: self.discriminator,
display_name: self.display_name, display_name: self.display_name,
avatar: self.avatar.map(|file| file.into()), avatar: self.avatar.map(|file| file.into()),
relations: if let Some(crate::User { id, .. }) = perspective { relations: vec![],
if id == &self.id {
self.relations
.unwrap_or_default()
.into_iter()
.map(|relation| relation.into())
.collect()
} else {
vec![]
}
} else {
vec![]
},
badges: self.badges.unwrap_or_default() as u32, badges: self.badges.unwrap_or_default() as u32,
online: can_see_profile online: can_see_profile
&& is_online && is_online