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        /// Avatar attachment
56        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57        pub avatar: Option<File>,
58
59        /// Member's roles
60        #[cfg_attr(
61            feature = "serde",
62            serde(skip_serializing_if = "Vec::is_empty", default)
63        )]
64        pub roles: Vec<String>,
65        /// Timestamp this member is timed out until
66        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
67        pub timeout: Option<Timestamp>,
68
69        /// Whether the member is server-wide voice muted
70        #[serde(skip_serializing_if = "is_true", default = "default_true")]
71        pub can_publish: bool,
72        /// Whether the member is server-wide voice deafened
73        #[serde(skip_serializing_if = "is_true", default = "default_true")]
74        pub can_receive: bool,
75    },
76    "PartialMember"
77);
78
79auto_derived!(
80    /// Composite primary key consisting of server and user id
81    #[derive(Hash, Default)]
82    pub struct MemberCompositeKey {
83        /// Server Id
84        pub server: String,
85        /// User Id
86        pub user: String,
87    }
88
89    /// Optional fields on server member object
90    pub enum FieldsMember {
91        Nickname,
92        Avatar,
93        Roles,
94        Timeout,
95        CanReceive,
96        CanPublish,
97        JoinedAt,
98    }
99
100    /// Member removal intention
101    pub enum RemovalIntention {
102        Leave,
103        Kick,
104        Ban,
105    }
106
107    /// Member response
108    #[serde(untagged)]
109    pub enum MemberResponse {
110        Member(Member),
111        MemberWithRoles {
112            member: Member,
113            roles: HashMap<String, Role>,
114        },
115    }
116
117    /// Options for fetching all members
118    #[cfg_attr(feature = "rocket", derive(FromForm))]
119    pub struct OptionsFetchAllMembers {
120        /// Whether to exclude offline users
121        pub exclude_offline: Option<bool>,
122    }
123
124    /// Response with all members
125    pub struct AllMemberResponse {
126        /// List of members
127        pub members: Vec<Member>,
128        /// List of users
129        pub users: Vec<User>,
130    }
131
132    /// New member information
133    #[cfg_attr(feature = "validator", derive(Validate))]
134    pub struct DataMemberEdit {
135        /// Member nickname
136        #[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
137        pub nickname: Option<String>,
138        /// Attachment Id to set for avatar
139        pub avatar: Option<String>,
140        /// Array of role ids
141        pub roles: Option<Vec<String>>,
142        /// Timestamp this member is timed out until
143        pub timeout: Option<Timestamp>,
144        /// server-wide voice muted
145        pub can_publish: Option<bool>,
146        /// server-wide voice deafened
147        pub can_receive: Option<bool>,
148        /// voice channel to move to if already in a voice channel
149        pub voice_channel: Option<String>,
150        /// Fields to remove from channel object
151        #[cfg_attr(feature = "serde", serde(default))]
152        pub remove: Vec<FieldsMember>,
153    }
154);