Skip to main content

revolt_models/v0/
server_members.rs

1use std::collections::HashMap;
2
3use super::{File, Role, User};
4
5use iso8601_timestamp::Timestamp;
6use once_cell::sync::Lazy;
7use regex::Regex;
8
9#[cfg(feature = "validator")]
10use validator::Validate;
11
12#[cfg(feature = "rocket")]
13use rocket::FromForm;
14
15/// Regex for valid role colours
16///
17/// Allows the use of named colours, rgb(a), variables and all gradients.
18///
19/// Flags:
20/// - Case-insensitive (`i`)
21///
22/// Source:
23/// ```regex
24/// VALUE = [a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+
25/// ADDITIONAL_VALUE = \d+deg
26/// STOP = ([ ]+(\d{1,3}%|0))?
27///
28/// ^(?:VALUE|(repeating-)?(linear|conic|radial)-gradient\((VALUE|ADDITIONAL_VALUE)STOP(,[ ]*(VALUE)STOP)+\))$
29/// ```
30pub static RE_COLOUR: Lazy<Regex> = Lazy::new(|| {
31    Regex::new(r"(?i)^(?:[a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+|(repeating-)?(linear|conic|radial)-gradient\(([a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+|\d+deg)([ ]+(\d{1,3}%|0))?(,[ ]*([a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+)([ ]+(\d{1,3}%|0))?)+\))$").unwrap()
32});
33
34fn default_true() -> bool {
35    true
36}
37
38fn is_true(x: &bool) -> bool {
39    *x
40}
41
42auto_derived_partial!(
43    /// Server Member
44    pub struct Member {
45        /// Unique member id
46        #[cfg_attr(feature = "serde", serde(rename = "_id"))]
47        pub id: MemberCompositeKey,
48
49        /// Time at which this user joined the server
50        pub joined_at: Timestamp,
51
52        /// Member's nickname
53        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
54        pub nickname: Option<String>,
55        /// Member's pronouns
56        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57        pub pronouns: Option<String>,
58        /// Avatar attachment
59        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
60        pub avatar: Option<File>,
61
62        /// Member's roles
63        #[cfg_attr(
64            feature = "serde",
65            serde(skip_serializing_if = "Vec::is_empty", default)
66        )]
67        pub roles: Vec<String>,
68        /// Timestamp this member is timed out until
69        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
70        pub timeout: Option<Timestamp>,
71
72        /// Whether the member is server-wide voice muted
73        #[serde(skip_serializing_if = "is_true", default = "default_true")]
74        pub can_publish: bool,
75        /// Whether the member is server-wide voice deafened
76        #[serde(skip_serializing_if = "is_true", default = "default_true")]
77        pub can_receive: bool,
78    },
79    "PartialMember"
80);
81
82auto_derived!(
83    /// Composite primary key consisting of server and user id
84    #[derive(Hash, Default)]
85    pub struct MemberCompositeKey {
86        /// Server Id
87        pub server: String,
88        /// User Id
89        pub user: String,
90    }
91
92    /// Optional fields on server member object
93    pub enum FieldsMember {
94        Nickname,
95        Pronouns,
96        Avatar,
97        Roles,
98        Timeout,
99        CanReceive,
100        CanPublish,
101        JoinedAt,
102        VoiceChannel,
103    }
104
105    /// Member removal intention
106    pub enum RemovalIntention {
107        Leave,
108        Kick,
109        Ban,
110    }
111
112    /// Member response
113    #[serde(untagged)]
114    pub enum MemberResponse {
115        Member(Member),
116        MemberWithRoles {
117            member: Member,
118            roles: HashMap<String, Role>,
119        },
120    }
121
122    /// Options for fetching all members
123    #[cfg_attr(feature = "rocket", derive(FromForm))]
124    pub struct OptionsFetchAllMembers {
125        /// Whether to exclude offline users
126        pub exclude_offline: Option<bool>,
127    }
128
129    /// Response with all members
130    pub struct AllMemberResponse {
131        /// List of members
132        pub members: Vec<Member>,
133        /// List of users
134        pub users: Vec<User>,
135    }
136
137    /// New member information
138    #[cfg_attr(feature = "validator", derive(Validate))]
139    pub struct DataMemberEdit {
140        /// Member nickname
141        #[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
142        pub nickname: Option<String>,
143        /// Member pronouns
144        #[cfg_attr(feature = "validator", validate(length(min = 1, max = 24)))]
145        pub pronouns: Option<String>,
146        /// Attachment Id to set for avatar
147        pub avatar: Option<String>,
148        /// Array of role ids
149        pub roles: Option<Vec<String>>,
150        /// Timestamp this member is timed out until
151        pub timeout: Option<Timestamp>,
152        /// server-wide voice muted
153        pub can_publish: Option<bool>,
154        /// server-wide voice deafened
155        pub can_receive: Option<bool>,
156        /// voice channel to move to if already in a voice channel
157        pub voice_channel: Option<String>,
158        /// Fields to remove from channel object
159        #[cfg_attr(feature = "serde", serde(default))]
160        pub remove: Vec<FieldsMember>,
161    }
162);