From 3d8d6b6f3be1d68f36b4b2f065a1f7673e604751 Mon Sep 17 00:00:00 2001 From: kozabrada123 <59031733+kozabrada123@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:24:32 +0200 Subject: [PATCH 01/31] Make GatewayHandle Clone --- src/api/auth/login.rs | 2 +- src/api/auth/register.rs | 2 +- src/gateway.rs | 6 ++---- src/instance.rs | 6 +++--- tests/common/mod.rs | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index 46951be..a95c3ca 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -46,7 +46,7 @@ impl Instance { self.clone_limits_if_some(), login_result.settings, Arc::new(RwLock::new(object)), - Arc::new(gateway), + gateway, ); Ok(user) } diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index 44c29d8..1a95d3d 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -54,7 +54,7 @@ impl Instance { self.clone_limits_if_some(), Arc::new(RwLock::new(settings)), Arc::new(RwLock::new(user_object)), - Arc::new(gateway), + gateway, ); Ok(user) } diff --git a/src/gateway.rs b/src/gateway.rs index 68205b5..ebe5ca2 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -158,7 +158,7 @@ pub type ObservableObject = dyn Send + Sync + Any; /// [`GatewayEvents`](GatewayEvent), which you can subscribe to. Gateway events include all currently /// implemented types with the trait [`WebSocketEvent`] /// Using this handle you can also send Gateway Events directly. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct GatewayHandle { pub url: String, pub events: Arc>, @@ -170,7 +170,6 @@ pub struct GatewayHandle { >, >, >, - pub handle: JoinHandle<()>, /// Tells gateway tasks to close kill_send: tokio::sync::broadcast::Sender<()>, pub(crate) store: Arc>>>>, @@ -410,7 +409,7 @@ impl Gateway { }; // Now we can continuously check for messages in a different task, since we aren't going to receive another hello - let handle: JoinHandle<()> = task::spawn(async move { + task::spawn(async move { gateway.gateway_listen_task().await; }); @@ -418,7 +417,6 @@ impl Gateway { url: websocket_url.clone(), events: shared_events, websocket_send: shared_websocket_send.clone(), - handle, kill_send: kill_send.clone(), store, }) diff --git a/src/instance.rs b/src/instance.rs index a3b5325..8ced86a 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -94,7 +94,7 @@ pub struct ChorusUser { pub limits: Option>, pub settings: Arc>, pub object: Arc>, - pub gateway: Arc, // TODO: Can this be an Arc? That way we could have Clone implemented on ChorusUser + pub gateway: GatewayHandle, } impl ChorusUser { @@ -117,7 +117,7 @@ impl ChorusUser { limits: Option>, settings: Arc>, object: Arc>, - gateway: Arc, + gateway: GatewayHandle, ) -> ChorusUser { ChorusUser { belongs_to, @@ -139,7 +139,7 @@ impl ChorusUser { let object = Arc::new(RwLock::new(User::default())); let wss_url = instance.read().unwrap().urls.wss.clone(); // Dummy gateway object - let gateway = Arc::new(Gateway::new(wss_url).await.unwrap()); + let gateway = Gateway::new(wss_url).await.unwrap(); ChorusUser { token, belongs_to: instance.clone(), diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 19c6509..a7b9d5d 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -42,7 +42,7 @@ impl TestBundle { limits: self.user.limits.clone(), settings: self.user.settings.clone(), object: self.user.object.clone(), - gateway: Arc::new(Gateway::new(self.instance.urls.wss.clone()).await.unwrap()), + gateway: Gateway::new(self.instance.urls.wss.clone()).await.unwrap(), } } } From 8c45355620d66156ae8788ab0458eb674dbdbf37 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 29 Aug 2023 14:45:10 +0200 Subject: [PATCH 02/31] Bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c8c26e..8a1e22a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.4.0" +version = "0.5.0" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index 3d2732b..312d9e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.4.0" +version = "0.5.0" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" From 141dc32819773a849ab39f6c4ba53fa5084227ea Mon Sep 17 00:00:00 2001 From: kozabrada123 <59031733+kozabrada123@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:38:26 +0000 Subject: [PATCH 03/31] Error observer (also merge perpetual/gateway-dev) (#425) * Add Webrtc Identify & Ready * Test error observer * Minor updates * More derives * Even more derives * Small types update * e --- src/errors.rs | 7 ++++++- src/gateway.rs | 9 ++++++--- src/types/events/call.rs | 6 +++--- src/types/events/hello.rs | 4 ++-- src/types/events/identify.rs | 8 ++++---- src/types/events/mod.rs | 6 +++++- src/types/events/presence.rs | 2 +- src/types/events/user.rs | 6 +++--- src/types/events/voice.rs | 4 ++-- src/types/events/webrtc/identify.rs | 18 ++++++++++++++++++ src/types/events/webrtc/mod.rs | 5 +++++ src/types/events/webrtc/ready.rs | 29 +++++++++++++++++++++++++++++ src/types/interfaces/activity.rs | 12 ++++++------ src/types/interfaces/status.rs | 2 +- src/types/schema/user.rs | 4 ++-- 15 files changed, 93 insertions(+), 29 deletions(-) create mode 100644 src/types/events/webrtc/identify.rs create mode 100644 src/types/events/webrtc/mod.rs create mode 100644 src/types/events/webrtc/ready.rs diff --git a/src/errors.rs b/src/errors.rs index eebfae3..642a3ba 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,6 +2,8 @@ use custom_error::custom_error; use reqwest::Error; +use crate::types::WebSocketEvent; + custom_error! { #[derive(PartialEq, Eq)] pub RegistrationError @@ -54,9 +56,10 @@ custom_error! { /// Supposed to be sent as numbers, though they are sent as string most of the time? /// /// Also includes errors when initiating a connection and unexpected opcodes - #[derive(PartialEq, Eq)] + #[derive(PartialEq, Eq, Default, Clone)] pub GatewayError // Errors we have received from the gateway + #[default] Unknown = "We're not sure what went wrong. Try reconnecting?", UnknownOpcode = "You sent an invalid Gateway opcode or an invalid payload for an opcode", Decode = "Gateway server couldn't decode payload", @@ -79,3 +82,5 @@ custom_error! { // Other misc errors UnexpectedOpcodeReceived{opcode: u8} = "Received an opcode we weren't expecting to receive: {opcode}", } + +impl WebSocketEvent for GatewayError {} diff --git a/src/gateway.rs b/src/gateway.rs index ebe5ca2..e9c6053 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -479,13 +479,15 @@ impl Gateway { return; } - // Todo: handle errors in a good way, maybe observers like events? if msg.is_error() { - warn!("GW: Received error, connection will close.."); + let error = msg.error().unwrap(); - let _error = msg.error(); + warn!("GW: Received error {:?}, connection will close..", error); self.close().await; + + self.events.lock().await.error.notify(error).await; + return; } @@ -935,6 +937,7 @@ mod events { pub webhooks: Webhooks, pub gateway_identify_payload: GatewayEvent, pub gateway_resume: GatewayEvent, + pub error: GatewayEvent, } #[derive(Default, Debug)] diff --git a/src/types/events/call.rs b/src/types/events/call.rs index e37c19d..508aae2 100644 --- a/src/types/events/call.rs +++ b/src/types/events/call.rs @@ -21,7 +21,7 @@ pub struct CallCreate { impl WebSocketEvent for CallCreate {} -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] /// Officially Undocumented; /// Updates the client on which calls are ringing, along with a specific call?; /// @@ -38,7 +38,7 @@ pub struct CallUpdate { impl WebSocketEvent for CallUpdate {} -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] /// Officially Undocumented; /// Deletes a ringing call; /// Ex: {"t":"CALL_DELETE","s":8,"op":0,"d":{"channel_id":"837609115475771392"}} @@ -48,7 +48,7 @@ pub struct CallDelete { impl WebSocketEvent for CallDelete {} -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] /// Officially Undocumented; /// See ; /// diff --git a/src/types/events/hello.rs b/src/types/events/hello.rs index 44f1e4f..fef3e22 100644 --- a/src/types/events/hello.rs +++ b/src/types/events/hello.rs @@ -2,7 +2,7 @@ use crate::types::WebSocketEvent; use serde::{Deserialize, Serialize}; /// Received on gateway init, tells the client how often to send heartbeats; -#[derive(Debug, Default, Deserialize, Serialize)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] pub struct GatewayHello { pub op: i32, pub d: HelloData, @@ -10,7 +10,7 @@ pub struct GatewayHello { impl WebSocketEvent for GatewayHello {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)] /// Contains info on how often the client should send heartbeats to the server; pub struct HelloData { /// How often a client should send heartbeats, in milliseconds diff --git a/src/types/events/identify.rs b/src/types/events/identify.rs index 35e1f78..12bc369 100644 --- a/src/types/events/identify.rs +++ b/src/types/events/identify.rs @@ -2,7 +2,7 @@ use crate::types::events::{PresenceUpdate, WebSocketEvent}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] pub struct GatewayIdentifyPayload { pub token: String, pub properties: GatewayIdentifyConnectionProps, @@ -68,7 +68,7 @@ impl GatewayIdentifyPayload { impl WebSocketEvent for GatewayIdentifyPayload {} -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] #[serde_as] pub struct GatewayIdentifyConnectionProps { /// Almost always sent @@ -144,7 +144,7 @@ impl GatewayIdentifyConnectionProps { referring_domain: None, referrer_current: None, release_channel: String::from("stable"), - client_build_number: 199933, + client_build_number: 0, } } @@ -159,7 +159,7 @@ impl GatewayIdentifyConnectionProps { system_locale: String::from("en-US"), os: String::from("Windows"), os_version: Some(String::from("10")), - client_build_number: 199933, + client_build_number: 222963, release_channel: String::from("stable"), ..Self::minimal() } diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs index 4f287ce..e440c05 100644 --- a/src/types/events/mod.rs +++ b/src/types/events/mod.rs @@ -5,6 +5,8 @@ use std::collections::HashMap; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +use serde_json::{from_str, from_value, to_value, Value}; + pub use application::*; pub use auto_moderation::*; pub use call::*; @@ -24,13 +26,13 @@ pub use ready::*; pub use relationship::*; pub use request_members::*; pub use resume::*; -use serde_json::{from_str, from_value, to_value, Value}; pub use session::*; pub use stage_instance::*; pub use thread::*; pub use user::*; pub use voice::*; pub use webhooks::*; +pub use webrtc::*; use crate::gateway::Updateable; @@ -62,6 +64,8 @@ mod user; mod voice; mod webhooks; +mod webrtc; + pub trait WebSocketEvent {} #[derive(Debug, Default, Serialize, Clone)] diff --git a/src/types/events/presence.rs b/src/types/events/presence.rs index c2d985e..e9a7dee 100644 --- a/src/types/events/presence.rs +++ b/src/types/events/presence.rs @@ -14,7 +14,7 @@ pub struct UpdatePresence { pub afk: bool, } -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq)] /// Received to tell the client that a user updated their presence / status /// See pub struct PresenceUpdate { diff --git a/src/types/events/user.rs b/src/types/events/user.rs index e3ce99a..7165812 100644 --- a/src/types/events/user.rs +++ b/src/types/events/user.rs @@ -4,7 +4,7 @@ use crate::types::entities::PublicUser; use crate::types::events::WebSocketEvent; use crate::types::utils::Snowflake; -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] /// See ; /// Sent to indicate updates to a user object; (name changes, discriminator changes, etc); pub struct UserUpdate { @@ -14,7 +14,7 @@ pub struct UserUpdate { impl WebSocketEvent for UserUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] /// Undocumented; /// /// Possibly an update for muted guild / channel settings for the current user; @@ -39,7 +39,7 @@ pub struct UserGuildSettingsUpdate { impl WebSocketEvent for UserGuildSettingsUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] /// Undocumented; /// /// Received in [UserGuildSettingsUpdate]; diff --git a/src/types/events/voice.rs b/src/types/events/voice.rs index ff13b73..2618ee1 100644 --- a/src/types/events/voice.rs +++ b/src/types/events/voice.rs @@ -1,7 +1,7 @@ use crate::types::{events::WebSocketEvent, Snowflake, VoiceState}; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize, Default)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, PartialEq, Eq)] /// /// Sent to the server to indicate an update of the voice state (leave voice channel, join voice channel, mute, deafen); /// @@ -28,7 +28,7 @@ pub struct VoiceStateUpdate { impl WebSocketEvent for VoiceStateUpdate {} -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] /// See ; /// /// Received to indicate which voice endpoint, token and guild_id to use; diff --git a/src/types/events/webrtc/identify.rs b/src/types/events/webrtc/identify.rs new file mode 100644 index 0000000..45f1037 --- /dev/null +++ b/src/types/events/webrtc/identify.rs @@ -0,0 +1,18 @@ +use crate::types::{Snowflake, WebSocketEvent}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] +/// The identify payload for the webrtc stream; +/// Contains info to begin a webrtc connection; +/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload; +pub struct VoiceIdentify { + server_id: Snowflake, + user_id: Snowflake, + session_id: String, + token: String, + #[serde(skip_serializing_if = "Option::is_none")] + /// Undocumented field, but is also in discord client comms + video: Option, +} + +impl WebSocketEvent for VoiceIdentify {} diff --git a/src/types/events/webrtc/mod.rs b/src/types/events/webrtc/mod.rs new file mode 100644 index 0000000..ebaf7b2 --- /dev/null +++ b/src/types/events/webrtc/mod.rs @@ -0,0 +1,5 @@ +pub use identify::*; +pub use ready::*; + +mod identify; +mod ready; diff --git a/src/types/events/webrtc/ready.rs b/src/types/events/webrtc/ready.rs new file mode 100644 index 0000000..008e41e --- /dev/null +++ b/src/types/events/webrtc/ready.rs @@ -0,0 +1,29 @@ +use std::net::Ipv4Addr; + +use crate::types::WebSocketEvent; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +/// The ready event for the webrtc stream; +/// Used to give info after the identify event; +/// See https://discord.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload; +pub struct VoiceReady { + ssrc: i32, + ip: Ipv4Addr, + port: u32, + modes: Vec, + // Heartbeat interval is also sent, but is "an erroneous field and should be ignored. The correct heartbeat_interval value comes from the Hello payload." +} + +impl Default for VoiceReady { + fn default() -> Self { + VoiceReady { + ssrc: 1, + ip: Ipv4Addr::UNSPECIFIED, + port: 0, + modes: Vec::new(), + } + } +} + +impl WebSocketEvent for VoiceReady {} diff --git a/src/types/interfaces/activity.rs b/src/types/interfaces/activity.rs index 1a48dfd..0da4747 100644 --- a/src/types/interfaces/activity.rs +++ b/src/types/interfaces/activity.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::types::{entities::Emoji, Snowflake}; -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] pub struct Activity { name: String, #[serde(rename = "type")] @@ -22,19 +22,19 @@ pub struct Activity { buttons: Option>, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] struct ActivityTimestamps { start: Option, end: Option, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] struct ActivityParty { id: Option, size: Option>, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] struct ActivityAssets { large_image: Option, large_text: Option, @@ -42,7 +42,7 @@ struct ActivityAssets { small_text: Option, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] struct ActivitySecrets { join: Option, spectate: Option, @@ -50,7 +50,7 @@ struct ActivitySecrets { match_string: Option, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] struct ActivityButton { label: String, url: String, diff --git a/src/types/interfaces/status.rs b/src/types/interfaces/status.rs index fadaf68..d5c07b6 100644 --- a/src/types/interfaces/status.rs +++ b/src/types/interfaces/status.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] /// See pub struct ClientStatusObject { pub desktop: Option, diff --git a/src/types/schema/user.rs b/src/types/schema/user.rs index 9946e73..5584cf4 100644 --- a/src/types/schema/user.rs +++ b/src/types/schema/user.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use crate::types::Snowflake; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] #[serde(rename_all = "snake_case")] /// A schema used to modify a user. pub struct UserModifySchema { @@ -29,7 +29,7 @@ pub struct UserModifySchema { /// /// # Reference: /// Read: -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] pub struct PrivateChannelCreateSchema { pub recipients: Option>, pub access_tokens: Option>, From 0dfd6226619aa63fc328077b54ea6df42b29a325 Mon Sep 17 00:00:00 2001 From: kozabrada123 <59031733+kozabrada123@users.noreply.github.com> Date: Wed, 30 Aug 2023 13:26:19 +0000 Subject: [PATCH 04/31] Fix failing build w/o client and move ratelimits (#426) * Fix failing build without client feature * Feature lock Updateable and Composite --- src/api/auth/login.rs | 3 +-- src/api/auth/register.rs | 2 +- src/api/channels/channels.rs | 5 ++-- src/api/channels/messages.rs | 5 ++-- src/api/channels/permissions.rs | 3 +-- src/api/channels/reactions.rs | 3 +-- src/api/guilds/guilds.rs | 3 +-- src/api/guilds/member.rs | 3 +-- src/api/guilds/roles.rs | 5 ++-- src/api/invites/mod.rs | 8 +++--- src/api/mod.rs | 1 - src/api/policies/instance/mod.rs | 2 -- src/api/policies/mod.rs | 2 -- src/api/users/channels.rs | 3 +-- src/api/users/guilds.rs | 5 ++-- src/api/users/relationships.rs | 4 +-- src/api/users/users.rs | 3 +-- src/instance.rs | 3 +-- src/ratelimiter.rs | 3 +-- .../config/types/subconfigs/limits/rates.rs | 8 +++--- src/types/entities/auto_moderation.rs | 7 +++++- src/types/entities/channel.rs | 24 +++++++++++------- src/types/entities/emoji.rs | 16 +++++++++--- src/types/entities/guild.rs | 25 ++++++++++++------- src/types/entities/mod.rs | 10 ++++++++ .../instance => types/entities}/ratelimits.rs | 0 src/types/entities/role.rs | 16 +++++++++--- src/types/entities/user.rs | 13 +++++++--- src/types/entities/user_settings.rs | 6 +++-- src/types/entities/voice_state.rs | 13 +++++++--- src/types/entities/webhook.rs | 13 +++++++--- src/types/events/auto_moderation.rs | 2 ++ src/types/events/channel.rs | 13 +++++++--- src/types/events/guild.rs | 11 +++++--- src/types/events/mod.rs | 25 +++++++++++++------ src/types/events/thread.rs | 2 ++ 36 files changed, 173 insertions(+), 97 deletions(-) rename src/{api/policies/instance => types/entities}/ratelimits.rs (100%) diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index a95c3ca..1564bfb 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -3,12 +3,11 @@ use std::sync::{Arc, RwLock}; use reqwest::Client; use serde_json::to_string; -use crate::api::LimitType; use crate::errors::ChorusResult; use crate::gateway::Gateway; use crate::instance::{ChorusUser, Instance}; use crate::ratelimiter::ChorusRequest; -use crate::types::{GatewayIdentifyPayload, LoginResult, LoginSchema}; +use crate::types::{GatewayIdentifyPayload, LimitType, LoginResult, LoginSchema}; impl Instance { /// Logs into an existing account on the spacebar server. diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index 1a95d3d..d278a50 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -6,10 +6,10 @@ use serde_json::to_string; use crate::gateway::Gateway; use crate::types::GatewayIdentifyPayload; use crate::{ - api::policies::instance::LimitType, errors::ChorusResult, instance::{ChorusUser, Instance, Token}, ratelimiter::ChorusRequest, + types::LimitType, types::RegisterSchema, }; diff --git a/src/api/channels/channels.rs b/src/api/channels/channels.rs index 7250b0e..9560d74 100644 --- a/src/api/channels/channels.rs +++ b/src/api/channels/channels.rs @@ -3,11 +3,12 @@ use serde_json::to_string; use crate::types::{AddChannelRecipientSchema, ModifyChannelPositionsSchema}; use crate::{ - api::LimitType, errors::{ChorusError, ChorusResult}, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{Channel, ChannelModifySchema, GetChannelMessagesSchema, Message, Snowflake}, + types::{ + Channel, ChannelModifySchema, GetChannelMessagesSchema, LimitType, Message, Snowflake, + }, }; impl Channel { diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 960e492..6dfdfbf 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -3,13 +3,12 @@ use http::HeaderMap; use reqwest::{multipart, Client}; use serde_json::{from_value, to_string, Value}; -use crate::api::LimitType; use crate::errors::{ChorusError, ChorusResult}; use crate::instance::ChorusUser; use crate::ratelimiter::ChorusRequest; use crate::types::{ - Channel, CreateGreetMessage, Message, MessageAck, MessageModifySchema, MessageSearchEndpoint, - MessageSearchQuery, MessageSendSchema, Snowflake, + Channel, CreateGreetMessage, LimitType, Message, MessageAck, MessageModifySchema, + MessageSearchEndpoint, MessageSearchQuery, MessageSendSchema, Snowflake, }; impl Message { diff --git a/src/api/channels/permissions.rs b/src/api/channels/permissions.rs index 7fa8edd..5360890 100644 --- a/src/api/channels/permissions.rs +++ b/src/api/channels/permissions.rs @@ -2,11 +2,10 @@ use reqwest::Client; use serde_json::to_string; use crate::{ - api::LimitType, errors::{ChorusError, ChorusResult}, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{self, PermissionOverwrite, Snowflake}, + types::{self, LimitType, PermissionOverwrite, Snowflake}, }; impl types::Channel { diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 81c0366..94d3087 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -1,9 +1,8 @@ use crate::{ - api::LimitType, errors::ChorusResult, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{self, PublicUser, Snowflake}, + types::{self, LimitType, PublicUser, Snowflake}, }; /// Useful metadata for working with [`types::Reaction`], bundled together nicely. diff --git a/src/api/guilds/guilds.rs b/src/api/guilds/guilds.rs index 8d5f0d6..b433c84 100644 --- a/src/api/guilds/guilds.rs +++ b/src/api/guilds/guilds.rs @@ -2,14 +2,13 @@ use reqwest::Client; use serde_json::from_str; use serde_json::to_string; -use crate::api::LimitType; use crate::errors::ChorusError; use crate::errors::ChorusResult; use crate::instance::ChorusUser; use crate::ratelimiter::ChorusRequest; use crate::types::{ Channel, ChannelCreateSchema, Guild, GuildBanCreateSchema, GuildBansQuery, GuildCreateSchema, - GuildMember, GuildMemberSearchSchema, GuildModifySchema, GuildPreview, + GuildMember, GuildMemberSearchSchema, GuildModifySchema, GuildPreview, LimitType, ModifyGuildMemberProfileSchema, ModifyGuildMemberSchema, UserProfileMetadata, }; use crate::types::{GuildBan, Snowflake}; diff --git a/src/api/guilds/member.rs b/src/api/guilds/member.rs index 01294bd..885ddf9 100644 --- a/src/api/guilds/member.rs +++ b/src/api/guilds/member.rs @@ -1,11 +1,10 @@ use reqwest::Client; use crate::{ - api::LimitType, errors::ChorusResult, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{self, GuildMember, Snowflake}, + types::{self, GuildMember, LimitType, Snowflake}, }; impl types::GuildMember { diff --git a/src/api/guilds/roles.rs b/src/api/guilds/roles.rs index 17d6f7b..f131367 100644 --- a/src/api/guilds/roles.rs +++ b/src/api/guilds/roles.rs @@ -2,11 +2,12 @@ use reqwest::Client; use serde_json::to_string; use crate::{ - api::LimitType, errors::{ChorusError, ChorusResult}, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{self, RoleCreateModifySchema, RoleObject, RolePositionUpdateSchema, Snowflake}, + types::{ + self, LimitType, RoleCreateModifySchema, RoleObject, RolePositionUpdateSchema, Snowflake, + }, }; impl types::RoleObject { diff --git a/src/api/invites/mod.rs b/src/api/invites/mod.rs index 658fb22..332570b 100644 --- a/src/api/invites/mod.rs +++ b/src/api/invites/mod.rs @@ -4,7 +4,7 @@ use serde_json::to_string; use crate::errors::ChorusResult; use crate::instance::ChorusUser; use crate::ratelimiter::ChorusRequest; -use crate::types::{CreateChannelInviteSchema, GuildInvite, Invite, Snowflake}; +use crate::types::{CreateChannelInviteSchema, GuildInvite, Invite, LimitType, Snowflake}; impl ChorusUser { /// Accepts an invite to a guild, group DM, or DM. @@ -26,7 +26,7 @@ impl ChorusUser { invite_code )) .header("Authorization", self.token()), - limit_type: super::LimitType::Global, + limit_type: LimitType::Global, }; if session_id.is_some() { request.request = request @@ -53,7 +53,7 @@ impl ChorusUser { .body(to_string(&code).unwrap()) .header("Authorization", self.token()) .header("Content-Type", "application/json"), - limit_type: super::LimitType::Global, + limit_type: LimitType::Global, } .deserialize_response::(self) .await @@ -81,7 +81,7 @@ impl ChorusUser { .header("Authorization", self.token()) .header("Content-Type", "application/json") .body(to_string(&create_channel_invite_schema).unwrap()), - limit_type: super::LimitType::Channel(channel_id), + limit_type: LimitType::Channel(channel_id), } .deserialize_response::(self) .await diff --git a/src/api/mod.rs b/src/api/mod.rs index 7329c50..ab3f9b9 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -3,7 +3,6 @@ pub use channels::messages::*; pub use guilds::*; pub use invites::*; pub use policies::instance::instance::*; -pub use policies::instance::ratelimits::*; pub use users::*; pub mod auth; diff --git a/src/api/policies/instance/mod.rs b/src/api/policies/instance/mod.rs index 0a1f245..b3a9148 100644 --- a/src/api/policies/instance/mod.rs +++ b/src/api/policies/instance/mod.rs @@ -1,5 +1,3 @@ pub use instance::*; -pub use ratelimits::*; pub mod instance; -pub mod ratelimits; diff --git a/src/api/policies/mod.rs b/src/api/policies/mod.rs index d0c29f1..1d5ea99 100644 --- a/src/api/policies/mod.rs +++ b/src/api/policies/mod.rs @@ -1,3 +1 @@ -pub use instance::ratelimits::*; - pub mod instance; diff --git a/src/api/users/channels.rs b/src/api/users/channels.rs index 8d5f063..330b3e3 100644 --- a/src/api/users/channels.rs +++ b/src/api/users/channels.rs @@ -2,11 +2,10 @@ use reqwest::Client; use serde_json::to_string; use crate::{ - api::LimitType, errors::ChorusResult, instance::ChorusUser, ratelimiter::ChorusRequest, - types::{Channel, PrivateChannelCreateSchema}, + types::{Channel, LimitType, PrivateChannelCreateSchema}, }; impl ChorusUser { diff --git a/src/api/users/guilds.rs b/src/api/users/guilds.rs index d2d5b9e..6ffcdfc 100644 --- a/src/api/users/guilds.rs +++ b/src/api/users/guilds.rs @@ -1,11 +1,10 @@ use reqwest::Client; use serde_json::to_string; -use crate::api::LimitType; use crate::errors::ChorusResult; use crate::instance::ChorusUser; use crate::ratelimiter::ChorusRequest; -use crate::types::{GetUserGuildSchema, Guild, Snowflake}; +use crate::types::{GetUserGuildSchema, Guild, LimitType, Snowflake}; impl ChorusUser { /// Leaves a given guild. @@ -26,7 +25,7 @@ impl ChorusUser { .header("Authorization", self.token()) .header("Content-Type", "application/json") .body(to_string(&lurking).unwrap()), - limit_type: crate::api::LimitType::Guild(*guild_id), + limit_type: LimitType::Guild(*guild_id), } .handle_request_as_result(self) .await diff --git a/src/api/users/relationships.rs b/src/api/users/relationships.rs index 8988871..4f9602c 100644 --- a/src/api/users/relationships.rs +++ b/src/api/users/relationships.rs @@ -2,12 +2,12 @@ use reqwest::Client; use serde_json::to_string; use crate::{ - api::LimitType, errors::ChorusResult, instance::ChorusUser, ratelimiter::ChorusRequest, types::{ - self, CreateUserRelationshipSchema, FriendRequestSendSchema, RelationshipType, Snowflake, + self, CreateUserRelationshipSchema, FriendRequestSendSchema, LimitType, RelationshipType, + Snowflake, }, }; diff --git a/src/api/users/users.rs b/src/api/users/users.rs index 25ac6cd..0f31d6f 100644 --- a/src/api/users/users.rs +++ b/src/api/users/users.rs @@ -4,11 +4,10 @@ use reqwest::Client; use serde_json::to_string; use crate::{ - api::LimitType, errors::{ChorusError, ChorusResult}, instance::{ChorusUser, Instance}, ratelimiter::ChorusRequest, - types::{User, UserModifySchema, UserSettings}, + types::{LimitType, User, UserModifySchema, UserSettings}, }; impl ChorusUser { diff --git a/src/instance.rs b/src/instance.rs index 8ced86a..aa5d4d1 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -8,12 +8,11 @@ use std::sync::{Arc, RwLock}; use reqwest::Client; use serde::{Deserialize, Serialize}; -use crate::api::{Limit, LimitType}; use crate::errors::ChorusResult; use crate::gateway::{Gateway, GatewayHandle}; use crate::ratelimiter::ChorusRequest; use crate::types::types::subconfigs::limits::rates::RateLimits; -use crate::types::{GeneralConfiguration, User, UserSettings}; +use crate::types::{GeneralConfiguration, Limit, LimitType, User, UserSettings}; use crate::UrlBundle; #[derive(Debug, Clone)] diff --git a/src/ratelimiter.rs b/src/ratelimiter.rs index 84bd641..d20e28a 100644 --- a/src/ratelimiter.rs +++ b/src/ratelimiter.rs @@ -8,10 +8,9 @@ use serde::Deserialize; use serde_json::from_str; use crate::{ - api::{Limit, LimitType}, errors::{ChorusError, ChorusResult}, instance::ChorusUser, - types::{types::subconfigs::limits::rates::RateLimits, LimitsConfiguration}, + types::{types::subconfigs::limits::rates::RateLimits, Limit, LimitType, LimitsConfiguration}, }; /// Chorus' request struct. This struct is used to send rate-limited requests to the Spacebar server. diff --git a/src/types/config/types/subconfigs/limits/rates.rs b/src/types/config/types/subconfigs/limits/rates.rs index ce1ea60..8fdd183 100644 --- a/src/types/config/types/subconfigs/limits/rates.rs +++ b/src/types/config/types/subconfigs/limits/rates.rs @@ -2,11 +2,9 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; -use crate::{ - api::LimitType, - types::config::types::subconfigs::limits::ratelimits::{ - route::RouteRateLimit, RateLimitOptions, - }, +use crate::types::{ + config::types::subconfigs::limits::ratelimits::{route::RouteRateLimit, RateLimitOptions}, + LimitType, }; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/types/entities/auto_moderation.rs b/src/types/entities/auto_moderation.rs index eaec2b0..a8910b1 100644 --- a/src/types/entities/auto_moderation.rs +++ b/src/types/entities/auto_moderation.rs @@ -1,13 +1,18 @@ use std::sync::{Arc, RwLock}; +#[cfg(feature = "client")] use crate::gateway::Updateable; + +#[cfg(feature = "client")] use chorus_macros::Updateable; + use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::utils::Snowflake; -#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable)] +#[cfg_attr(feature = "client", derive(Updateable))] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] /// See pub struct AutoModerationRule { pub id: Snowflake, diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index 84530c9..280401c 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -1,21 +1,28 @@ use std::sync::{Arc, RwLock}; -use chorus_macros::{observe_option_vec, Composite, Updateable}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_aux::prelude::deserialize_string_from_number; use serde_repr::{Deserialize_repr, Serialize_repr}; use std::fmt::Debug; -use crate::gateway::{GatewayHandle, Updateable}; use crate::types::{ entities::{GuildMember, User}, utils::Snowflake, - Composite, }; -#[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable, Composite)] +#[cfg(feature = "client")] +use crate::types::Composite; + +#[cfg(feature = "client")] +use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] +use chorus_macros::{observe_option_vec, Composite, Updateable}; + +#[derive(Default, Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] /// Represents a guild or private channel /// /// # Reference @@ -60,13 +67,13 @@ pub struct Channel { #[cfg(feature = "sqlx")] pub permission_overwrites: Option>>, #[cfg(not(feature = "sqlx"))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub permission_overwrites: Option>>>, pub permissions: Option, pub position: Option, pub rate_limit_per_user: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub recipients: Option>>>, pub rtc_region: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] @@ -126,9 +133,8 @@ pub struct Tag { pub emoji_name: Option, } -#[derive( - Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Updateable, Composite, -)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] pub struct PermissionOverwrite { pub id: Snowflake, #[serde(rename = "type")] diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs index d80e487..51f78fb 100644 --- a/src/types/entities/emoji.rs +++ b/src/types/entities/emoji.rs @@ -1,14 +1,22 @@ use std::fmt::Debug; use std::sync::{Arc, RwLock}; -use chorus_macros::{Composite, Updateable}; use serde::{Deserialize, Serialize}; -use crate::gateway::{GatewayHandle, Updateable}; use crate::types::entities::User; -use crate::types::{Composite, Snowflake}; +use crate::types::Snowflake; -#[derive(Debug, Clone, Deserialize, Serialize, Default, Updateable, Composite)] +#[cfg(feature = "client")] +use crate::types::Composite; + +#[cfg(feature = "client")] +use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] +use chorus_macros::{Composite, Updateable}; + +#[derive(Debug, Clone, Deserialize, Serialize, Default)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// # Reference /// See diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index 93b13fc..d810aea 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -1,25 +1,32 @@ use std::fmt::Debug; use std::sync::{Arc, RwLock}; -use chorus_macros::{observe_option_vec, observe_vec, Composite, Updateable}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::gateway::{GatewayHandle, Updateable}; use crate::types::types::guild_configuration::GuildFeaturesList; use crate::types::{ entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook}, interfaces::WelcomeScreenObject, utils::Snowflake, - Composite, }; use bitflags::bitflags; use super::PublicUser; +#[cfg(feature = "client")] +use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] +use chorus_macros::{observe_option_vec, observe_vec, Composite, Updateable}; + +#[cfg(feature = "client")] +use crate::types::Composite; + /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Guild { pub afk_channel_id: Option, @@ -34,14 +41,14 @@ pub struct Guild { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub bans: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub channels: Option>>>, pub default_message_notifications: Option, pub description: Option, pub discovery_splash: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] + #[cfg_attr(feature = "client", observe_vec)] #[serde(default)] - #[observe_vec] pub emojis: Vec>>, pub explicit_content_filter: Option, //#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))] @@ -77,7 +84,7 @@ pub struct Guild { pub public_updates_channel_id: Option, pub region: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub roles: Option>>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] pub rules_channel: Option, @@ -91,10 +98,10 @@ pub struct Guild { pub vanity_url_code: Option, pub verification_level: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub voice_states: Option>>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[observe_option_vec] + #[cfg_attr(feature = "client", observe_option_vec)] pub webhooks: Option>>>, #[cfg(feature = "sqlx")] pub welcome_screen: Option>, diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index abdf976..a14ef2c 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -10,6 +10,7 @@ pub use guild_member::*; pub use integration::*; pub use invite::*; pub use message::*; +pub use ratelimits::*; pub use relationship::*; pub use role::*; pub use security_key::*; @@ -22,9 +23,16 @@ pub use user_settings::*; pub use voice_state::*; pub use webhook::*; +#[cfg(feature = "client")] use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] use async_trait::async_trait; + +#[cfg(feature = "client")] use std::fmt::Debug; + +#[cfg(feature = "client")] use std::sync::{Arc, RwLock}; mod application; @@ -39,6 +47,7 @@ mod guild_member; mod integration; mod invite; mod message; +mod ratelimits; mod relationship; mod role; mod security_key; @@ -51,6 +60,7 @@ mod user_settings; mod voice_state; mod webhook; +#[cfg(feature = "client")] #[async_trait(?Send)] pub trait Composite { async fn watch_whole(self, gateway: &GatewayHandle) -> Self; diff --git a/src/api/policies/instance/ratelimits.rs b/src/types/entities/ratelimits.rs similarity index 100% rename from src/api/policies/instance/ratelimits.rs rename to src/types/entities/ratelimits.rs diff --git a/src/types/entities/role.rs b/src/types/entities/role.rs index 22dceff..087a775 100644 --- a/src/types/entities/role.rs +++ b/src/types/entities/role.rs @@ -1,13 +1,21 @@ use bitflags::bitflags; -use chorus_macros::{Composite, Updateable}; use serde::{Deserialize, Serialize}; use serde_aux::prelude::{deserialize_option_number_from_string, deserialize_string_from_number}; use std::fmt::Debug; -use crate::gateway::{GatewayHandle, Updateable}; -use crate::types::{utils::Snowflake, Composite}; +use crate::types::utils::Snowflake; -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Updateable, Composite)] +#[cfg(feature = "client")] +use chorus_macros::{Composite, Updateable}; + +#[cfg(feature = "client")] +use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] +use crate::types::Composite; + +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// See pub struct RoleObject { diff --git a/src/types/entities/user.rs b/src/types/entities/user.rs index 64334ff..81d737a 100644 --- a/src/types/entities/user.rs +++ b/src/types/entities/user.rs @@ -1,11 +1,17 @@ -use chorus_macros::{Composite, Updateable}; +use crate::types::utils::Snowflake; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_aux::prelude::deserialize_option_number_from_string; use std::fmt::Debug; +#[cfg(feature = "client")] use crate::gateway::{GatewayHandle, Updateable}; -use crate::types::{utils::Snowflake, Composite}; + +#[cfg(feature = "client")] +use crate::types::Composite; + +#[cfg(feature = "client")] +use chorus_macros::{Composite, Updateable}; use super::Emoji; @@ -21,7 +27,8 @@ impl User { PublicUser::from(self) } } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Updateable, Composite)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct User { pub id: Snowflake, diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index 1be2c0a..e6db7e7 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -53,15 +53,17 @@ pub struct UserSettings { pub friend_source_flags: sqlx::types::Json, #[cfg(not(feature = "sqlx"))] pub friend_source_flags: FriendSourceFlags, - pub gateway_connected: bool, + pub gateway_connected: Option, pub gif_auto_play: bool, #[cfg(feature = "sqlx")] pub guild_folders: sqlx::types::Json>, #[cfg(not(feature = "sqlx"))] pub guild_folders: Vec, #[cfg(feature = "sqlx")] + #[serde(default)] pub guild_positions: sqlx::types::Json>, #[cfg(not(feature = "sqlx"))] + #[serde(default)] pub guild_positions: Vec, pub inline_attachment_media: bool, pub inline_embed_media: bool, @@ -98,7 +100,7 @@ impl Default for UserSettings { enable_tts_command: false, explicit_content_filter: 0, friend_source_flags: Default::default(), - gateway_connected: false, + gateway_connected: Some(false), gif_auto_play: false, guild_folders: Default::default(), guild_positions: Default::default(), diff --git a/src/types/entities/voice_state.rs b/src/types/entities/voice_state.rs index c879c8e..e764296 100644 --- a/src/types/entities/voice_state.rs +++ b/src/types/entities/voice_state.rs @@ -1,20 +1,27 @@ use std::sync::{Arc, RwLock}; +#[cfg(feature = "client")] use chorus_macros::{Composite, Updateable}; + +#[cfg(feature = "client")] +use crate::types::Composite; + +#[cfg(feature = "client")] +use crate::gateway::{GatewayHandle, Updateable}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; -use crate::gateway::{GatewayHandle, Updateable}; use crate::types::{ entities::{Guild, GuildMember}, utils::Snowflake, - Composite, }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] pub struct VoiceState { pub guild_id: Option, pub guild: Option, diff --git a/src/types/entities/webhook.rs b/src/types/entities/webhook.rs index 7771dbf..b544ec9 100644 --- a/src/types/entities/webhook.rs +++ b/src/types/entities/webhook.rs @@ -1,18 +1,25 @@ use std::fmt::Debug; use std::sync::{Arc, RwLock}; -use chorus_macros::{Composite, Updateable}; use serde::{Deserialize, Serialize}; +#[cfg(feature = "client")] use crate::gateway::{GatewayHandle, Updateable}; + +#[cfg(feature = "client")] +use chorus_macros::{Composite, Updateable}; + +#[cfg(feature = "client")] +use crate::types::Composite; + use crate::types::{ entities::{Guild, User}, utils::Snowflake, - Composite, }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable, Composite)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Webhook { pub id: Snowflake, diff --git a/src/types/events/auto_moderation.rs b/src/types/events/auto_moderation.rs index 376e523..2764ebf 100644 --- a/src/types/events/auto_moderation.rs +++ b/src/types/events/auto_moderation.rs @@ -7,6 +7,7 @@ use crate::types::{ WebSocketEvent, }; +#[cfg(feature = "client")] use super::UpdateMessage; #[derive(Debug, Deserialize, Serialize, Default, Clone)] @@ -27,6 +28,7 @@ pub struct AutoModerationRuleUpdate { pub json: String, } +#[cfg(feature = "client")] impl UpdateMessage for AutoModerationRuleUpdate { fn id(&self) -> Option { Some(self.rule.id) diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs index ae84b79..6156c33 100644 --- a/src/types/events/channel.rs +++ b/src/types/events/channel.rs @@ -1,14 +1,18 @@ -use std::sync::{Arc, RwLock}; - use crate::types::events::WebSocketEvent; -use crate::types::Guild; use crate::types::{entities::Channel, JsonField, Snowflake}; use chorus_macros::JsonField; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +#[cfg(feature = "client")] use super::UpdateMessage; +#[cfg(feature = "client")] +use std::sync::{Arc, RwLock}; + +#[cfg(feature = "client")] +use crate::types::Guild; + #[derive(Debug, Default, Deserialize, Serialize)] /// See pub struct ChannelPinsUpdate { @@ -30,6 +34,7 @@ pub struct ChannelCreate { impl WebSocketEvent for ChannelCreate {} +#[cfg(feature = "client")] impl UpdateMessage for ChannelCreate { fn id(&self) -> Option { self.channel.guild_id @@ -57,6 +62,7 @@ pub struct ChannelUpdate { impl WebSocketEvent for ChannelUpdate {} +#[cfg(feature = "client")] impl UpdateMessage for ChannelUpdate { fn update(&mut self, object_to_update: Arc>) { let mut write = object_to_update.write().unwrap(); @@ -96,6 +102,7 @@ pub struct ChannelDelete { pub json: String, } +#[cfg(feature = "client")] impl UpdateMessage for ChannelDelete { fn id(&self) -> Option { self.channel.guild_id diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index 0afa9d6..8225961 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -1,5 +1,3 @@ -use std::sync::{Arc, RwLock}; - use chorus_macros::JsonField; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -11,7 +9,12 @@ use crate::types::{ Sticker, }; -use super::{PresenceUpdate, UpdateMessage}; +use super::PresenceUpdate; + +#[cfg(feature = "client")] +use super::UpdateMessage; +#[cfg(feature = "client")] +use std::sync::{Arc, RwLock}; #[derive(Debug, Deserialize, Serialize, Default, Clone)] /// See ; @@ -179,6 +182,7 @@ pub struct GuildRoleCreate { impl WebSocketEvent for GuildRoleCreate {} +#[cfg(feature = "client")] impl UpdateMessage for GuildRoleCreate { fn id(&self) -> Option { Some(self.guild_id) @@ -209,6 +213,7 @@ pub struct GuildRoleUpdate { impl WebSocketEvent for GuildRoleUpdate {} +#[cfg(feature = "client")] impl UpdateMessage for GuildRoleUpdate { fn id(&self) -> Option { Some(self.role.id) diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs index e440c05..4e213a1 100644 --- a/src/types/events/mod.rs +++ b/src/types/events/mod.rs @@ -1,12 +1,5 @@ -use std::sync::{Arc, RwLock}; - -use std::collections::HashMap; - -use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use serde_json::{from_str, from_value, to_value, Value}; - pub use application::*; pub use auto_moderation::*; pub use call::*; @@ -34,9 +27,23 @@ pub use voice::*; pub use webhooks::*; pub use webrtc::*; +#[cfg(feature = "client")] +use super::Snowflake; + +#[cfg(feature = "client")] use crate::gateway::Updateable; -use super::Snowflake; +#[cfg(feature = "client")] +use serde_json::{from_str, from_value, to_value, Value}; + +#[cfg(feature = "client")] +use std::collections::HashMap; + +#[cfg(feature = "client")] +use std::sync::{Arc, RwLock}; + +#[cfg(feature = "client")] +use serde::de::DeserializeOwned; mod application; mod auto_moderation; @@ -107,6 +114,7 @@ pub struct GatewayReceivePayload<'a> { impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {} +#[cfg(feature = "client")] /// An [`UpdateMessage`] represents a received Gateway Message which contains updated /// information for an [`Updateable`] of Type T. /// # Example: @@ -134,6 +142,7 @@ pub(crate) trait JsonField: Clone { fn get_json(&self) -> String; } +#[cfg(feature = "client")] /// Only applicable for events where the Update struct is the same as the Entity struct pub(crate) fn update_object( value: String, diff --git a/src/types/events/thread.rs b/src/types/events/thread.rs index 19f1cde..5995c19 100644 --- a/src/types/events/thread.rs +++ b/src/types/events/thread.rs @@ -5,6 +5,7 @@ use crate::types::entities::{Channel, ThreadMember}; use crate::types::events::WebSocketEvent; use crate::types::{JsonField, Snowflake}; +#[cfg(feature = "client")] use super::UpdateMessage; #[derive(Debug, Default, Deserialize, Serialize, Clone)] @@ -27,6 +28,7 @@ pub struct ThreadUpdate { impl WebSocketEvent for ThreadUpdate {} +#[cfg(feature = "client")] impl UpdateMessage for ThreadUpdate { fn id(&self) -> Option { Some(self.thread.id) From b949477b245af21f24a36777a6bace2d8146aeb9 Mon Sep 17 00:00:00 2001 From: fowb Date: Wed, 30 Aug 2023 15:29:14 +0200 Subject: [PATCH 05/31] Bump Version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a1e22a..77ed466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.5.0" +version = "0.6.0" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index 312d9e9..747acd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.5.0" +version = "0.6.0" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" From fe8baeb699d2ef721a580bdbf81d15d8644f023d Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Wed, 30 Aug 2023 19:13:46 +0200 Subject: [PATCH 06/31] Make UrlBundle `Hash` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2edecc2..e63c41d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ pub mod types; #[cfg(feature = "client")] pub mod voice; -#[derive(Clone, Default, Debug, PartialEq, Eq)] +#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] /// A URLBundle bundles together the API-, Gateway- and CDN-URLs of a Spacebar instance. /// /// # Notes From c9c222664d696499b554de3d615638a71fdef8d2 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 00:49:42 +0200 Subject: [PATCH 07/31] Bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77ed466..7c7a258 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.6.0" +version = "0.7.0" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index 747acd9..629d985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.6.0" +version = "0.7.0" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" From a46ffc965c763a163693cd4dc7cff33230f98c76 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 00:49:59 +0200 Subject: [PATCH 08/31] Bump dependencies --- Cargo.lock | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c7a258..9502610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" dependencies = [ "memchr", ] @@ -220,9 +220,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" dependencies = [ "android-tzdata", "iana-time-zone", @@ -231,7 +231,7 @@ dependencies = [ "serde", "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets", ] [[package]] @@ -439,9 +439,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", @@ -686,21 +686,20 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ "hashbrown 0.14.0", ] [[package]] name = "headers" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64 0.21.3", "bytes", "headers-core", "http", @@ -1033,9 +1032,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" [[package]] name = "mime" @@ -1199,11 +1198,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.56" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if", "foreign-types", "libc", @@ -1231,9 +1230,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" dependencies = [ "cc", "libc", @@ -1588,9 +1587,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.9" +version = "0.38.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" dependencies = [ "bitflags 2.4.0", "errno", @@ -1734,7 +1733,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros", - "time 0.3.27", + "time 0.3.28", ] [[package]] @@ -1799,7 +1798,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.27", + "time 0.3.28", ] [[package]] @@ -2165,9 +2164,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" dependencies = [ "deranged", "itoa", @@ -2184,9 +2183,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" dependencies = [ "time-core", ] @@ -2447,9 +2446,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", From 9b0567ac9e0bbc04b7632c23ab20457d51636f03 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 00:50:07 +0200 Subject: [PATCH 09/31] Remove borrow --- src/gateway.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gateway.rs b/src/gateway.rs index e9c6053..db26617 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -292,7 +292,7 @@ impl GatewayHandle { /// Sends an update voice state to the server pub async fn send_update_voice_state(&self, to_send: types::UpdateVoiceState) { - let to_send_value = serde_json::to_value(&to_send).unwrap(); + let to_send_value = serde_json::to_value(to_send).unwrap(); trace!("GW: Sending Update Voice State.."); From 42f2f7bfbed373fe4b2bc67edd1f1c514a647942 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 00:50:19 +0200 Subject: [PATCH 10/31] Add Default to LoginSchema --- src/types/schema/auth.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/schema/auth.rs b/src/types/schema/auth.rs index 60e23a4..2159de9 100644 --- a/src/types/schema/auth.rs +++ b/src/types/schema/auth.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub struct RegisterSchema { pub username: String, @@ -15,7 +15,7 @@ pub struct RegisterSchema { pub promotional_email_opt_in: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub struct LoginSchema { /// For Discord, usernames must be between 2 and 32 characters, From 6e136fba832acb0520be5c72a5b49370be89b115 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 01:17:23 +0200 Subject: [PATCH 11/31] Make ChorusError Clone --- src/api/policies/instance/instance.rs | 2 +- src/errors.rs | 4 ++-- src/ratelimiter.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/policies/instance/instance.rs b/src/api/policies/instance/instance.rs index aa529ad..4de5fd8 100644 --- a/src/api/policies/instance/instance.rs +++ b/src/api/policies/instance/instance.rs @@ -19,7 +19,7 @@ impl Instance { Err(e) => { return Err(ChorusError::RequestFailed { url: endpoint_url, - error: e, + error: e.to_string(), }); } }; diff --git a/src/errors.rs b/src/errors.rs index 642a3ba..11a7632 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,6 +1,5 @@ //! Contains all the errors that can be returned by the library. use custom_error::custom_error; -use reqwest::Error; use crate::types::WebSocketEvent; @@ -13,11 +12,12 @@ custom_error! { pub type ChorusResult = std::result::Result; custom_error! { + #[derive(Clone)] pub ChorusError /// Server did not respond. NoResponse = "Did not receive a response from the Server.", /// Reqwest returned an Error instead of a Response object. - RequestFailed{url:String, error: Error} = "An error occured while trying to GET from {url}: {error}", + RequestFailed{url:String, error: String} = "An error occured while trying to GET from {url}: {error}", /// Response received, however, it was not of the successful responses type. Used when no other, special case applies. ReceivedErrorCode{error_code: u16, error: String} = "Received the following error code while requesting from the route: {error_code}", /// Used when there is likely something wrong with the instance, the request was directed to. diff --git a/src/ratelimiter.rs b/src/ratelimiter.rs index d20e28a..88d4a02 100644 --- a/src/ratelimiter.rs +++ b/src/ratelimiter.rs @@ -91,7 +91,7 @@ impl ChorusRequest { log::warn!("Request failed: {:?}", error); return Err(ChorusError::RequestFailed { url: error.url().unwrap().to_string(), - error, + error: error.to_string(), }); } }; @@ -359,7 +359,7 @@ impl ChorusRequest { Err(e) => { return Err(ChorusError::RequestFailed { url: url_api.to_string(), - error: e, + error: e.to_string(), }) } }; From a8bcb5849328699e8576262e3f9083f8e5a36677 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 12:12:07 +0200 Subject: [PATCH 12/31] Make auth functions take owned values, similar to the rest of the API --- src/api/auth/login.rs | 4 ++-- src/api/auth/register.rs | 4 ++-- tests/auth.rs | 2 +- tests/common/mod.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index 1564bfb..78826b7 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -14,12 +14,12 @@ impl Instance { /// /// # Reference /// See - pub async fn login_account(&mut self, login_schema: &LoginSchema) -> ChorusResult { + pub async fn login_account(&mut self, login_schema: LoginSchema) -> ChorusResult { let endpoint_url = self.urls.api.clone() + "/auth/login"; let chorus_request = ChorusRequest { request: Client::new() .post(endpoint_url) - .body(to_string(login_schema).unwrap()) + .body(to_string(&login_schema).unwrap()) .header("Content-Type", "application/json"), limit_type: LimitType::AuthLogin, }; diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index d278a50..2f1bb28 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -20,13 +20,13 @@ impl Instance { /// See pub async fn register_account( &mut self, - register_schema: &RegisterSchema, + register_schema: RegisterSchema, ) -> ChorusResult { let endpoint_url = self.urls.api.clone() + "/auth/register"; let chorus_request = ChorusRequest { request: Client::new() .post(endpoint_url) - .body(to_string(register_schema).unwrap()) + .body(to_string(®ister_schema).unwrap()) .header("Content-Type", "application/json"), limit_type: LimitType::AuthRegister, }; diff --git a/tests/auth.rs b/tests/auth.rs index c26552f..f94f024 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -11,6 +11,6 @@ async fn test_registration() { consent: true, ..Default::default() }; - bundle.instance.register_account(®).await.unwrap(); + bundle.instance.register_account(reg).await.unwrap(); common::teardown(bundle).await; } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index a7b9d5d..e17c354 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -31,7 +31,7 @@ impl TestBundle { ..Default::default() }; self.instance - .register_account(®ister_schema) + .register_account(register_schema) .await .unwrap() } @@ -91,7 +91,7 @@ pub(crate) async fn setup() -> TestBundle { default_thread_rate_limit_per_user: Some(0), video_quality_mode: None, }; - let mut user = instance.register_account(®).await.unwrap(); + let mut user = instance.register_account(reg).await.unwrap(); let guild = Guild::create(&mut user, guild_create_schema).await.unwrap(); let channel = Channel::create(&mut user, guild.id, None, channel_create_schema) .await From e17fcd9e0fb50ad9746a6ec1412903c3cfbf0731 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 13:01:50 +0200 Subject: [PATCH 13/31] Make login only take owned values --- src/api/auth/login.rs | 2 +- src/api/auth/register.rs | 4 ++-- tests/common/mod.rs | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index 78826b7..272ee04 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -14,7 +14,7 @@ impl Instance { /// /// # Reference /// See - pub async fn login_account(&mut self, login_schema: LoginSchema) -> ChorusResult { + pub async fn login_account(mut self, login_schema: LoginSchema) -> ChorusResult { let endpoint_url = self.urls.api.clone() + "/auth/login"; let chorus_request = ChorusRequest { request: Client::new() diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index 2f1bb28..d10915e 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -19,7 +19,7 @@ impl Instance { /// # Reference /// See pub async fn register_account( - &mut self, + mut self, register_schema: RegisterSchema, ) -> ChorusResult { let endpoint_url = self.urls.api.clone() + "/auth/register"; @@ -43,7 +43,7 @@ impl Instance { self.limits_information.as_mut().unwrap().ratelimits = shell.limits.unwrap(); } let user_object = self.get_user(token.clone(), None).await.unwrap(); - let settings = ChorusUser::get_settings(&token, &self.urls.api.clone(), self).await?; + let settings = ChorusUser::get_settings(&token, &self.urls.api.clone(), &mut self).await?; let mut identify = GatewayIdentifyPayload::common(); let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap(); identify.token = token.clone(); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index e17c354..ce42578 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -31,6 +31,7 @@ impl TestBundle { ..Default::default() }; self.instance + .clone() .register_account(register_schema) .await .unwrap() @@ -54,7 +55,7 @@ pub(crate) async fn setup() -> TestBundle { "ws://localhost:3001".to_string(), "http://localhost:3001".to_string(), ); - let mut instance = Instance::new(urls.clone(), true).await.unwrap(); + let instance = Instance::new(urls.clone(), true).await.unwrap(); // Requires the existance of the below user. let reg = RegisterSchema { username: "integrationtestuser".into(), @@ -91,7 +92,7 @@ pub(crate) async fn setup() -> TestBundle { default_thread_rate_limit_per_user: Some(0), video_quality_mode: None, }; - let mut user = instance.register_account(reg).await.unwrap(); + let mut user = instance.clone().register_account(reg).await.unwrap(); let guild = Guild::create(&mut user, guild_create_schema).await.unwrap(); let channel = Channel::create(&mut user, guild.id, None, channel_create_schema) .await From 635361a4174f9cdc17b7b47f69246ff6b28608a9 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 13:02:11 +0200 Subject: [PATCH 14/31] Bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9502610..73fa34e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.7.0" +version = "0.8.0" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index 629d985..f3d20db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.7.0" +version = "0.8.0" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" From c6fa385e2822b39f04f55ca34aff1f89271607ac Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 15:02:44 +0200 Subject: [PATCH 15/31] Fix auth --- tests/auth.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auth.rs b/tests/auth.rs index f94f024..f89e5e4 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -4,13 +4,13 @@ mod common; #[tokio::test] async fn test_registration() { - let mut bundle = common::setup().await; + let bundle = common::setup().await; let reg = RegisterSchema { username: "Hiiii".into(), date_of_birth: Some("2000-01-01".to_string()), consent: true, ..Default::default() }; - bundle.instance.register_account(reg).await.unwrap(); + bundle.instance.clone().register_account(reg).await.unwrap(); common::teardown(bundle).await; } From 47ba03102cfbd30b4c03bb8ce3c76fbbe3713805 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Fri, 1 Sep 2023 15:02:57 +0200 Subject: [PATCH 16/31] Bugfix time --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73fa34e..6ec87c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.8.0" +version = "0.8.1" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index f3d20db..9055ee9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.8.0" +version = "0.8.1" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" From bc5e64b79d30a5af75392b5522c56ca7e6f834d7 Mon Sep 17 00:00:00 2001 From: kozabrada123 <59031733+kozabrada123@users.noreply.github.com> Date: Fri, 1 Sep 2023 15:17:49 +0000 Subject: [PATCH 17/31] Add option to login with only a token (#427) * Add login with token --- src/api/auth/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/api/auth/mod.rs b/src/api/auth/mod.rs index 663bf5e..3ad4a60 100644 --- a/src/api/auth/mod.rs +++ b/src/api/auth/mod.rs @@ -1,5 +1,41 @@ +use std::sync::{Arc, RwLock}; + pub use login::*; pub use register::*; +use crate::{ + errors::ChorusResult, + gateway::Gateway, + instance::{ChorusUser, Instance}, + types::{GatewayIdentifyPayload, User}, +}; + pub mod login; pub mod register; + +impl Instance { + /// Logs into an existing account on the spacebar server, using only a token. + pub async fn login_with_token(&mut self, token: String) -> ChorusResult { + let object_result = self.get_user(token.clone(), None).await; + if let Err(e) = object_result { + return Result::Err(e); + } + + let user_settings = User::get_settings(&token, &self.urls.api, &mut self.clone()) + .await + .unwrap(); + let mut identify = GatewayIdentifyPayload::common(); + let gateway = Gateway::new(self.urls.wss.clone()).await.unwrap(); + identify.token = token.clone(); + gateway.send_identify(identify).await; + let user = ChorusUser::new( + Arc::new(RwLock::new(self.clone())), + token.clone(), + self.clone_limits_if_some(), + Arc::new(RwLock::new(user_settings)), + Arc::new(RwLock::new(object_result.unwrap())), + gateway, + ); + Ok(user) + } +} From db533f9700bd0c4ce76cee18cae3b2322e64f2b6 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 16:55:19 +0200 Subject: [PATCH 18/31] Make Errors Hash and Eq, bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/errors.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ec87c6..2a78751 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,7 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chorus" -version = "0.8.1" +version = "0.9.0" dependencies = [ "async-trait", "base64 0.21.3", diff --git a/Cargo.toml b/Cargo.toml index 9055ee9..b8de308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "chorus" description = "A library for interacting with multiple Spacebar-compatible Instances at once." -version = "0.8.1" +version = "0.9.0" license = "AGPL-3.0" edition = "2021" repository = "https://github.com/polyphony-chat/chorus" diff --git a/src/errors.rs b/src/errors.rs index 11a7632..4099a6b 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -4,7 +4,7 @@ use custom_error::custom_error; use crate::types::WebSocketEvent; custom_error! { - #[derive(PartialEq, Eq)] + #[derive(PartialEq, Eq, Clone, Hash)] pub RegistrationError Consent = "Consent must be 'true' to register.", } @@ -12,7 +12,7 @@ custom_error! { pub type ChorusResult = std::result::Result; custom_error! { - #[derive(Clone)] + #[derive(Clone, Hash, PartialEq, Eq)] pub ChorusError /// Server did not respond. NoResponse = "Did not receive a response from the Server.", From b7ae75f7ce8611dc62377bfb37470b07066fc1f5 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 16:55:34 +0200 Subject: [PATCH 19/31] Add semicolon --- src/gateway.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gateway.rs b/src/gateway.rs index db26617..1eac899 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -499,7 +499,7 @@ impl Gateway { GATEWAY_DISPATCH => { let Some(event_name) = gateway_payload.event_name else { warn!("Gateway dispatch op without event_name"); - return + return; }; trace!("Gateway: Received {event_name}"); From 1340a11a65ed435d7138aee80c504b10dfaa9c38 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 17:09:44 +0200 Subject: [PATCH 20/31] impl Hash for Guild --- src/types/config/types/guild_configuration.rs | 4 +- src/types/entities/emoji.rs | 13 +++ src/types/entities/guild.rs | 91 +++++++++++++++++-- src/types/entities/sticker.rs | 16 ++++ src/types/entities/user.rs | 4 +- src/types/interfaces/guild_welcome_screen.rs | 4 +- 6 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/types/config/types/guild_configuration.rs b/src/types/config/types/guild_configuration.rs index 96e6ea8..65897ea 100644 --- a/src/types/config/types/guild_configuration.rs +++ b/src/types/config/types/guild_configuration.rs @@ -18,7 +18,7 @@ use crate::types::config::types::subconfigs::guild::{ }; use crate::types::{Error, GuildError}; -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Hash)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum GuildFeatures { ActivitiesAlpha, @@ -139,7 +139,7 @@ pub enum GuildFeatures { InvitesClosed, } -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Eq)] +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Eq, Hash)] pub struct GuildFeaturesList(Vec); impl Deref for GuildFeaturesList { diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs index 51f78fb..4f56af5 100644 --- a/src/types/entities/emoji.rs +++ b/src/types/entities/emoji.rs @@ -35,6 +35,19 @@ pub struct Emoji { pub available: Option, } +impl std::hash::Hash for Emoji { + fn hash(&self, state: &mut H) { + self.id.hash(state); + self.name.hash(state); + self.roles.hash(state); + self.roles.hash(state); + self.require_colons.hash(state); + self.managed.hash(state); + self.animated.hash(state); + self.available.hash(state); + } +} + impl PartialEq for Emoji { fn eq(&self, other: &Self) -> bool { !(self.id != other.id diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index d810aea..3739cd2 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -111,8 +111,60 @@ pub struct Guild { pub widget_enabled: Option, } +impl std::hash::Hash for Guild { + fn hash(&self, state: &mut H) { + self.afk_channel_id.hash(state); + self.afk_timeout.hash(state); + self.application_id.hash(state); + self.approximate_member_count.hash(state); + self.approximate_presence_count.hash(state); + self.banner.hash(state); + self.bans.hash(state); + self.default_message_notifications.hash(state); + self.description.hash(state); + self.discovery_splash.hash(state); + self.explicit_content_filter.hash(state); + self.features.hash(state); + self.icon.hash(state); + self.icon_hash.hash(state); + self.id.hash(state); + self.invites.hash(state); + self.joined_at.hash(state); + self.large.hash(state); + self.max_members.hash(state); + self.max_presences.hash(state); + self.max_stage_video_channel_users.hash(state); + self.max_video_channel_users.hash(state); + self.mfa_level.hash(state); + self.name.hash(state); + self.nsfw_level.hash(state); + self.owner.hash(state); + self.owner_id.hash(state); + self.permissions.hash(state); + self.preferred_locale.hash(state); + self.premium_progress_bar_enabled.hash(state); + self.premium_subscription_count.hash(state); + self.premium_tier.hash(state); + self.primary_category_id.hash(state); + self.public_updates_channel_id.hash(state); + self.region.hash(state); + self.rules_channel.hash(state); + self.rules_channel_id.hash(state); + self.splash.hash(state); + self.stickers.hash(state); + self.system_channel_flags.hash(state); + self.system_channel_id.hash(state); + self.vanity_url_code.hash(state); + self.verification_level.hash(state); + self.welcome_screen.hash(state); + self.welcome_screen.hash(state); + self.widget_channel_id.hash(state); + self.widget_enabled.hash(state); + } +} + /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildBan { pub user: PublicUser, @@ -142,7 +194,26 @@ pub struct GuildInvite { pub vanity_url: Option, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +impl std::hash::Hash for GuildInvite { + fn hash(&self, state: &mut H) { + self.code.hash(state); + self.temporary.hash(state); + self.uses.hash(state); + self.max_uses.hash(state); + self.max_age.hash(state); + self.created_at.hash(state); + self.expires_at.hash(state); + self.guild_id.hash(state); + self.channel_id.hash(state); + self.inviter_id.hash(state); + self.target_user_id.hash(state); + self.target_user.hash(state); + self.target_user_type.hash(state); + self.vanity_url.hash(state); + } +} + +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)] pub struct UnavailableGuild { id: Snowflake, unavailable: bool, @@ -209,7 +280,7 @@ pub struct GuildScheduledEventEntityMetadata { pub location: Option, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq, Hash)] pub struct VoiceRegion { id: String, name: String, @@ -218,7 +289,7 @@ pub struct VoiceRegion { custom: bool, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -228,7 +299,7 @@ pub enum MessageNotificationLevel { OnlyMentions = 1, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -239,7 +310,7 @@ pub enum ExplicitContentFilterLevel { AllMembers = 2, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -252,7 +323,7 @@ pub enum VerificationLevel { VeryHigh = 4, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -262,7 +333,7 @@ pub enum MFALevel { Elevated = 1, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -274,7 +345,7 @@ pub enum NSFWLevel { AgeRestricted = 3, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -287,7 +358,7 @@ pub enum PremiumTier { } bitflags! { - #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] /// # Reference /// See pub struct SystemChannelFlags: u64 { diff --git a/src/types/entities/sticker.rs b/src/types/entities/sticker.rs index c2cdb46..593206d 100644 --- a/src/types/entities/sticker.rs +++ b/src/types/entities/sticker.rs @@ -28,6 +28,22 @@ pub struct Sticker { pub sort_value: Option, } +impl std::hash::Hash for Sticker { + fn hash(&self, state: &mut H) { + self.id.hash(state); + self.pack_id.hash(state); + self.name.hash(state); + self.description.hash(state); + self.tags.hash(state); + self.asset.hash(state); + self.sticker_type.hash(state); + self.format_type.hash(state); + self.available.hash(state); + self.guild_id.hash(state); + self.sort_value.hash(state); + } +} + impl PartialEq for Sticker { fn eq(&self, other: &Self) -> bool { self.id == other.id diff --git a/src/types/entities/user.rs b/src/types/entities/user.rs index 81d737a..eca5344 100644 --- a/src/types/entities/user.rs +++ b/src/types/entities/user.rs @@ -27,7 +27,7 @@ impl User { PublicUser::from(self) } } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct User { @@ -63,7 +63,7 @@ pub struct User { pub disabled: Option, } -#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct PublicUser { pub id: Snowflake, pub username: Option, diff --git a/src/types/interfaces/guild_welcome_screen.rs b/src/types/interfaces/guild_welcome_screen.rs index 4912a78..dbeef0f 100644 --- a/src/types/interfaces/guild_welcome_screen.rs +++ b/src/types/interfaces/guild_welcome_screen.rs @@ -2,14 +2,14 @@ use serde::{Deserialize, Serialize}; use crate::types::utils::Snowflake; -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)] pub struct WelcomeScreenObject { pub enabled: bool, pub description: Option, pub welcome_channels: Vec, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)] pub struct WelcomeScreenChannel { pub channel_id: Snowflake, pub description: String, From e6300b3e306166e3a8a3e844b2d14480691cf87c Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 18:29:33 +0200 Subject: [PATCH 21/31] Impl PartialEq, Eq for Guild --- src/types/entities/guild.rs | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index 3739cd2..bdd4998 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -163,6 +163,59 @@ impl std::hash::Hash for Guild { } } +impl std::cmp::PartialEq for Guild { + fn eq(&self, other: &Self) -> bool { + self.afk_channel_id == other.afk_channel_id + && self.afk_timeout == other.afk_timeout + && self.application_id == other.application_id + && self.approximate_member_count == other.approximate_member_count + && self.approximate_presence_count == other.approximate_presence_count + && self.banner == other.banner + && self.bans == other.bans + && self.default_message_notifications == other.default_message_notifications + && self.description == other.description + && self.discovery_splash == other.discovery_splash + && self.explicit_content_filter == other.explicit_content_filter + && self.features == other.features + && self.icon == other.icon + && self.icon_hash == other.icon_hash + && self.id == other.id + && self.joined_at == other.joined_at + && self.large == other.large + && self.max_members == other.max_members + && self.max_presences == other.max_presences + && self.max_stage_video_channel_users == other.max_stage_video_channel_users + && self.max_video_channel_users == other.max_video_channel_users + && self.mfa_level == other.mfa_level + && self.name == other.name + && self.nsfw_level == other.nsfw_level + && self.owner == other.owner + && self.owner_id == other.owner_id + && self.permissions == other.permissions + && self.preferred_locale == other.preferred_locale + && self.premium_progress_bar_enabled == other.premium_progress_bar_enabled + && self.premium_subscription_count == other.premium_subscription_count + && self.premium_tier == other.premium_tier + && self.primary_category_id == other.primary_category_id + && self.public_updates_channel_id == other.public_updates_channel_id + && self.region == other.region + && self.rules_channel == other.rules_channel + && self.rules_channel_id == other.rules_channel_id + && self.splash == other.splash + && self.stickers == other.stickers + && self.system_channel_flags == other.system_channel_flags + && self.system_channel_id == other.system_channel_id + && self.vanity_url_code == other.vanity_url_code + && self.verification_level == other.verification_level + && self.welcome_screen == other.welcome_screen + && self.welcome_screen == other.welcome_screen + && self.widget_channel_id == other.widget_channel_id + && self.widget_enabled == other.widget_enabled + } +} + +impl std::cmp::Eq for Guild {} + /// See #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] From 78b21e9df3729894c857deac8dcb406b57066968 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 19:59:03 +0200 Subject: [PATCH 22/31] Derive Default for Instance --- src/instance.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instance.rs b/src/instance.rs index aa5d4d1..72bf350 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -15,7 +15,7 @@ use crate::types::types::subconfigs::limits::rates::RateLimits; use crate::types::{GeneralConfiguration, Limit, LimitType, User, UserSettings}; use crate::UrlBundle; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] /// The [`Instance`]; what you will be using to perform all sorts of actions on the Spacebar server. /// If `limits_information` is `None`, then the instance will not be rate limited. pub struct Instance { @@ -25,7 +25,7 @@ pub struct Instance { pub client: Client, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct LimitsInformation { pub ratelimits: HashMap, pub configuration: RateLimits, From c822dc84bbd23b8def302b3f4ac29ee92cdf1957 Mon Sep 17 00:00:00 2001 From: Flori <39242991+bitfl0wer@users.noreply.github.com> Date: Sun, 3 Sep 2023 20:00:23 +0200 Subject: [PATCH 23/31] Update rust-clippy.yml --- .github/workflows/rust-clippy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml index dbbba76..0c3840f 100644 --- a/.github/workflows/rust-clippy.yml +++ b/.github/workflows/rust-clippy.yml @@ -11,7 +11,7 @@ name: rust-clippy analyze on: push: - branches: [ "main", "preserve/*" ] + branches: [ "main", "preserve/*", "dev" ] pull_request: # The branches below must be a subset of the branches above branches: [ "main" ] From 10b623dbf64fe0316abf586c668e9640eb1df510 Mon Sep 17 00:00:00 2001 From: Flori <39242991+bitfl0wer@users.noreply.github.com> Date: Sun, 3 Sep 2023 20:00:45 +0200 Subject: [PATCH 24/31] Update build_and_test.yml --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 398c52f..b192a3c 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -2,7 +2,7 @@ name: Build and Test on: push: - branches: [ "main" ] + branches: [ "main", "dev" ] pull_request: branches: [ "main" ] From 7938f0295e1695f69e9daa0dcf119401567d95c1 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 3 Sep 2023 21:00:48 +0200 Subject: [PATCH 25/31] Add source url field trait --- Cargo.lock | 72 +++++++++++++++-------------- Cargo.toml | 2 +- chorus-macros/Cargo.toml | 2 +- chorus-macros/src/lib.rs | 19 ++++++++ src/gateway.rs | 5 +- src/types/events/auto_moderation.rs | 8 ++-- src/types/events/channel.rs | 16 +++++-- src/types/events/guild.rs | 24 ++++++++-- src/types/events/mod.rs | 7 ++- src/types/events/thread.rs | 8 ++-- 10 files changed, 108 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a78751..df89f42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,7 +67,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -211,11 +211,13 @@ dependencies = [ [[package]] name = "chorus-macros" -version = "0.1.0" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a81545a60b926f815517dadbbd40cd502294ae2baea25fa8194d854d607512b0" dependencies = [ "async-trait", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -345,7 +347,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -356,7 +358,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -581,7 +583,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1032,9 +1034,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "mime" @@ -1183,9 +1185,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -1219,7 +1221,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1310,7 +1312,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1354,9 +1356,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "poem" -version = "1.3.57" +version = "1.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d92c532a37a9e98c0e9a0411e6852b8acccf9ec07d5e6e450b01cbf947d90b" +checksum = "ebc7ae19f3e791ae8108b08801abb3708d64d3a16490c720e0b81040cae87b5d" dependencies = [ "async-trait", "bytes", @@ -1383,14 +1385,14 @@ dependencies = [ [[package]] name = "poem-derive" -version = "1.3.57" +version = "1.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5dd58846a1f582215370384c3090c62c9ef188e9d798ffc67ea90d0a1a8a3b8" +checksum = "2550a0bce7273b278894ef3ccc5a6869e7031b6870042f3cc6826ed9faa980a6" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1468,9 +1470,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", @@ -1480,9 +1482,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -1682,7 +1684,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1704,7 +1706,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1745,7 +1747,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2109,9 +2111,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -2133,22 +2135,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2232,7 +2234,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2337,7 +2339,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2515,7 +2517,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-shared", ] @@ -2549,7 +2551,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index b8de308..42a5130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ thiserror = "1.0.47" jsonwebtoken = "8.3.0" log = "0.4.20" async-trait = "0.1.73" -chorus-macros = { path = "chorus-macros", version = "0.1.0" } +chorus-macros = "0.2.0" [dev-dependencies] tokio = { version = "1.32.0", features = ["full"] } diff --git a/chorus-macros/Cargo.toml b/chorus-macros/Cargo.toml index 098159f..272d99f 100644 --- a/chorus-macros/Cargo.toml +++ b/chorus-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chorus-macros" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "AGPL-3.0" description = "Macros for the chorus crate." diff --git a/chorus-macros/src/lib.rs b/chorus-macros/src/lib.rs index f825568..fd68df0 100644 --- a/chorus-macros/src/lib.rs +++ b/chorus-macros/src/lib.rs @@ -37,6 +37,25 @@ pub fn jsonfield_macro_derive(input: TokenStream) -> TokenStream { .into() } +#[proc_macro_derive(SourceUrlField)] +pub fn source_url_macro_derive(input: TokenStream) -> TokenStream { + let ast: syn::DeriveInput = syn::parse(input).unwrap(); + + let name = &ast.ident; + // No need for macro hygiene, we're only using this in chorus + quote! { + impl SourceUrlField for #name { + fn get_source_url(&self) -> String { + self.source_url.clone() + } + fn set_source_url(&mut self, url: String) { + self.source_url = url; + } + } + } + .into() +} + #[proc_macro_attribute] pub fn observe_option(_args: TokenStream, input: TokenStream) -> TokenStream { input diff --git a/src/gateway.rs b/src/gateway.rs index 1eac899..25072e4 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -5,7 +5,7 @@ use crate::gateway::events::Events; use crate::types::{ self, AutoModerationRule, AutoModerationRuleUpdate, Channel, ChannelCreate, ChannelDelete, ChannelUpdate, Composite, Guild, GuildRoleCreate, GuildRoleUpdate, JsonField, RoleObject, - Snowflake, ThreadUpdate, UpdateMessage, WebSocketEvent, + Snowflake, SourceUrlField, ThreadUpdate, UpdateMessage, WebSocketEvent, }; use async_trait::async_trait; use std::any::Any; @@ -343,6 +343,7 @@ pub struct Gateway { websocket_receive: SplitStream>>, kill_send: tokio::sync::broadcast::Sender<()>, store: Arc>>>>, + url: String, } impl Gateway { @@ -406,6 +407,7 @@ impl Gateway { websocket_receive, kill_send: kill_send.clone(), store: store.clone(), + url: websocket_url.clone(), }; // Now we can continuously check for messages in a different task, since we aren't going to receive another hello @@ -534,6 +536,7 @@ impl Gateway { let downcasted = unsafe { Arc::from_raw(ptr as *const RwLock<$update_type>).clone() }; drop(inner_object); message.set_json(json.to_string()); + message.set_source_url(self.url.clone()); message.update(downcasted.clone()); } else { warn!("Received {} for {}, but it has been observed to be a different type!", $name, id) diff --git a/src/types/events/auto_moderation.rs b/src/types/events/auto_moderation.rs index 2764ebf..2a2eb6b 100644 --- a/src/types/events/auto_moderation.rs +++ b/src/types/events/auto_moderation.rs @@ -1,5 +1,5 @@ -use crate::types::JsonField; -use chorus_macros::JsonField; +use crate::types::{JsonField, SourceUrlField}; +use chorus_macros::{JsonField, SourceUrlField}; use serde::{Deserialize, Serialize}; use crate::types::{ @@ -19,13 +19,15 @@ pub struct AutoModerationRuleCreate { impl WebSocketEvent for AutoModerationRuleCreate {} -#[derive(Debug, Deserialize, Serialize, Default, Clone, JsonField)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, JsonField, SourceUrlField)] /// See pub struct AutoModerationRuleUpdate { #[serde(flatten)] pub rule: AutoModerationRule, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } #[cfg(feature = "client")] diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs index 6156c33..001be0e 100644 --- a/src/types/events/channel.rs +++ b/src/types/events/channel.rs @@ -1,6 +1,6 @@ use crate::types::events::WebSocketEvent; -use crate::types::{entities::Channel, JsonField, Snowflake}; -use chorus_macros::JsonField; +use crate::types::{entities::Channel, JsonField, Snowflake, SourceUrlField}; +use chorus_macros::{JsonField, SourceUrlField}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -23,13 +23,15 @@ pub struct ChannelPinsUpdate { impl WebSocketEvent for ChannelPinsUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct ChannelCreate { #[serde(flatten)] pub channel: Channel, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } impl WebSocketEvent for ChannelCreate {} @@ -51,13 +53,15 @@ impl UpdateMessage for ChannelCreate { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct ChannelUpdate { #[serde(flatten)] pub channel: Channel, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } impl WebSocketEvent for ChannelUpdate {} @@ -93,13 +97,15 @@ pub struct ChannelUnreadUpdateObject { impl WebSocketEvent for ChannelUnreadUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct ChannelDelete { #[serde(flatten)] pub channel: Channel, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } #[cfg(feature = "client")] diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index 8225961..b0126c6 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -1,4 +1,4 @@ -use chorus_macros::JsonField; +use chorus_macros::{JsonField, SourceUrlField}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -6,7 +6,7 @@ use crate::types::entities::{Guild, PublicUser, UnavailableGuild}; use crate::types::events::WebSocketEvent; use crate::types::{ AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, JsonField, RoleObject, Snowflake, - Sticker, + SourceUrlField, Sticker, }; use super::PresenceUpdate; @@ -60,16 +60,26 @@ pub struct GuildBanRemove { impl WebSocketEvent for GuildBanRemove {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField)] /// See ; /// Received to give info about a guild being updated; pub struct GuildUpdate { #[serde(flatten)] pub guild: Guild, + #[serde(skip)] + pub source_url: String, + #[serde(skip)] + pub json: String, } impl WebSocketEvent for GuildUpdate {} +impl UpdateMessage for GuildUpdate { + fn id(&self) -> Option { + Some(self.guild.id) + } +} + #[derive(Debug, Default, Deserialize, Serialize, Clone)] /// See ; /// Received to tell the client about a guild being deleted; @@ -171,13 +181,15 @@ pub struct GuildMembersChunk { impl WebSocketEvent for GuildMembersChunk {} -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct GuildRoleCreate { pub guild_id: Snowflake, pub role: RoleObject, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } impl WebSocketEvent for GuildRoleCreate {} @@ -202,13 +214,15 @@ impl UpdateMessage for GuildRoleCreate { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct GuildRoleUpdate { pub guild_id: Snowflake, pub role: RoleObject, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } impl WebSocketEvent for GuildRoleUpdate {} diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs index 4e213a1..2bca363 100644 --- a/src/types/events/mod.rs +++ b/src/types/events/mod.rs @@ -127,7 +127,7 @@ impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {} /// This would imply, that the [`WebSocketEvent`] "[`ChannelUpdate`]" contains new/updated information /// about a [`Channel`]. The update method describes how this new information will be turned into /// a [`Channel`] object. -pub(crate) trait UpdateMessage: Clone + JsonField +pub(crate) trait UpdateMessage: Clone + JsonField + SourceUrlField where T: Updateable + Serialize + DeserializeOwned + Clone, { @@ -142,6 +142,11 @@ pub(crate) trait JsonField: Clone { fn get_json(&self) -> String; } +pub trait SourceUrlField: Clone { + fn set_source_url(&mut self, url: String); + fn get_source_url(&self) -> String; +} + #[cfg(feature = "client")] /// Only applicable for events where the Update struct is the same as the Entity struct pub(crate) fn update_object( diff --git a/src/types/events/thread.rs b/src/types/events/thread.rs index 5995c19..cff5f6f 100644 --- a/src/types/events/thread.rs +++ b/src/types/events/thread.rs @@ -1,9 +1,9 @@ -use chorus_macros::JsonField; +use chorus_macros::{JsonField, SourceUrlField}; use serde::{Deserialize, Serialize}; use crate::types::entities::{Channel, ThreadMember}; use crate::types::events::WebSocketEvent; -use crate::types::{JsonField, Snowflake}; +use crate::types::{JsonField, Snowflake, SourceUrlField}; #[cfg(feature = "client")] use super::UpdateMessage; @@ -17,13 +17,15 @@ pub struct ThreadCreate { impl WebSocketEvent for ThreadCreate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField)] /// See pub struct ThreadUpdate { #[serde(flatten)] pub thread: Channel, #[serde(skip)] pub json: String, + #[serde(skip)] + pub source_url: String, } impl WebSocketEvent for ThreadUpdate {} From 242021a50ab59a531750db03ed2af7459c734346 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 5 Sep 2023 13:33:50 +0200 Subject: [PATCH 26/31] Make the fields on this type public --- src/types/entities/guild.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index bdd4998..bb4db0c 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -268,8 +268,8 @@ impl std::hash::Hash for GuildInvite { #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)] pub struct UnavailableGuild { - id: Snowflake, - unavailable: bool, + pub id: Snowflake, + pub unavailable: bool, } #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] From 59ab862b17a3c200feaa0590c5c04e7e6d29ade7 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 5 Sep 2023 13:34:22 +0200 Subject: [PATCH 27/31] Simplify this loop --- src/types/events/channel.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs index 001be0e..eb557d7 100644 --- a/src/types/events/channel.rs +++ b/src/types/events/channel.rs @@ -124,11 +124,7 @@ impl UpdateMessage for ChannelDelete { } for (iteration, item) in (0_u32..).zip(write.channels.as_mut().unwrap().iter()) { if item.read().unwrap().id == self.id().unwrap() { - write - .channels - .as_mut() - .unwrap() - .swap_remove(iteration as usize); + write.channels.as_mut().unwrap().remove(iteration as usize); return; } } From c037c7907bdcca9468ae63924f2832d99f5515f8 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 5 Sep 2023 13:35:01 +0200 Subject: [PATCH 28/31] Implement UpdateMessage for GuildDelete --- src/types/events/guild.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index b0126c6..faf713b 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -80,12 +80,23 @@ impl UpdateMessage for GuildUpdate { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField)] /// See ; /// Received to tell the client about a guild being deleted; pub struct GuildDelete { #[serde(flatten)] pub guild: UnavailableGuild, + #[serde(skip)] + pub source_url: String, + #[serde(skip)] + pub json: String, +} + +impl UpdateMessage for GuildDelete { + fn id(&self) -> Option { + Some(self.guild.id) + } + fn update(&mut self, _: Arc>) {} } impl WebSocketEvent for GuildDelete {} From 3e864602710e6e27d8607fe12dc13e56e0a9abdb Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 5 Sep 2023 14:41:02 +0200 Subject: [PATCH 29/31] Implement UpdateMessage for GuildCreate --- src/types/events/guild.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index faf713b..0c6bb05 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -16,13 +16,28 @@ use super::UpdateMessage; #[cfg(feature = "client")] use std::sync::{Arc, RwLock}; -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, SourceUrlField, JsonField)] /// See ; /// Received to give data about a guild; // This one is particularly painful, it can be a Guild object with an extra field or an unavailable guild object pub struct GuildCreate { #[serde(flatten)] pub d: GuildCreateDataOption, + #[serde(skip)] + pub source_url: String, + #[serde(skip)] + pub json: String, +} + +impl UpdateMessage for GuildCreate { + fn id(&self) -> Option { + match &self.d { + GuildCreateDataOption::UnavailableGuild(unavailable) => Some(unavailable.id), + GuildCreateDataOption::Guild(guild) => Some(guild.id), + } + } + + fn update(&mut self, _: Arc>) {} } #[derive(Debug, Deserialize, Serialize, Clone)] From 33b99534caeaab6894b88825ede8b01eb803a843 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Tue, 5 Sep 2023 22:29:04 +0200 Subject: [PATCH 30/31] Make WebsocketEvent send, Sznc, Debug --- src/types/events/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs index 2bca363..f4e926c 100644 --- a/src/types/events/mod.rs +++ b/src/types/events/mod.rs @@ -39,6 +39,7 @@ use serde_json::{from_str, from_value, to_value, Value}; #[cfg(feature = "client")] use std::collections::HashMap; +use std::fmt::Debug; #[cfg(feature = "client")] use std::sync::{Arc, RwLock}; @@ -73,7 +74,7 @@ mod webhooks; mod webrtc; -pub trait WebSocketEvent {} +pub trait WebSocketEvent: Send + Sync + Debug {} #[derive(Debug, Default, Serialize, Clone)] /// The payload used for sending events to the gateway From c4b0891ec8098b627dfd2d73f0b1149aa4f322dc Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Wed, 6 Sep 2023 01:32:38 +0200 Subject: [PATCH 31/31] Make events module pub --- src/gateway.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gateway.rs b/src/gateway.rs index 25072e4..8689406 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -917,7 +917,7 @@ impl GatewayEvent { } } -mod events { +pub mod events { use super::*; #[derive(Default, Debug)]