summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--common/rust/Cargo.toml2
-rw-r--r--common/rust/src/config.rs5
-rw-r--r--common/rust/src/discord_models/application.rs38
-rw-r--r--common/rust/src/discord_models/audit_log.rs208
-rw-r--r--common/rust/src/discord_models/channel.rs341
-rw-r--r--common/rust/src/discord_models/emoji.rs15
-rw-r--r--common/rust/src/discord_models/gateway.rs118
-rw-r--r--common/rust/src/discord_models/guild.rs255
-rw-r--r--common/rust/src/discord_models/guild_template.rs18
-rw-r--r--common/rust/src/discord_models/invite.rs48
-rw-r--r--common/rust/src/discord_models/message_components.rs75
-rw-r--r--common/rust/src/discord_models/mod.rs16
-rw-r--r--common/rust/src/discord_models/permissions.rs21
-rw-r--r--common/rust/src/discord_models/slash_commands.rs104
-rw-r--r--common/rust/src/discord_models/stage_instance.rs19
-rw-r--r--common/rust/src/discord_models/teams.rs28
-rw-r--r--common/rust/src/discord_models/user.rs73
-rw-r--r--common/rust/src/discord_models/voice.rs30
-rw-r--r--common/rust/src/discord_models/webhook.rs29
-rw-r--r--common/rust/src/lib.rs4
-rw-r--r--common/rust/src/nats.rs4
-rw-r--r--common/rust/src/payloads.rs271
23 files changed, 1708 insertions, 16 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c25dbfe..e8b87c7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -205,6 +205,7 @@ name = "common"
version = "0.1.0"
dependencies = [
"config",
+ "enumflags2",
"hyper",
"log",
"nats",
@@ -212,6 +213,7 @@ dependencies = [
"prometheus",
"redis",
"serde 1.0.130",
+ "serde_repr",
"testcontainers",
"tokio",
]
diff --git a/common/rust/Cargo.toml b/common/rust/Cargo.toml
index d54eea9..234f1b1 100644
--- a/common/rust/Cargo.toml
+++ b/common/rust/Cargo.toml
@@ -7,9 +7,11 @@ edition = "2018"
pretty_env_logger = "0.4"
log = { version = "0.4", features = ["std"] }
serde = { version = "1.0.8", features = ["derive"] }
+serde_repr = "0.1"
config = "0.11"
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
+enumflags2 = { version = "0.7.1", features = ["serde"] }
prometheus = { version = "0.12.0", features = ["process"] }
nats = "0.15.2"
testcontainers = "0.12.0"
diff --git a/common/rust/src/config.rs b/common/rust/src/config.rs
index e4dbade..327f6f8 100644
--- a/common/rust/src/config.rs
+++ b/common/rust/src/config.rs
@@ -22,6 +22,7 @@ impl<T> Settings<T>
where
T: Deserialize<'static> + std::default::Default + Clone,
{
+
/// Initializes a new configuration like the other components of nova
/// And starts the prometheus metrics server if needed.
pub fn new(service_name: &str) -> Result<Settings<T>, ConfigError> {
@@ -42,7 +43,9 @@ where
let mut config: Settings<T> = default.clone().try_into().unwrap();
// try to load the config
- config.config = default.get::<T>(&service_name).unwrap();
+ config.config = default.get::<T>(service_name).unwrap();
+ // todo(MatthieuCodder): the following line was not present in the conflict
+ // pretty_env_logger::init();
// start the monitoring system if needed
crate::monitoring::start_monitoring(&config.monitoring);
diff --git a/common/rust/src/discord_models/application.rs b/common/rust/src/discord_models/application.rs
new file mode 100644
index 0000000..65707d2
--- /dev/null
+++ b/common/rust/src/discord_models/application.rs
@@ -0,0 +1,38 @@
+use enumflags2::{bitflags, BitFlags};
+use serde::{Deserialize, Serialize};
+
+use super::{teams::Team, user::User};
+
+#[bitflags]
+#[repr(u64)]
+#[derive(Debug, Clone, Copy)]
+pub enum ApplicationFlags {
+ GatewayPresence = 1 << 12,
+ GatewayPresenceLimit = 1 << 13,
+ GatewayGuildMembers = 1 << 14,
+ GatewayGuildMembersLimited = 1 << 15,
+ VerificationPendingGuildLimit = 1 << 16,
+ Embedded = 1 << 17,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Application {
+ pub id: String,
+ pub name: String,
+ pub icon: Option<String>,
+ pub description: String,
+ pub rpc_origins: Option<Vec<String>>,
+ pub bot_public: bool,
+ pub bot_require_code_grant: bool,
+ pub terms_of_service_url: Option<String>,
+ pub privacy_policy_url: Option<String>,
+ pub owner: Option<User>,
+ pub summary: String,
+ pub verify_key: String,
+ pub team: Option<Team>,
+ pub guild_id: Option<String>,
+ pub primary_sku_id: Option<String>,
+ pub slug: Option<String>,
+ pub cover_image: Option<String>,
+ pub flags: Option<BitFlags<ApplicationFlags>>,
+}
diff --git a/common/rust/src/discord_models/audit_log.rs b/common/rust/src/discord_models/audit_log.rs
new file mode 100644
index 0000000..0579a37
--- /dev/null
+++ b/common/rust/src/discord_models/audit_log.rs
@@ -0,0 +1,208 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{guild::Integration, user::User, webhook::Webhook};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum AuditLogEvents {
+ GuildUpdate = 1,
+ ChannelCreate = 10,
+ ChannelUpdate = 11,
+ ChannelDelete = 12,
+ ChannelOverwriteCreate = 13,
+ ChannelOverwriteUpdate = 14,
+ ChannelOverwriteDelete = 15,
+ MemberKick = 20,
+ MemberPrune = 21,
+ MemberBanAdd = 22,
+ MemberBanRemove = 23,
+ MemberUpdate = 24,
+ MemberRoleUpdate = 25,
+ MemberMove = 26,
+ MemberDisconnect = 27,
+ BotAdd = 28,
+ RoleCreate = 30,
+ RoleUpdate = 31,
+ RoleDelete = 32,
+ InviteCreate = 40,
+ InviteUpdate = 41,
+ InviteDelete = 42,
+ WebhookCreate = 50,
+ WebhookUpdate = 51,
+ WebhookDelete = 52,
+ EmojiCreate = 60,
+ EmojiUpdate = 61,
+ EmojiDelete = 62,
+ MessageDelete = 72,
+ MessageBulkDelete = 73,
+ MessagePin = 74,
+ MessageUnpin = 75,
+ IntegrationCreate = 80,
+ IntegrationUpdate = 81,
+ IntegrationDelete = 82,
+ StageInstanceCreate = 83,
+ StageInstanceUpdate = 84,
+ StageInstanceDelete = 85,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub enum OptionalAuditEntryInfoType {
+ #[serde(rename = "0")]
+ Role,
+ #[serde(rename = "1")]
+ Member,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct OptionalAuditEntryInfo {
+ pub delete_member_days: Option<String>,
+ pub members_removed: Option<String>,
+ pub channel_id: Option<String>,
+ pub message_id: Option<String>,
+ pub count: Option<String>,
+ pub id: Option<String>,
+ #[serde(rename = "type")]
+ pub type_: Option<Box<OptionalAuditEntryInfo>>,
+ pub role_name: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub enum AuditLogChangeKey {
+ #[serde(rename = "name")]
+ Name,
+ #[serde(rename = "description")]
+ Description,
+ #[serde(rename = "icon_hash")]
+ IconHash,
+ #[serde(rename = "splash_hash")]
+ SplashHash,
+ #[serde(rename = "discovery_splash_hash")]
+ DiscoverySplashHash,
+ #[serde(rename = "banner_hash")]
+ BannerHash,
+ #[serde(rename = "owner_id")]
+ OwnerId,
+ #[serde(rename = "region")]
+ Region,
+ #[serde(rename = "preferred_locale")]
+ PreferredLocale,
+ #[serde(rename = "afk_channel_id")]
+ AfkChannelId,
+ #[serde(rename = "afk_timeout")]
+ AfkTimeout,
+ #[serde(rename = "rules_channel_id")]
+ RulesChannelId,
+ #[serde(rename = "public_updates_channel_id")]
+ PublicUpdatesChannelId,
+ #[serde(rename = "mfa_level")]
+ MfaLevel,
+ #[serde(rename = "verification_level")]
+ VerificationLevel,
+ #[serde(rename = "explicit_content_filter")]
+ ExplicitContentFilter,
+ #[serde(rename = "default_message_notifications")]
+ DefaultMessageNotifications,
+ #[serde(rename = "vanity_url_code")]
+ VanityUrlCode,
+ #[serde(rename = "$add")]
+ Add,
+ #[serde(rename = "$remove")]
+ Remove,
+ #[serde(rename = "prune_delete_days")]
+ PruneDeleteDays,
+ #[serde(rename = "widget_enabled")]
+ WidgetEnabled,
+ #[serde(rename = "widget_channel_id")]
+ WidgetChannelId,
+ #[serde(rename = "system_channel_id")]
+ SystemChannelId,
+ #[serde(rename = "position")]
+ Position,
+ #[serde(rename = "topic")]
+ Topic,
+ #[serde(rename = "bitrate")]
+ Bitrate,
+ #[serde(rename = "permission_overwrites")]
+ PermissionOverwrites,
+ #[serde(rename = "nsfw")]
+ Nsfw,
+ #[serde(rename = "application_id")]
+ ApplicationId,
+ #[serde(rename = "rate_limit_per_user")]
+ RateLimitPerUser,
+ #[serde(rename = "permissions")]
+ Permissions,
+ #[serde(rename = "color")]
+ Color,
+ #[serde(rename = "hoist")]
+ Hoist,
+ #[serde(rename = "mentionable")]
+ Mentionable,
+ #[serde(rename = "allow")]
+ Allow,
+ #[serde(rename = "deny")]
+ Deny,
+ #[serde(rename = "code")]
+ Code,
+ #[serde(rename = "channel_id")]
+ ChannelId,
+ #[serde(rename = "inviter_id")]
+ InviterId,
+ #[serde(rename = "max_uses")]
+ MaxUses,
+ #[serde(rename = "uses")]
+ Uses,
+ #[serde(rename = "max_age")]
+ MaxAge,
+ #[serde(rename = "temporary")]
+ Temporary,
+ #[serde(rename = "deaf")]
+ Deaf,
+ #[serde(rename = "mute")]
+ Mute,
+ #[serde(rename = "nick")]
+ Nick,
+ #[serde(rename = "avatar_hash")]
+ AvatarHash,
+ #[serde(rename = "id")]
+ Id,
+ #[serde(rename = "type")]
+ Type,
+ #[serde(rename = "enable_emoticons")]
+ EnableEmoticons,
+ #[serde(rename = "expire_behavior")]
+ ExpireBehavior,
+ #[serde(rename = "expire_grace_period")]
+ ExpireGracePeriod,
+ #[serde(rename = "user_limit")]
+ UserLimit,
+ #[serde(rename = "privacy_level")]
+ PrivacyLevel,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct AuditLogChange {
+ pub new_value: Option<String>,
+ pub old_value: Option<String>,
+ pub key: AuditLogChangeKey,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct AuditLogEntry {
+ pub target_id: Option<String>,
+ pub changes: Option<Vec<AuditLogChange>>,
+ pub user_id: Option<String>,
+ pub id: String,
+ pub action_type: AuditLogEvents,
+ pub options: Option<OptionalAuditEntryInfo>,
+ pub reason: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct AuditLog {
+ pub webhooks: Vec<Webhook>,
+ pub users: Vec<User>,
+ pub audit_log_entries: Vec<AuditLogEntry>,
+ pub integrations: Vec<Integration>,
+}
diff --git a/common/rust/src/discord_models/channel.rs b/common/rust/src/discord_models/channel.rs
new file mode 100644
index 0000000..ef31aa1
--- /dev/null
+++ b/common/rust/src/discord_models/channel.rs
@@ -0,0 +1,341 @@
+use enumflags2::{bitflags, BitFlags};
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{
+ application::Application, emoji::Emoji, guild::GuildMember, message_components::Component,
+ slash_commands::MessageInteraction, user::User,
+};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ChannelTypes {
+ GuildText = 0,
+ Dm = 1,
+ GuildVoice = 2,
+ GroupDm = 3,
+ GuildCategory = 4,
+ GuildNews = 5,
+ GuildStore = 6,
+ GuildNewsThread = 10,
+ GuildPublicThread = 11,
+ GuildPrivateThread = 12,
+ GuildStageVoice = 13,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum VideoQualityModes {
+ Auto = 1,
+ Full = 2,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum OverwriteTypes {
+ Role = 0,
+ Member = 1,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Overwrite {
+ pub id: String,
+ #[serde(rename = "type")]
+ pub type_: OverwriteTypes,
+ pub allow: String,
+ pub deny: String,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ThreadMetadata {
+ pub archived: bool,
+ pub auto_archive_duration: i64,
+ pub archive_timestamp: String,
+ pub locked: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ThreadMember {
+ pub id: Option<String>,
+ pub user_id: Option<String>,
+ pub join_timestamp: String,
+ pub flags: i64,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Channel {
+ pub id: String,
+ #[serde(rename = "type")]
+ pub type_: ChannelTypes,
+ pub guild_id: Option<String>,
+ pub position: Option<i64>,
+ pub permission_overwrites: Option<Vec<Overwrite>>,
+ pub name: Option<String>,
+ pub topic: Option<String>,
+ pub nsfw: Option<bool>,
+ pub last_message_id: Option<String>,
+ pub bitrate: Option<i64>,
+ pub user_limit: Option<i64>,
+ pub rate_limit_per_user: Option<i64>,
+ pub recipients: Option<Vec<User>>,
+ pub icon: Option<String>,
+ pub owner_id: Option<String>,
+ pub application_id: Option<String>,
+ pub parent_id: Option<String>,
+ pub last_pin_timestamp: Option<String>,
+ pub rtc_region: Option<String>,
+ pub video_quality_mode: Option<VideoQualityModes>,
+ pub message_count: Option<i64>,
+ pub member_count: Option<i64>,
+ pub thread_metadata: Option<ThreadMetadata>,
+ pub member: Option<ThreadMember>,
+ pub default_auto_archive_duration: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Attachment {
+ pub id: String,
+ pub filename: String,
+ pub content_type: String,
+ pub size: i64,
+ pub url: String,
+ pub proxy_url: String,
+ pub height: Option<i64>,
+ pub width: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ChannelMention {
+ pub id: String,
+ pub guild_id: String,
+ #[serde(rename = "type")]
+ pub type_: ChannelTypes,
+ pub name: String,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub enum EmbedTypes {
+ #[serde(rename = "rich")]
+ Rich,
+ #[serde(rename = "image")]
+ Image,
+ #[serde(rename = "video")]
+ Video,
+ #[serde(rename = "gifv")]
+ Gifv,
+ #[serde(rename = "article")]
+ Article,
+ #[serde(rename = "link")]
+ Link,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedThumbnail {
+ pub url: Option<String>,
+ pub proxy_url: Option<String>,
+ pub height: Option<i64>,
+ pub width: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedVideo {
+ pub url: Option<String>,
+ pub proxy_url: Option<String>,
+ pub height: Option<i64>,
+ pub width: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedImage {
+ pub url: Option<String>,
+ pub proxy_url: Option<String>,
+ pub height: Option<i64>,
+ pub width: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedProvider {
+ pub name: Option<String>,
+ pub url: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedAuthor {
+ pub name: Option<String>,
+ pub url: Option<String>,
+ pub icon_url: Option<String>,
+ pub proxy_icon_url: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedFooter {
+ pub text: String,
+ pub icon_url: Option<String>,
+ pub proxy_icon_url: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EmbedField {
+ pub name: String,
+ pub value: String,
+ pub inline: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Embed {
+ pub title: Option<String>,
+ #[serde(rename = "type")]
+ pub type_: Option<EmbedTypes>,
+ pub description: Option<String>,
+ pub url: Option<String>,
+ pub timestamp: Option<String>,
+ pub color: Option<i64>,
+ pub footer: Option<EmbedFooter>,
+ pub image: Option<EmbedImage>,
+ pub thumbnail: Option<EmbedThumbnail>,
+ pub video: Option<EmbedVideo>,
+ pub provider: Option<EmbedProvider>,
+ pub author: Option<EmbedAuthor>,
+ pub fields: Option<Vec<EmbedField>>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Reaction {
+ pub count: i64,
+ pub me: bool,
+ pub emoji: Emoji,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum MessageTypes {
+ Default = 0,
+ RecipientAdd = 1,
+ RecipientRemove = 2,
+ Call = 3,
+ ChannelNameChange = 4,
+ ChannelIconChange = 5,
+ ChannelPinnedMessage = 6,
+ GuildMemberJoin = 7,
+ UserPremiumGuildSubscription = 8,
+ UserPremiumGuildSubscriptionTier1 = 9,
+ UserPremiumGuildSubscriptionTier2 = 10,
+ UserPremiumGuildSubscriptionTier3 = 11,
+ ChannelFollowAdd = 12,
+ GuildDiscoveryDisqualified = 14,
+ GuildDiscoveryRequalified = 15,
+ GuildDiscoveryGracePeriodInitialWarning = 16,
+ GuildDiscoveryGracePeriodFinalWarning = 17,
+ ThreadCreated = 18,
+ Reply = 19,
+ ApplicationCommand = 20,
+ ThreadStarterMessage = 21,
+ GuildInviteReminder = 22,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum MessageActivityTypes {
+ Join = 1,
+ Spectate = 2,
+ Listen = 3,
+ JoinRequest = 5,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct MessageActivity {
+ #[serde(rename = "type")]
+ pub type_: MessageActivityTypes,
+ pub party_id: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct MessageReference {
+ pub message_id: Option<String>,
+ pub channel_id: Option<String>,
+ pub guild_id: Option<String>,
+ pub fail_if_not_exists: Option<bool>,
+}
+
+#[bitflags]
+#[repr(u64)]
+#[derive(Debug, Clone, Copy)]
+pub enum MessageFlags {
+ Crossposted = 1 << 0,
+ IsCrosspost = 1 << 1,
+ SuppressEmbeds = 1 << 2,
+ SourceMessageDeleted = 1 << 3,
+ Urgent = 1 << 4,
+ HasThread = 1 << 5,
+ Ephemeral = 1 << 6,
+ Loading = 1 << 7,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum MessageStickerFormatTypes {
+ Png = 1,
+ Apng = 2,
+ Lottie = 3,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct MessageStickerItem {
+ pub id: String,
+ pub name: String,
+ pub format_type: MessageStickerFormatTypes,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct MessageSticker {
+ pub id: String,
+ pub pack_id: Option<String>,
+ pub name: String,
+ pub description: String,
+ pub tags: String,
+ // deprecated
+ // pub asset: String,
+ pub format_type: MessageStickerFormatTypes,
+ pub available: Option<bool>,
+ pub guild_id: Option<String>,
+ pub user: Option<User>,
+ pub sort_value: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Message {
+ pub id: String,
+ pub channel_id: String,
+ pub guild_id: Option<String>,
+ pub author: User,
+ pub member: Option<GuildMember>,
+ pub content: String,
+ pub timestamp: String,
+ pub edited_timestamp: String,
+ pub tts: bool,
+ pub mention_everyone: bool,
+ pub mentions: Vec<User>, // todo: It is a Vector of User objects, with an additional partial member field (GuildMember)
+ pub mentions_roles: Vec<String>,
+ pub mention_channels: Option<Vec<Channel>>,
+ pub attachments: Vec<Attachment>,
+ pub embeds: Vec<Embed>,
+ pub reactions: Option<Vec<Reaction>>,
+ /// ! Can be a String or an int !
+ pub nonce: Option<String>,
+ pub pinned: bool,
+ pub webhook_id: Option<String>,
+ #[serde(rename = "type")]
+ pub type_: MessageTypes,
+ pub activity: Option<MessageActivity>,
+ pub application: Option<Application>,
+ pub application_id: Option<String>,
+ pub message_reference: Option<MessageReference>,
+ pub flags: Option<BitFlags<MessageFlags>>,
+ pub referenced_message: Option<Box<Message>>,
+ pub interaction: Option<MessageInteraction>,
+ pub thread: Option<Channel>,
+ pub components: Option<Component>,
+ pub sticker_items: Option<Vec<MessageStickerItem>>,
+ // deprecated
+ // pub stickers: Option<Vec<MessageSticker>>,
+}
diff --git a/common/rust/src/discord_models/emoji.rs b/common/rust/src/discord_models/emoji.rs
new file mode 100644
index 0000000..eec02e7
--- /dev/null
+++ b/common/rust/src/discord_models/emoji.rs
@@ -0,0 +1,15 @@
+use serde::{Deserialize, Serialize};
+
+use super::user::User;
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Emoji {
+ pub id: Option<String>,
+ pub name: Option<String>,
+ pub roles: Vec<String>,
+ pub user: Option<User>,
+ pub require_colons: Option<bool>,
+ pub managed: Option<bool>,
+ pub animated: Option<bool>,
+ pub available: Option<bool>,
+}
diff --git a/common/rust/src/discord_models/gateway.rs b/common/rust/src/discord_models/gateway.rs
new file mode 100644
index 0000000..dbdf60d
--- /dev/null
+++ b/common/rust/src/discord_models/gateway.rs
@@ -0,0 +1,118 @@
+use enumflags2::{bitflags, BitFlags};
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::user::User;
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub enum PresenceUpdateStatus {
+ #[serde(rename = "online")]
+ Online,
+ #[serde(rename = "idle")]
+ Idle,
+ #[serde(rename = "dnd")]
+ Dnd,
+ #[serde(rename = "offline")]
+ Offline,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ClientStatus {
+ pub desktop: Option<String>,
+ pub mobile: Option<String>,
+ pub web: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct PresenceUpdate {
+ pub user: User,
+ pub guild_id: String,
+ pub status: PresenceUpdateStatus,
+ pub activities: Vec<Activity>,
+ pub client_status: ClientStatus,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ActivityTypes {
+ Game = 0,
+ Streaming = 1,
+ Listening = 2,
+ Watching = 3,
+ Custom = 4,
+ Competing = 5,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivityTimestamps {
+ pub start: Option<i64>,
+ pub end: Option<i64>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivityEmoji {
+ pub name: String,
+ pub id: Option<String>,
+ pub animated: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivityParty {
+ pub id: Option<String>,
+ /// [current_size, max_size]
+ pub size: Option<Vec<i64>>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivityAssets {
+ pub large_image: Option<String>,
+ pub large_text: Option<String>,
+ pub small_image: Option<String>,
+ pub small_text: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivitySecrets {
+ pub join: Option<String>,
+ pub spectate: Option<String>,
+ #[serde(rename = "match")]
+ pub match_: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ActivityButtons {
+ pub label: String,
+ pub url: String,
+}
+
+#[bitflags]
+#[repr(u64)]
+#[derive(Debug, Clone, Copy)]
+pub enum ActivityFlags {
+ Instance = 1 << 0,
+ Join = 1 << 1,
+ Spectate = 1 << 2,
+ JoinRequest = 1 << 3,
+ Sync = 1 << 4,
+ Play = 1 << 5,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Activity {
+ pub name: String,
+ #[serde(rename = "type")]
+ pub type_: ActivityTypes,
+ pub url: Option<String>,
+ pub created_at: String,
+ pub timestamps: Option<ActivityTimestamps>,
+ pub application_id: Option<String>,
+ pub details: Option<String>,
+ pub state: Option<String>,
+ pub emoji: Option<ActivityEmoji>,
+ pub party: Option<ActivityParty>,
+ pub assets: Option<ActivityAssets>,
+ pub secrets: Option<ActivitySecrets>,
+ pub instance: Option<bool>,
+ pub flags: Option<BitFlags<ActivityFlags>>,
+ pub buttons: Option<Vec<ActivityButtons>>,
+}
diff --git a/common/rust/src/discord_models/guild.rs b/common/rust/src/discord_models/guild.rs
new file mode 100644
index 0000000..85da5b2
--- /dev/null
+++ b/common/rust/src/discord_models/guild.rs
@@ -0,0 +1,255 @@
+use enumflags2::{bitflags, BitFlags};
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{
+ channel::Channel, emoji::Emoji, gateway::PresenceUpdate, permissions::Role,
+ stage_instance::StageInstance, user::User, voice::VoiceState,
+};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum IntegrationExpireBehavior {
+ RemoveRole = 0,
+ Kick = 1,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct IntegrationAccount {
+ pub id: String,
+ pub name: String,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct IntegrationApplication {
+ pub id: String,
+ pub name: String,
+ pub icon: Option<String>,
+ pub description: String,
+ pub summary: Option<String>,
+ pub bot: Option<User>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Integration {
+ pub id: String,
+ pub name: String,
+ #[serde(rename = "type")]
+ pub type_: String,
+ pub enabled: bool,
+ pub syncing: Option<bool>,
+ pub role_id: Option<String>,
+ pub enable_emoticons: Option<bool>,
+ pub expire_behavior: Option<IntegrationExpireBehavior>,
+ pub expire_grace_period: Option<i64>,
+ pub user: Option<User>,
+ pub account: IntegrationAccount,
+ pub synced_at: Option<String>,
+ pub subscriber_count: Option<i64>,
+ pub revoked: Option<bool>,
+ pub application: Option<IntegrationApplication>,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum VerificationLevel {
+ None = 0,
+ Low = 1,
+ Medium = 2,
+ High = 3,
+ VeryHigh = 4,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum PremiumTier {
+ None = 0,
+ Tier1 = 1,
+ Tier2 = 2,
+ Tier3 = 3,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ExplicitContentFilter {
+ Disabled = 0,
+ MembersWithoutRoles = 1,
+ AllMembers = 2,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum MfaLevel {
+ None = 0,
+ Elevated = 1,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum DefaultMessageNotificationLevel {
+ AllMessages = 0,
+ OnlyMentions = 1,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum GuildNsfwLevel {
+ Default = 0,
+ Explicit = 1,
+ Safe = 2,
+ AgeRestricted = 3,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum GuildFeatures {
+ #[serde(rename = "ANIMATED_ICON")]
+ AnimatedIcon,
+ #[serde(rename = "BANNER")]
+ Banner,
+ #[serde(rename = "COMMERCE")]
+ Commerce,
+ #[serde(rename = "COMMUNITY")]
+ Community,
+ #[serde(rename = "DISCOVERABLE")]
+ Discoverable,
+ #[serde(rename = "FEATURABLE")]
+ Featurable,
+ #[serde(rename = "INVITE_SPLASH")]
+ InviteSplash,
+ #[serde(rename = "MEMBER_VERIFICATION_GATE_ENABLED")]
+ MemberVerificationGateEnabled,
+ #[serde(rename = "NEWS")]
+ News,
+ #[serde(rename = "PARTNERED")]
+ Partnered,
+ #[serde(rename = "PREVIEW_ENABLED")]
+ PreviewEnabled,
+ #[serde(rename = "VANITY_URL")]
+ VanityUrl,
+ #[serde(rename = "VERIFIED")]
+ Verified,
+ #[serde(rename = "VIP_REGIONS")]
+ VipRegions,
+ #[serde(rename = "WELCOME_SCREEN_ENABLED")]
+ WelcomeScreenEnabled,
+ #[serde(rename = "TICKETED_EVENTS_ENABLED")]
+ TicketedEventsEnabled,
+ #[serde(rename = "MONETIZATION_ENABLED")]
+ MonetizationEnabled,
+ #[serde(rename = "MORE_STICKERS")]
+ MoreStickers,
+ #[serde(rename = "THREE_DAY_THREAD_ARCHIVE")]
+ ThreeDayThreadArchive,
+ #[serde(rename = "SEVEN_DAY_THREAD_ARCHIVE")]
+ SevenDayThreadArchive,
+ #[serde(rename = "PRIVATE_THREADS")]
+ PrivateThreads,
+}
+
+#[bitflags]
+#[repr(u64)]
+#[derive(Debug, Clone, Copy)]
+pub enum SystemChannelFlags {
+ SuppressJoinNotifications = 1 << 0,
+ SuppressPremiumSubscriptions = 1 << 1,
+ SuppressGuildReminderNotifications = 1 << 2,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct WelcomeScreenChannel {
+ pub channel_id: String,
+ pub description: String,
+ pub emoji_id: Option<String>,
+ pub emoji_name: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct WelcomeScreen {
+ pub description: String,
+ pub welcome_channels: Vec<WelcomeScreenChannel>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Guild {
+ pub id: String,
+ pub name: String,
+ pub icon: Option<String>,
+ pub icon_hash: Option<String>,
+ pub splash: Option<String>,
+ pub discovery_splash: Option<String>,
+ pub owner: Option<bool>,
+ pub owner_id: String,
+ pub permissions: Option<String>,
+ /// DEPRECATED
+ pub region: Option<String>,
+ pub afk_channel_id: Option<String>,
+ pub afk_timeout: i64,
+ pub widget_enabled: Option<bool>,
+ pub widget_channel_id: Option<String>,
+ pub verification_level: VerificationLevel,
+ pub default_message_notifications: DefaultMessageNotificationLevel,
+ pub explicit_content_filter: ExplicitContentFilter,
+ pub roles: Vec<Role>,
+ pub emojis: Vec<Emoji>,
+ pub features: Vec<GuildFeatures>,
+ pub mfa_level: MfaLevel,
+ pub application_id: Option<String>,
+ pub system_channel_id: Option<String>,
+ pub system_channel_flags: BitFlags<SystemChannelFlags>,
+ pub rules_channel_id: Option<String>,
+ pub joined_at: Option<String>,
+ pub large: Option<bool>,
+ pub unavailable: Option<bool>,
+ pub member_count: Option<i64>,
+ pub voice_states: Option<Vec<VoiceState>>,
+ pub members: Option<Vec<GuildMember>>,
+ pub channels: Option<Vec<Channel>>,
+ pub threads: Option<Vec<Channel>>,
+ pub presences: Option<Vec<PresenceUpdate>>,
+ pub max_presences: Option<i64>,
+ pub vanity_url_code: Option<String>,
+ pub description: Option<String>,
+ pub banner: Option<String>,
+ pub premium_tier: PremiumTier,
+ pub premium_subscription_count: i64,
+ pub preferred_locale: String,
+ pub public_updates_channel_id: Option<String>,
+ pub max_video_channel_users: Option<i64>,
+ pub approximate_member_count: Option<i64>,
+ pub welcome_screen: Option<WelcomeScreen>,
+ pub nsfw_level: GuildNsfwLevel,
+ pub stage_instances: Option<Vec<StageInstance>>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct GuildMember {
+ pub user: Option<User>,
+ pub nick: Option<String>,
+ pub roles: Vec<String>,
+ pub joined_at: String,
+ pub premium_since: Option<String>,
+ pub deaf: bool,
+ pub mute: bool,
+ pub pending: Option<bool>,
+ pub permissions: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct GuildPreview {
+ pub id: String,
+ pub name: String,
+ pub icon: Option<String>,
+ pub splash: Option<String>,
+ pub discovery_splash: Option<String>,
+ pub emojis: Vec<Emoji>,
+ pub features: Vec<GuildFeatures>,
+ pub approximate_member_count: i64,
+ pub approximate_presence_count: i64,
+ pub description: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct GuildWidget {
+ pub enabled: bool,
+ pub channel_id: Option<String>,
+}
diff --git a/common/rust/src/discord_models/guild_template.rs b/common/rust/src/discord_models/guild_template.rs
new file mode 100644
index 0000000..960631d
--- /dev/null
+++ b/common/rust/src/discord_models/guild_template.rs
@@ -0,0 +1,18 @@
+use serde::{Deserialize, Serialize};
+
+use super::{guild::Guild, user::User};
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct GuildTemplate {
+ pub code: String,
+ pub name: String,
+ pub description: Option<String>,
+ pub usage_count: i64,
+ pub creator_id: String,
+ pub creator: User,
+ pub created_at: String,
+ pub updated_at: String,
+ pub source_guild_ild: String,
+ pub serialized_source_guild: Guild,
+ pub is_dirty: Option<bool>,
+}
diff --git a/common/rust/src/discord_models/invite.rs b/common/rust/src/discord_models/invite.rs
new file mode 100644
index 0000000..639278c
--- /dev/null
+++ b/common/rust/src/discord_models/invite.rs
@@ -0,0 +1,48 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{
+ application::Application,
+ channel::Channel,
+ guild::{Guild, GuildMember},
+ user::User,
+};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum InviteTargetTypes {
+ Stream = 1,
+ EmbeddedApplication = 2,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct InviteStageInstance {
+ pub members: Vec<GuildMember>,
+ pub participant_count: i64,
+ pub speaker_count: i64,
+ pub topic: String,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Invite {
+ pub code: String,
+ pub guild: Option<Guild>,
+ pub channel: Channel,
+ pub inviter: Option<User>,
+ pub target_type: Option<InviteTargetTypes>,
+ pub target_user: Option<User>,
+ pub target_application: Option<Application>,
+ pub approximate_presence_count: Option<i64>,
+ pub approximate_member_count: Option<i64>,
+ pub expires_at: Option<String>,
+ pub stage_instance: Option<InviteStageInstance>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct InviteMetadata {
+ pub uses: i64,
+ pub max_uses: i64,
+ pub max_age: i64,
+ pub temporary: bool,
+ pub created_at: String,
+}
diff --git a/common/rust/src/discord_models/message_components.rs b/common/rust/src/discord_models/message_components.rs
new file mode 100644
index 0000000..f71d7ed
--- /dev/null
+++ b/common/rust/src/discord_models/message_components.rs
@@ -0,0 +1,75 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::emoji::Emoji;
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ComponentTypes {
+ ActionRow = 1,
+ Button = 2,
+ SelectMenu = 3,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+/// Global representation of a Component, more detailed are Button (if button) and Select Menu (if select menu)
+/// Action Rows are just type: 1, content + components
+pub struct Component {
+ #[serde(rename = "type")]
+ pub type_: ComponentTypes,
+ pub custom_id: Option<String>,
+ pub disabled: Option<bool>,
+ pub style: Option<ButtonStyles>,
+ pub label: Option<String>,
+ pub emoji: Option<Emoji>,
+ pub url: Option<String>,
+ pub options: Vec<SelectOption>,
+ pub placeholder: Option<String>,
+ pub min_values: Option<u8>,
+ pub max_values: Option<u8>,
+ pub components: Option<Vec<Component>>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Button {
+ #[serde(rename = "type")]
+ /// it should be `2`
+ pub type_: ComponentTypes,
+ pub style: ButtonStyles,
+ pub label: Option<String>,
+ pub emoji: Option<Emoji>,
+ pub custom_id: Option<String>,
+ pub url: Option<String>,
+ pub disabled: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ButtonStyles {
+ Primary = 1,
+ Secondary = 2,
+ Success = 3,
+ Danger = 4,
+ Link = 5,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct SelectOption {
+ pub label: String,
+ pub value: String,
+ pub description: Option<String>,
+ pub emoji: Option<Emoji>,
+ pub default: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct SelectMenu {
+ /// it should be 3
+ pub type_: ComponentTypes,
+ pub custom_id: String,
+ pub options: Vec<SelectOption>,
+ pub placeholder: Option<String>,
+ pub min_values: Option<u8>,
+ pub max_values: Option<u8>,
+ pub disabled: Option<bool>,
+}
diff --git a/common/rust/src/discord_models/mod.rs b/common/rust/src/discord_models/mod.rs
new file mode 100644
index 0000000..8017e2a
--- /dev/null
+++ b/common/rust/src/discord_models/mod.rs
@@ -0,0 +1,16 @@
+pub mod application;
+pub mod audit_log;
+pub mod channel;
+pub mod emoji;
+pub mod gateway;
+pub mod guild;
+pub mod guild_template;
+pub mod invite;
+pub mod message_components;
+pub mod permissions;
+pub mod slash_commands;
+pub mod stage_instance;
+pub mod teams;
+pub mod user;
+pub mod voice;
+pub mod webhook;
diff --git a/common/rust/src/discord_models/permissions.rs b/common/rust/src/discord_models/permissions.rs
new file mode 100644
index 0000000..76fa34a
--- /dev/null
+++ b/common/rust/src/discord_models/permissions.rs
@@ -0,0 +1,21 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct RoleTags {
+ pub bot_id: Option<String>,
+ pub integration_id: Option<String>,
+ pub premium_subscriber: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Role {
+ pub id: String,
+ pub name: String,
+ pub color: i64,
+ pub hoist: bool,
+ pub position: i64,
+ pub permissions: String,
+ pub managed: bool,
+ pub mentionable: bool,
+ pub tags: Option<RoleTags>,
+}
diff --git a/common/rust/src/discord_models/slash_commands.rs b/common/rust/src/discord_models/slash_commands.rs
new file mode 100644
index 0000000..ae0f190
--- /dev/null
+++ b/common/rust/src/discord_models/slash_commands.rs
@@ -0,0 +1,104 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{channel::Message, guild::GuildMember, user::User};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ApplicationCommandOptionType {
+ SubCommand = 1,
+ SubCommandGroup = 2,
+ String = 3,
+ Integer = 4,
+ Boolean = 5,
+ User = 6,
+ Channel = 7,
+ Role = 8,
+ Mentionable = 9,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ApplicationCommandOptionChoice {
+ pub name: String,
+ /// todo: Can also be a String!!!!
+ pub value: i64,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ApplicationCommandOption {
+ #[serde(rename = "type")]
+ pub type_: ApplicationCommandOptionType,
+ pub name: String,
+ pub description: String,
+ pub required: Option<bool>,
+ pub choices: Option<Vec<ApplicationCommandOptionChoice>>,
+ pub options: Option<Vec<ApplicationCommandOption>>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ApplicationCommand {
+ pub id: String,
+ pub application_id: String,
+ pub guild_id: Option<String>,
+ pub name: String,
+ pub description: String,
+ pub options: Option<Vec<ApplicationCommandOption>>,
+ pub default_permission: Option<bool>,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum ApplicationCommandPermissionType {
+ Role = 1,
+ User = 2,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct GuildApplicationCommandPermissions {
+ pub id: String,
+ pub application_id: String,
+ pub guild_id: String,
+ pub permissions: Vec<ApplicationCommandPermissions>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct ApplicationCommandPermissions {
+ pub id: String,
+ #[serde(rename = "type")]
+ pub type_: ApplicationCommandPermissionType,
+ pub permission: bool,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum InteractionRequestType {
+ Ping = 1,
+ ApplicationCommand = 2,
+ MessageComponent = 3,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct MessageInteraction {
+ pub id: String,
+ #[serde(rename = "type")]
+ pub type_: InteractionRequestType,
+ pub name: String,
+ pub user: User,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Interaction {
+ pub id: String,
+ pub application_id: String,
+ #[serde(rename = "type")]
+ pub type_: InteractionRequestType,
+ /// i am not sure about this one https://canary.discord.com/developers/docs/interactions/slash-commands#interaction-object-application-command-interaction-data
+ pub data: ApplicationCommand,
+ pub guild_id: Option<String>,
+ pub channel_id: Option<String>,
+ pub member: Option<GuildMember>,
+ pub user: Option<User>,
+ pub token: String,
+ pub version: i64,
+ pub message: Option<Message>,
+}
diff --git a/common/rust/src/discord_models/stage_instance.rs b/common/rust/src/discord_models/stage_instance.rs
new file mode 100644
index 0000000..1eee1c2
--- /dev/null
+++ b/common/rust/src/discord_models/stage_instance.rs
@@ -0,0 +1,19 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum PrivacyLevel {
+ Public = 1,
+ GuildOnly = 2,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct StageInstance {
+ pub id: String,
+ pub guild_id: String,
+ pub channel_id: String,
+ pub topic: String,
+ pub privacy_level: PrivacyLevel,
+ pub discoverable_disabled: bool,
+}
diff --git a/common/rust/src/discord_models/teams.rs b/common/rust/src/discord_models/teams.rs
new file mode 100644
index 0000000..369b3cd
--- /dev/null
+++ b/common/rust/src/discord_models/teams.rs
@@ -0,0 +1,28 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::user::User;
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum MembershipState {
+ Invited = 0,
+ Accepted = 1,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct TeamMembers {
+ pub membership_state: MembershipState,
+ pub permissions: Vec<String>,
+ pub team_id: String,
+ pub user: User,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Team {
+ pub icon: Option<String>,
+ pub id: String,
+ pub members: Vec<TeamMembers>,
+ pub name: String,
+ pub owner_user_id: String,
+}
diff --git a/common/rust/src/discord_models/user.rs b/common/rust/src/discord_models/user.rs
new file mode 100644
index 0000000..36914ce
--- /dev/null
+++ b/common/rust/src/discord_models/user.rs
@@ -0,0 +1,73 @@
+use enumflags2::{bitflags, BitFlags};
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::guild::Integration;
+
+#[bitflags]
+#[repr(u64)]
+#[derive(Debug, Clone, Copy)]
+pub enum UserFlags {
+ // None = 0 << 0,
+ DiscordEmployee = 1 << 0,
+ PartneredServerOwner = 1 << 1,
+ HypesquadEvents = 1 << 2,
+ BugHunterLevel1 = 1 << 3,
+ HouseBravery = 1 << 6,
+ HouseBrilliance = 1 << 7,
+ HouseBalance = 1 << 8,
+ EarlySupporter = 1 << 9,
+ TeamUser = 1 << 10,
+ BugHunterLevel2 = 1 << 14,
+ VerifiedBot = 1 << 16,
+ EarlyVerifiedBotDeveloper = 1 << 17,
+ DiscordCertifiedModerator = 1 << 18,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum PremiumTypes {
+ None = 0,
+ NitroClassic = 1,
+ Nitro = 2,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+/// Represents a User within Discord
+pub struct User {
+ pub id: String,
+ pub username: String,
+ pub discriminator: String,
+ pub avatar: Option<String>,
+ pub bot: Option<bool>,
+ pub system: Option<bool>,
+ pub mfa_enabled: Option<bool>,
+ pub locale: Option<String>,
+ pub verified: Option<bool>,
+ pub email: Option<String>,
+ pub flags: Option<BitFlags<UserFlags>>,
+ pub premium_type: Option<PremiumTypes>,
+ pub public_flags: Option<BitFlags<UserFlags>>,
+}
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum VisibilityTypes {
+ None = 0,
+ Everyone = 1,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+/// The connection object that the user has attached.
+pub struct Connection {
+ pub id: String,
+ pub name: String,
+ #[serde(rename = "type")]
+ pub type_: String,
+ pub revoked: Option<bool>,
+ pub integrations: Option<Vec<Integration>>,
+ pub verified: bool,
+ pub friend_sync: bool,
+ pub show_activity: bool,
+ pub visibility: VisibilityTypes,
+}
diff --git a/common/rust/src/discord_models/voice.rs b/common/rust/src/discord_models/voice.rs
new file mode 100644
index 0000000..8263af5
--- /dev/null
+++ b/common/rust/src/discord_models/voice.rs
@@ -0,0 +1,30 @@
+use serde::{Deserialize, Serialize};
+
+use super::guild::GuildMember;
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct VoiceState {
+ pub guild_id: Option<String>,
+ pub channel_id: Option<String>,
+ pub user_id: String,
+ pub member: Option<GuildMember>,
+ pub session_id: String,
+ pub deaf: bool,
+ pub mute: bool,
+ pub self_deaf: bool,
+ pub self_mute: bool,
+ pub self_stream: Option<bool>,
+ pub self_video: bool,
+ pub suppress: bool,
+ pub request_to_speak_timestamp: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct VoiceRegion {
+ pub id: String,
+ pub name: String,
+ pub vip: bool,
+ pub optimal: bool,
+ pub deprecated: bool,
+ pub custom: bool,
+}
diff --git a/common/rust/src/discord_models/webhook.rs b/common/rust/src/discord_models/webhook.rs
new file mode 100644
index 0000000..4648772
--- /dev/null
+++ b/common/rust/src/discord_models/webhook.rs
@@ -0,0 +1,29 @@
+use serde::{Deserialize, Serialize};
+use serde_repr::{Deserialize_repr, Serialize_repr};
+
+use super::{channel::Channel, guild::Guild, user::User};
+
+#[derive(Debug, Clone, Deserialize_repr, Serialize_repr)]
+#[repr(u8)]
+pub enum WebhookTypes {
+ Incoming = 1,
+ ChannelFollower = 2,
+ Application = 3,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Webhook {
+ pub id: String,
+ #[serde(rename = "type")]
+ pub type_: WebhookTypes,
+ pub guild_id: Option<String>,
+ pub channel_id: Option<String>,
+ pub user: Option<User>,
+ pub name: Option<String>,
+ pub avatar: Option<String>,
+ pub token: Option<String>,
+ pub application_id: Option<String>,
+ pub source_guild: Option<Guild>,
+ pub source_channel: Option<Channel>,
+ pub url: String,
+}
diff --git a/common/rust/src/lib.rs b/common/rust/src/lib.rs
index f4e27fc..5418d0a 100644
--- a/common/rust/src/lib.rs
+++ b/common/rust/src/lib.rs
@@ -1,6 +1,8 @@
/// This crate is all the utilities shared by the nova rust projects
/// It includes loging, config and protocols.
pub mod config;
+pub mod discord_models;
+pub mod error;
pub mod monitoring;
pub mod nats;
pub mod payloads;
@@ -13,4 +15,4 @@ pub use ::config as config_crate;
pub use prometheus as prometheus;
pub use ::nats as nats_crate;
pub use testcontainers as testcontainers;
-pub use ::redis as redis_crate; \ No newline at end of file
+pub use ::redis as redis_crate;
diff --git a/common/rust/src/nats.rs b/common/rust/src/nats.rs
index c61aa4c..a001dc9 100644
--- a/common/rust/src/nats.rs
+++ b/common/rust/src/nats.rs
@@ -6,6 +6,7 @@ pub struct NatsConfigurationClientCert {
pub cert: String,
pub key: String,
}
+
#[derive(Clone, Debug, Deserialize)]
pub struct NatsConfigurationTls {
pub mtu: Option<usize>,
@@ -24,6 +25,7 @@ pub struct NatsConfiguration {
pub host: String,
}
+// todo: Prefer From since it automatically gives a free Into implementation
// Allows the configuration to directly create a nats connection
impl Into<Connection> for NatsConfiguration {
fn into(self) -> Connection {
@@ -47,7 +49,7 @@ impl Into<Connection> for NatsConfiguration {
options = options.no_echo();
options = options.reconnect_buffer_size(self.reconnect_buffer_size.unwrap_or(64 * 1024));
options = options.tls_required(self.tls_required.unwrap_or(false));
- options = options.with_name(&self.client_name.unwrap_or("Nova".to_string()));
+ options = options.with_name(&self.client_name.unwrap_or_else(|| "Nova".to_string()));
if let Some(tls) = self.tls {
let mut config = nats::rustls::ClientConfig::new();
diff --git a/common/rust/src/payloads.rs b/common/rust/src/payloads.rs
index c97ac1d..d8d06f2 100644
--- a/common/rust/src/payloads.rs
+++ b/common/rust/src/payloads.rs
@@ -1,24 +1,269 @@
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
-/// Data structure sent to the cache component
-/// by the gateway & webhook.
-#[derive(Serialize, Deserialize, Debug)]
-#[serde(bound(deserialize = "T: Deserialize<'de> + Debug"))]
-pub struct CachePayload<T> {
+use crate::discord_models::{
+ application::Application,
+ channel::{Channel, Message, ThreadMember},
+ emoji::Emoji,
+ gateway::PresenceUpdate,
+ guild::{Guild, GuildMember, Integration},
+ invite::InviteTargetTypes,
+ permissions::Role,
+ slash_commands::{ApplicationCommand, Interaction},
+ stage_instance::StageInstance,
+ user::User,
+ voice::VoiceState,
+};
- #[serde(rename = "tr")]
+/// Payload send to the nova cache queues
+#[derive(Serialize, Deserialize, Debug, Clone)]
+// #[serde(bound(deserialize = "T: Deserialize<'de> + std::default::Default + Clone"))]
+pub struct CachePayload {
pub tracing: Tracing,
-
- #[serde(rename = "d")]
- pub data: T,
-
- #[serde(rename = "o")]
- pub operation: String,
+ pub data: CacheData,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Tracing {
pub node_id: String,
- pub span: Option<String>
+ pub span: Option<String>,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum CacheData {
+ Ready {
+ version: u8,
+ user: User,
+ guilds: Vec<Guild>,
+ session_id: String,
+ shard: Option<Vec<i64>>,
+ application: Application,
+ },
+ ApplicationCommandCreate {
+ guild_id: Option<String>,
+ command: ApplicationCommand,
+ },
+ ApplicationCommandUpdate {
+ guild_id: Option<String>,
+ command: ApplicationCommand,
+ },
+ ApplicationCommandDelete {
+ guild_id: Option<String>,
+ command: ApplicationCommand,
+ },
+ ChannelCreate {
+ channel: Channel,
+ },
+ ChannelUpdate {
+ channel: Channel,
+ },
+ ChannelDelete {
+ channel: Channel,
+ },
+ ThreadCreate {
+ channel: Channel,
+ },
+ ThreadUpdate {
+ channel: Channel,
+ },
+ ThreadDelete {
+ channel: Channel,
+ },
+ ThreadListSync {
+ guild_id: String,
+ channel_ids: Option<Vec<String>>,
+ threads: Vec<Channel>,
+ members: Vec<ThreadMember>,
+ },
+ ThreadMemberUpdate {
+ member: ThreadMember,
+ },
+ ThreadMembersUpdate {
+ id: String,
+ guild_id: String,
+ member_count: i64,
+ added_members: Option<Vec<ThreadMember>>,
+ removed_member_ids: Option<Vec<String>>,
+ },
+ ChannelPinsUpdate {
+ guild_id: Option<String>,
+ channel_id: String,
+ last_pin_timestamp: Option<String>,
+ },
+ GuildCreate {
+ guild: Guild,
+ },
+ GuildUpdate {
+ guild: Guild,
+ },
+ GuildDelete {
+ guild: Guild,
+ },
+ GuildBanAdd {
+ guild_id: String,
+ user: User,
+ },
+ GuildBanRemove {
+ guild_id: String,
+ user: User,
+ },
+ GuildEmojisUpdate {
+ guild_id: String,
+ emojis: Vec<Emoji>,
+ },
+ GuildIntegrationsUpdate {
+ guild_id: String,
+ },
+ GuildMemberAdd {
+ guild_id: String,
+ member: GuildMember,
+ },
+ GuildMemberRemove {
+ guild_id: String,
+ user: User,
+ },
+ GuildMemberUpdate {
+ guild_id: String,
+ roles: Vec<String>,
+ user: User,
+ nick: Option<String>,
+ joined_at: Option<String>,
+ premium_since: Option<String>,
+ deaf: Option<bool>,
+ mute: Option<bool>,
+ pending: Option<bool>,
+ },
+ GuildMembersChunk {
+ guild_id: String,
+ members: Vec<GuildMember>,
+ chunk_index: i64,
+ chunk_count: i64,
+ not_found: Option<Vec<String>>,
+ presences: Option<Vec<PresenceUpdate>>,
+ nonce: Option<String>,
+ },
+ GuildRoleCreate {
+ guild_id: String,
+ role: Role,
+ },
+ GuildRoleUpdate {
+ guild_id: String,
+ role: Role,
+ },
+ GuildRoleDelete {
+ guild_id: String,
+ role_id: String,
+ },
+ IntegrationCreate {
+ guild_id: String,
+ integration: Integration,
+ },
+ IntegrationUpdate {
+ guild_id: String,
+ integration: Integration,
+ },
+ IntegrationDelete {
+ id: String,
+ guild_id: String,
+ application_id: Option<String>,
+ },
+ InviteCreate {
+ channel_id: String,
+ code: String,
+ created_at: String,
+ guild_id: Option<String>,
+ inviter: Option<User>,
+ max_age: i64,
+ max_uses: i64,
+ target_type: Option<InviteTargetTypes>,
+ target_user: Option<User>,
+ target_application: Option<Application>,
+ temporary: bool,
+ uses: i64,
+ },
+ InviteDelete {
+ channel_id: String,
+ guild_id: Option<String>,
+ code: String,
+ },
+ InteractionCreate {
+ // boxed to avoid a large difference size between variants (https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
+ interaction: Box<Interaction>,
+ },
+ MessageCreate {
+ message: Message,
+ },
+ MessageUpdate {
+ message: Message,
+ },
+ MessageDelete {
+ id: String,
+ channel_id: String,
+ guild_id: Option<String>,
+ },
+ MessageDeleteBulk {
+ ids: Vec<String>,
+ channel_id: String,
+ guild_id: Option<String>,
+ },
+ MessageReactionAdd {
+ user_id: String,
+ channel_id: String,
+ message_id: String,
+ guild_id: Option<String>,
+ member: Option<GuildMember>,
+ emoji: Emoji,
+ },
+ MessageReactionRemove {
+ user_id: String,
+ channel_id: String,
+ message_id: String,
+ guild_id: Option<String>,
+ emoji: Emoji,
+ },
+ MessageReactionRemoveAll {
+ channel_id: String,
+ message_id: String,
+ guild_id: Option<String>,
+ },
+ MessageReactionRemoveEmoji {
+ channel_id: String,
+ message_id: String,
+ guild_id: Option<String>,
+ emoji: Emoji,
+ },
+ PresenceUpdate {
+ presence: PresenceUpdate,
+ },
+ TypingStart {
+ channel_id: String,
+ guild_id: Option<String>,
+ user_id: String,
+ timestamp: i64,
+ member: Option<GuildMember>,
+ },
+ UserUpdate {
+ user: User,
+ },
+ VoiceStateUpdate {
+ state: VoiceState,
+ },
+ VoiceServerUpdate {
+ token: String,
+ guild_id: String,
+ endpoint: Option<String>,
+ },
+ WebhookUpdate {
+ guild_id: String,
+ channel_id: String,
+ },
+ StageInstanceCreate {
+ instance: StageInstance,
+ },
+ StageInstanceUpdate {
+ instance: StageInstance,
+ },
+ StageInstanceDelete {
+ instance: StageInstance,
+ },
}