Add partial emoji and custom reaction types, refine SQLx mapping
This commit is contained in:
parent
590a6d6828
commit
bec0269e70
|
@ -3,6 +3,7 @@
|
|||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_aux::prelude::deserialize_number_from_string;
|
||||
|
||||
use crate::types::{config::types::subconfigs::register::{
|
||||
DateOfBirthConfiguration, PasswordConfiguration, RegistrationEmailConfiguration,
|
||||
|
@ -22,6 +23,7 @@ pub struct RegisterConfiguration {
|
|||
pub allow_multiple_accounts: bool,
|
||||
pub block_proxies: bool,
|
||||
pub incrementing_discriminators: bool,
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||
pub default_rights: Rights,
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,9 @@ pub struct Channel {
|
|||
pub managed: Option<bool>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub member: Option<ThreadMember>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub member_count: Option<i32>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub message_count: Option<i32>,
|
||||
pub name: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
|
@ -75,6 +77,7 @@ pub struct Channel {
|
|||
#[cfg(not(feature = "sqlx"))]
|
||||
#[cfg_attr(feature = "client", observe_option_vec)]
|
||||
pub permission_overwrites: Option<Vec<Shared<PermissionOverwrite>>>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub permissions: Option<String>,
|
||||
pub position: Option<i32>,
|
||||
pub rate_limit_per_user: Option<i32>,
|
||||
|
@ -85,6 +88,7 @@ pub struct Channel {
|
|||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub thread_metadata: Option<ThreadMetadata>,
|
||||
pub topic: Option<String>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub total_message_sent: Option<i32>,
|
||||
pub user_limit: Option<i32>,
|
||||
pub video_quality_mode: Option<i32>,
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::fmt::Debug;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::Shared;
|
||||
use crate::types::{PartialEmoji, Shared};
|
||||
use crate::types::entities::User;
|
||||
use crate::types::Snowflake;
|
||||
|
||||
|
@ -66,3 +66,18 @@ impl PartialEq for Emoji {
|
|||
|| self.available != other.available)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PartialEmoji> for Emoji {
|
||||
fn from(value: PartialEmoji) -> Self {
|
||||
Self {
|
||||
id: value.id.unwrap_or_default(), // TODO: this should be handled differently
|
||||
name: Some(value.name),
|
||||
roles: None,
|
||||
user: None,
|
||||
require_colons: Some(value.animated),
|
||||
managed: None,
|
||||
animated: Some(value.animated),
|
||||
available: None,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ pub struct Guild {
|
|||
pub emojis: Vec<Shared<Emoji>>,
|
||||
pub explicit_content_filter: Option<ExplicitContentFilterLevel>,
|
||||
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
|
||||
pub features: Option<GuildFeaturesList>,
|
||||
pub features: GuildFeaturesList,
|
||||
pub icon: Option<String>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub icon_hash: Option<String>,
|
||||
|
@ -111,7 +111,7 @@ pub struct Guild {
|
|||
#[cfg_attr(feature = "client", observe_option_vec)]
|
||||
pub webhooks: Option<Vec<Shared<Webhook>>>,
|
||||
#[cfg(feature = "sqlx")]
|
||||
pub welcome_screen: Option<sqlx::types::Json<WelcomeScreenObject>>,
|
||||
pub welcome_screen: sqlx::types::Json<Option<WelcomeScreenObject>>,
|
||||
#[cfg(not(feature = "sqlx"))]
|
||||
pub welcome_screen: Option<WelcomeScreenObject>,
|
||||
pub widget_channel_id: Option<Snowflake>,
|
||||
|
|
|
@ -16,7 +16,9 @@ use super::{Application, Channel, GuildMember, NSFWLevel, User};
|
|||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||
pub struct Invite {
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub approximate_member_count: Option<i32>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub approximate_presence_count: Option<i32>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub channel: Option<Channel>,
|
||||
|
@ -45,7 +47,7 @@ pub struct Invite {
|
|||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub target_user: Option<User>,
|
||||
pub temporary: Option<bool>,
|
||||
pub uses: Option<i32>,
|
||||
pub uses: Option<u32>,
|
||||
}
|
||||
|
||||
/// The guild an invite is for.
|
||||
|
@ -77,16 +79,16 @@ impl From<Guild> for InviteGuild {
|
|||
icon: value.icon,
|
||||
splash: value.splash,
|
||||
verification_level: value.verification_level.unwrap_or_default(),
|
||||
features: value.features.unwrap_or_default(),
|
||||
features: value.features,
|
||||
vanity_url_code: value.vanity_url_code,
|
||||
description: value.description,
|
||||
banner: value.banner,
|
||||
premium_subscription_count: value.premium_subscription_count,
|
||||
nsfw_deprecated: None,
|
||||
nsfw_level: value.nsfw_level.unwrap_or_default(),
|
||||
welcome_screen: value.welcome_screen.map(|obj| {
|
||||
welcome_screen: value.welcome_screen.0.map(|obj| {
|
||||
#[cfg(feature = "sqlx")]
|
||||
let res = obj.0;
|
||||
let res = obj;
|
||||
#[cfg(not(feature = "sqlx"))]
|
||||
let res = obj;
|
||||
res
|
||||
|
|
|
@ -75,13 +75,14 @@ pub struct Message {
|
|||
pub interaction: Option<MessageInteraction>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub thread: Option<Channel>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
#[cfg(feature = "sqlx")]
|
||||
pub components: Option<sqlx::types::Json<Vec<Component>>>,
|
||||
#[cfg(not(feature = "sqlx"))]
|
||||
pub components: Option<Vec<Component>>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub sticker_items: Option<Vec<StickerItem>>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub stickers: Option<Vec<Sticker>>,
|
||||
pub position: Option<i32>,
|
||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||
pub role_subscription_data: Option<RoleSubscriptionData>,
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ impl PartialEq for Message {
|
|||
&& self.thread == other.thread
|
||||
&& self.components == other.components
|
||||
&& self.sticker_items == other.sticker_items
|
||||
&& self.position == other.position
|
||||
// && self.position == other.position
|
||||
&& self.role_subscription_data == other.role_subscription_data
|
||||
}
|
||||
}
|
||||
|
@ -125,12 +126,22 @@ impl PartialEq for Message {
|
|||
/// # Reference
|
||||
/// See <https://discord-userdoccers.vercel.app/resources/message#message-reference-object>
|
||||
pub struct MessageReference {
|
||||
#[serde(rename = "type")]
|
||||
pub reference_type: MessageReferenceType,
|
||||
pub message_id: Snowflake,
|
||||
pub channel_id: Snowflake,
|
||||
pub guild_id: Option<Snowflake>,
|
||||
pub fail_if_not_exists: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Ord, PartialOrd)]
|
||||
pub enum MessageReferenceType {
|
||||
/// A standard reference used by replies and system messages
|
||||
Default = 0,
|
||||
/// A reference used to point to a message at a point in time
|
||||
Forward = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct MessageInteraction {
|
||||
pub id: Snowflake,
|
||||
|
@ -405,3 +416,21 @@ bitflags! {
|
|||
const HAS_SNAPSHOT = 1 << 14;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct PartialEmoji {
|
||||
#[serde(default)]
|
||||
pub id: Option<Snowflake>,
|
||||
pub name: String,
|
||||
#[serde(default)]
|
||||
pub animated: bool
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, PartialOrd)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
|
||||
#[repr(u8)]
|
||||
pub enum ReactionType {
|
||||
Normal = 0,
|
||||
Burst = 1, // The dreaded super reactions
|
||||
}
|
|
@ -59,7 +59,7 @@ pub struct GetChannelMessagesSchema {
|
|||
/// Between 1 and 100, defaults to 50.
|
||||
pub limit: Option<i32>,
|
||||
#[serde(flatten)]
|
||||
pub anchor: ChannelMessagesAnchor,
|
||||
pub anchor: Option<ChannelMessagesAnchor>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
|
||||
|
@ -74,21 +74,21 @@ impl GetChannelMessagesSchema {
|
|||
pub fn before(anchor: Snowflake) -> Self {
|
||||
Self {
|
||||
limit: None,
|
||||
anchor: ChannelMessagesAnchor::Before(anchor),
|
||||
anchor: Some(ChannelMessagesAnchor::Before(anchor)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn around(anchor: Snowflake) -> Self {
|
||||
Self {
|
||||
limit: None,
|
||||
anchor: ChannelMessagesAnchor::Around(anchor),
|
||||
anchor: Some(ChannelMessagesAnchor::Around(anchor)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn after(anchor: Snowflake) -> Self {
|
||||
Self {
|
||||
limit: None,
|
||||
anchor: ChannelMessagesAnchor::After(anchor),
|
||||
anchor: Some(ChannelMessagesAnchor::After(anchor)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::types::entities::{
|
||||
AllowedMention, Component, Embed, MessageReference, PartialDiscordFileAttachment,
|
||||
};
|
||||
use crate::types::{Attachment, MessageFlags, MessageType, Snowflake};
|
||||
use crate::types::{Attachment, MessageFlags, MessageType, ReactionType, Snowflake};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
@ -118,13 +118,21 @@ pub struct MessageAck {
|
|||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd)]
|
||||
pub struct MessageModifySchema {
|
||||
content: Option<String>,
|
||||
embeds: Option<Vec<Embed>>,
|
||||
embed: Option<Embed>,
|
||||
allowed_mentions: Option<AllowedMention>,
|
||||
components: Option<Vec<Component>>,
|
||||
flags: Option<MessageFlags>,
|
||||
files: Option<Vec<u8>>,
|
||||
payload_json: Option<String>,
|
||||
attachments: Option<Vec<Attachment>>,
|
||||
pub content: Option<String>,
|
||||
pub embeds: Option<Vec<Embed>>,
|
||||
pub embed: Option<Embed>,
|
||||
pub allowed_mentions: Option<AllowedMention>,
|
||||
pub components: Option<Vec<Component>>,
|
||||
pub flags: Option<MessageFlags>,
|
||||
pub files: Option<Vec<u8>>,
|
||||
pub payload_json: Option<String>,
|
||||
pub attachments: Option<Vec<Attachment>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd)]
|
||||
pub struct ReactionQuerySchema {
|
||||
pub after: Option<Snowflake>,
|
||||
pub limit: Option<u32>,
|
||||
#[serde(rename = "type")]
|
||||
pub reaction_type: Option<ReactionType>
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
// 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::num::ParseIntError;
|
||||
use std::str::FromStr;
|
||||
use bitflags::bitflags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
use sqlx::{{Decode, Encode, MySql}, database::{HasArguments, HasValueRef}, encode::IsNull, error::BoxDynError, mysql::MySqlValueRef};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use crate::types::UserFlags;
|
||||
|
||||
bitflags! {
|
||||
/// Rights are instance-wide, per-user permissions for everything you may perform on the instance,
|
||||
|
@ -18,7 +18,7 @@ bitflags! {
|
|||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.spacebar.chat/setup/server/security/rights/>
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, chorus_macros::SqlxBitFlags)]
|
||||
pub struct Rights: u64 {
|
||||
/// All rights
|
||||
const OPERATOR = 1 << 0;
|
||||
|
@ -132,32 +132,27 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Type<MySql> for Rights {
|
||||
fn type_info() -> <sqlx::MySql as sqlx::Database>::TypeInfo {
|
||||
u64::type_info()
|
||||
}
|
||||
impl FromStr for Rights {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn compatible(ty: &<sqlx::MySql as sqlx::Database>::TypeInfo) -> bool {
|
||||
u64::compatible(ty)
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
s.parse::<u64>().map(Rights::from_bits).map(|f| f.unwrap_or(Rights::empty()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl<'q> Encode<'q, MySql> for Rights {
|
||||
fn encode_by_ref(&self, buf: &mut <MySql as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
|
||||
<u64 as Encode<MySql>>::encode_by_ref(&self.0.0, buf)
|
||||
impl Serialize for Rights {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&self.bits().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl<'r> Decode<'r, MySql> for Rights {
|
||||
fn decode(value: <MySql as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
|
||||
let raw = <u64 as Decode<MySql>>::decode(value)?;
|
||||
Ok(Rights::from_bits(raw).unwrap())
|
||||
}
|
||||
}
|
||||
impl<'de> Deserialize<'de> for Rights {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
||||
let s = String::deserialize(deserializer)?.parse::<u64>().map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(Rights::from_bits(s).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Rights {
|
||||
pub fn any(&self, permission: Rights, check_operator: bool) -> bool {
|
||||
|
|
|
@ -8,6 +8,9 @@ use std::{
|
|||
};
|
||||
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use sqlx::{MySql, TypeInfo};
|
||||
use sqlx::database::HasArguments;
|
||||
use sqlx::encode::IsNull;
|
||||
#[cfg(feature = "sqlx")]
|
||||
use sqlx::Type;
|
||||
|
||||
|
@ -19,8 +22,6 @@ const EPOCH: i64 = 1420070400000;
|
|||
/// # Reference
|
||||
/// See <https://discord.com/developers/docs/reference#snowflakes>
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[cfg_attr(feature = "sqlx", derive(Type))]
|
||||
#[cfg_attr(feature = "sqlx", sqlx(transparent))]
|
||||
pub struct Snowflake(pub u64);
|
||||
|
||||
impl Snowflake {
|
||||
|
@ -102,6 +103,24 @@ impl<'de> serde::Deserialize<'de> for Snowflake {
|
|||
}
|
||||
}
|
||||
|
||||
impl sqlx::Type<sqlx::MySql> for Snowflake {
|
||||
fn type_info() -> <sqlx::MySql as sqlx::Database>::TypeInfo {
|
||||
<String as sqlx::Type<sqlx::MySql>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'q> sqlx::Encode<'q, sqlx::MySql> for Snowflake {
|
||||
fn encode_by_ref(&self, buf: &mut <sqlx::MySql as sqlx::database::HasArguments<'q>>::ArgumentBuffer) -> sqlx::encode::IsNull {
|
||||
<String as sqlx::Encode<'q, sqlx::MySql>>::encode_by_ref(&self.0.to_string(), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> sqlx::Decode<'d, sqlx::MySql> for Snowflake {
|
||||
fn decode(value: <sqlx::MySql as sqlx::database::HasValueRef<'d>>::ValueRef) -> Result<Self, sqlx::error::BoxDynError> {
|
||||
<String as sqlx::Decode<'d, sqlx::MySql>>::decode(value).map(|s| s.parse::<u64>().map(Snowflake).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use chrono::{DateTime, Utc};
|
||||
|
|
Loading…
Reference in New Issue