diff --git a/.gitignore b/.gitignore index d3170e2..1bb4c89 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Generated by Cargo # will have compiled files and executables -/target/ +/**/target/ # These are backup files generated by rustfmt **/*.rs.bk diff --git a/Cargo.toml b/Cargo.toml index 8dbb172..6c15102 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,19 +10,19 @@ backend = ["poem", "sqlx"] client = [] [dependencies] -tokio = {version = "1.29.1", features = ["macros"]} -serde = {version = "1.0.171", features = ["derive"]} -serde_json = {version= "1.0.103", features = ["raw_value"]} +tokio = { version = "1.29.1", features = ["macros"] } +serde = { version = "1.0.171", features = ["derive", "rc"] } +serde_json = { version = "1.0.103", features = ["raw_value"] } serde-aux = "4.2.0" serde_with = "3.0.0" serde_repr = "0.1.14" -reqwest = {version = "0.11.18", features = ["multipart"]} +reqwest = { version = "0.11.18", features = ["multipart"] } url = "2.4.0" -chrono = {version = "0.4.26", features = ["serde"]} +chrono = { version = "0.4.26", features = ["serde"] } regex = "1.9.1" custom_error = "1.9.2" native-tls = "0.2.11" -tokio-tungstenite = {version = "0.19.0", features = ["native-tls"]} +tokio-tungstenite = { version = "0.19.0", features = ["native-tls"] } futures-util = "0.3.28" http = "0.2.9" openssl = "0.10.55" @@ -31,14 +31,22 @@ hostname = "0.3.1" bitflags = { version = "2.3.3", features = ["serde"] } lazy_static = "1.4.0" poem = { version = "1.3.56", optional = true } -sqlx = { git = "https://github.com/zert3x/sqlx", branch="feature/skip", features = ["mysql", "sqlite", "json", "chrono", "ipnetwork", "runtime-tokio-native-tls", "any"], optional = true } +sqlx = { git = "https://github.com/zert3x/sqlx", branch = "feature/skip", features = [ + "mysql", + "sqlite", + "json", + "chrono", + "ipnetwork", + "runtime-tokio-native-tls", + "any", +], optional = true } thiserror = "1.0.43" jsonwebtoken = "8.3.0" log = "0.4.19" async-trait = "0.1.71" -chorus-macros = {path = "chorus-macros"} +chorus-macros = { path = "chorus-macros" } [dev-dependencies] -tokio = {version = "1.29.1", features = ["full"]} +tokio = { version = "1.29.1", features = ["full"] } lazy_static = "1.4.0" rusty-hook = "0.11.2" diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs index a360170..447e4c0 100644 --- a/src/api/auth/login.rs +++ b/src/api/auth/login.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::sync::{Arc, Mutex}; use reqwest::Client; use serde_json::to_string; @@ -45,7 +46,7 @@ impl Instance { login_result.token, self.clone_limits_if_some(), login_result.settings, - object, + Arc::new(Mutex::new(object)), gateway, ); Ok(user) diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs index f1f279e..ea74f29 100644 --- a/src/api/auth/register.rs +++ b/src/api/auth/register.rs @@ -1,3 +1,4 @@ +use std::sync::{Arc, Mutex}; use std::{cell::RefCell, rc::Rc}; use reqwest::Client; @@ -51,8 +52,8 @@ impl Instance { Rc::new(RefCell::new(self.clone())), token.clone(), self.clone_limits_if_some(), - settings, - user_object, + Arc::new(Mutex::new(settings)), + Arc::new(Mutex::new(user_object)), gateway, ); Ok(user) diff --git a/src/api/users/users.rs b/src/api/users/users.rs index 3d95e54..03af2f9 100644 --- a/src/api/users/users.rs +++ b/src/api/users/users.rs @@ -1,3 +1,4 @@ +use std::sync::{Arc, Mutex}; use std::{cell::RefCell, rc::Rc}; use reqwest::Client; @@ -59,7 +60,7 @@ impl UserMeta { .deserialize_response::(self) .await .unwrap(); - let _ = std::mem::replace(&mut self.object, user_updated.clone()); + self.object = Arc::new(Mutex::new(user_updated.clone())); Ok(user_updated) } diff --git a/src/instance.rs b/src/instance.rs index f034513..5c2e98b 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::rc::Rc; +use std::sync::{Arc, Mutex}; use reqwest::Client; use serde::{Deserialize, Serialize}; @@ -90,8 +91,8 @@ pub struct UserMeta { pub belongs_to: Rc>, pub token: String, pub limits: Option>, - pub settings: UserSettings, - pub object: User, + pub settings: Arc>, + pub object: Arc>, pub gateway: GatewayHandle, } @@ -113,8 +114,8 @@ impl UserMeta { belongs_to: Rc>, token: String, limits: Option>, - settings: UserSettings, - object: User, + settings: Arc>, + object: Arc>, gateway: GatewayHandle, ) -> UserMeta { UserMeta { @@ -133,8 +134,8 @@ impl UserMeta { /// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify /// first. pub(crate) async fn shell(instance: Rc>, token: String) -> UserMeta { - let settings = UserSettings::default(); - let object = User::default(); + let settings = Arc::new(Mutex::new(UserSettings::default())); + let object = Arc::new(Mutex::new(User::default())); let wss_url = instance.borrow().urls.wss.clone(); // Dummy gateway object let gateway = Gateway::new(wss_url).await.unwrap(); diff --git a/src/types/entities/application.rs b/src/types/entities/application.rs index d4805e9..ad48ab4 100644 --- a/src/types/entities/application.rs +++ b/src/types/entities/application.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use bitflags::bitflags; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -6,7 +8,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::utils::Snowflake; use crate::types::{Team, User}; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// # Reference /// See @@ -25,7 +27,7 @@ pub struct Application { pub bot_require_code_grant: bool, pub verify_key: String, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub owner: User, + pub owner: Arc>, pub flags: u64, #[cfg(feature = "sqlx")] pub redirect_uris: Option>>, @@ -47,7 +49,7 @@ pub struct Application { #[cfg(feature = "sqlx")] pub install_params: Option>, #[cfg(not(feature = "sqlx"))] - pub install_params: Option, + pub install_params: Option>>, pub terms_of_service_url: Option, pub privacy_policy_url: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] @@ -103,7 +105,7 @@ pub struct InstallParams { } bitflags! { - #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] /// # Reference /// See pub struct ApplicationFlags: u64 { @@ -132,7 +134,7 @@ bitflags! { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] /// # Reference /// See pub struct ApplicationCommand { @@ -140,10 +142,10 @@ pub struct ApplicationCommand { pub application_id: Snowflake, pub name: String, pub description: String, - pub options: Vec, + pub options: Vec>>, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] /// Reference /// See pub struct ApplicationCommandOption { @@ -152,7 +154,7 @@ pub struct ApplicationCommandOption { pub description: String, pub required: bool, pub choices: Vec, - pub options: Vec, + pub options: Arc>>, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -161,7 +163,7 @@ pub struct ApplicationCommandOptionChoice { pub value: Value, } -#[derive(Debug, Clone, Copy, PartialEq, Serialize_repr, Deserialize_repr)] +#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, PartialEq, Eq, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(i32)] /// # Reference @@ -184,27 +186,27 @@ pub enum ApplicationCommandOptionType { Attachment = 11, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ApplicationCommandInteractionData { pub id: Snowflake, pub name: String, - pub options: Vec, + pub options: Vec>>, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ApplicationCommandInteractionDataOption { pub name: String, pub value: Value, - pub options: Vec, + pub options: Vec>>, } -#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] /// See pub struct GuildApplicationCommandPermissions { pub id: Snowflake, pub application_id: Snowflake, pub guild_id: Snowflake, - pub permissions: Vec, + pub permissions: Vec>>, } #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] @@ -217,7 +219,7 @@ pub struct ApplicationCommandPermission { pub permission: bool, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, PartialEq)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, PartialEq, Eq, Hash)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[repr(u8)] /// See diff --git a/src/types/entities/audit_log.rs b/src/types/entities/audit_log.rs index 8965a05..e0d05e3 100644 --- a/src/types/entities/audit_log.rs +++ b/src/types/entities/audit_log.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::utils::Snowflake; @@ -6,7 +8,7 @@ use crate::types::utils::Snowflake; /// See pub struct AuditLogEntry { pub target_id: Option, - pub changes: Option>, + pub changes: Option>>>, pub user_id: Option, pub id: Snowflake, // to:do implement an enum for these types diff --git a/src/types/entities/auto_moderation.rs b/src/types/entities/auto_moderation.rs index 0feadde..afb1ec6 100644 --- a/src/types/entities/auto_moderation.rs +++ b/src/types/entities/auto_moderation.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -12,8 +14,8 @@ pub struct AutoModerationRule { pub creator_id: Snowflake, pub event_type: AutoModerationRuleEventType, pub trigger_type: AutoModerationRuleTriggerType, - pub trigger_metadata: AutoModerationRuleTriggerMetadata, - pub actions: Vec, + pub trigger_metadata: Arc>, + pub actions: Vec>>, pub enabled: bool, pub exempt_roles: Vec, pub exempt_channels: Vec, @@ -90,7 +92,7 @@ pub enum AutoModerationRuleKeywordPresetType { pub struct AutoModerationAction { #[serde(rename = "type")] pub action_type: AutoModerationActionType, - pub metadata: Option, + pub metadata: Option>>, } #[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index 60304f9..61754f0 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chorus_macros::Updateable; use chrono::Utc; use serde::{Deserialize, Serialize}; @@ -10,7 +12,7 @@ use crate::types::{ utils::Snowflake, }; -#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Updateable)] +#[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a guild of private channel /// @@ -46,7 +48,7 @@ pub struct Channel { pub last_pin_timestamp: Option, pub managed: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub member: Option, + pub member: Option>>, pub member_count: Option, pub message_count: Option, pub name: Option, @@ -56,12 +58,12 @@ pub struct Channel { #[cfg(feature = "sqlx")] pub permission_overwrites: Option>>, #[cfg(not(feature = "sqlx"))] - pub permission_overwrites: Option>, + pub permission_overwrites: Option>>>, pub permissions: Option, pub position: Option, pub rate_limit_per_user: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub recipients: Option>, + pub recipients: Option>>>, pub rtc_region: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] pub thread_metadata: Option, @@ -71,7 +73,41 @@ pub struct Channel { pub video_quality_mode: Option, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +impl PartialEq for Channel { + fn eq(&self, other: &Self) -> bool { + self.application_id == other.application_id + && self.bitrate == other.bitrate + && self.channel_type == other.channel_type + && self.created_at == other.created_at + && self.default_auto_archive_duration == other.default_auto_archive_duration + && self.default_forum_layout == other.default_forum_layout + && self.default_sort_order == other.default_sort_order + && self.default_thread_rate_limit_per_user == other.default_thread_rate_limit_per_user + && self.flags == other.flags + && self.guild_id == other.guild_id + && self.icon == other.icon + && self.id == other.id + && self.last_message_id == other.last_message_id + && self.last_pin_timestamp == other.last_pin_timestamp + && self.managed == other.managed + && self.member_count == other.member_count + && self.message_count == other.message_count + && self.name == other.name + && self.nsfw == other.nsfw + && self.owner_id == other.owner_id + && self.parent_id == other.parent_id + && self.permissions == other.permissions + && self.position == other.position + && self.rate_limit_per_user == other.rate_limit_per_user + && self.rtc_region == other.rtc_region + && self.topic == other.topic + && self.total_message_sent == other.total_message_sent + && self.user_limit == other.user_limit + && self.video_quality_mode == other.video_quality_mode + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] /// A tag that can be applied to a thread in a [ChannelType::GuildForum] or [ChannelType::GuildMedia] channel. /// /// # Reference @@ -112,7 +148,7 @@ pub struct ThreadMetadata { pub create_timestamp: Option, } -#[derive(Default, Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[derive(Default, Debug, Deserialize, Serialize, Clone)] /// # Reference /// See pub struct ThreadMember { @@ -120,7 +156,7 @@ pub struct ThreadMember { pub user_id: Option, pub join_timestamp: Option, pub flags: Option, - pub member: Option, + pub member: Option>>, } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] @@ -134,7 +170,7 @@ pub struct DefaultReaction { pub emoji_name: Option, } -#[derive(Default, Clone, Copy, Debug, Serialize_repr, Deserialize_repr, PartialEq, Eq)] +#[derive(Default, Clone, Copy, Debug, Serialize_repr, Deserialize_repr, PartialEq, Eq, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[repr(i32)] diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs index 2a38066..38d7da7 100644 --- a/src/types/entities/emoji.rs +++ b/src/types/entities/emoji.rs @@ -1,9 +1,11 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::entities::User; use crate::types::Snowflake; -#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// # Reference /// See @@ -15,7 +17,7 @@ pub struct Emoji { #[cfg(not(feature = "sqlx"))] pub roles: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub user: Option, + pub user: Option>>, pub require_colons: Option, pub managed: Option, pub animated: Option, diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index f9bddd2..651884f 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -10,7 +12,7 @@ use crate::types::{ }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Guild { pub afk_channel_id: Option, @@ -25,13 +27,13 @@ pub struct Guild { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub bans: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub channels: Option>, + pub channels: Option>>>, pub default_message_notifications: Option, pub description: Option, pub discovery_splash: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] #[serde(default)] - pub emojis: Vec, + pub emojis: Vec>>, pub explicit_content_filter: Option, //#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))] pub features: Option, @@ -40,7 +42,7 @@ pub struct Guild { pub icon_hash: Option, pub id: Snowflake, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub invites: Option>, + pub invites: Option>>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] pub joined_at: Option, pub large: Option, @@ -66,7 +68,7 @@ pub struct Guild { pub public_updates_channel_id: Option, pub region: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub roles: Option>, + pub roles: Option>>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] pub rules_channel: Option, pub rules_channel_id: Option, @@ -79,13 +81,13 @@ pub struct Guild { pub vanity_url_code: Option, pub verification_level: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub voice_states: Option>, + pub voice_states: Option>>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub webhooks: Option>, + pub webhooks: Option>>>, #[cfg(feature = "sqlx")] pub welcome_screen: Option>, #[cfg(not(feature = "sqlx"))] - pub welcome_screen: Option, + pub welcome_screen: Option>>, pub widget_channel_id: Option, pub widget_enabled: Option, } @@ -100,7 +102,7 @@ pub struct GuildBan { } /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildInvite { pub code: String, @@ -111,11 +113,11 @@ pub struct GuildInvite { pub created_at: DateTime, pub expires_at: Option>, pub guild_id: Snowflake, - pub guild: Option, + pub guild: Option>>, pub channel_id: Snowflake, - pub channel: Option, + pub channel: Option>>, pub inviter_id: Option, - pub inviter: Option, + pub inviter: Option>>, pub target_user_id: Option, pub target_user: Option, pub target_user_type: Option, @@ -149,7 +151,7 @@ pub struct GuildScheduledEvent { pub entity_type: GuildScheduledEventEntityType, pub entity_id: Option, pub entity_metadata: Option, - pub creator: Option, + pub creator: Option>>, pub user_count: Option, pub image: Option, } diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index b613800..af63cfb 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -1,14 +1,16 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::{entities::PublicUser, Snowflake}; -#[derive(Debug, Deserialize, Default, Serialize, Clone, PartialEq, Eq)] +#[derive(Debug, Deserialize, Default, Serialize, Clone)] /// Represents a participating user in a guild. /// /// # Reference /// See pub struct GuildMember { - pub user: Option, + pub user: Option>>, pub nick: Option, pub avatar: Option, pub roles: Vec, diff --git a/src/types/entities/integration.rs b/src/types/entities/integration.rs index f083dae..a95c33c 100644 --- a/src/types/entities/integration.rs +++ b/src/types/entities/integration.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -21,14 +23,14 @@ pub struct Integration { pub expire_behaviour: Option, pub expire_grace_period: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub user: Option, + pub user: Option>>, #[cfg_attr(feature = "sqlx", sqlx(skip))] pub account: IntegrationAccount, pub synced_at: Option>, pub subscriber_count: Option, pub revoked: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub application: Option, + pub application: Option>>, pub scopes: Option>, } diff --git a/src/types/entities/invite.rs b/src/types/entities/invite.rs index 6d7b570..7eefd98 100644 --- a/src/types/entities/invite.rs +++ b/src/types/entities/invite.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -68,7 +70,7 @@ pub enum NSFWLevel { /// See #[derive(Debug, Serialize, Deserialize)] pub struct InviteStageInstance { - pub members: Vec, + pub members: Vec>>, pub participant_count: i32, pub speaker_count: i32, pub topic: String, diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index 6e14a59..f104f97 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -8,7 +8,7 @@ use crate::types::{ utils::Snowflake, }; -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a message sent in a channel. /// @@ -77,7 +77,7 @@ pub struct MessageReference { pub fail_if_not_exists: Option, } -#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct MessageInteraction { pub id: Snowflake, #[serde(rename = "type")] @@ -112,7 +112,7 @@ pub struct ChannelMention { name: String, } -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Embed { title: Option, #[serde(rename = "type")] @@ -182,7 +182,7 @@ pub struct EmbedField { inline: Option, } -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Reaction { pub count: u32, pub burst_count: u32, diff --git a/src/types/entities/relationship.rs b/src/types/entities/relationship.rs index 168f362..a5f5bcb 100644 --- a/src/types/entities/relationship.rs +++ b/src/types/entities/relationship.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -6,17 +8,26 @@ use crate::types::Snowflake; use super::PublicUser; -#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, Default)] /// See pub struct Relationship { pub id: Snowflake, #[serde(rename = "type")] pub relationship_type: RelationshipType, pub nickname: Option, - pub user: PublicUser, + pub user: Arc>, pub since: Option>, } +impl PartialEq for Relationship { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.relationship_type == other.relationship_type + && self.since == other.since + && self.nickname == other.nickname + } +} + #[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default, Eq, PartialEq)] #[repr(u8)] /// See diff --git a/src/types/entities/role.rs b/src/types/entities/role.rs index 0748453..3ad53ce 100644 --- a/src/types/entities/role.rs +++ b/src/types/entities/role.rs @@ -34,7 +34,7 @@ pub struct RoleSubscriptionData { pub is_renewal: bool, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)] /// See pub struct RoleTags { #[serde(default)] @@ -53,7 +53,7 @@ pub struct RoleTags { } bitflags! { - #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] + #[derive(Debug, Default, Clone, Hash, Serialize, Deserialize, PartialEq, Eq)] /// Permissions limit what users of certain roles can do on a Guild to Guild basis. /// /// # Reference: diff --git a/src/types/entities/sticker.rs b/src/types/entities/sticker.rs index 6263f48..42edb7f 100644 --- a/src/types/entities/sticker.rs +++ b/src/types/entities/sticker.rs @@ -1,8 +1,10 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::{entities::User, utils::Snowflake}; -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a sticker that can be sent in messages. /// @@ -22,7 +24,7 @@ pub struct Sticker { pub available: Option, pub guild_id: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub user: Option, + pub user: Option>>, pub sort_value: Option, } diff --git a/src/types/entities/team.rs b/src/types/entities/team.rs index a6f2ef1..fe6562b 100644 --- a/src/types/entities/team.rs +++ b/src/types/entities/team.rs @@ -1,9 +1,11 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::entities::User; use crate::types::Snowflake; -#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Team { pub icon: Option, @@ -14,10 +16,10 @@ pub struct Team { pub owner_user_id: Snowflake, } -#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct TeamMember { pub membership_state: u8, pub permissions: Vec, pub team_id: Snowflake, - pub user: User, + pub user: Arc>, } diff --git a/src/types/entities/template.rs b/src/types/entities/template.rs index 2f934c9..0550e9e 100644 --- a/src/types/entities/template.rs +++ b/src/types/entities/template.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -7,7 +9,7 @@ use crate::types::{ }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildTemplate { pub code: String, @@ -16,13 +18,13 @@ pub struct GuildTemplate { pub usage_count: Option, pub creator_id: Snowflake, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub creator: User, + pub creator: Arc>, pub created_at: DateTime, pub updated_at: DateTime, pub source_guild_id: Snowflake, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub source_guild: Vec, + pub source_guild: Vec>>, // Unsure how a {recursive: Guild} looks like, might be a Vec? #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub serialized_source_guild: Vec, + pub serialized_source_guild: Vec>>, } diff --git a/src/types/entities/user.rs b/src/types/entities/user.rs index 469c45e..5b31b6d 100644 --- a/src/types/entities/user.rs +++ b/src/types/entities/user.rs @@ -91,7 +91,7 @@ impl From for PublicUser { const CUSTOM_USER_FLAG_OFFSET: u64 = 1 << 32; bitflags::bitflags! { - #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] + #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] pub struct UserFlags: u64 { const DISCORD_EMPLOYEE = 1 << 0; diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index 40b936a..4705a92 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{serde::ts_milliseconds_option, Utc}; use serde::{Deserialize, Serialize}; @@ -28,7 +30,7 @@ pub enum UserTheme { Light, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct UserSettings { pub afk_timeout: u16, @@ -73,7 +75,7 @@ pub struct UserSettings { #[cfg(not(feature = "sqlx"))] pub restricted_guilds: Vec, pub show_current_game: bool, - pub status: UserStatus, + pub status: Arc>, pub stream_notifications_enabled: bool, pub theme: UserTheme, pub timezone_offset: i16, @@ -109,7 +111,7 @@ impl Default for UserSettings { render_reactions: true, restricted_guilds: Default::default(), show_current_game: true, - status: UserStatus::Online, + status: Arc::new(Mutex::new(UserStatus::Online)), stream_notifications_enabled: false, theme: UserTheme::Dark, timezone_offset: 0, @@ -138,7 +140,7 @@ impl Default for FriendSourceFlags { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GuildFolder { pub color: u32, pub guild_ids: Vec, @@ -149,5 +151,5 @@ pub struct GuildFolder { #[derive(Debug, Serialize, Deserialize)] pub struct LoginResult { pub token: String, - pub settings: UserSettings, + pub settings: Arc>, } diff --git a/src/types/entities/voice_state.rs b/src/types/entities/voice_state.rs index 94d3d79..29b8e6e 100644 --- a/src/types/entities/voice_state.rs +++ b/src/types/entities/voice_state.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -7,14 +9,14 @@ use crate::types::{ }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct VoiceState { pub guild_id: Option, pub guild: Option, pub channel_id: Option, pub user_id: Snowflake, - pub member: Option, + pub member: Option>>, pub session_id: Snowflake, pub token: Option, pub deaf: bool, diff --git a/src/types/entities/webhook.rs b/src/types/entities/webhook.rs index f953149..f8b6530 100644 --- a/src/types/entities/webhook.rs +++ b/src/types/entities/webhook.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use serde::{Deserialize, Serialize}; use crate::types::{ @@ -6,7 +8,7 @@ use crate::types::{ }; /// See -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Webhook { pub id: Snowflake, @@ -20,10 +22,10 @@ pub struct Webhook { pub application_id: Snowflake, #[serde(skip_serializing_if = "Option::is_none")] #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub user: Option, + pub user: Option>>, #[serde(skip_serializing_if = "Option::is_none")] #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub source_guild: Option, + pub source_guild: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, } diff --git a/tests/channels.rs b/tests/channels.rs index c8564d7..d810c10 100644 --- a/tests/channels.rs +++ b/tests/channels.rs @@ -59,8 +59,9 @@ async fn modify_channel() { PermissionFlags::MANAGE_CHANNELS, PermissionFlags::MANAGE_MESSAGES, ])); + let user_id: types::Snowflake = bundle.user.object.lock().unwrap().id; let permission_override = PermissionOverwrite { - id: bundle.user.object.id, + id: user_id, overwrite_type: "1".to_string(), allow: permission_override, deny: "0".to_string(), @@ -143,7 +144,7 @@ async fn create_dm() { let other_user = bundle.create_user("integrationtestuser2").await; let user = &mut bundle.user; let private_channel_create_schema = PrivateChannelCreateSchema { - recipients: Some(Vec::from([other_user.object.id])), + recipients: Some(Vec::from([other_user.object.lock().unwrap().id])), access_tokens: None, nicks: None, }; @@ -153,26 +154,47 @@ async fn create_dm() { .unwrap(); assert!(dm_channel.recipients.is_some()); assert_eq!( - dm_channel.recipients.as_ref().unwrap().get(0).unwrap().id, - other_user.object.id + dm_channel + .recipients + .as_ref() + .unwrap() + .get(0) + .unwrap() + .lock() + .unwrap() + .id + .clone(), + other_user.object.lock().unwrap().id ); assert_eq!( - dm_channel.recipients.as_ref().unwrap().get(1).unwrap().id, - user.object.id + dm_channel + .recipients + .as_ref() + .unwrap() + .get(1) + .unwrap() + .lock() + .unwrap() + .id + .clone(), + user.object.lock().unwrap().id.clone() ); common::teardown(bundle).await; } // #[tokio::test] -// This test currently is broken due to an issue with the Spacebar Server. +// TODO This test currently is broken due to an issue with the Spacebar Server. #[allow(dead_code)] async fn remove_add_person_from_to_dm() { let mut bundle = common::setup().await; let mut other_user = bundle.create_user("integrationtestuser2").await; let mut third_user = bundle.create_user("integrationtestuser3").await; + let third_user_id = third_user.object.lock().unwrap().id; + let other_user_id = other_user.object.lock().unwrap().id; + let user_id = bundle.user.object.lock().unwrap().id; let user = &mut bundle.user; let private_channel_create_schema = PrivateChannelCreateSchema { - recipients: Some(Vec::from([other_user.object.id, third_user.object.id])), + recipients: Some(Vec::from([other_user_id, third_user_id])), access_tokens: None, nicks: None, }; @@ -181,36 +203,52 @@ async fn remove_add_person_from_to_dm() { .await .unwrap(); // Creates the Channel and stores the response Channel object dm_channel - .remove_channel_recipient(other_user.object.id, user) + .remove_channel_recipient(other_user_id, user) .await .unwrap(); assert!(dm_channel.recipients.as_ref().unwrap().get(1).is_none()); other_user - .modify_user_relationship(user.object.id, RelationshipType::Friends) + .modify_user_relationship(user_id, RelationshipType::Friends) .await .unwrap(); - user.modify_user_relationship(other_user.object.id, RelationshipType::Friends) + user.modify_user_relationship(other_user_id, RelationshipType::Friends) .await .unwrap(); third_user - .modify_user_relationship(user.object.id, RelationshipType::Friends) + .modify_user_relationship(user_id, RelationshipType::Friends) .await .unwrap(); - user.modify_user_relationship(third_user.object.id, RelationshipType::Friends) + user.modify_user_relationship(third_user_id, RelationshipType::Friends) .await .unwrap(); // Users 1-2 and 1-3 are now friends dm_channel - .add_channel_recipient(other_user.object.id, user, None) + .add_channel_recipient(other_user_id, user, None) .await .unwrap(); assert!(dm_channel.recipients.is_some()); assert_eq!( - dm_channel.recipients.as_ref().unwrap().get(0).unwrap().id, - other_user.object.id + dm_channel + .recipients + .as_ref() + .unwrap() + .get(0) + .unwrap() + .lock() + .unwrap() + .id, + other_user_id ); assert_eq!( - dm_channel.recipients.as_ref().unwrap().get(1).unwrap().id, - user.object.id + dm_channel + .recipients + .as_ref() + .unwrap() + .get(1) + .unwrap() + .lock() + .unwrap() + .id, + user_id ); } diff --git a/tests/members.rs b/tests/members.rs index 9710d7f..a314be7 100644 --- a/tests/members.rs +++ b/tests/members.rs @@ -7,7 +7,7 @@ async fn add_remove_role() -> ChorusResult<()> { let mut bundle = common::setup().await; let guild = bundle.guild.id; let role = bundle.role.id; - let member_id = bundle.user.object.id; + let member_id = bundle.user.object.lock().unwrap().id; GuildMember::add_role(&mut bundle.user, guild, member_id, role).await?; let member = GuildMember::get(&mut bundle.user, guild, member_id) .await diff --git a/tests/relationships.rs b/tests/relationships.rs index 00ef9cf..2773474 100644 --- a/tests/relationships.rs +++ b/tests/relationships.rs @@ -7,15 +7,18 @@ async fn test_get_mutual_relationships() { let mut bundle = common::setup().await; let mut other_user = bundle.create_user("integrationtestuser2").await; let user = &mut bundle.user; + let username = user.object.lock().unwrap().username.clone(); + let discriminator = user.object.lock().unwrap().discriminator.clone(); + let other_user_id: types::Snowflake = other_user.object.lock().unwrap().id; let friend_request_schema = types::FriendRequestSendSchema { - username: user.object.username.clone(), - discriminator: Some(user.object.discriminator.clone()), + username, + discriminator: Some(discriminator), }; - let _ = other_user.send_friend_request(friend_request_schema).await; - let relationships = user - .get_mutual_relationships(other_user.object.id) + other_user + .send_friend_request(friend_request_schema) .await .unwrap(); + let relationships = user.get_mutual_relationships(other_user_id).await.unwrap(); println!("{:?}", relationships); common::teardown(bundle).await } @@ -25,16 +28,21 @@ async fn test_get_relationships() { let mut bundle = common::setup().await; let mut other_user = bundle.create_user("integrationtestuser2").await; let user = &mut bundle.user; + let username = user.object.lock().unwrap().username.clone(); + let discriminator = user.object.lock().unwrap().discriminator.clone(); let friend_request_schema = types::FriendRequestSendSchema { - username: user.object.username.clone(), - discriminator: Some(user.object.discriminator.clone()), + username, + discriminator: Some(discriminator), }; other_user .send_friend_request(friend_request_schema) .await .unwrap(); let relationships = user.get_relationships().await.unwrap(); - assert_eq!(relationships.get(0).unwrap().id, other_user.object.id); + assert_eq!( + relationships.get(0).unwrap().id, + other_user.object.lock().unwrap().id + ); common::teardown(bundle).await } @@ -43,23 +51,33 @@ async fn test_modify_relationship_friends() { let mut bundle = common::setup().await; let mut other_user = bundle.create_user("integrationtestuser2").await; let user = &mut bundle.user; - let _ = other_user - .modify_user_relationship(user.object.id, types::RelationshipType::Friends) - .await; + let user_id: types::Snowflake = user.object.lock().unwrap().id; + let other_user_id: types::Snowflake = other_user.object.lock().unwrap().id; + + other_user + .modify_user_relationship(user_id, types::RelationshipType::Friends) + .await + .unwrap(); let relationships = user.get_relationships().await.unwrap(); - assert_eq!(relationships.get(0).unwrap().id, other_user.object.id); + assert_eq!( + relationships.get(0).unwrap().id, + other_user.object.lock().unwrap().id + ); assert_eq!( relationships.get(0).unwrap().relationship_type, RelationshipType::Incoming ); let relationships = other_user.get_relationships().await.unwrap(); - assert_eq!(relationships.get(0).unwrap().id, user.object.id); + assert_eq!( + relationships.get(0).unwrap().id, + user.object.lock().unwrap().id + ); assert_eq!( relationships.get(0).unwrap().relationship_type, RelationshipType::Outgoing ); let _ = user - .modify_user_relationship(other_user.object.id, RelationshipType::Friends) + .modify_user_relationship(other_user_id, RelationshipType::Friends) .await; assert_eq!( other_user @@ -71,7 +89,7 @@ async fn test_modify_relationship_friends() { .relationship_type, RelationshipType::Friends ); - let _ = user.remove_relationship(other_user.object.id).await; + let _ = user.remove_relationship(other_user_id).await; assert_eq!( other_user.get_relationships().await.unwrap(), Vec::::new() @@ -84,18 +102,24 @@ async fn test_modify_relationship_block() { let mut bundle = common::setup().await; let mut other_user = bundle.create_user("integrationtestuser2").await; let user = &mut bundle.user; - let _ = other_user - .modify_user_relationship(user.object.id, types::RelationshipType::Blocked) - .await; + let user_id: types::Snowflake = user.object.lock().unwrap().id; + + other_user + .modify_user_relationship(user_id, types::RelationshipType::Blocked) + .await + .unwrap(); let relationships = user.get_relationships().await.unwrap(); assert_eq!(relationships, Vec::::new()); let relationships = other_user.get_relationships().await.unwrap(); - assert_eq!(relationships.get(0).unwrap().id, user.object.id); + assert_eq!( + relationships.get(0).unwrap().id, + user.object.lock().unwrap().id + ); assert_eq!( relationships.get(0).unwrap().relationship_type, RelationshipType::Blocked ); - let _ = other_user.remove_relationship(user.object.id).await; + other_user.remove_relationship(user_id).await.unwrap(); assert_eq!( other_user.get_relationships().await.unwrap(), Vec::::new()