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 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, 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 851bfda..260b10e 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -3,10 +3,10 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use bitflags::bitflags; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::de::Visitor; -use crate::types::ChannelType; -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")] @@ -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, @@ -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, } @@ -131,15 +131,79 @@ 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; + const VIEWED = 1 << 1; + } +} + +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 { + 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 { + 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")] +#[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,