From f876f25a2ca464fae4410829e0a407c771cb1f8e Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 18:00:07 -0400 Subject: [PATCH 01/38] Update poem dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a31a9da..936e149 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ http = "0.2.11" base64 = "0.21.7" bitflags = { version = "2.4.1", features = ["serde"] } lazy_static = "1.4.0" -poem = { version = "1.3.59", optional = true } +poem = { version = "3.0.1", optional = true } thiserror = "1.0.56" jsonwebtoken = "8.3.0" log = "0.4.20" From d1b3a9ad9efc2183c9d16105d094d125fff9d533 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 18:09:43 -0400 Subject: [PATCH 02/38] Convert timestamp fields to DateTime's --- src/types/entities/channel.rs | 12 +- src/types/entities/guild.rs | 5 +- src/types/entities/guild_member.rs | 8 +- src/types/entities/message.rs | 9 +- src/types/schema/auth.rs | 5 +- src/types/utils/mod.rs | 2 + src/types/utils/serde.rs | 263 +++++++++++++++++++++++++++++ 7 files changed, 292 insertions(+), 12 deletions(-) create mode 100644 src/types/utils/serde.rs diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index fd0c077..dc1e6ad 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -11,7 +11,7 @@ use std::fmt::Debug; use crate::types::Shared; use crate::types::{ entities::{GuildMember, User}, - utils::Snowflake, + utils::{Snowflake, serde::*}, }; #[cfg(feature = "client")] @@ -60,6 +60,7 @@ pub struct Channel { pub icon: Option, pub id: Snowflake, pub last_message_id: Option, + #[serde(with = "ts_seconds_option_str")] pub last_pin_timestamp: Option>, pub managed: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] @@ -160,10 +161,12 @@ pub struct PermissionOverwrite { pub struct ThreadMetadata { pub archived: bool, pub auto_archive_duration: i32, - pub archive_timestamp: String, + #[serde(with = "ts_seconds_str")] + pub archive_timestamp: DateTime, pub locked: bool, pub invitable: Option, - pub create_timestamp: Option, + #[serde(with = "ts_seconds_option_str")] + pub create_timestamp: Option>, } #[derive(Default, Debug, Deserialize, Serialize, Clone)] @@ -172,7 +175,8 @@ pub struct ThreadMetadata { pub struct ThreadMember { pub id: Option, pub user_id: Option, - pub join_timestamp: Option, + #[serde(with = "ts_seconds_option_str")] + pub join_timestamp: Option>, pub flags: Option, pub member: Option>, } diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index 2b7ae44..b259056 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -14,7 +14,7 @@ use crate::types::types::guild_configuration::GuildFeaturesList; use crate::types::{ entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook}, interfaces::WelcomeScreenObject, - utils::Snowflake, + utils::{Snowflake, serde::*}, }; use super::PublicUser; @@ -67,7 +67,8 @@ pub struct Guild { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub invites: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - pub joined_at: Option, + #[serde(with = "ts_seconds_option_str")] + pub joined_at: Option>, pub large: Option, pub max_members: Option, pub max_presences: Option, diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index 5cd5ad1..2a3c184 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -2,10 +2,12 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use crate::types::Shared; use crate::types::{entities::PublicUser, Snowflake}; +use crate::types::utils::serde::*; #[derive(Debug, Deserialize, Default, Serialize, Clone)] /// Represents a participating user in a guild. @@ -17,12 +19,14 @@ pub struct GuildMember { pub nick: Option, pub avatar: Option, pub roles: Vec, - pub joined_at: String, + #[serde(with = "ts_seconds_str")] + pub joined_at: DateTime, pub premium_since: Option, pub deaf: bool, pub mute: bool, pub flags: Option, pub pending: Option, pub permissions: Option, - pub communication_disabled_until: Option, + #[serde(with = "ts_seconds_option_str")] + pub communication_disabled_until: Option>, } diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index e03a078..607ccf2 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use crate::types::{ @@ -10,7 +11,7 @@ use crate::types::{ Application, Attachment, Channel, Emoji, GuildMember, PublicUser, RoleSubscriptionData, Sticker, StickerItem, User, }, - utils::Snowflake, + utils::{Snowflake, serde::*}, }; #[derive(Debug, Serialize, Deserialize, Default, Clone)] @@ -25,8 +26,10 @@ pub struct Message { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub author: Option, pub content: Option, - pub timestamp: String, - pub edited_timestamp: Option, + #[serde(with = "ts_seconds_str")] + pub timestamp: DateTime, + #[serde(with = "ts_seconds_option_str")] + pub edited_timestamp: Option>, pub tts: Option, pub mention_everyone: bool, #[cfg_attr(feature = "sqlx", sqlx(skip))] diff --git a/src/types/schema/auth.rs b/src/types/schema/auth.rs index 2796805..c1c1f55 100644 --- a/src/types/schema/auth.rs +++ b/src/types/schema/auth.rs @@ -2,7 +2,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use crate::types::utils::serde::ts_seconds_option_str; #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] @@ -13,7 +15,8 @@ pub struct RegisterSchema { pub email: Option, pub fingerprint: Option, pub invite: Option, - pub date_of_birth: Option, + #[serde(with = "ts_seconds_option_str")] + pub date_of_birth: Option>, pub gift_code_sku_id: Option, pub captcha_key: Option, pub promotional_email_opt_in: Option, diff --git a/src/types/utils/mod.rs b/src/types/utils/mod.rs index 8879688..5608fe7 100644 --- a/src/types/utils/mod.rs +++ b/src/types/utils/mod.rs @@ -11,3 +11,5 @@ pub mod jwt; mod regexes; mod rights; mod snowflake; +pub mod serde; + diff --git a/src/types/utils/serde.rs b/src/types/utils/serde.rs new file mode 100644 index 0000000..28d6e60 --- /dev/null +++ b/src/types/utils/serde.rs @@ -0,0 +1,263 @@ +use core::fmt; +use chrono::{LocalResult, NaiveDateTime}; +use serde::de; +use chrono::serde::ts_seconds; + +#[doc(hidden)] +#[derive(Debug)] +pub struct SecondsStringTimestampVisitor; + + +/// Ser/de to/from timestamps in seconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{TimeZone, DateTime, Utc}; +/// # use serde::{Deserialize, Serialize}; +/// use chrono::serde::ts_seconds; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_seconds_str")] +/// time: DateTime +/// } +/// +/// let time = Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap(); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":"1431684000"}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` + +pub mod ts_seconds_str { + use core::fmt; + use chrono::{DateTime, LocalResult, Utc}; + use super::SecondsStringTimestampVisitor; + use serde::{de, ser}; + use chrono::TimeZone; + use super::serde_from; + + /// Serialize a UTC datetime into an integer number of seconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{TimeZone, DateTime, Utc}; + /// # use serde::Serialize; + /// use chrono::serde::ts_seconds::serialize as to_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "ts_seconds_str")] + /// time: DateTime + /// } + /// + /// let my_s = S { + /// time: Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap(), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize(dt: &DateTime, serializer: S) -> Result + where + S: ser::Serializer, + { + serializer.serialize_str(&format!("{}", dt.timestamp())) + } + + /// Deserialize a `DateTime` from a seconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{DateTime, TimeZone, Utc}; + /// # use serde::Deserialize; + /// use chrono::serde::ts_seconds::deserialize as from_ts; + /// #[derive(Debug, PartialEq, Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "ts_seconds_str")] + /// time: DateTime + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; + /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).unwrap() }); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_str(SecondsStringTimestampVisitor) + } + + impl<'de> de::Visitor<'de> for SecondsStringTimestampVisitor { + type Value = DateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in seconds") + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + serde_from(Utc.timestamp_opt(value.parse::().map_err(|e| E::custom(e))?, 0), &value) + } + } +} + +/// Ser/de to/from optional timestamps in seconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{TimeZone, DateTime, Utc}; +/// # use serde::{Deserialize, Serialize}; +/// use chrono::serde::ts_seconds_option; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_seconds_option_str")] +/// time: Option> +/// } +/// +/// let time = Some(Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap()); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":"1431684000"}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_seconds_option_str { + use core::fmt; + use chrono::{DateTime, Utc}; + use serde::{de, ser}; + use super::SecondsStringTimestampVisitor; + + /// Serialize a UTC datetime into an integer number of seconds since the epoch or none + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{TimeZone, DateTime, Utc}; + /// # use serde::Serialize; + /// use chrono::serde::ts_seconds_option::serialize as to_tsopt; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "ts_seconds_option_str")] + /// time: Option> + /// } + /// + /// let my_s = S { + /// time: Some(Utc.with_ymd_and_hms(2015, 5, 15, 10, 0, 0).unwrap()), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize(opt: &Option>, serializer: S) -> Result + where + S: ser::Serializer, + { + match *opt { + Some(ref dt) => serializer.serialize_some(&dt.timestamp().to_string()), + None => serializer.serialize_none(), + } + } + + /// Deserialize a `DateTime` from a seconds timestamp or none + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{DateTime, TimeZone, Utc}; + /// # use serde::Deserialize; + /// use chrono::serde::ts_seconds_option::deserialize as from_tsopt; + /// #[derive(Debug, PartialEq, Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "ts_seconds_option_str")] + /// time: Option> + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; + /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).single() }); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result>, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_option(OptionSecondsTimestampVisitor) + } + + struct OptionSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for OptionSecondsTimestampVisitor { + type Value = Option>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in seconds or none") + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_some(self, d: D) -> Result + where + D: de::Deserializer<'de>, + { + d.deserialize_str(SecondsStringTimestampVisitor).map(Some) + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_none(self) -> Result + where + E: de::Error, + { + Ok(None) + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(None) + } + } +} + +pub(crate) fn serde_from(me: LocalResult, ts: &V) -> Result + where + E: de::Error, + V: fmt::Display, + T: fmt::Display, +{ + // TODO: Make actual error type + match me { + LocalResult::None => Err(E::custom("value is not a legal timestamp")), + LocalResult::Ambiguous(min, max) => { + Err(E::custom("value is an ambiguous timestamp")) + } + LocalResult::Single(val) => Ok(val), + } +} \ No newline at end of file From c44521320d5ca68d7a43324621624b72d70d3db9 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 18:10:57 -0400 Subject: [PATCH 03/38] Feature lock different types for UserSettings::status --- src/types/entities/user_settings.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index db13efc..1eef5d2 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -83,6 +83,9 @@ pub struct UserSettings { #[cfg(not(feature = "sqlx"))] pub restricted_guilds: Vec, pub show_current_game: bool, + #[cfg(feature = "sqlx")] + pub status: UserStatus, + #[cfg(not(feature = "sqlx"))] pub status: Shared, pub stream_notifications_enabled: bool, pub theme: UserTheme, @@ -119,7 +122,7 @@ impl Default for UserSettings { render_reactions: true, restricted_guilds: Default::default(), show_current_game: true, - status: Arc::new(RwLock::new(UserStatus::Online)), + status: Default::default(), stream_notifications_enabled: false, theme: UserTheme::Dark, timezone_offset: 0, From 7b7294433b957e86dd7d0988581f2ed1cfe34c2f Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 18:11:39 -0400 Subject: [PATCH 04/38] Make config register_configuration use Rights bitflag object --- src/types/config/types/register_configuration.rs | 8 ++++---- src/types/utils/rights.rs | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/types/config/types/register_configuration.rs b/src/types/config/types/register_configuration.rs index a4573bf..19cedfb 100644 --- a/src/types/config/types/register_configuration.rs +++ b/src/types/config/types/register_configuration.rs @@ -4,9 +4,9 @@ use serde::{Deserialize, Serialize}; -use crate::types::config::types::subconfigs::register::{ +use crate::types::{config::types::subconfigs::register::{ DateOfBirthConfiguration, PasswordConfiguration, RegistrationEmailConfiguration, -}; +}, Rights}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -22,7 +22,7 @@ pub struct RegisterConfiguration { pub allow_multiple_accounts: bool, pub block_proxies: bool, pub incrementing_discriminators: bool, - pub default_rights: String, + pub default_rights: Rights, } impl Default for RegisterConfiguration { @@ -39,7 +39,7 @@ impl Default for RegisterConfiguration { allow_multiple_accounts: true, block_proxies: true, incrementing_discriminators: false, - default_rights: String::from("875069521787904"), + default_rights: Rights::from_bits(648540060672).expect("failed to parse default_rights"), } } } diff --git a/src/types/utils/rights.rs b/src/types/utils/rights.rs index 4b1aa13..63bbeb2 100644 --- a/src/types/utils/rights.rs +++ b/src/types/utils/rights.rs @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use bitflags::bitflags; +use serde::{Deserialize, Serialize}; bitflags! { /// Rights are instance-wide, per-user permissions for everything you may perform on the instance, @@ -14,6 +15,7 @@ bitflags! { /// /// # Reference /// See + #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] pub struct Rights: u64 { /// All rights const OPERATOR = 1 << 0; @@ -151,6 +153,12 @@ impl Rights { } } +impl Default for Rights { + fn default() -> Self { + Self::empty() + } +} + #[allow(dead_code)] // FIXME: Remove this when we use this fn all_rights() -> Rights { Rights::OPERATOR From ab4435a79faa570bb7c69e87688bd33163ae64e9 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 18:12:52 -0400 Subject: [PATCH 05/38] Update tests to use DateTime's for timestamps --- tests/auth.rs | 8 +++++--- tests/common/mod.rs | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/auth.rs b/tests/auth.rs index 35007f1..6266aa3 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::str::FromStr; +use chrono::DateTime; use chorus::types::{LoginSchema, RegisterSchema}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -16,7 +18,7 @@ async fn test_registration() { let mut bundle = common::setup().await; let reg = RegisterSchema { username: "Hiiii".into(), - date_of_birth: Some("2000-01-01".to_string()), + date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), consent: true, ..Default::default() }; @@ -32,7 +34,7 @@ async fn test_login() { username: "Hiiii".into(), email: Some("testuser1@integrationtesting.xyz".into()), password: Some("Correct-Horse-Battery-Staple1".into()), - date_of_birth: Some("2000-01-01".to_string()), + date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), consent: true, ..Default::default() }; @@ -54,7 +56,7 @@ async fn test_wrong_login() { username: "Hiiii".into(), email: Some("testuser2@integrationtesting.xyz".into()), password: Some("Correct-Horse-Battery-Staple1".into()), - date_of_birth: Some("2000-01-01".to_string()), + date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), consent: true, ..Default::default() }; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index a98667c..4abedd5 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -2,6 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::str::FromStr; +use chrono::DateTime; use chorus::gateway::Gateway; use chorus::types::IntoShared; use chorus::{ @@ -30,7 +32,7 @@ impl TestBundle { let register_schema = RegisterSchema { username: username.to_string(), consent: true, - date_of_birth: Some("2000-01-01".to_string()), + date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), ..Default::default() }; self.instance @@ -60,7 +62,7 @@ pub(crate) async fn setup() -> TestBundle { let reg = RegisterSchema { username: "integrationtestuser".into(), consent: true, - date_of_birth: Some("2000-01-01".to_string()), + date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), ..Default::default() }; let guild_create_schema = GuildCreateSchema { From 08952db0141bff12a247e15db1a50c1b79d9c9dd Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 19:02:36 -0400 Subject: [PATCH 06/38] Fix tests --- tests/auth.rs | 7 +++---- tests/common/mod.rs | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/auth.rs b/tests/auth.rs index 6266aa3..a2f2c3f 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -2,7 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use std::str::FromStr; use chrono::DateTime; use chorus::types::{LoginSchema, RegisterSchema}; #[cfg(target_arch = "wasm32")] @@ -18,7 +17,7 @@ async fn test_registration() { let mut bundle = common::setup().await; let reg = RegisterSchema { username: "Hiiii".into(), - date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), + date_of_birth: Some(DateTime::from_timestamp(978325200, 0).unwrap()), consent: true, ..Default::default() }; @@ -34,7 +33,7 @@ async fn test_login() { username: "Hiiii".into(), email: Some("testuser1@integrationtesting.xyz".into()), password: Some("Correct-Horse-Battery-Staple1".into()), - date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), + date_of_birth: Some(DateTime::from_timestamp(978325200, 0).unwrap()), consent: true, ..Default::default() }; @@ -56,7 +55,7 @@ async fn test_wrong_login() { username: "Hiiii".into(), email: Some("testuser2@integrationtesting.xyz".into()), password: Some("Correct-Horse-Battery-Staple1".into()), - date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), + date_of_birth: Some(DateTime::from_timestamp(978325200, 0).unwrap()), consent: true, ..Default::default() }; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 4abedd5..a07e503 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -2,7 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use std::str::FromStr; use chrono::DateTime; use chorus::gateway::Gateway; use chorus::types::IntoShared; @@ -32,7 +31,7 @@ impl TestBundle { let register_schema = RegisterSchema { username: username.to_string(), consent: true, - date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), + date_of_birth: Some(DateTime::from_timestamp(978325200, 0).unwrap()), ..Default::default() }; self.instance @@ -62,7 +61,7 @@ pub(crate) async fn setup() -> TestBundle { let reg = RegisterSchema { username: "integrationtestuser".into(), consent: true, - date_of_birth: Some(DateTime::from_str("2000-01-01").unwrap()), + date_of_birth: Some(DateTime::from_timestamp(978325200, 0).unwrap()), ..Default::default() }; let guild_create_schema = GuildCreateSchema { From 8c5d80d3f1d8992dbe319fc0eadbc16b6fe9b897 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 19:18:43 -0400 Subject: [PATCH 07/38] Allow joined_at to default if field is not in responses. --- src/types/entities/guild.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index b259056..af6f153 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -67,7 +67,7 @@ pub struct Guild { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub invites: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[serde(with = "ts_seconds_option_str")] + #[serde(with = "ts_seconds_option_str", default)] pub joined_at: Option>, pub large: Option, pub max_members: Option, From a75701d9c6483cc3a68a9bc3de3fac694514bdf4 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 20:06:01 -0400 Subject: [PATCH 08/38] Allow last_pin_timestamp to default if field is not in responses. --- src/types/entities/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index dc1e6ad..b5e604d 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -60,7 +60,7 @@ pub struct Channel { pub icon: Option, pub id: Snowflake, pub last_message_id: Option, - #[serde(with = "ts_seconds_option_str")] + #[serde(with = "ts_seconds_option_str", default)] pub last_pin_timestamp: Option>, pub managed: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] From eefdd4aebfccc344f3e006f003759a493a973dd0 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Sun, 2 Jun 2024 20:17:48 -0400 Subject: [PATCH 09/38] Remove serde(with) for message timestamps --- src/types/entities/message.rs | 62 +++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index 607ccf2..4f444e3 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -26,9 +26,9 @@ pub struct Message { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub author: Option, pub content: Option, - #[serde(with = "ts_seconds_str")] + // #[serde(with = "ts_seconds_str")] pub timestamp: DateTime, - #[serde(with = "ts_seconds_option_str")] + // #[serde(with = "ts_seconds_option_str")] pub edited_timestamp: Option>, pub tts: Option, pub mention_everyone: bool, @@ -255,3 +255,61 @@ pub struct MessageActivity { pub activity_type: i64, pub party_id: Option, } + +#[cfg(test)] +mod tests { + #[test] + fn test_deserialize_message() { + let raw = r#"{ + "id":"1246967362553443002", + "channel_id":"1246967361836216935", + "guild_id":"1246967361001550368", + "author":{ + "username":"integrationtestuser", + "discriminator":"3864", + "id":"1246967359860699591", + "public_flags":0, + "avatar":null, + "accent_color":null, + "banner":null, + "bio":"", + "bot":false, + "premium_since":"2024-06-02T23:23:06.124+00:00", + "premium_type":2, + "theme_colors":null, + "pronouns":null + }, + "member":{ + "index":142, + "id":"1246967359860699591", + "guild_id":"1246967361001550368", + "nick":null, + "joined_at":"2024-06-02T23:23:06.526+00:00", + "premium_since":null,"deaf":false,"mute":false,"pending":false, + "last_message_id":null, + "joined_by":null, + "avatar":null, + "banner":null, + "bio":"", + "theme_colors":null, + "pronouns":null, + "communication_disabled_until":null, + "roles":[] + }, + "content":"A Message!", + "timestamp":"2024-06-02T23:23:06.762+00:00", + "edited_timestamp":null, + "tts":false, + "mention_everyone":false, + "mentions":[], + "mention_roles":[], + "attachments":[], + "embeds":[], + "reactions":[], + "pinned":false, + "type":0, + "flags":null + }"#; + let message: super::Message = serde_json::from_str(raw).unwrap(); + } +} \ No newline at end of file From 0bc54ce46fa100b5e9655a8e1dd58f9c623f804f Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 01:41:52 -0400 Subject: [PATCH 10/38] Add sqlx::FromRow derive to GuildMember --- src/types/entities/guild_member.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index 2a3c184..09e8554 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -10,6 +10,7 @@ use crate::types::{entities::PublicUser, Snowflake}; use crate::types::utils::serde::*; #[derive(Debug, Deserialize, Default, Serialize, Clone)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a participating user in a guild. /// /// # Reference From d6ad68c0444f722e466eda05a59847b152651577 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 01:42:31 -0400 Subject: [PATCH 11/38] remove dep: prefix in backend feature list --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 936e149..6a3b384 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ rust-version = "1.67.1" [features] default = ["client", "rt-multi-thread"] -backend = ["dep:poem", "dep:sqlx"] +backend = ["poem", "sqlx"] rt-multi-thread = ["tokio/rt-multi-thread"] rt = ["tokio/rt"] client = [] From 85aa85495373c417335c6c447b0ba5b067e9181b Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 22:58:05 -0400 Subject: [PATCH 12/38] Implement sqlx Encode, Decode, Type for Rights bitflag object. --- src/types/utils/rights.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/types/utils/rights.rs b/src/types/utils/rights.rs index 63bbeb2..e4fff31 100644 --- a/src/types/utils/rights.rs +++ b/src/types/utils/rights.rs @@ -4,6 +4,10 @@ use bitflags::bitflags; use serde::{Deserialize, Serialize}; +use tokio::io::AsyncWriteExt; + +#[cfg(feature = "sqlx")] +use sqlx::{{Decode, Encode, MySql}, database::{HasArguments, HasValueRef}, encode::IsNull, error::BoxDynError, mysql::MySqlValueRef}; bitflags! { /// Rights are instance-wide, per-user permissions for everything you may perform on the instance, @@ -129,6 +133,33 @@ bitflags! { } } +#[cfg(feature = "sqlx")] +impl sqlx::Type for Rights { + fn type_info() -> ::TypeInfo { + u64::type_info() + } + + fn compatible(ty: &::TypeInfo) -> bool { + u64::compatible(ty) + } +} + +#[cfg(feature = "sqlx")] +impl<'q> Encode<'q, MySql> for Rights { + fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { + >::encode_by_ref(&self.0.0, buf) + } +} + +#[cfg(feature = "sqlx")] +impl<'r> Decode<'r, MySql> for Rights { + fn decode(value: >::ValueRef) -> Result { + let raw = >::decode(value)?; + Ok(Rights::from_bits(raw).unwrap()) + } +} + + impl Rights { pub fn any(&self, permission: Rights, check_operator: bool) -> bool { (check_operator && self.contains(Rights::OPERATOR)) || self.contains(permission) From 7d55bbea4b0e2b853d4e508a0354fa65acaf61e0 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 23:53:15 -0400 Subject: [PATCH 13/38] Use Snowflake in Claims --- src/types/utils/jwt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/utils/jwt.rs b/src/types/utils/jwt.rs index 6addb4c..0919a5a 100644 --- a/src/types/utils/jwt.rs +++ b/src/types/utils/jwt.rs @@ -19,7 +19,7 @@ pub struct Claims { /// When the token was issued pub iat: i64, pub email: String, - pub id: String, + pub id: Snowflake, } impl Claims { @@ -27,7 +27,7 @@ impl Claims { let unix = chrono::Utc::now().timestamp(); Self { exp: unix + (60 * 60 * 24), - id: id.to_string(), + id: *id, iat: unix, email: user.to_string(), } From 179b8d228ae1680bfde3d0d39cf1df8f3189098a Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 23:54:17 -0400 Subject: [PATCH 14/38] Use ChannelType enum on ChannelModifySchema --- src/types/schema/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 1502f97..851bfda 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -36,7 +36,7 @@ pub struct ChannelCreateSchema { #[serde(rename_all = "snake_case")] pub struct ChannelModifySchema { pub name: Option, - pub channel_type: Option, + pub channel_type: Option, pub topic: Option, pub icon: Option, pub bitrate: Option, From 40bdafd1a3ea1c9ad3e612e2f6437cc68cdbe5eb Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 23:56:17 -0400 Subject: [PATCH 15/38] Feature lock Shared, so backend feature gets a facade type --- src/types/entities/mod.rs | 1 + src/types/mod.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index d5d70e6..5b498d6 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -134,6 +134,7 @@ pub trait IntoShared { fn into_shared(self) -> Shared; } +#[cfg(feature = "client")] impl IntoShared for T { fn into_shared(self) -> Shared { Arc::new(RwLock::new(self)) diff --git a/src/types/mod.rs b/src/types/mod.rs index c4cc190..9ff2c09 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -28,4 +28,7 @@ mod utils; /// /// While `T` does not have to implement `Composite` to be used with `Shared`, /// the primary use of `Shared` is with types that implement `Composite`. +#[cfg(feature = "client")] pub type Shared = Arc>; +#[cfg(not(feature = "client"))] +pub type Shared = T; From 4d75aa89c9ebda2753e787922f6f90eb08282e11 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Mon, 3 Jun 2024 23:59:21 -0400 Subject: [PATCH 16/38] Remove erroneous serde with attributes --- src/types/entities/guild.rs | 3 +-- src/types/entities/guild_member.rs | 3 --- src/types/entities/message.rs | 4 +--- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index af6f153..8544b0b 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -14,7 +14,7 @@ use crate::types::types::guild_configuration::GuildFeaturesList; use crate::types::{ entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook}, interfaces::WelcomeScreenObject, - utils::{Snowflake, serde::*}, + utils::Snowflake, }; use super::PublicUser; @@ -67,7 +67,6 @@ pub struct Guild { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub invites: Option>, #[cfg_attr(feature = "sqlx", sqlx(skip))] - #[serde(with = "ts_seconds_option_str", default)] pub joined_at: Option>, pub large: Option, pub max_members: Option, diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index 09e8554..83adb0b 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize}; use crate::types::Shared; use crate::types::{entities::PublicUser, Snowflake}; -use crate::types::utils::serde::*; #[derive(Debug, Deserialize, Default, Serialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -20,7 +19,6 @@ pub struct GuildMember { pub nick: Option, pub avatar: Option, pub roles: Vec, - #[serde(with = "ts_seconds_str")] pub joined_at: DateTime, pub premium_since: Option, pub deaf: bool, @@ -28,6 +26,5 @@ pub struct GuildMember { pub flags: Option, pub pending: Option, pub permissions: Option, - #[serde(with = "ts_seconds_option_str")] pub communication_disabled_until: Option>, } diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index c4abb8e..4b57e06 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -11,7 +11,7 @@ use crate::types::{ Application, Attachment, Channel, Emoji, GuildMember, PublicUser, RoleSubscriptionData, Sticker, StickerItem, User, }, - utils::{Snowflake, serde::*}, + utils::Snowflake, }; #[derive(Debug, Serialize, Deserialize, Default, Clone)] @@ -26,9 +26,7 @@ pub struct Message { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub author: Option, pub content: Option, - // #[serde(with = "ts_seconds_str")] pub timestamp: DateTime, - // #[serde(with = "ts_seconds_option_str")] pub edited_timestamp: Option>, pub tts: Option, pub mention_everyone: bool, From 97f10aaa61d6484a5e36a37b6cccec46f97581ce Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:21:38 -0400 Subject: [PATCH 17/38] Add From> impl for GuildFeaturesList --- src/types/config/types/guild_configuration.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/types/config/types/guild_configuration.rs b/src/types/config/types/guild_configuration.rs index af40b30..d2b3f16 100644 --- a/src/types/config/types/guild_configuration.rs +++ b/src/types/config/types/guild_configuration.rs @@ -376,6 +376,12 @@ impl FromStr for GuildFeatures { } } +impl From> for GuildFeaturesList { + fn from(features: Vec) -> GuildFeaturesList { + Self(features) + } +} + impl GuildFeatures { pub fn to_str(&self) -> &'static str { match *self { From 2b06742a62c8d0cdf471882608bf19efd1ffcaac Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:22:12 -0400 Subject: [PATCH 18/38] Add feature sqlx locks for user, roles on GuildMember --- src/types/entities/guild_member.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index 83adb0b..bdfd1a9 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -15,9 +15,11 @@ use crate::types::{entities::PublicUser, Snowflake}; /// # Reference /// See pub struct GuildMember { + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub user: Option>, pub nick: Option, pub avatar: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub roles: Vec, pub joined_at: DateTime, pub premium_since: Option, From f178e517d3f5e69187323e8183161afac063c091 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:22:52 -0400 Subject: [PATCH 19/38] Use distinct type for explicit_content_filter --- src/types/entities/guild.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index 8544b0b..66b9335 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -57,7 +57,7 @@ pub struct Guild { #[cfg_attr(feature = "client", observe_vec)] #[serde(default)] pub emojis: Vec>, - pub explicit_content_filter: Option, + pub explicit_content_filter: Option, //#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))] pub features: Option, pub icon: Option, From 2b4e9fa1491db750153e37b26ed3d450e043dc76 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:38:49 -0400 Subject: [PATCH 20/38] Remove unused imports --- src/types/entities/user_settings.rs | 2 -- src/types/utils/rights.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index 1eef5d2..2e0d84d 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -2,8 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use std::sync::{Arc, RwLock}; - use chrono::{serde::ts_milliseconds_option, Utc}; use serde::{Deserialize, Serialize}; diff --git a/src/types/utils/rights.rs b/src/types/utils/rights.rs index e4fff31..63978da 100644 --- a/src/types/utils/rights.rs +++ b/src/types/utils/rights.rs @@ -4,7 +4,6 @@ use bitflags::bitflags; use serde::{Deserialize, Serialize}; -use tokio::io::AsyncWriteExt; #[cfg(feature = "sqlx")] use sqlx::{{Decode, Encode, MySql}, database::{HasArguments, HasValueRef}, encode::IsNull, error::BoxDynError, mysql::MySqlValueRef}; From 119a09ae8880496a8b248c72d258352feaa00d54 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:38:59 -0400 Subject: [PATCH 21/38] Revert c4452132 --- src/types/entities/user_settings.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index 2e0d84d..0dbce3e 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -81,9 +81,6 @@ pub struct UserSettings { #[cfg(not(feature = "sqlx"))] pub restricted_guilds: Vec, pub show_current_game: bool, - #[cfg(feature = "sqlx")] - pub status: UserStatus, - #[cfg(not(feature = "sqlx"))] pub status: Shared, pub stream_notifications_enabled: bool, pub theme: UserTheme, From fcda4cc2cab80eda306fe7583ea91bdf88c66741 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:41:03 -0400 Subject: [PATCH 22/38] Remove final usages of erroneous serde impl --- src/types/entities/channel.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index b5e604d..262897c 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -11,7 +11,7 @@ use std::fmt::Debug; use crate::types::Shared; use crate::types::{ entities::{GuildMember, User}, - utils::{Snowflake, serde::*}, + utils::Snowflake, }; #[cfg(feature = "client")] @@ -60,7 +60,6 @@ pub struct Channel { pub icon: Option, pub id: Snowflake, pub last_message_id: Option, - #[serde(with = "ts_seconds_option_str", default)] pub last_pin_timestamp: Option>, pub managed: Option, #[cfg_attr(feature = "sqlx", sqlx(skip))] @@ -161,11 +160,9 @@ pub struct PermissionOverwrite { pub struct ThreadMetadata { pub archived: bool, pub auto_archive_duration: i32, - #[serde(with = "ts_seconds_str")] pub archive_timestamp: DateTime, pub locked: bool, pub invitable: Option, - #[serde(with = "ts_seconds_option_str")] pub create_timestamp: Option>, } @@ -175,7 +172,6 @@ pub struct ThreadMetadata { pub struct ThreadMember { pub id: Option, pub user_id: Option, - #[serde(with = "ts_seconds_option_str")] pub join_timestamp: Option>, pub flags: Option, pub member: Option>, From 2db91e8538ee9e059896a3dd6b6fc9b36e70ac37 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:51:22 -0400 Subject: [PATCH 23/38] Fix errors in documentation tests --- src/types/utils/serde.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/types/utils/serde.rs b/src/types/utils/serde.rs index 28d6e60..2f273c2 100644 --- a/src/types/utils/serde.rs +++ b/src/types/utils/serde.rs @@ -33,7 +33,7 @@ pub struct SecondsStringTimestampVisitor; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); /// let my_s: S = serde_json::from_str(&as_string)?; /// assert_eq!(my_s.time, time); -/// # Ok::<(), serde_json::Error>(()) +/// // Ok::<(), serde_json::Error>(()) /// ``` pub mod ts_seconds_str { @@ -65,7 +65,7 @@ pub mod ts_seconds_str { /// }; /// let as_string = serde_json::to_string(&my_s)?; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); - /// # Ok::<(), serde_json::Error>(()) + /// // Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(dt: &DateTime, serializer: S) -> Result where @@ -92,7 +92,7 @@ pub mod ts_seconds_str { /// /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).unwrap() }); - /// # Ok::<(), serde_json::Error>(()) + /// // Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result, D::Error> where @@ -143,7 +143,7 @@ pub mod ts_seconds_str { /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); /// let my_s: S = serde_json::from_str(&as_string)?; /// assert_eq!(my_s.time, time); -/// # Ok::<(), serde_json::Error>(()) +/// // Ok::<(), serde_json::Error>(()) /// ``` pub mod ts_seconds_option_str { use core::fmt; @@ -172,7 +172,7 @@ pub mod ts_seconds_option_str { /// }; /// let as_string = serde_json::to_string(&my_s)?; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); - /// # Ok::<(), serde_json::Error>(()) + /// // Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(opt: &Option>, serializer: S) -> Result where @@ -202,7 +202,7 @@ pub mod ts_seconds_option_str { /// /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).single() }); - /// # Ok::<(), serde_json::Error>(()) + /// // Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result>, D::Error> where From 50c5c29caee4772b4e61328ac8fd62ba1d69552d Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 00:53:08 -0400 Subject: [PATCH 24/38] update dev-dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a3b384..a3b0b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,5 +76,5 @@ wasmtimer = "0.2.0" [dev-dependencies] lazy_static = "1.4.0" -wasm-bindgen-test = "0.3.39" -wasm-bindgen = "0.2.89" +wasm-bindgen-test = "0.3.42" +wasm-bindgen = "0.2.92" From 32677b8cd938abba621f4bef5c03d51cad5a82c9 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 01:02:06 -0400 Subject: [PATCH 25/38] actually fix linux tests --- src/types/utils/serde.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/types/utils/serde.rs b/src/types/utils/serde.rs index 2f273c2..8a1555f 100644 --- a/src/types/utils/serde.rs +++ b/src/types/utils/serde.rs @@ -1,7 +1,6 @@ use core::fmt; use chrono::{LocalResult, NaiveDateTime}; use serde::de; -use chrono::serde::ts_seconds; #[doc(hidden)] #[derive(Debug)] @@ -17,7 +16,7 @@ pub struct SecondsStringTimestampVisitor; /// ```rust /// # use chrono::{TimeZone, DateTime, Utc}; /// # use serde::{Deserialize, Serialize}; -/// use chrono::serde::ts_seconds; +/// use chorus::types::serde::ts_seconds_str; /// #[derive(Deserialize, Serialize)] /// struct S { /// #[serde(with = "ts_seconds_str")] @@ -33,7 +32,7 @@ pub struct SecondsStringTimestampVisitor; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); /// let my_s: S = serde_json::from_str(&as_string)?; /// assert_eq!(my_s.time, time); -/// // Ok::<(), serde_json::Error>(()) +/// # Ok::<(), serde_json::Error>(()) /// ``` pub mod ts_seconds_str { @@ -53,10 +52,10 @@ pub mod ts_seconds_str { /// ```rust /// # use chrono::{TimeZone, DateTime, Utc}; /// # use serde::Serialize; - /// use chrono::serde::ts_seconds::serialize as to_ts; + /// use chorus::types::serde::ts_seconds_str::serialize as to_ts; /// #[derive(Serialize)] /// struct S { - /// #[serde(serialize_with = "ts_seconds_str")] + /// #[serde(serialize_with = "to_ts")] /// time: DateTime /// } /// @@ -65,7 +64,7 @@ pub mod ts_seconds_str { /// }; /// let as_string = serde_json::to_string(&my_s)?; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); - /// // Ok::<(), serde_json::Error>(()) + /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(dt: &DateTime, serializer: S) -> Result where @@ -83,16 +82,16 @@ pub mod ts_seconds_str { /// ```rust /// # use chrono::{DateTime, TimeZone, Utc}; /// # use serde::Deserialize; - /// use chrono::serde::ts_seconds::deserialize as from_ts; + /// use chorus::types::serde::ts_seconds_str::deserialize as from_ts; /// #[derive(Debug, PartialEq, Deserialize)] /// struct S { - /// #[serde(deserialize_with = "ts_seconds_str")] + /// #[serde(deserialize_with = "from_ts")] /// time: DateTime /// } /// /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).unwrap() }); - /// // Ok::<(), serde_json::Error>(()) + /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result, D::Error> where @@ -127,7 +126,7 @@ pub mod ts_seconds_str { /// ```rust /// # use chrono::{TimeZone, DateTime, Utc}; /// # use serde::{Deserialize, Serialize}; -/// use chrono::serde::ts_seconds_option; +/// use chorus::types::serde::ts_seconds_option_str; /// #[derive(Deserialize, Serialize)] /// struct S { /// #[serde(with = "ts_seconds_option_str")] @@ -143,7 +142,7 @@ pub mod ts_seconds_str { /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); /// let my_s: S = serde_json::from_str(&as_string)?; /// assert_eq!(my_s.time, time); -/// // Ok::<(), serde_json::Error>(()) +/// # Ok::<(), serde_json::Error>(()) /// ``` pub mod ts_seconds_option_str { use core::fmt; @@ -160,10 +159,10 @@ pub mod ts_seconds_option_str { /// ```rust /// # use chrono::{TimeZone, DateTime, Utc}; /// # use serde::Serialize; - /// use chrono::serde::ts_seconds_option::serialize as to_tsopt; + /// use chorus::types::serde::ts_seconds_option_str::serialize as from_tsopt; /// #[derive(Serialize)] /// struct S { - /// #[serde(serialize_with = "ts_seconds_option_str")] + /// #[serde(serialize_with = "from_tsopt")] /// time: Option> /// } /// @@ -172,7 +171,7 @@ pub mod ts_seconds_option_str { /// }; /// let as_string = serde_json::to_string(&my_s)?; /// assert_eq!(as_string, r#"{"time":"1431684000"}"#); - /// // Ok::<(), serde_json::Error>(()) + /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(opt: &Option>, serializer: S) -> Result where @@ -193,16 +192,16 @@ pub mod ts_seconds_option_str { /// ```rust /// # use chrono::{DateTime, TimeZone, Utc}; /// # use serde::Deserialize; - /// use chrono::serde::ts_seconds_option::deserialize as from_tsopt; + /// use chorus::types::serde::ts_seconds_option_str::deserialize as from_tsopt; /// #[derive(Debug, PartialEq, Deserialize)] /// struct S { - /// #[serde(deserialize_with = "ts_seconds_option_str")] + /// #[serde(deserialize_with = "from_tsopt")] /// time: Option> /// } /// /// let my_s: S = serde_json::from_str(r#"{ "time": "1431684000" }"#)?; /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).single() }); - /// // Ok::<(), serde_json::Error>(()) + /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result>, D::Error> where From 0c9e9cf3673c48a02b4074561ce9a3e32238fdce Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 12:57:48 -0400 Subject: [PATCH 26/38] clear warnings --- src/types/entities/mod.rs | 1 + src/types/mod.rs | 1 + src/types/utils/serde.rs | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index 5b498d6..4227e24 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -28,6 +28,7 @@ pub use voice_state::*; pub use webhook::*; use crate::types::Shared; +#[cfg(feature = "client")] use std::sync::{Arc, RwLock}; #[cfg(feature = "client")] diff --git a/src/types/mod.rs b/src/types/mod.rs index 9ff2c09..e67c203 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -4,6 +4,7 @@ //! All the types, entities, events and interfaces of the Spacebar API. +#[cfg(feature = "client")] use std::sync::{Arc, RwLock}; pub use config::*; diff --git a/src/types/utils/serde.rs b/src/types/utils/serde.rs index 8a1555f..8584004 100644 --- a/src/types/utils/serde.rs +++ b/src/types/utils/serde.rs @@ -245,7 +245,7 @@ pub mod ts_seconds_option_str { } } -pub(crate) fn serde_from(me: LocalResult, ts: &V) -> Result +pub(crate) fn serde_from(me: LocalResult, _ts: &V) -> Result where E: de::Error, V: fmt::Display, @@ -254,7 +254,7 @@ pub(crate) fn serde_from(me: LocalResult, ts: &V) -> Result // TODO: Make actual error type match me { LocalResult::None => Err(E::custom("value is not a legal timestamp")), - LocalResult::Ambiguous(min, max) => { + LocalResult::Ambiguous(_min, _max) => { Err(E::custom("value is an ambiguous timestamp")) } LocalResult::Single(val) => Ok(val), From 82c8f570f23582319eec48485ab5a558741853bf Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 13:33:40 -0400 Subject: [PATCH 27/38] Update Cargo.lock --- Cargo.lock | 234 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53283cc..61d67fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,13 +101,19 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atomic-write-file" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" dependencies = [ - "nix", + "nix 0.27.1", "rand", ] @@ -207,6 +213,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chorus" version = "0.15.0" @@ -222,7 +234,7 @@ dependencies = [ "futures-util", "getrandom", "hostname", - "http", + "http 0.2.11", "jsonwebtoken", "lazy_static", "log", @@ -725,7 +737,26 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.11", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", "indexmap 2.1.0", "slab", "tokio", @@ -760,14 +791,14 @@ dependencies = [ [[package]] name = "headers" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http", + "http 1.1.0", "httpdate", "mime", "sha1", @@ -775,11 +806,11 @@ dependencies = [ [[package]] name = "headers-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http", + "http 1.1.0", ] [[package]] @@ -852,6 +883,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -859,7 +901,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.11", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -885,9 +950,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.11", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -899,6 +964,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -906,12 +991,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "tokio", +] + [[package]] name = "iana-time-zone" version = "0.1.59" @@ -1014,9 +1114,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1046,9 +1146,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -1182,6 +1282,18 @@ dependencies = [ "libc", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "no-std-net" version = "0.6.0" @@ -1466,18 +1578,19 @@ dependencies = [ [[package]] name = "poem" -version = "1.3.59" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504774c97b0744c1ee108a37e5a65a9745a4725c4c06277521dabc28eb53a904" +checksum = "e88b6912ed1e8833d7c22c9c986c517f4518d7d37e3c04566d917c789aaea591" dependencies = [ - "async-trait", "bytes", "futures-util", "headers", - "http", - "hyper", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", "mime", - "nix", + "nix 0.28.0", "parking_lot", "percent-encoding", "pin-project-lite", @@ -1488,6 +1601,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", + "sync_wrapper", "thiserror", "tokio", "tokio-util", @@ -1497,9 +1611,9 @@ dependencies = [ [[package]] name = "poem-derive" -version = "1.3.59" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ddcf4680d8d867e1e375116203846acb088483fa2070244f90589f458bbb31" +checksum = "c2b961d58a6c53380c20236394381d9292fda03577f902b158f1638932964dcf" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1532,11 +1646,10 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", "toml_edit", ] @@ -1637,10 +1750,10 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.26", + "http 0.2.11", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-tls", "ipnet", "js-sys", @@ -2024,9 +2137,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -2323,6 +2436,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -2511,15 +2633,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.1.0", "toml_datetime", @@ -2579,7 +2701,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.11", "httparse", "log", "rand", @@ -2727,9 +2849,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2737,9 +2859,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -2752,9 +2874,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -2764,9 +2886,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2774,9 +2896,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -2787,15 +2909,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-bindgen-test" -version = "0.3.39" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" +checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" dependencies = [ "console_error_panic_hook", "js-sys", @@ -2807,9 +2929,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.39" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" +checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", From cb905d0a834deea6677d6933ef185e67e698e7c5 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 13:34:58 -0400 Subject: [PATCH 28/38] Expand documentation to explain facade type --- src/types/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index e67c203..f41a083 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -29,6 +29,9 @@ mod utils; /// /// While `T` does not have to implement `Composite` to be used with `Shared`, /// the primary use of `Shared` is with types that implement `Composite`. +/// +/// When the `client` feature is disabled, this does nothing (same as just `T`), +/// since `Composite` structures are disabled. #[cfg(feature = "client")] pub type Shared = Arc>; #[cfg(not(feature = "client"))] From 0bf5091f3c95dd0d8d63f964b30aa9f818c946cc Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 13:35:28 -0400 Subject: [PATCH 29/38] Fix oversight for premium_since --- src/types/entities/guild_member.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index bdfd1a9..df07583 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -22,7 +22,7 @@ pub struct GuildMember { #[cfg_attr(feature = "sqlx", sqlx(skip))] pub roles: Vec, pub joined_at: DateTime, - pub premium_since: Option, + pub premium_since: Option>, pub deaf: bool, pub mute: bool, pub flags: Option, From c96dcd5c33f7e93b70ba2cca1cf06854073d682e Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 22:19:48 -0400 Subject: [PATCH 30/38] Distinguish InviteType and InviteTargetType --- src/types/schema/channel.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 851bfda..91e7d30 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -109,7 +109,7 @@ pub struct CreateChannelInviteSchema { pub temporary: Option, pub unique: Option, pub validate: Option, - pub target_type: Option, + pub target_type: Option, pub target_user_id: Option, pub target_application_id: Option, } @@ -138,8 +138,21 @@ bitflags! { } #[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[repr(u8)] pub enum InviteType { + #[default] + Guild = 0, + GroupDm = 1, + Friend = 2, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[repr(u8)] +pub enum InviteTargetType { #[default] Stream = 1, EmbeddedApplication = 2, From 6c1493f362fc0533b86417b93e5210a2208323a3 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 22:21:48 -0400 Subject: [PATCH 31/38] Add sqlx Type, Encode, Decode impl for InviteFlags bitflag object. --- src/types/schema/channel.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 91e7d30..d716399 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -137,6 +137,29 @@ bitflags! { } } +#[cfg(feature = "sqlx")] +impl sqlx::Type for InviteFlags { + fn type_info() -> sqlx::mysql::MySqlTypeInfo { + u64::type_info() + } +} + +#[cfg(feature = "sqlx")] +impl<'q> sqlx::Encode<'q, sqlx::MySql> for InviteFlags { + fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> sqlx::encode::IsNull { + u64::encode_by_ref(&self.0.0, buf) + } +} + +#[cfg(feature = "sqlx")] +impl<'r> sqlx::Decode<'r, sqlx::MySql> for InviteFlags { + fn decode(value: >::ValueRef) -> Result { + let raw = u64::decode(value)?; + + Ok(Self::from_bits(raw).unwrap()) + } +} + #[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] From 133b03f1c8acbf073a9c21814ac216468b5e74c2 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 22:22:39 -0400 Subject: [PATCH 32/38] Use distinct type `DefaultReaction` --- src/types/schema/channel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index d716399..68abc79 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -5,7 +5,7 @@ use bitflags::bitflags; use serde::{Deserialize, Serialize}; -use crate::types::ChannelType; +use crate::types::{ChannelType, DefaultReaction}; use crate::types::{entities::PermissionOverwrite, Snowflake}; #[derive(Debug, Deserialize, Serialize, Default, PartialEq, PartialOrd)] @@ -48,7 +48,7 @@ pub struct ChannelModifySchema { pub nsfw: Option, pub rtc_region: Option, pub default_auto_archive_duration: Option, - pub default_reaction_emoji: Option, + pub default_reaction_emoji: Option, pub flags: Option, pub default_thread_rate_limit_per_user: Option, pub video_quality_mode: Option, From 450aa9f4407dd6c26933edf197d08c8f248862dc Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 22:24:03 -0400 Subject: [PATCH 33/38] Update fields for backend/sqlx compatibility. --- src/types/entities/invite.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/types/entities/invite.rs b/src/types/entities/invite.rs index e9c9bd8..8455f16 100644 --- a/src/types/entities/invite.rs +++ b/src/types/entities/invite.rs @@ -5,7 +5,7 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use crate::types::{Snowflake, WelcomeScreenObject, Shared}; +use crate::types::{Snowflake, WelcomeScreenObject, Shared, InviteFlags, InviteType, InviteTargetType}; use super::guild::GuildScheduledEvent; use super::{Application, Channel, GuildMember, NSFWLevel, User}; @@ -13,25 +13,35 @@ use super::{Application, Channel, GuildMember, NSFWLevel, User}; /// Represents a code that when used, adds a user to a guild or group DM channel, or creates a relationship between two users. /// See #[derive(Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Invite { pub approximate_member_count: Option, pub approximate_presence_count: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub channel: Option, pub code: String, pub created_at: Option>, pub expires_at: Option>, - pub flags: Option, + pub flags: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub guild: Option, pub guild_id: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub guild_scheduled_event: Option>, #[serde(rename = "type")] - pub invite_type: Option, + #[cfg_attr(feature = "sqlx", sqlx(rename = "type"))] + pub invite_type: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub inviter: Option, - pub max_age: Option, - pub max_uses: Option, + pub max_age: Option, + pub max_uses: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub stage_instance: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub target_application: Option, - pub target_type: Option, + #[cfg_attr(feature = "sqlx", sqlx(rename = "target_user_type"))] + pub target_type: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub target_user: Option, pub temporary: Option, pub uses: Option, From 9f281879a9e0b98a7c81d1b7e5cd8eff6e229dd2 Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 22:24:28 -0400 Subject: [PATCH 34/38] Update derive for backend/sqlx compatibility. --- src/types/entities/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index 262897c..3d6b4ca 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -177,7 +177,7 @@ pub struct ThreadMember { pub member: Option>, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd)] /// Specifies the emoji to use as the default way to react to a [ChannelType::GuildForum] or [ChannelType::GuildMedia] channel post. /// /// # Reference From cab4cb1ce63dc79b127ac60540246c50e791da5f Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 23:07:04 -0400 Subject: [PATCH 35/38] Write custom serialize/deserialize impl's for InviteFlags --- src/types/errors.rs | 3 +++ src/types/schema/channel.rs | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/types/errors.rs b/src/types/errors.rs index f0a488c..f417aef 100644 --- a/src/types/errors.rs +++ b/src/types/errors.rs @@ -21,6 +21,9 @@ pub enum Error { #[error(transparent)] Guild(#[from] GuildError), + + #[error("Invalid flags value: {0}")] + InvalidFlags(u64) } #[derive(Debug, PartialEq, Eq, thiserror::Error)] diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 68abc79..da49aec 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -2,10 +2,14 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use std::error::Error as StdError; +use std::num::ParseIntError; use bitflags::bitflags; -use serde::{Deserialize, Serialize}; +use bitflags::parser::ParseHex; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::de::{DeserializeOwned, Visitor}; -use crate::types::{ChannelType, DefaultReaction}; +use crate::types::{ChannelType, DefaultReaction, Error}; use crate::types::{entities::PermissionOverwrite, Snowflake}; #[derive(Debug, Deserialize, Serialize, Default, PartialEq, PartialOrd)] @@ -131,12 +135,39 @@ impl Default for CreateChannelInviteSchema { } bitflags! { - #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct InviteFlags: u64 { const GUEST = 1 << 0; } } +impl Serialize for InviteFlags { + fn serialize(&self, serializer: S) -> Result { + self.bits().to_string().serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for InviteFlags { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + struct FlagsVisitor; + + impl<'de> Visitor<'de> for FlagsVisitor + { + type Value = InviteFlags; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("a raw u64 value of flags") + } + + fn visit_u64(self, v: u64) -> Result where E: serde::de::Error { + InviteFlags::from_bits(v).ok_or(serde::de::Error::custom(Error::InvalidFlags(v))) + } + } + + deserializer.deserialize_u64(FlagsVisitor) + } +} + #[cfg(feature = "sqlx")] impl sqlx::Type for InviteFlags { fn type_info() -> sqlx::mysql::MySqlTypeInfo { From 0f1e693d6041c3b9634b0d1b55a2f7598822e1cc Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 23:45:22 -0400 Subject: [PATCH 36/38] Clear warnings --- src/types/schema/channel.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index da49aec..7f99394 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -2,12 +2,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use std::error::Error as StdError; -use std::num::ParseIntError; use bitflags::bitflags; -use bitflags::parser::ParseHex; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde::de::{DeserializeOwned, Visitor}; +use serde::de::Visitor; use crate::types::{ChannelType, DefaultReaction, Error}; use crate::types::{entities::PermissionOverwrite, Snowflake}; From c34b1da8d050efaf7d1d6b226b2275754a7bccdf Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Tue, 4 Jun 2024 23:53:21 -0400 Subject: [PATCH 37/38] Add InviteFlags::VIEWED --- src/types/schema/channel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 7f99394..60caf39 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -6,8 +6,7 @@ use bitflags::bitflags; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::de::Visitor; -use crate::types::{ChannelType, DefaultReaction, Error}; -use crate::types::{entities::PermissionOverwrite, Snowflake}; +use crate::types::{ChannelType, DefaultReaction, Error, entities::PermissionOverwrite, Snowflake}; #[derive(Debug, Deserialize, Serialize, Default, PartialEq, PartialOrd)] #[serde(rename_all = "snake_case")] @@ -135,6 +134,7 @@ bitflags! { #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct InviteFlags: u64 { const GUEST = 1 << 0; + const VIEWED = 1 << 1; } } From 0d01536f5962d83e9047e9d0ae54422dcd5c398f Mon Sep 17 00:00:00 2001 From: Quat3rnion Date: Wed, 5 Jun 2024 00:46:29 -0400 Subject: [PATCH 38/38] Remove double bound for E --- src/types/schema/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index 60caf39..260b10e 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -156,7 +156,7 @@ impl<'de> Deserialize<'de> for InviteFlags { formatter.write_str("a raw u64 value of flags") } - fn visit_u64(self, v: u64) -> Result where E: serde::de::Error { + fn visit_u64(self, v: u64) -> Result { InviteFlags::from_bits(v).ok_or(serde::de::Error::custom(Error::InvalidFlags(v))) } }