diff --git a/Cargo.toml b/Cargo.toml index 055071e..1c5a178 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,11 @@ version = "0.1.0" license = "AGPL-3" edition = "2021" +[features] +default = ["client"] +backend = ["poem", "sqlx"] +client = [] + [dependencies] tokio = {version = "1.28.1", features = ["rt", "macros", "rt-multi-thread", "full"]} serde = {version = "1.0.163", features = ["derive"]} @@ -28,7 +33,7 @@ bigdecimal = "0.3.1" num-bigint = "0.4.3" lazy_static = "1.4.0" poem = { version = "1.3.55", optional = true } -sqlx = { version = "0.6.3", features = ["mysql", "sqlite", "json", "chrono", "ipnetwork", "runtime-tokio-native-tls", "any"], optional = true } +sqlx = { git = "https://github.com/zert3x/sqlx", branch="feature/skip", features = ["mysql", "sqlite", "json", "chrono", "ipnetwork", "runtime-tokio-native-tls", "any"], optional = true } thiserror = "1.0.40" jsonwebtoken = "8.3.0" diff --git a/README.md b/README.md index 1161e10..37dc52e 100644 --- a/README.md +++ b/README.md @@ -31,24 +31,77 @@ ## Roadmap - -Core functionality: - +### Core Functionality - [x] Rate Limiter (hint: couldn't be fully tested due to [an Issue with the Spacebar Server](https://github.com/spacebarchat/server/issues/1022)) -- [x] Login (conventional way) (Guess what? Found [an Issue with the Spacebar Server](https://github.com/spacebarchat/server/pull/1043) :3) -- [ ] 2FA -- [x] Registration (encountered another [Issue with the Spacebar Server](https://github.com/spacebarchat/server/issues/1040) which makes some error messages an empty string) -- [x] Gateway Events, multithreaded -- [x] Sending messages (Text, Images, Attachments) -- [x] Events (Message, User, Channel, etc.) -- [ ] Adding, deleting and editing channels -- [ ] User profile customization +- [x] [Login (the conventional way)](https://github.com/polyphony-chat/chorus/issues/1) +- [ ] [2FA](https://github.com/polyphony-chat/chorus/issues/40) +- [x] [Registration](https://github.com/polyphony-chat/chorus/issues/1) + +### Messaging +- [x] [Sending messages](https://github.com/polyphony-chat/chorus/issues/23) +- [ ] [Events (Message, User, Channel, etc.)](https://github.com/polyphony-chat/chorus/issues/51) +- [x] Channel creation +- [x] Channel deletion +- [ ] Channel management (name, description, icon, etc.) - [ ] Deleting messages +- [ ] Message threads +- [ ] Reactions +- [ ] Message Search +- [ ] Message history + +### User Management +- [ ] User profile customization +- [x] Gettings users and user profiles +- [ ] Friend requests +- [ ] Blocking users +- [ ] User presence (online, offline, idle, etc.) +- [ ] User status (custom status, etc.) +- [x] Account deletion + +### Additional Features - [ ] Emoji - [ ] Stickers -- [ ] Listing users and user profiles -- [ ] Message threads - [ ] Forum channels +- [ ] Server discovery +- [ ] Server templates + +### Voice and Video +- [ ] Voice chat support +- [ ] Video chat support + +### Permissions and Roles +- [ ] Role management (creation, deletion, modification) +- [ ] Permission management (assigning and revoking permissions) +- [ ] Channel-specific permissions +- [ ] Role-based access control + +### Server Management +- [x] Server creation +- [x] Server deletion +- [ ] Server settings management (name, description, icon, etc.) +- [ ] Member management (adding, removing, banning, unbanning) +- [ ] Server invites + +### Moderation +- [ ] Channel moderation (slow mode, etc.) +- [ ] User sanctions (mute, kick, ban) +- [ ] Audit logs + +### Embeds and Rich Content +- [x] Sending rich content in messages (links, images, videos) +- [ ] Customizing embed appearance (title, description, color, fields) + +### Notifications and Push Notifications +- [ ] Notification settings management + +### Webhooks +- [ ] Webhook creation and management +- [ ] Handling incoming webhook events + +### Documentation and Examples +- [ ] Comprehensive documentation +- [ ] Example usage and code snippets +- [ ] Tutorials and guides [Rust]: https://img.shields.io/badge/Rust-orange?style=plastic&logo=rust [Rust-url]: https://www.rust-lang.org/ diff --git a/src/lib.rs b/src/lib.rs index aa73302..a849188 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,14 @@ +#[cfg(feature = "client")] pub mod api; pub mod errors; +#[cfg(feature = "client")] pub mod gateway; +#[cfg(feature = "client")] pub mod instance; +#[cfg(feature = "client")] pub mod limit; pub mod types; +#[cfg(feature = "client")] pub mod voice; use url::{ParseError, Url}; diff --git a/src/types/entities/application.rs b/src/types/entities/application.rs index 96fda98..2aa0515 100644 --- a/src/types/entities/application.rs +++ b/src/types/entities/application.rs @@ -1,4 +1,5 @@ use crate::types::utils::Snowflake; +use crate::types::{Team, User}; use bitflags::{bitflags, Flags}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -7,7 +8,7 @@ use serde_repr::{Serialize_repr, Deserialize_repr}; use sqlx::FromRow; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[cfg_attr(feature = "sqlx", derive(FromRow))] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Application { pub id: Snowflake, pub name: String, @@ -22,7 +23,8 @@ pub struct Application { pub bot_public: bool, pub bot_require_code_grant: bool, pub verify_key: String, - pub owner_id: Snowflake, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub owner: User, pub flags: u64, #[cfg(feature = "sqlx")] pub redirect_uris: Option>>, @@ -36,7 +38,6 @@ pub struct Application { pub integration_require_code_grant: bool, pub discoverability_state: i64, pub discovery_eligibility_flags: i64, - pub bot_user_id: Snowflake, #[cfg(feature = "sqlx")] pub tags: Option>>, #[cfg(not(feature = "sqlx"))] @@ -48,7 +49,8 @@ pub struct Application { pub install_params: Option, pub terms_of_service_url: Option, pub privacy_policy_url: Option, - pub team_id: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub team: Option, } impl Application { diff --git a/src/types/entities/attachment.rs b/src/types/entities/attachment.rs index c93ab8f..210f738 100644 --- a/src/types/entities/attachment.rs +++ b/src/types/entities/attachment.rs @@ -1,8 +1,10 @@ +use crate::types::Message; use serde::{Deserialize, Serialize}; use crate::types::utils::Snowflake; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Attachment { pub id: Snowflake, pub filename: String, @@ -13,11 +15,11 @@ pub struct Attachment { pub proxy_url: String, pub height: Option, pub width: Option, - pub message_id: Snowflake, pub ephemeral: Option, pub duration_secs: Option, pub waveform: Option, #[serde(skip_serializing)] + #[cfg_attr(feature = "sqlx", sqlx(default))] pub content: Vec, } diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index 39d300e..a0c2bcb 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -1,3 +1,4 @@ +use chrono::Utc; use serde::{Deserialize, Serialize}; use serde_aux::prelude::{deserialize_number_from_string, deserialize_option_number_from_string, deserialize_string_from_number}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -8,12 +9,17 @@ use crate::types::{ }; #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Channel { pub id: Snowflake, + pub created_at: chrono::DateTime, #[serde(rename = "type")] pub channel_type: ChannelType, pub guild_id: Option, pub position: Option, + #[cfg(feature = "sqlx")] + pub permission_overwrites: Option>>, + #[cfg(not(feature = "sqlx"))] pub permission_overwrites: Option>, pub name: Option, pub topic: Option, @@ -22,24 +28,37 @@ pub struct Channel { pub bitrate: Option, pub user_limit: Option, pub rate_limit_per_user: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub recipients: Option>, pub icon: Option, - pub owner_id: Option, - pub application_id: Option, + pub owner_id: Option, + pub application_id: Option, + pub managed: Option, pub parent_id: Option, pub last_pin_timestamp: Option, pub rtc_region: Option, pub video_quality_mode: Option, pub message_count: Option, pub member_count: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub thread_metadata: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub member: Option, pub default_auto_archive_duration: Option, pub permissions: Option, pub flags: Option, pub total_message_sent: Option, + #[cfg(feature = "sqlx")] + pub available_tags: Option>>, + #[cfg(not(feature = "sqlx"))] pub available_tags: Option>, + #[cfg(feature = "sqlx")] + pub applied_tags: Option>>, + #[cfg(not(feature = "sqlx"))] pub applied_tags: Option>, + #[cfg(feature = "sqlx")] + pub default_reaction_emoji: Option>, + #[cfg(not(feature = "sqlx"))] pub default_reaction_emoji: Option, pub default_thread_rate_limit_per_user: Option, pub default_sort_order: Option, @@ -101,6 +120,7 @@ pub struct DefaultReaction { } #[derive(Default, Clone, Copy, Debug, Serialize_repr, Deserialize_repr, PartialEq, Eq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[repr(i32)] pub enum ChannelType { diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs index 1e83b64..c9811af 100644 --- a/src/types/entities/emoji.rs +++ b/src/types/entities/emoji.rs @@ -2,14 +2,18 @@ use serde::{Deserialize, Serialize}; use serde_aux::prelude::deserialize_option_number_from_string; use crate::types::entities::User; +use crate::types::{Guild, Snowflake}; -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, Default)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Emoji { - #[serde(default)] - #[serde(deserialize_with = "deserialize_option_number_from_string")] - pub id: Option, + pub id: Option, pub name: Option, - pub roles: Option>, + #[cfg(feature = "sqlx")] + pub roles: Option>>, + #[cfg(not(feature = "sqlx"))] + pub roles: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub user: Option, pub require_colons: Option, pub managed: Option, diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index adafb4b..c79ee1d 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -9,7 +9,8 @@ use crate::types::{ }; /// See https://discord.com/developers/docs/resources/guild -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Guild { pub id: Snowflake, pub name: Option, @@ -17,24 +18,27 @@ pub struct Guild { pub icon_hash: Option, pub splash: Option, pub discovery_splash: Option, - pub owner: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub owner: bool, // True if requesting user is owner pub owner_id: Option, pub permissions: Option, pub afk_channel_id: Option, pub afk_timeout: Option, pub widget_enabled: Option, pub widget_channel_id: Option, - pub widget_channel: Option, pub verification_level: Option, pub default_message_notifications: Option, pub explicit_content_filter: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub roles: Vec, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub emojis: Vec, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub features: Option>, pub application_id: Option, pub system_channel_id: Option, pub system_channel_flags: Option, - pub rules_channel_id: Option, + pub rules_channel_id: Option, pub rules_channel: Option, pub max_presences: Option, pub max_members: Option, @@ -45,47 +49,48 @@ pub struct Guild { pub premium_subscription_count: Option, pub preferred_locale: Option, pub public_updates_channel_id: Option, - pub public_updates_channel: Option, pub max_video_channel_users: Option, pub max_stage_video_channel_users: Option, pub approximate_member_count: Option, pub approximate_presence_count: Option, - pub member_count: Option, - pub presence_count: Option, + #[cfg(feature = "sqlx")] + pub welcome_screen: Option>, + #[cfg(not(feature = "sqlx"))] pub welcome_screen: Option, pub nsfw_level: Option, - pub nsfw: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub stickers: Option>, pub premium_progress_bar_enabled: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub joined_at: String, - pub afk_channel: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub bans: Option>, pub primary_category_id: Option, pub large: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub channels: Option>, - pub template_id: Option, - pub template: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub invites: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub voice_states: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub webhooks: Option>, pub mfa_level: Option, pub region: Option, - pub unavailable: Option, - pub parent: Option, } /// See https://docs.spacebar.chat/routes/#get-/guilds/-guild_id-/bans/-user- -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildBan { - pub id: Snowflake, pub user_id: Snowflake, pub guild_id: Snowflake, - pub executor_id: Snowflake, pub reason: Option, } /// See https://docs.spacebar.chat/routes/#cmp--schemas-invite -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildInvite { pub code: String, pub temporary: Option, @@ -106,13 +111,13 @@ pub struct GuildInvite { pub vanity_url: Option, } -#[derive(Serialize, Deserialize, Debug, Default)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] pub struct UnavailableGuild { id: String, unavailable: bool, } -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] pub struct GuildCreateResponse { pub id: String, } diff --git a/src/types/entities/integration.rs b/src/types/entities/integration.rs index d4ed911..8076e70 100644 --- a/src/types/entities/integration.rs +++ b/src/types/entities/integration.rs @@ -7,6 +7,7 @@ use crate::types::{ }; #[derive(Default, Debug, Deserialize, Serialize, Clone)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// See https://discord.com/developers/docs/resources/guild#integration-object-integration-structure pub struct Integration { pub id: Snowflake, @@ -19,11 +20,14 @@ pub struct Integration { pub enabled_emoticons: Option, pub expire_behaviour: Option, pub expire_grace_period: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub user: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub account: IntegrationAccount, pub synced_at: Option>, pub subscriber_count: Option, pub revoked: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub application: Option, pub scopes: Option>, } diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index afb7d83..484a575 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -8,43 +8,62 @@ use crate::types::{ utils::Snowflake, }; -#[derive(Debug, Serialize, Deserialize, Default)] +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Message { - id: Snowflake, + pub id: Snowflake, pub channel_id: Snowflake, - author: User, - content: String, - timestamp: String, - edited_timestamp: Option, - tts: bool, - mention_everyone: bool, - mentions: Option>, - mention_roles: Vec, - mention_channels: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub author: User, + pub content: String, + pub timestamp: String, + pub edited_timestamp: Option, + pub tts: bool, + pub mention_everyone: bool, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub mentions: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub mention_roles: Vec, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub mention_channels: Option>, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub attachments: Vec, - embeds: Vec, - reactions: Option>, - nonce: Option, - pinned: bool, - webhook_id: Option, + #[cfg(feature = "sqlx")] + pub embeds: Vec>, + #[cfg(not(feature = "sqlx"))] + pub embeds: Vec, + #[cfg(feature = "sqlx")] + pub reactions: Option>>, + #[cfg(not(feature = "sqlx"))] + pub reactions: Option>, + pub nonce: Option, + pub pinned: bool, + pub webhook_id: Option, #[serde(rename = "type")] - message_type: i32, - activity: Option, - application: Option, - application_id: Option, - message_reference: Option, - flags: Option, - referenced_message: Option>, - interaction: Option, - thread: Option, - components: Option>, - sticker_items: Option>, - stickers: Option>, - position: Option, - role_subscription_data: Option, + pub message_type: i32, + #[cfg(feature = "sqlx")] + pub activity: Option>, + #[cfg(not(feature = "sqlx"))] + pub activity: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] + pub application: Option, + pub application_id: Option, + #[cfg(feature = "sqlx")] + pub message_reference: Option>, + #[cfg(not(feature = "sqlx"))] + pub message_reference: Option, + pub flags: Option, + pub referenced_message: Option>, + pub interaction: Option, + pub thread: Option, + pub components: Option>, + pub sticker_items: Option>, + pub stickers: Option>, + pub position: Option, + pub role_subscription_data: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct MessageReference { pub message_id: Snowflake, pub channel_id: Snowflake, @@ -52,7 +71,7 @@ pub struct MessageReference { pub fail_if_not_exists: Option, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] pub struct MessageInteraction { pub id: Snowflake, #[serde(rename = "type")] @@ -62,7 +81,7 @@ pub struct MessageInteraction { pub member: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct AllowedMention { parse: Vec, roles: Vec, @@ -70,7 +89,7 @@ pub struct AllowedMention { replied_user: bool, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AllowedMentionType { Roles, @@ -78,16 +97,16 @@ pub enum AllowedMentionType { Everyone, } -#[derive(Debug, Serialize, Deserialize)] -struct ChannelMention { - id: Snowflake, - guild_id: Snowflake, +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ChannelMention { + pub id: Snowflake, + pub guild_id: Snowflake, #[serde(rename = "type")] channel_type: i32, name: String, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct Embed { title: Option, #[serde(rename = "type")] @@ -105,30 +124,30 @@ pub struct Embed { fields: Option>, } -#[derive(Debug, Serialize, Deserialize)] -struct EmbedFooter { +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct EmbedFooter { text: String, icon_url: Option, proxy_icon_url: Option, } -#[derive(Debug, Serialize, Deserialize)] -struct EmbedImage { +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct EmbedImage { url: String, proxy_url: String, height: Option, width: Option, } -#[derive(Debug, Serialize, Deserialize)] -struct EmbedThumbnail { +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct EmbedThumbnail { url: String, proxy_url: Option, height: Option, width: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] struct EmbedVideo { url: Option, proxy_url: Option, @@ -136,36 +155,36 @@ struct EmbedVideo { width: Option, } -#[derive(Debug, Serialize, Deserialize)] -struct EmbedProvider { +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct EmbedProvider { name: Option, url: Option, } -#[derive(Debug, Serialize, Deserialize)] -struct EmbedAuthor { +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct EmbedAuthor { name: String, url: Option, icon_url: Option, proxy_icon_url: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -struct EmbedField { +pub struct EmbedField { name: String, value: String, inline: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct Reaction { pub count: i32, pub me: bool, pub emoji: Emoji, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] pub enum Component { ActionRow = 1, Button = 2, @@ -177,7 +196,7 @@ pub enum Component { ChannelSelect = 8, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct MessageActivity { #[serde(rename = "type")] pub activity_type: i64, diff --git a/src/types/entities/role.rs b/src/types/entities/role.rs index a345528..a9e479b 100644 --- a/src/types/entities/role.rs +++ b/src/types/entities/role.rs @@ -3,7 +3,8 @@ use serde_aux::prelude::{deserialize_string_from_number, deserialize_option_numb use crate::types::utils::Snowflake; -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// See https://discord.com/developers/docs/topics/permissions#role-object pub struct RoleObject { pub id: Snowflake, @@ -21,7 +22,7 @@ pub struct RoleObject { pub tags: Option } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RoleSubscriptionData { pub role_subscription_listing_id: Snowflake, pub tier_name: String, diff --git a/src/types/entities/security_key.rs b/src/types/entities/security_key.rs index 09112cc..2cf8f66 100644 --- a/src/types/entities/security_key.rs +++ b/src/types/entities/security_key.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::types::utils::Snowflake; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct SecurityKey { pub id: String, pub user_id: String, diff --git a/src/types/entities/sticker.rs b/src/types/entities/sticker.rs index b350dd5..a3a79de 100644 --- a/src/types/entities/sticker.rs +++ b/src/types/entities/sticker.rs @@ -3,7 +3,8 @@ use serde_aux::prelude::{deserialize_option_number_from_string}; use crate::types::{entities::User, utils::Snowflake}; -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Sticker { #[serde(default)] pub id: Snowflake, @@ -16,14 +17,13 @@ pub struct Sticker { pub sticker_type: u8, pub format_type: u8, pub available: Option, - #[serde(default)] - #[serde(deserialize_with = "deserialize_option_number_from_string")] - pub guild_id: Option, + pub guild_id: Option, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub user: Option, pub sort_value: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct StickerItem { pub id: Snowflake, pub name: String, diff --git a/src/types/entities/team.rs b/src/types/entities/team.rs index 7c381a6..a6f2ef1 100644 --- a/src/types/entities/team.rs +++ b/src/types/entities/team.rs @@ -1,20 +1,23 @@ use serde::{Deserialize, Serialize}; use crate::types::entities::User; +use crate::types::Snowflake; -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Team { pub icon: Option, - pub id: u64, + pub id: Snowflake, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub members: Vec, pub name: String, - pub owner_user_id: u64, + pub owner_user_id: Snowflake, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] pub struct TeamMember { pub membership_state: u8, pub permissions: Vec, - pub team_id: u64, + pub team_id: Snowflake, pub user: User, } diff --git a/src/types/entities/template.rs b/src/types/entities/template.rs index dfbd98a..aa87251 100644 --- a/src/types/entities/template.rs +++ b/src/types/entities/template.rs @@ -7,18 +7,21 @@ use crate::types::{ }; /// See https://docs.spacebar.chat/routes/#cmp--schemas-template -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct GuildTemplate { pub code: String, pub name: String, pub description: Option, pub usage_count: Option, pub creator_id: Snowflake, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub creator: User, pub created_at: DateTime, pub updated_at: DateTime, pub source_guild_id: String, + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub source_guild: Vec, // Unsure how a {recursive: Guild} looks like, might be a Vec? + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub serialized_source_guild: Vec, - id: Snowflake, } diff --git a/src/types/entities/user.rs b/src/types/entities/user.rs index bcd8171..f6bf5c0 100644 --- a/src/types/entities/user.rs +++ b/src/types/entities/user.rs @@ -2,8 +2,6 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_aux::prelude::deserialize_option_number_from_string; use serde_json::{Map, Value}; -#[cfg(feature = "sqlx")] -use sqlx::{FromRow, Type}; use crate::types::{ errors::Error, @@ -11,7 +9,7 @@ use crate::types::{ }; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] -#[cfg_attr(feature = "sqlx", derive(Type))] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] pub struct UserData { pub valid_tokens_since: DateTime, pub hash: Option, @@ -24,36 +22,38 @@ impl User { } #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct User { pub id: Snowflake, - username: String, - discriminator: String, - avatar: Option, - bot: Option, - system: Option, - mfa_enabled: Option, - accent_color: Option, - locale: Option, - verified: Option, - email: Option, + pub username: String, + pub discriminator: String, + pub avatar: Option, + pub bot: Option, + pub system: Option, + pub mfa_enabled: Option, + pub accent_color: Option, + #[cfg_attr(feature = "sqlx", sqlx(default))] + pub locale: Option, + pub verified: Option, + pub email: Option, /// This field comes as either a string or a number as a string /// So we need to account for that #[serde(default)] #[serde(deserialize_with = "deserialize_option_number_from_string")] flags: Option, - premium_since: Option>, - premium_type: u8, - pronouns: Option, - public_flags: Option, - banner: Option, - bio: String, - theme_colors: Option>, - phone: Option, - nsfw_allowed: bool, - premium: bool, - purchased_flags: i32, - premium_usage_flags: Option, - disabled: Option, + pub premium_since: Option>, + pub premium_type: u8, + pub pronouns: Option, + pub public_flags: Option, + pub banner: Option, + pub bio: String, + pub theme_colors: Option>, + pub phone: Option, + pub nsfw_allowed: bool, + pub premium: bool, + pub purchased_flags: i32, + pub premium_usage_flags: Option, + pub disabled: Option, } #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] @@ -97,7 +97,7 @@ const CUSTOM_USER_FLAG_OFFSET: u64 = 1 << 32; bitflags::bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] - #[cfg_attr(feature = "sqlx", derive(Type))] + #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] pub struct UserFlags: u64 { const DISCORD_EMPLOYEE = 1 << 0; const PARTNERED_SERVER_OWNER = 1 << 1; diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index 6f3ac53..f34a159 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use crate::types::utils::Snowflake; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "lowercase")] pub enum UserStatus { #[default] @@ -15,6 +16,7 @@ pub enum UserStatus { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "lowercase")] pub enum UserTheme { #[default] @@ -23,6 +25,7 @@ pub enum UserTheme { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct UserSettings { pub afk_timeout: u16, pub allow_accessibility_detection: bool, @@ -30,6 +33,9 @@ pub struct UserSettings { pub animate_stickers: u8, pub contact_sync_enabled: bool, pub convert_emoticons: bool, + #[cfg(feature = "sqlx")] + pub custom_status: Option>, + #[cfg(not(feature = "sqlx"))] pub custom_status: Option, pub default_guilds_restricted: bool, pub detect_platform_accounts: bool, @@ -37,10 +43,19 @@ pub struct UserSettings { pub disable_games_tab: bool, pub enable_tts_command: bool, pub explicit_content_filter: u8, + #[cfg(feature = "sqlx")] + pub friend_source_flags: sqlx::types::Json, + #[cfg(not(feature = "sqlx"))] pub friend_source_flags: FriendSourceFlags, pub gateway_connected: bool, pub gif_auto_play: bool, + #[cfg(feature = "sqlx")] + pub guild_folders: sqlx::types::Json>, + #[cfg(not(feature = "sqlx"))] pub guild_folders: Vec, + #[cfg(feature = "sqlx")] + pub guild_positions: sqlx::types::Json>, + #[cfg(not(feature = "sqlx"))] pub guild_positions: Vec, pub inline_attachment_media: bool, pub inline_embed_media: bool, @@ -49,6 +64,9 @@ pub struct UserSettings { pub native_phone_integration_enabled: bool, pub render_embeds: bool, pub render_reactions: bool, + #[cfg(feature = "sqlx")] + pub restricted_guilds: sqlx::types::Json>, + #[cfg(not(feature = "sqlx"))] pub restricted_guilds: Vec, pub show_current_game: bool, pub status: UserStatus, @@ -73,11 +91,11 @@ impl Default for UserSettings { disable_games_tab: true, enable_tts_command: false, explicit_content_filter: 0, - friend_source_flags: FriendSourceFlags::default(), + friend_source_flags: Default::default(), gateway_connected: false, gif_auto_play: false, - guild_folders: Vec::new(), - guild_positions: Vec::new(), + guild_folders: Default::default(), + guild_positions: Default::default(), inline_attachment_media: true, inline_embed_media: true, locale: "en-US".to_string(), @@ -85,7 +103,7 @@ impl Default for UserSettings { native_phone_integration_enabled: true, render_embeds: true, render_reactions: true, - restricted_guilds: Vec::new(), + restricted_guilds: Default::default(), show_current_game: true, status: UserStatus::Online, stream_notifications_enabled: false, @@ -96,6 +114,7 @@ impl Default for UserSettings { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct CustomStatus { pub emoji_id: Option, pub emoji_name: Option, diff --git a/src/types/entities/voice_state.rs b/src/types/entities/voice_state.rs index 20045db..dd0ab15 100644 --- a/src/types/entities/voice_state.rs +++ b/src/types/entities/voice_state.rs @@ -7,14 +7,13 @@ use crate::types::{ }; /// See https://docs.spacebar.chat/routes/#cmp--schemas-voicestate -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct VoiceState { pub guild_id: Option, pub guild: Option, pub channel_id: Snowflake, - pub channel: Option, pub user_id: Snowflake, - pub user: Option, pub member: Option, pub session_id: Snowflake, pub token: Option, diff --git a/src/types/entities/webhook.rs b/src/types/entities/webhook.rs index 26fa81f..0097d81 100644 --- a/src/types/entities/webhook.rs +++ b/src/types/entities/webhook.rs @@ -6,27 +6,24 @@ use crate::types::{ }; /// See https://docs.spacebar.chat/routes/#cmp--schemas-webhook -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] pub struct Webhook { + pub id: Snowflake, #[serde(rename = "type")] pub webhook_type: i32, pub name: String, pub avatar: String, pub token: String, pub guild_id: Snowflake, - #[serde(skip_serializing_if = "Option::is_none")] - pub guild: Option, pub channel_id: Snowflake, - #[serde(skip_serializing_if = "Option::is_none")] - pub channel: Option, pub application_id: Snowflake, #[serde(skip_serializing_if = "Option::is_none")] - pub application: Option, - pub user_id: Snowflake, - #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub user: Option, - pub source_guild_id: Snowflake, #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "sqlx", sqlx(skip))] pub source_guild: Option, - pub id: Snowflake, + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, } diff --git a/src/types/interfaces/guild_welcome_screen.rs b/src/types/interfaces/guild_welcome_screen.rs index f799b1d..0260ab3 100644 --- a/src/types/interfaces/guild_welcome_screen.rs +++ b/src/types/interfaces/guild_welcome_screen.rs @@ -1,14 +1,14 @@ use crate::types::utils::Snowflake; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] pub struct WelcomeScreenObject { pub enabled: bool, pub description: Option, pub welcome_channels: Vec, } -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] pub struct WelcomeScreenChannel { pub channel_id: Snowflake, pub description: String,