essence/models/
user.rs

1use std::collections::HashMap;
2
3#[cfg(feature = "db")]
4use crate::db::{DbRelationship, DbRelationshipType};
5use crate::models::Permissions;
6use crate::serde_for_bitflags;
7use serde::{Deserialize, Serialize};
8#[cfg(feature = "utoipa")]
9use utoipa::ToSchema;
10
11/// Represents a user account.
12///
13/// A lot of information is stored in the user's flags, including whether or not the user is a bot
14/// account.
15#[derive(Clone, Debug, Default, Serialize)]
16#[cfg_attr(feature = "client", derive(Deserialize))]
17#[cfg_attr(feature = "utoipa", derive(ToSchema))]
18#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
19pub struct User {
20    /// The snowflake ID of the user.
21    pub id: u64,
22    /// The username of the user.
23    pub username: String,
24    /// The display name of the user. This is `None` if the user has no display name.
25    pub display_name: Option<String>,
26    /// The URL of the user's avatar. This is `None` if the user has no avatar.
27    pub avatar: Option<String>,
28    /// The URL of the user's banner. This is `None` if the user has no banner.
29    pub banner: Option<String>,
30    /// The user's bio. This is `None` if the user has no bio.
31    pub bio: Option<String>,
32    /// A bitmask of extra information associated with this user.
33    #[cfg_attr(feature = "bincode", bincode(with_serde))]
34    pub flags: UserFlags,
35}
36
37bitflags::bitflags! {
38    /// A bitmask of extra information associated with a user.
39    #[derive(Default)]
40    pub struct UserFlags: u32 {
41        /// The user is a bot account.
42        const BOT = 1 << 0;
43        /// The user has a verified email address.
44        const VERIFIED = 1 << 1;
45        /// The user is a maintainer of Adapt.
46        const MAINTAINER = 1 << 2;
47        /// The user is a contributor to Adapt.
48        const CONTRIBUTOR = 1 << 3;
49        /// The user has reported security issues or bugs within Adapt.
50        const BUG_HUNTER = 1 << 4;
51        /// The user has elevated privileges on the Adapt platform.
52        const PRIVILEGED = 1 << 5;
53    }
54}
55
56serde_for_bitflags!(u32: UserFlags);
57
58/// Represents information such as the name and color of a guild folder.
59/// This is only shown in the client's UI.
60#[derive(Clone, Debug, Deserialize, Serialize)]
61#[cfg_attr(feature = "utoipa", derive(ToSchema))]
62pub struct GuildFolderInfo {
63    /// The name of the folder.
64    pub name: String,
65    /// The color of the folder.
66    pub color: u32,
67}
68
69/// Represents a folder that contains a collection of guilds. This is only shown in the client's UI.
70#[derive(Clone, Debug, Deserialize, Serialize)]
71#[cfg_attr(feature = "utoipa", derive(ToSchema))]
72pub struct GuildFolder {
73    /// The path of the folder, with the top-level folder first.
74    ///
75    /// This is `None` if this folder represents the collection of guilds
76    /// that are not in any folders, or in other terms, the root folder.
77    pub path: Option<Vec<GuildFolderInfo>>,
78    /// A list of guild IDs representing guilds that were placed in this folder, in order from
79    /// top to bottom.
80    pub guilds: Vec<u64>,
81}
82
83/// Represents user info about the client. This has other information that is not available to the
84/// public, such as emails, guilds, and relationships (friends and blocked users).
85#[derive(Clone, Debug, Default, Serialize)]
86#[cfg_attr(feature = "client", derive(Deserialize))]
87#[cfg_attr(feature = "utoipa", derive(ToSchema))]
88#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
89pub struct ClientUser {
90    /// The public user info about the client.
91    #[serde(flatten)]
92    pub user: User,
93    /// The associated email of the client's account.
94    ///
95    /// If the client is a bot, this is `None`.
96    #[cfg_attr(feature = "utoipa", schema(format = "email"))]
97    pub email: Option<String>,
98    /// (Used internally) The hashed password of the client's account.
99    ///
100    /// This will never be present:
101    /// * The **field** will exist if the `db` feature enabled, otherwise this field is not
102    ///   present and guarded by a `cfg` attribute.
103    /// * The **value** will always be `None` unless it is internally returned by the database.
104    #[serde(skip)]
105    #[cfg(feature = "db")]
106    pub password: Option<String>,
107    /// Controls who can open and/or send direct messages to the client.
108    #[cfg_attr(feature = "bincode", bincode(with_serde))]
109    pub dm_privacy: PrivacyConfiguration,
110    /// Controls who can add the client to group DMs.
111    #[cfg_attr(feature = "bincode", bincode(with_serde))]
112    pub group_dm_privacy: PrivacyConfiguration,
113    /// Controls who can request to add the client as a friend.
114    #[cfg_attr(feature = "bincode", bincode(with_serde))]
115    pub friend_request_privacy: PrivacyConfiguration,
116    /// Onboarding flags that indicate which onboarding steps the user has completed.
117    #[cfg_attr(feature = "bincode", bincode(with_serde))]
118    pub onboarding_flags: UserOnboardingFlags,
119    /// Bitmask of client settings.
120    #[cfg_attr(feature = "bincode", bincode(with_serde))]
121    pub settings: Settings,
122    /// A map for notification settings override.
123    #[cfg_attr(feature = "bincode", bincode(with_serde))]
124    pub notification_override: HashMap<u64, NotificationFlags>,
125}
126
127bitflags::bitflags! {
128    #[derive(Default)]
129    pub struct Settings: i32 {
130        /// Whether the user wants to receive push notifications.
131        const NOTIFICATIONS = 1 << 0;
132        /// Whether the user wants to always show guilds in the sidebar.
133        const ALWAYS_SHOW_GUILDS_IN_SIDEBAR = 1 << 1;
134    }
135}
136
137bitflags::bitflags! {
138    #[derive(Default)]
139    pub struct NotificationFlags: i16 {
140        const ALL = 1 << 0;
141        const ALL_MENTIONS = 1 << 1;
142        const DIRECT_MENTIONS = 1 << 2;
143        const HIGHLIGHTS = 1 << 3;
144    }
145}
146
147serde_for_bitflags!(i32: Settings);
148serde_for_bitflags!(i16: NotificationFlags);
149
150impl std::ops::Deref for ClientUser {
151    type Target = User;
152
153    fn deref(&self) -> &Self::Target {
154        &self.user
155    }
156}
157
158impl std::ops::DerefMut for ClientUser {
159    fn deref_mut(&mut self) -> &mut Self::Target {
160        &mut self.user
161    }
162}
163
164bitflags::bitflags! {
165    /// Represents a privacy configuration.
166    #[derive(Default)]
167    pub struct PrivacyConfiguration: i16 {
168        /// This configuration is public for friends.
169        const FRIENDS = 1 << 0;
170        /// This configuration is public for mutual friends (friends of friends).
171        const MUTUAL_FRIENDS = 1 << 1;
172        /// This configuration is public for users who share a guild with you.
173        const GUILD_MEMBERS = 1 << 2;
174        /// This configuration is public for everyone. This overwrites all other configurations.
175        const EVERYONE = 1 << 3;
176
177        // Aliases
178        /// Default configuration for ``dm_privacy``.
179        const DEFAULT_DM_PRIVACY = Self::FRIENDS.bits
180            | Self::MUTUAL_FRIENDS.bits
181            | Self::GUILD_MEMBERS.bits;
182        /// Default configuration for ``group_dm_privacy``.
183        const DEFAULT_GROUP_DM_PRIVACY = Self::FRIENDS.bits;
184        /// Default configuration for ``friend_request_privacy``.
185        const DEFAULT_FRIEND_REQUEST_PRIVACY = Self::EVERYONE.bits;
186    }
187}
188
189serde_for_bitflags!(i16: PrivacyConfiguration);
190
191bitflags::bitflags! {
192    /// A bitmask of onboarding and tutorial steps that a user has completed.
193    #[derive(Default)]
194    pub struct UserOnboardingFlags: i64 {
195        // Learn Adapt
196        const CONNECT_WITH_FRIENDS = 1 << 0;
197        const CREATE_A_COMMUNITY = 1 << 1;
198        const DISCOVER_COMMUNITIES = 1 << 2;
199    }
200}
201
202serde_for_bitflags!(i64: UserOnboardingFlags);
203
204/// A section to include in a user's sidebar.
205#[derive(Clone, Debug, Serialize)]
206#[cfg_attr(feature = "client", derive(Deserialize))]
207#[cfg_attr(feature = "utoipa", derive(ToSchema))]
208#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
209#[serde(rename_all = "snake_case")]
210pub enum SidebarSection {
211    /// Show unmuted channels that recently had activity. (Unread messages)
212    UnreadMessages,
213    /// Show channels you recently accessed.
214    RecentChannels,
215}
216
217/// Represents the type of relationship a user has with another user.
218#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
219#[cfg_attr(feature = "utoipa", derive(ToSchema))]
220#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
221#[serde(rename_all = "snake_case")]
222pub enum RelationshipType {
223    /// The other user is added as a friend.
224    Friend,
225    /// The client user has sent a friend request to the other user which is still pending.
226    OutgoingRequest,
227    /// The other user has sent a friend request to the client user which is still pending.
228    IncomingRequest,
229    /// The client user has blocked the other user.
230    Blocked,
231}
232
233#[cfg(feature = "db")]
234impl From<DbRelationshipType> for RelationshipType {
235    #[inline]
236    fn from(kind: DbRelationshipType) -> Self {
237        match kind {
238            DbRelationshipType::Friend => Self::Friend,
239            DbRelationshipType::Incoming => Self::IncomingRequest,
240            DbRelationshipType::Outgoing => Self::OutgoingRequest,
241            DbRelationshipType::Blocked => Self::Blocked,
242        }
243    }
244}
245
246/// Represents a relationship that a user has with another user.
247#[derive(Clone, Debug, Serialize)]
248#[cfg_attr(feature = "client", derive(Deserialize))]
249#[cfg_attr(feature = "utoipa", derive(ToSchema))]
250#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
251pub struct Relationship {
252    /// The user that this relationship is with.
253    pub user: User,
254    /// The type of relationship this is.
255    #[serde(rename = "type")]
256    pub kind: RelationshipType,
257}
258
259#[cfg(feature = "db")]
260impl Relationship {
261    /// Creates a new relationship from a database row.
262    /// This is used internally by the database module.
263    #[inline]
264    #[allow(clippy::missing_const_for_fn)] // false positive
265    pub(crate) fn from_db_relationship(data: DbRelationship) -> Self {
266        Self {
267            user: User {
268                id: data.target_id as _,
269                username: data.username,
270                display_name: data.display_name,
271                avatar: data.avatar,
272                banner: data.banner,
273                bio: data.bio,
274                flags: UserFlags::from_bits_truncate(data.flags as _),
275            },
276            kind: RelationshipType::from(data.kind),
277        }
278    }
279}
280
281/// Represents details about a bot.
282#[derive(Clone, Debug, Serialize)]
283#[cfg_attr(feature = "client", derive(Deserialize))]
284#[cfg_attr(feature = "utoipa", derive(ToSchema))]
285#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
286pub struct Bot {
287    /// The user this bot is associated with.
288    pub user: User,
289    /// The ID of the user who owns this bot.
290    pub owner_id: u64,
291    /// The default permissions the bot has when added to a guild.
292    #[cfg_attr(feature = "bincode", bincode(with_serde))]
293    pub default_permissions: Permissions,
294    /// A bitmask of extra information associated with the bot.
295    #[cfg_attr(feature = "bincode", bincode(with_serde))]
296    pub flags: BotFlags,
297}
298
299bitflags::bitflags! {
300    /// A bitmask of extra information associated with a bot.
301    #[derive(Default)]
302    pub struct BotFlags: u32 {
303        /// The bot is a verified bot account.
304        const VERIFIED = 1 << 0;
305        /// The bot is public. Bots that are not public can only be added by the owner.
306        const PUBLIC = 1 << 1;
307        /// This bot is allowed to be added to guilds.
308        const GUILD_ENABLED = 1 << 2;
309        /// This bot is allowed to be added to group DMs.
310        const GROUP_DM_ENABLED = 1 << 3;
311        /// This bot is allowed to be used anywhere, including guilds, group DMs, and direct DMs.
312        /// Global bots are restricted to ephemeral messages unless authorized in a direct DM.
313        const GLOBAL_ENABLED = 1 << 4;
314    }
315}
316
317serde_for_bitflags!(u32: BotFlags);