forked from jmug/stoatchat
feat: ready payload field customisation
This commit is contained in:
committed by
Angelo Kontaxis
parent
a186732ca5
commit
db57706794
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -6294,6 +6294,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"querystring",
|
"querystring",
|
||||||
"redis-kiss",
|
"redis-kiss",
|
||||||
|
"regex",
|
||||||
"revolt-config",
|
"revolt-config",
|
||||||
"revolt-database",
|
"revolt-database",
|
||||||
"revolt-models",
|
"revolt-models",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ async-channel = "2.3.1"
|
|||||||
|
|
||||||
# parsing
|
# parsing
|
||||||
querystring = "1.1.0"
|
querystring = "1.1.0"
|
||||||
|
regex = "1.11.1"
|
||||||
|
|
||||||
# serde
|
# serde
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
use async_tungstenite::tungstenite::{handshake, Message};
|
use async_tungstenite::tungstenite::{handshake, Message};
|
||||||
use futures::channel::oneshot::Sender;
|
use futures::channel::oneshot::Sender;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use revolt_database::events::client::ReadyPayloadFields;
|
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};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
/// matches either a single word ie "users" or a key and value ie "settings[notifications]"
|
||||||
|
static READY_PAYLOAD_FIELD_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"^(\w+)(?:\[(\w+)\])?$"#).unwrap());
|
||||||
|
|
||||||
/// Enumeration of supported protocol formats
|
/// Enumeration of supported protocol formats
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -17,6 +22,7 @@ pub struct ProtocolConfiguration {
|
|||||||
protocol_version: i32,
|
protocol_version: i32,
|
||||||
format: ProtocolFormat,
|
format: ProtocolFormat,
|
||||||
session_token: Option<String>,
|
session_token: Option<String>,
|
||||||
|
ready_payload_fields: ReadyPayloadFields
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProtocolConfiguration {
|
impl ProtocolConfiguration {
|
||||||
@@ -25,11 +31,13 @@ impl ProtocolConfiguration {
|
|||||||
protocol_version: i32,
|
protocol_version: i32,
|
||||||
format: ProtocolFormat,
|
format: ProtocolFormat,
|
||||||
session_token: Option<String>,
|
session_token: Option<String>,
|
||||||
|
ready_payload_fields: ReadyPayloadFields
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
protocol_version,
|
protocol_version,
|
||||||
format,
|
format,
|
||||||
session_token,
|
session_token,
|
||||||
|
ready_payload_fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,14 +94,8 @@ impl ProtocolConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get ready payload fields
|
/// Get ready payload fields
|
||||||
pub fn get_ready_payload_fields(&self) -> Vec<ReadyPayloadFields> {
|
pub fn get_ready_payload_fields(&self) -> &ReadyPayloadFields {
|
||||||
vec![
|
&self.ready_payload_fields
|
||||||
ReadyPayloadFields::Users,
|
|
||||||
ReadyPayloadFields::Servers,
|
|
||||||
ReadyPayloadFields::Channels,
|
|
||||||
ReadyPayloadFields::Members,
|
|
||||||
ReadyPayloadFields::Emoji,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +126,7 @@ impl handshake::server::Callback for WebsocketHandshakeCallback {
|
|||||||
let mut protocol_version = 1;
|
let mut protocol_version = 1;
|
||||||
let mut format = ProtocolFormat::Json;
|
let mut format = ProtocolFormat::Json;
|
||||||
let mut session_token = None;
|
let mut session_token = None;
|
||||||
|
let mut ready_payload_fields = ReadyPayloadFields::default();
|
||||||
|
|
||||||
// Parse and map parameters from key-value to known variables.
|
// Parse and map parameters from key-value to known variables.
|
||||||
for (key, value) in params {
|
for (key, value) in params {
|
||||||
@@ -139,6 +142,26 @@ impl handshake::server::Callback for WebsocketHandshakeCallback {
|
|||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
"token" => session_token = Some(value.into()),
|
"token" => session_token = Some(value.into()),
|
||||||
|
"ready" => {
|
||||||
|
if let Some(captures) = READY_PAYLOAD_FIELD_REGEX.captures(value) {
|
||||||
|
if let Some(field) = captures.get(0) {
|
||||||
|
match field.as_str() {
|
||||||
|
"users" => ready_payload_fields.users = true,
|
||||||
|
"servers" => ready_payload_fields.servers = true,
|
||||||
|
"channels" => ready_payload_fields.channels = true,
|
||||||
|
"members" => ready_payload_fields.members = true,
|
||||||
|
"emojis" => ready_payload_fields.emojis = true,
|
||||||
|
"channel_unreads" => ready_payload_fields.channel_unreads = true,
|
||||||
|
"user_settings" => {
|
||||||
|
if let Some(subkey) = captures.get(1) {
|
||||||
|
ready_payload_fields.user_settings.push(subkey.as_str().to_string());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,6 +174,7 @@ impl handshake::server::Callback for WebsocketHandshakeCallback {
|
|||||||
protocol_version,
|
protocol_version,
|
||||||
format,
|
format,
|
||||||
session_token,
|
session_token,
|
||||||
|
ready_payload_fields
|
||||||
})
|
})
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl State {
|
|||||||
pub async fn generate_ready_payload(
|
pub async fn generate_ready_payload(
|
||||||
&mut self,
|
&mut self,
|
||||||
db: &Database,
|
db: &Database,
|
||||||
fields: Vec<ReadyPayloadFields>,
|
fields: &ReadyPayloadFields,
|
||||||
) -> Result<EventV1> {
|
) -> 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();
|
||||||
@@ -168,7 +168,7 @@ impl State {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Fetch customisations.
|
// Fetch customisations.
|
||||||
let emojis = if fields.contains(&ReadyPayloadFields::Emoji) {
|
let emojis = if fields.emojis {
|
||||||
Some(
|
Some(
|
||||||
db.fetch_emoji_by_parent_ids(
|
db.fetch_emoji_by_parent_ids(
|
||||||
&servers
|
&servers
|
||||||
@@ -183,17 +183,14 @@ impl State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Fetch user settings
|
// Fetch user settings
|
||||||
let user_settings = if let Some(ReadyPayloadFields::UserSettings(keys)) = fields
|
let user_settings = if !fields.user_settings.is_empty() {
|
||||||
.iter()
|
Some(db.fetch_user_settings(&user.id, &fields.user_settings).await?)
|
||||||
.find(|e| matches!(e, ReadyPayloadFields::UserSettings(_)))
|
|
||||||
{
|
|
||||||
Some(db.fetch_user_settings(&user.id, keys).await?)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch channel unreads
|
// Fetch channel unreads
|
||||||
let channel_unreads = if fields.contains(&ReadyPayloadFields::ChannelUnreads) {
|
let channel_unreads = if fields.channel_unreads {
|
||||||
Some(db.fetch_unreads(&user.id).await?)
|
Some(db.fetch_unreads(&user.id).await?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -241,22 +238,22 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(EventV1::Ready {
|
Ok(EventV1::Ready {
|
||||||
users: if fields.contains(&ReadyPayloadFields::Users) {
|
users: if fields.users {
|
||||||
Some(users)
|
Some(users)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
servers: if fields.contains(&ReadyPayloadFields::Servers) {
|
servers: if fields.servers {
|
||||||
Some(servers.into_iter().map(Into::into).collect())
|
Some(servers.into_iter().map(Into::into).collect())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
channels: if fields.contains(&ReadyPayloadFields::Channels) {
|
channels: if fields.channels {
|
||||||
Some(channels.into_iter().map(Into::into).collect())
|
Some(channels.into_iter().map(Into::into).collect())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
members: if fields.contains(&ReadyPayloadFields::Members) {
|
members: if fields.members {
|
||||||
Some(members.into_iter().map(Into::into).collect())
|
Some(members.into_iter().map(Into::into).collect())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -20,16 +20,29 @@ pub enum Ping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fields provided in Ready payload
|
/// Fields provided in Ready payload
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq, Debug, Clone, Deserialize)]
|
||||||
pub enum ReadyPayloadFields {
|
pub struct ReadyPayloadFields {
|
||||||
Users,
|
pub users: bool,
|
||||||
Servers,
|
pub servers: bool,
|
||||||
Channels,
|
pub channels: bool,
|
||||||
Members,
|
pub members: bool,
|
||||||
Emoji,
|
pub emojis: bool,
|
||||||
|
pub user_settings: Vec<String>,
|
||||||
|
pub channel_unreads: bool
|
||||||
|
}
|
||||||
|
|
||||||
UserSettings(Vec<String>),
|
impl Default for ReadyPayloadFields {
|
||||||
ChannelUnreads,
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
users: true,
|
||||||
|
servers: true,
|
||||||
|
channels: true,
|
||||||
|
members: true,
|
||||||
|
emojis: true,
|
||||||
|
user_settings: Vec::new(),
|
||||||
|
channel_unreads: false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Protocol Events
|
/// Protocol Events
|
||||||
|
|||||||
Reference in New Issue
Block a user