feat(core/events): add user settings / unreads to Ready payload

refactor(core/events): make all Ready payload items optional
This commit is contained in:
Paul Makles
2024-07-14 17:03:40 +01:00
parent caa0795d07
commit 412f4a99d7
4 changed files with 109 additions and 26 deletions

View File

@@ -1,5 +1,6 @@
use async_tungstenite::tungstenite::{handshake, Message};
use futures::channel::oneshot::Sender;
use revolt_database::events::client::ReadyPayloadFields;
use revolt_result::{create_error, Result};
use serde::{Deserialize, Serialize};
@@ -83,6 +84,17 @@ impl ProtocolConfiguration {
pub fn get_protocol_format(&self) -> &ProtocolFormat {
&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

View File

@@ -1,8 +1,9 @@
use std::collections::HashSet;
use revolt_database::{
events::client::EventV1, util::permissions::DatabasePermissionQuery, Channel, Database, Member,
MemberCompositeKey, Presence, RelationshipStatus,
events::client::{EventV1, ReadyPayloadFields},
util::permissions::DatabasePermissionQuery,
Channel, Database, Member, MemberCompositeKey, Presence, RelationshipStatus,
};
use revolt_models::v0;
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
@@ -90,7 +91,11 @@ impl Cache {
/// State Manager
impl State {
/// 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();
self.cache.is_bot = user.bot.is_some();
@@ -150,14 +155,36 @@ impl State {
.await?;
// Fetch customisations.
let emojis = db
.fetch_emoji_by_parent_ids(
&servers
.iter()
.map(|x| x.id.to_string())
.collect::<Vec<String>>(),
let emojis = if fields.contains(&ReadyPayloadFields::Emoji) {
Some(
db.fetch_emoji_by_parent_ids(
&servers
.iter()
.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.
self.cache.users = users.iter().cloned().map(|x| (x.id.clone(), x)).collect();
@@ -201,13 +228,31 @@ impl State {
for channel in &channels {
self.insert_subscription(channel.id().to_string()).await;
}
Ok(EventV1::Ready {
users,
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(),
users: if fields.contains(&ReadyPayloadFields::Users) {
Some(users)
} else {
None
},
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.
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,
Err(err) => {
sentry::capture_error(&err);

View File

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