forked from jmug/stoatchat
chore(monorepo): delta, january, quark
This commit is contained in:
11
crates/quark/src/models/admin/migrations.rs
Normal file
11
crates/quark/src/models/admin/migrations.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Document representing migration information
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MigrationInfo {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: i32,
|
||||
/// Current database revision
|
||||
revision: i32,
|
||||
}
|
||||
8
crates/quark/src/models/admin/simple.rs
Normal file
8
crates/quark/src/models/admin/simple.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Simple database model for testing
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct SimpleModel {
|
||||
pub number: i32,
|
||||
pub value: String,
|
||||
}
|
||||
61
crates/quark/src/models/autumn/attachment.rs
Normal file
61
crates/quark/src/models/autumn/attachment.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Metadata associated with file
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Metadata {
|
||||
/// File is just a generic uncategorised file
|
||||
File,
|
||||
/// File contains textual data and should be displayed as such
|
||||
Text,
|
||||
/// File is an image with specific dimensions
|
||||
Image { width: isize, height: isize },
|
||||
/// File is a video with specific dimensions
|
||||
Video { width: isize, height: isize },
|
||||
/// File is audio
|
||||
Audio,
|
||||
}
|
||||
|
||||
impl Default for Metadata {
|
||||
fn default() -> Metadata {
|
||||
Metadata::File
|
||||
}
|
||||
}
|
||||
|
||||
/// Representation of a File on Revolt
|
||||
/// Generated by Autumn
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Default)]
|
||||
pub struct File {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
/// Tag / bucket this file was uploaded to
|
||||
pub tag: String,
|
||||
/// Original filename
|
||||
pub filename: String,
|
||||
/// Parsed metadata of this file
|
||||
pub metadata: Metadata,
|
||||
/// Raw content type of this file
|
||||
pub content_type: String,
|
||||
/// Size of this file (in bytes)
|
||||
pub size: isize,
|
||||
|
||||
/// Whether this file was deleted
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub deleted: Option<bool>,
|
||||
/// Whether this file was reported
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reported: Option<bool>,
|
||||
|
||||
// ! THE FOLLOWING SHOULD BE DEPRECATED
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub message_id: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_id: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub server_id: Option<String>,
|
||||
|
||||
/// Id of the object this file is associated with
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub object_id: Option<String>,
|
||||
}
|
||||
169
crates/quark/src/models/channels/channel.rs
Normal file
169
crates/quark/src/models/channels/channel.rs
Normal file
@@ -0,0 +1,169 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{models::attachment::File, OverrideField};
|
||||
|
||||
/// Utility function to check if a boolean value is false
|
||||
pub fn if_false(t: &bool) -> bool {
|
||||
!t
|
||||
}
|
||||
|
||||
/// Representation of a channel on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[serde(tag = "channel_type")]
|
||||
pub enum Channel {
|
||||
/// Personal "Saved Notes" channel which allows users to save messages
|
||||
SavedMessages {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: String,
|
||||
/// Id of the user this channel belongs to
|
||||
user: String,
|
||||
},
|
||||
/// Direct message channel between two users
|
||||
DirectMessage {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: String,
|
||||
|
||||
/// Whether this direct message channel is currently open on both sides
|
||||
active: bool,
|
||||
/// 2-tuple of user ids participating in direct message
|
||||
recipients: Vec<String>,
|
||||
/// Id of the last message sent in this channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
last_message_id: Option<String>,
|
||||
},
|
||||
/// Group channel between 1 or more participants
|
||||
Group {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: String,
|
||||
|
||||
/// Display name of the channel
|
||||
name: String,
|
||||
/// User id of the owner of the group
|
||||
owner: String,
|
||||
/// Channel description
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
description: Option<String>,
|
||||
/// Array of user ids participating in channel
|
||||
recipients: Vec<String>,
|
||||
|
||||
/// Custom icon attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
icon: Option<File>,
|
||||
/// Id of the last message sent in this channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
last_message_id: Option<String>,
|
||||
|
||||
/// Permissions assigned to members of this group
|
||||
/// (does not apply to the owner of the group)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
permissions: Option<i64>,
|
||||
|
||||
/// Whether this group is marked as not safe for work
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
nsfw: bool,
|
||||
},
|
||||
/// Text channel belonging to a server
|
||||
TextChannel {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: String,
|
||||
/// Id of the server this channel belongs to
|
||||
server: String,
|
||||
|
||||
/// Display name of the channel
|
||||
name: String,
|
||||
/// Channel description
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
description: Option<String>,
|
||||
|
||||
/// Custom icon attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
icon: Option<File>,
|
||||
/// Id of the last message sent in this channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
last_message_id: Option<String>,
|
||||
|
||||
/// Default permissions assigned to users in this channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
default_permissions: Option<OverrideField>,
|
||||
/// Permissions assigned based on role to this channel
|
||||
#[serde(
|
||||
default = "HashMap::<String, OverrideField>::new",
|
||||
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||
)]
|
||||
role_permissions: HashMap<String, OverrideField>,
|
||||
|
||||
/// Whether this channel is marked as not safe for work
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
nsfw: bool,
|
||||
},
|
||||
/// Voice channel belonging to a server
|
||||
VoiceChannel {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
id: String,
|
||||
/// Id of the server this channel belongs to
|
||||
server: String,
|
||||
|
||||
/// Display name of the channel
|
||||
name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// Channel description
|
||||
description: Option<String>,
|
||||
/// Custom icon attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
icon: Option<File>,
|
||||
|
||||
/// Default permissions assigned to users in this channel
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
default_permissions: Option<OverrideField>,
|
||||
/// Permissions assigned based on role to this channel
|
||||
#[serde(
|
||||
default = "HashMap::<String, OverrideField>::new",
|
||||
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||
)]
|
||||
role_permissions: HashMap<String, OverrideField>,
|
||||
|
||||
/// Whether this channel is marked as not safe for work
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
nsfw: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// Partial values of [Channel]
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
pub struct PartialChannel {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub owner: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub icon: Option<File>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nsfw: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub active: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub permissions: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub role_permissions: Option<HashMap<String, OverrideField>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub default_permissions: Option<OverrideField>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_message_id: Option<String>,
|
||||
}
|
||||
|
||||
/// Optional fields on channel object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
|
||||
pub enum FieldsChannel {
|
||||
Description,
|
||||
Icon,
|
||||
DefaultPermissions,
|
||||
}
|
||||
32
crates/quark/src/models/channels/channel_invite.rs
Normal file
32
crates/quark/src/models/channels/channel_invite.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Representation of an invite to a channel on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Invite {
|
||||
/// Invite to a specific server channel
|
||||
Server {
|
||||
/// Invite code
|
||||
#[serde(rename = "_id")]
|
||||
code: String,
|
||||
/// Id of the server this invite points to
|
||||
server: String,
|
||||
/// Id of user who created this invite
|
||||
creator: String,
|
||||
/// Id of the server channel this invite points to
|
||||
channel: String,
|
||||
},
|
||||
/// Invite to a group channel
|
||||
Group {
|
||||
/// Invite code
|
||||
#[serde(rename = "_id")]
|
||||
code: String,
|
||||
/// Id of user who created this invite
|
||||
creator: String,
|
||||
/// Id of the group channel this invite points to
|
||||
channel: String,
|
||||
}, /* User {
|
||||
code: String,
|
||||
user: String
|
||||
} */
|
||||
}
|
||||
25
crates/quark/src/models/channels/channel_unread.rs
Normal file
25
crates/quark/src/models/channels/channel_unread.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Composite primary key consisting of channel and user id
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct ChannelCompositeKey {
|
||||
/// Channel Id
|
||||
pub channel: String,
|
||||
/// User Id
|
||||
pub user: String,
|
||||
}
|
||||
|
||||
/// Representation of the state of a channel from the perspective of a user
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct ChannelUnread {
|
||||
/// Composite key pointing to a user's view of a channel
|
||||
#[serde(rename = "_id")]
|
||||
pub id: ChannelCompositeKey,
|
||||
|
||||
/// Id of the last message read in this channel by a user
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_id: Option<String>,
|
||||
/// Array of message ids that mention the user
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mentions: Option<Vec<String>>,
|
||||
}
|
||||
170
crates/quark/src/models/channels/message.rs
Normal file
170
crates/quark/src/models/channels/message.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
use iso8601_timestamp::Timestamp;
|
||||
|
||||
#[cfg(feature = "rocket_impl")]
|
||||
use rocket::FromFormField;
|
||||
|
||||
use crate::{
|
||||
models::{attachment::File, Member, User},
|
||||
types::january::Embed,
|
||||
};
|
||||
|
||||
/// # Reply
|
||||
///
|
||||
/// Representation of a message reply before it is sent.
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
|
||||
pub struct Reply {
|
||||
/// Message Id
|
||||
pub id: String,
|
||||
/// Whether this reply should mention the message's author
|
||||
pub mention: bool,
|
||||
}
|
||||
|
||||
/// Representation of a text embed before it is sent.
|
||||
#[derive(Validate, Serialize, Deserialize, JsonSchema, Clone, Debug)]
|
||||
pub struct SendableEmbed {
|
||||
#[validate(length(min = 1, max = 128))]
|
||||
pub icon_url: Option<String>,
|
||||
pub url: Option<String>,
|
||||
#[validate(length(min = 1, max = 100))]
|
||||
pub title: Option<String>,
|
||||
#[validate(length(min = 1, max = 2000))]
|
||||
pub description: Option<String>,
|
||||
pub media: Option<String>,
|
||||
#[validate(length(min = 1, max = 64))]
|
||||
pub colour: Option<String>,
|
||||
}
|
||||
|
||||
/// Representation of a system event message
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum SystemMessage {
|
||||
#[serde(rename = "text")]
|
||||
Text { content: String },
|
||||
#[serde(rename = "user_added")]
|
||||
UserAdded { id: String, by: String },
|
||||
#[serde(rename = "user_remove")]
|
||||
UserRemove { id: String, by: String },
|
||||
#[serde(rename = "user_joined")]
|
||||
UserJoined { id: String },
|
||||
#[serde(rename = "user_left")]
|
||||
UserLeft { id: String },
|
||||
#[serde(rename = "user_kicked")]
|
||||
UserKicked { id: String },
|
||||
#[serde(rename = "user_banned")]
|
||||
UserBanned { id: String },
|
||||
#[serde(rename = "channel_renamed")]
|
||||
ChannelRenamed { name: String, by: String },
|
||||
#[serde(rename = "channel_description_changed")]
|
||||
ChannelDescriptionChanged { by: String },
|
||||
#[serde(rename = "channel_icon_changed")]
|
||||
ChannelIconChanged { by: String },
|
||||
}
|
||||
|
||||
/// Name and / or avatar override information
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Validate)]
|
||||
pub struct Masquerade {
|
||||
/// Replace the display name shown on this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[validate(length(min = 1, max = 32))]
|
||||
pub name: Option<String>,
|
||||
/// Replace the avatar shown on this message (URL to image file)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[validate(length(min = 1, max = 128))]
|
||||
pub avatar: Option<String>,
|
||||
}
|
||||
|
||||
/// Representation of a Message on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialMessage"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct Message {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
/// Unique value generated by client sending this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nonce: Option<String>,
|
||||
/// Id of the channel this message was sent in
|
||||
pub channel: String,
|
||||
/// Id of the user that sent this message
|
||||
pub author: String,
|
||||
|
||||
/// Message content
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub content: Option<String>,
|
||||
/// System message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub system: Option<SystemMessage>,
|
||||
/// Array of attachments
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub attachments: Option<Vec<File>>,
|
||||
/// Time at which this message was last edited
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub edited: Option<Timestamp>,
|
||||
/// Attached embeds to this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub embeds: Option<Vec<Embed>>,
|
||||
/// Array of user ids mentioned in this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mentions: Option<Vec<String>>,
|
||||
/// Array of message ids this message is replying to
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub replies: Option<Vec<String>>,
|
||||
/// Name and / or avatar overrides for this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub masquerade: Option<Masquerade>,
|
||||
}
|
||||
|
||||
/// # Message Sort
|
||||
///
|
||||
/// Sort used for retrieving messages
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "rocket_impl", derive(FromFormField))]
|
||||
pub enum MessageSort {
|
||||
/// Sort by the most relevant messages
|
||||
Relevance,
|
||||
/// Sort by the newest messages first
|
||||
Latest,
|
||||
/// Sort by the oldest messages first
|
||||
Oldest,
|
||||
}
|
||||
|
||||
impl Default for MessageSort {
|
||||
fn default() -> MessageSort {
|
||||
MessageSort::Relevance
|
||||
}
|
||||
}
|
||||
|
||||
/// # Bulk Message Response
|
||||
///
|
||||
/// Response used when multiple messages are fetched
|
||||
#[derive(Serialize, JsonSchema)]
|
||||
#[serde(untagged)]
|
||||
pub enum BulkMessageResponse {
|
||||
JustMessages(
|
||||
/// List of messages
|
||||
Vec<Message>,
|
||||
),
|
||||
MessagesAndUsers {
|
||||
/// List of messages
|
||||
messages: Vec<Message>,
|
||||
/// List of users
|
||||
users: Vec<User>,
|
||||
/// List of members
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
members: Option<Vec<Member>>,
|
||||
},
|
||||
}
|
||||
|
||||
/// # Appended Information
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct AppendMessage {
|
||||
/// Additional embeds to include in this message
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub embeds: Option<Vec<Embed>>,
|
||||
}
|
||||
47
crates/quark/src/models/mod.rs
Normal file
47
crates/quark/src/models/mod.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
mod admin {
|
||||
pub mod migrations;
|
||||
pub mod simple;
|
||||
}
|
||||
|
||||
mod autumn {
|
||||
pub mod attachment;
|
||||
}
|
||||
|
||||
mod channels {
|
||||
pub mod channel;
|
||||
pub mod channel_invite;
|
||||
pub mod channel_unread;
|
||||
pub mod message;
|
||||
}
|
||||
|
||||
mod servers {
|
||||
pub mod server;
|
||||
pub mod server_ban;
|
||||
pub mod server_member;
|
||||
}
|
||||
|
||||
mod users {
|
||||
pub mod bot;
|
||||
pub mod user;
|
||||
pub mod user_settings;
|
||||
}
|
||||
|
||||
pub use admin::*;
|
||||
pub use autumn::*;
|
||||
pub use channels::*;
|
||||
pub use servers::*;
|
||||
pub use users::*;
|
||||
|
||||
pub use attachment::File;
|
||||
pub use bot::Bot;
|
||||
pub use channel::Channel;
|
||||
pub use channel_invite::Invite;
|
||||
pub use channel_unread::ChannelUnread;
|
||||
pub use message::Message;
|
||||
pub use migrations::MigrationInfo;
|
||||
pub use server::Server;
|
||||
pub use server_ban::ServerBan;
|
||||
pub use server_member::Member;
|
||||
pub use simple::SimpleModel;
|
||||
pub use user::User;
|
||||
pub use user_settings::UserSettings;
|
||||
150
crates/quark/src/models/servers/server.rs
Normal file
150
crates/quark/src/models/servers/server.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use num_enum::TryFromPrimitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
use crate::{models::attachment::File, OverrideField};
|
||||
|
||||
/// Utility function to check if a boolean value is false
|
||||
pub fn if_false(t: &bool) -> bool {
|
||||
!t
|
||||
}
|
||||
|
||||
/// Representation of a server role
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Default)]
|
||||
#[optional_name = "PartialRole"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct Role {
|
||||
/// Role name
|
||||
pub name: String,
|
||||
/// Permissions available to this role
|
||||
pub permissions: OverrideField,
|
||||
/// Colour used for this role
|
||||
///
|
||||
/// This can be any valid CSS colour
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub colour: Option<String>,
|
||||
/// Whether this role should be shown separately on the member sidebar
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub hoist: bool,
|
||||
/// Ranking of this role
|
||||
#[serde(default)]
|
||||
pub rank: i64,
|
||||
}
|
||||
|
||||
/// Channel category
|
||||
#[derive(Validate, Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct Category {
|
||||
/// Unique ID for this category
|
||||
#[validate(length(min = 1, max = 32))]
|
||||
pub id: String,
|
||||
/// Title for this category
|
||||
#[validate(length(min = 1, max = 32))]
|
||||
pub title: String,
|
||||
/// Channels in this category
|
||||
pub channels: Vec<String>,
|
||||
}
|
||||
|
||||
/// System message channel assignments
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct SystemMessageChannels {
|
||||
/// ID of channel to send user join messages in
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_joined: Option<String>,
|
||||
/// ID of channel to send user left messages in
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_left: Option<String>,
|
||||
/// ID of channel to send user kicked messages in
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_kicked: Option<String>,
|
||||
/// ID of channel to send user banned messages in
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_banned: Option<String>,
|
||||
}
|
||||
|
||||
/// Server flag enum
|
||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
|
||||
#[repr(i32)]
|
||||
pub enum ServerFlags {
|
||||
Verified = 1,
|
||||
Official = 2,
|
||||
}
|
||||
|
||||
/// Representation of a server on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialServer"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct Server {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
/// User id of the owner
|
||||
pub owner: String,
|
||||
|
||||
/// Name of the server
|
||||
pub name: String,
|
||||
/// Description for the server
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
|
||||
/// Channels within this server
|
||||
// ! FIXME: this may be redundant
|
||||
pub channels: Vec<String>,
|
||||
/// Categories for this server
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub categories: Option<Vec<Category>>,
|
||||
/// Configuration for sending system event messages
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub system_messages: Option<SystemMessageChannels>,
|
||||
|
||||
/// Roles for this server
|
||||
#[serde(
|
||||
default = "HashMap::<String, Role>::new",
|
||||
skip_serializing_if = "HashMap::<String, Role>::is_empty"
|
||||
)]
|
||||
pub roles: HashMap<String, Role>,
|
||||
/// Default set of server and channel permissions
|
||||
pub default_permissions: i64,
|
||||
|
||||
/// Icon attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub icon: Option<File>,
|
||||
/// Banner attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub banner: Option<File>,
|
||||
|
||||
/// Enum of server flags
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub flags: Option<i32>,
|
||||
|
||||
/// Whether this server is flagged as not safe for work
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub nsfw: bool,
|
||||
/// Whether to enable analytics
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub analytics: bool,
|
||||
/// Whether this server should be publicly discoverable
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub discoverable: bool,
|
||||
}
|
||||
|
||||
/// Optional fields on server object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
|
||||
pub enum FieldsServer {
|
||||
Description,
|
||||
Categories,
|
||||
SystemMessages,
|
||||
Icon,
|
||||
Banner,
|
||||
}
|
||||
|
||||
/// Optional fields on server object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
|
||||
pub enum FieldsRole {
|
||||
Colour,
|
||||
}
|
||||
13
crates/quark/src/models/servers/server_ban.rs
Normal file
13
crates/quark/src/models/servers/server_ban.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::server_member::MemberCompositeKey;
|
||||
|
||||
/// Representation of a server ban on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct ServerBan {
|
||||
/// Unique member id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: MemberCompositeKey,
|
||||
/// Reason for ban creation
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
50
crates/quark/src/models/servers/server_member.rs
Normal file
50
crates/quark/src/models/servers/server_member.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models::attachment::File;
|
||||
|
||||
/// Composite primary key consisting of server and user id
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Default)]
|
||||
pub struct MemberCompositeKey {
|
||||
/// Server Id
|
||||
pub server: String,
|
||||
/// User Id
|
||||
pub user: String,
|
||||
}
|
||||
|
||||
/// Representation of a member of a server on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialMember"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct Member {
|
||||
/// Unique member id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: MemberCompositeKey,
|
||||
|
||||
/// Member's nickname
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nickname: Option<String>,
|
||||
/// Avatar attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar: Option<File>,
|
||||
|
||||
/// Member's roles
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub roles: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Optional fields on server member object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
|
||||
pub enum FieldsMember {
|
||||
Nickname,
|
||||
Avatar,
|
||||
Roles,
|
||||
}
|
||||
|
||||
/// Member removal intention
|
||||
pub enum RemovalIntention {
|
||||
Leave,
|
||||
Kick,
|
||||
Ban,
|
||||
}
|
||||
63
crates/quark/src/models/users/bot.rs
Normal file
63
crates/quark/src/models/users/bot.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use num_enum::TryFromPrimitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Utility function to check if a boolean value is false
|
||||
pub fn if_false(t: &bool) -> bool {
|
||||
!t
|
||||
}
|
||||
|
||||
/// Bot flag enum
|
||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
|
||||
#[repr(i32)]
|
||||
pub enum BotFlags {
|
||||
Verified = 1,
|
||||
Official = 2,
|
||||
}
|
||||
|
||||
/// Representation of a bot on Revolt
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialBot"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct Bot {
|
||||
/// Bot Id
|
||||
///
|
||||
/// This equals the associated bot user's id.
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
/// User Id of the bot owner
|
||||
pub owner: String,
|
||||
/// Token used to authenticate requests for this bot
|
||||
pub token: String,
|
||||
/// Whether the bot is public
|
||||
/// (may be invited by anyone)
|
||||
pub public: bool,
|
||||
|
||||
/// Whether to enable analytics
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub analytics: bool,
|
||||
/// Whether this bot should be publicly discoverable
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub discoverable: bool,
|
||||
/// Reserved; URL for handling interactions
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub interactions_url: Option<String>,
|
||||
/// URL for terms of service
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub terms_of_service_url: Option<String>,
|
||||
/// URL for privacy policy
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub privacy_policy_url: Option<String>,
|
||||
|
||||
/// Enum of bot flags
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub flags: Option<i32>,
|
||||
}
|
||||
|
||||
/// Optional fields on bot object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq)]
|
||||
pub enum FieldsBot {
|
||||
Token,
|
||||
InteractionsURL,
|
||||
}
|
||||
177
crates/quark/src/models/users/user.rs
Normal file
177
crates/quark/src/models/users/user.rs
Normal file
@@ -0,0 +1,177 @@
|
||||
use num_enum::TryFromPrimitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
use crate::models::attachment::File;
|
||||
|
||||
/// Utility function to check if a boolean value is false
|
||||
pub fn if_false(t: &bool) -> bool {
|
||||
!t
|
||||
}
|
||||
|
||||
/// User's relationship with another user (or themselves)
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]
|
||||
pub enum RelationshipStatus {
|
||||
None,
|
||||
User,
|
||||
Friend,
|
||||
Outgoing,
|
||||
Incoming,
|
||||
Blocked,
|
||||
BlockedOther,
|
||||
}
|
||||
|
||||
/// Relationship entry indicating current status with other user
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct Relationship {
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
pub status: RelationshipStatus,
|
||||
}
|
||||
|
||||
/// Presence status
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]
|
||||
pub enum Presence {
|
||||
Online,
|
||||
Idle,
|
||||
Busy,
|
||||
Invisible,
|
||||
}
|
||||
|
||||
/// User's active status
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Validate, Default)]
|
||||
pub struct UserStatus {
|
||||
/// Custom status text
|
||||
#[validate(length(min = 1, max = 128))]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub text: Option<String>,
|
||||
/// Current presence option
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub presence: Option<Presence>,
|
||||
}
|
||||
|
||||
/// User's profile
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Default)]
|
||||
pub struct UserProfile {
|
||||
/// Text content on user's profile
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub content: Option<String>,
|
||||
/// Background visible on user's profile
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub background: Option<File>,
|
||||
}
|
||||
|
||||
/// User badge bitfield
|
||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
|
||||
#[repr(i32)]
|
||||
pub enum Badges {
|
||||
/// Revolt Developer
|
||||
Developer = 1,
|
||||
/// Helped translate Revolt
|
||||
Translator = 2,
|
||||
/// Monetarily supported Revolt
|
||||
Supporter = 4,
|
||||
/// Responsibly disclosed a security issue
|
||||
ResponsibleDisclosure = 8,
|
||||
/// Revolt Founder
|
||||
Founder = 16,
|
||||
/// Platform moderator
|
||||
PlatformModeration = 32,
|
||||
/// Active monetary supporter
|
||||
ActiveSupporter = 64,
|
||||
/// 🦊🦝
|
||||
Paw = 128,
|
||||
/// Joined as one of the first 1000 users in 2021
|
||||
EarlyAdopter = 256,
|
||||
/// Amogus
|
||||
ReservedRelevantJokeBadge1 = 512,
|
||||
/// Low resolution troll face
|
||||
ReservedRelevantJokeBadge2 = 1024,
|
||||
}
|
||||
|
||||
/// User flag enum
|
||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
|
||||
#[repr(i32)]
|
||||
pub enum Flags {
|
||||
/// User has been suspended from the platform
|
||||
Suspended = 1,
|
||||
/// User has deleted their account
|
||||
Deleted = 2,
|
||||
/// User was banned off the platform
|
||||
Banned = 4,
|
||||
}
|
||||
|
||||
/// Bot information for if the user is a bot
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct BotInformation {
|
||||
/// Id of the owner of this bot
|
||||
pub owner: String,
|
||||
}
|
||||
|
||||
/// Representiation of a User on Revolt.
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct, Default)]
|
||||
#[optional_derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||
#[optional_name = "PartialUser"]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
pub struct User {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
/// Username
|
||||
pub username: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// Avatar attachment
|
||||
pub avatar: Option<File>,
|
||||
/// Relationships with other users
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub relations: Option<Vec<Relationship>>,
|
||||
|
||||
/// Bitfield of user badges
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub badges: Option<i32>,
|
||||
/// User's current status
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status: Option<UserStatus>,
|
||||
/// User's profile page
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub profile: Option<UserProfile>,
|
||||
|
||||
/// Enum of user flags
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub flags: Option<i32>,
|
||||
/// Whether this user is privileged
|
||||
#[serde(skip_serializing_if = "if_false", default)]
|
||||
pub privileged: bool,
|
||||
/// Bot information
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bot: Option<BotInformation>,
|
||||
|
||||
// ? Entries below should never be pushed to the database
|
||||
/// Current session user's relationship with this user
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub relationship: Option<RelationshipStatus>,
|
||||
/// Whether this user is currently online
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub online: Option<bool>,
|
||||
}
|
||||
|
||||
/// Optional fields on user object
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
|
||||
pub enum FieldsUser {
|
||||
Avatar,
|
||||
StatusText,
|
||||
StatusPresence,
|
||||
ProfileContent,
|
||||
ProfileBackground,
|
||||
}
|
||||
|
||||
/// Enumeration providing a hint to the type of user we are handling
|
||||
pub enum UserHint {
|
||||
/// Could be either a user or a bot
|
||||
Any,
|
||||
/// Only match bots
|
||||
Bot,
|
||||
/// Only match users
|
||||
User,
|
||||
}
|
||||
6
crates/quark/src/models/users/user_settings.rs
Normal file
6
crates/quark/src/models/users/user_settings.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// HashMap of user settings
|
||||
/// Each key is mapped to a tuple consisting of the
|
||||
/// revision timestamp and serialised data (in JSON format)
|
||||
pub type UserSettings = HashMap<String, (i64, String)>;
|
||||
Reference in New Issue
Block a user