1use bitflags::bitflags;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 autumn::{Attachment, AttachmentId},
6 id::UserId,
7};
8
9#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[serde(transparent)]
18pub struct Username(pub String);
19
20#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
24pub enum RelationshipStatus {
25 None,
26 User,
27 Friend,
28 Outgoing,
29 Incoming,
30 Blocked,
31 BlockedOther,
32}
33
34#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
42#[serde(deny_unknown_fields)]
43pub struct Relationship {
44 pub status: RelationshipStatus,
45 #[serde(rename = "_id")]
47 pub id: UserId,
48}
49
50#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
54#[serde(deny_unknown_fields)]
55pub enum UserPresence {
56 Online,
57 Idle,
58 Busy,
59 Invisible,
60}
61
62#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
65#[serde(deny_unknown_fields)]
66pub struct Status {
67 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub text: Option<String>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub presence: Option<UserPresence>,
73}
74
75bitflags! {
78 #[derive(Serialize, Deserialize)]
79 #[serde(transparent)]
80 #[doc = "User badges"]
81 pub struct Badges: u32 {
82 const DEVELOPER = 1;
83 const TRANSLATOR = 2;
84 const SUPPORTER = 4;
85 const RESPONSIBLE_DISCLOSURE = 8;
86 const REVOLT_TEAM = 16;
87 const EARLY_ADOPTER = 256;
88 }
89}
90
91#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
95#[serde(deny_unknown_fields)]
96pub struct BotInformation {
97 pub owner: UserId,
99}
100
101#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
105#[serde(deny_unknown_fields)]
106pub struct User {
107 #[serde(rename = "_id")]
109 pub id: UserId,
110 pub username: Username,
112 #[serde(default, skip_serializing_if = "Option::is_none")]
114 pub avatar: Option<Attachment>,
115 #[serde(default, skip_serializing_if = "Vec::is_empty")]
120 pub relations: Vec<Relationship>,
121 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub badges: Option<Badges>,
124 #[serde(default, skip_serializing_if = "Option::is_none")]
126 pub status: Option<Status>,
127 #[serde(default, skip_serializing_if = "Option::is_none")]
130 pub relationship: Option<RelationshipStatus>,
131 #[serde(default, skip_serializing_if = "Option::is_none")]
133 pub online: Option<bool>,
134 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub flags: Option<UserFlags>,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
141 pub bot: Option<BotInformation>,
142
143 #[serde(default, skip_serializing_if = "Option::is_none")]
147 pub profile: Option<Profile>,
148}
149
150bitflags! {
153 #[derive(Serialize, Deserialize)]
154 #[serde(transparent)]
155 #[doc = "User flags"]
156 pub struct UserFlags: u32 {
157 const SUSPENDED = 0x1;
158 const DELETED = 0x2;
159 const BANNED = 0x4;
160 }
161}
162
163#[derive(Serialize, Deserialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
167#[serde(deny_unknown_fields)]
168pub struct Profile {
169 #[serde(default, skip_serializing_if = "Option::is_none")]
170 pub content: Option<String>,
171 #[serde(default, skip_serializing_if = "Option::is_none")]
172 pub background: Option<Attachment>,
173}
174
175#[derive(Serialize, Deserialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
183#[serde(deny_unknown_fields)]
184pub struct UserPatch {
185 #[serde(rename = "_id", default, skip_serializing_if = "Option::is_none")]
186 pub id: Option<UserId>,
187 #[serde(default, skip_serializing_if = "Option::is_none")]
188 pub username: Option<Username>,
189 #[serde(default, skip_serializing_if = "Option::is_none")]
190 pub avatar: Option<Attachment>,
191 #[serde(default, skip_serializing_if = "Option::is_none")]
192 pub relations: Option<Vec<Relationship>>,
193 #[serde(default, skip_serializing_if = "Option::is_none")]
194 pub badges: Option<Badges>,
195 #[serde(default, skip_serializing_if = "Option::is_none")]
196 pub status: Option<Status>,
197 #[serde(default, skip_serializing_if = "Option::is_none")]
198 pub relationship: Option<RelationshipStatus>,
199 #[serde(default, skip_serializing_if = "Option::is_none")]
200 pub online: Option<bool>,
201 #[serde(default, skip_serializing_if = "Option::is_none")]
202 pub flags: Option<UserFlags>,
203 #[serde(default, skip_serializing_if = "Option::is_none")]
204 pub bot: Option<BotInformation>,
205 #[serde(
206 rename = "profile.content",
207 default,
208 skip_serializing_if = "Option::is_none"
209 )]
210 pub profile_content: Option<String>,
211 #[serde(
212 rename = "profile.background",
213 default,
214 skip_serializing_if = "Option::is_none"
215 )]
216 pub profile_background: Option<Attachment>,
217}
218
219impl UserPatch {
220 pub fn patch(self, user: &mut User) {
224 let UserPatch {
225 id: pid,
226 username: pusername,
227 avatar: pavatar,
228 relations: prelations,
229 badges: pbadges,
230 status: pstatus,
231 relationship: prelationship,
232 online: ponline,
233 flags: pflags,
234 bot: pbot,
235 profile_content: pprofile_content,
236 profile_background: pprofile_background,
237 } = self;
238 let User {
239 id,
240 username,
241 avatar,
242 relations,
243 badges,
244 status,
245 relationship,
246 online,
247 flags,
248 bot,
249 profile,
250 } = user;
251
252 if let Some(pid) = pid {
253 *id = pid;
254 }
255 if let Some(pusername) = pusername {
256 *username = pusername;
257 }
258 if let Some(pavatar) = pavatar {
259 *avatar = Some(pavatar);
260 }
261 if let Some(prelations) = prelations {
262 *relations = prelations;
263 }
264 if let Some(pbadges) = pbadges {
265 *badges = Some(pbadges);
266 }
267 if let Some(pstatus) = pstatus {
268 *status = Some(pstatus);
269 }
270 if let Some(prelationship) = prelationship {
271 *relationship = Some(prelationship);
272 }
273 if let Some(ponline) = ponline {
274 *online = Some(ponline);
275 }
276 if let Some(pflags) = pflags {
277 *flags = Some(pflags);
278 }
279 if let Some(pbot) = pbot {
280 *bot = Some(pbot);
281 }
282 if let Some(pprofile_content) = pprofile_content {
283 profile.get_or_insert(Default::default()).content = Some(pprofile_content);
284 }
285 if let Some(pprofile_background) = pprofile_background {
286 profile.get_or_insert(Default::default()).background = Some(pprofile_background);
287 }
288 }
289}
290
291#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
293pub enum UserField {
294 Avatar,
295 ProfileBackground,
296 ProfileContent,
297 StatusText,
298}
299
300impl UserField {
301 pub fn remove_patch(self, user: &mut User) {
303 match self {
304 Self::Avatar => user.avatar = None,
305 Self::ProfileBackground => {}
306 Self::ProfileContent => {}
307 Self::StatusText => {
308 if let Some(Status { text, .. }) = &mut user.status {
309 *text = None
310 }
311 }
312 }
313 }
314}
315
316#[derive(Serialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
318pub struct UserProfileDataPatch {
319 #[serde(default, skip_serializing_if = "Option::is_none")]
320 pub content: Option<String>,
321 #[serde(default, skip_serializing_if = "Option::is_none")]
322 pub background: Option<AttachmentId>,
323}
324
325#[derive(Serialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
327#[non_exhaustive]
328pub struct UserEditPatch {
329 #[serde(skip_serializing_if = "Option::is_none")]
330 pub status: Option<Status>,
331 #[serde(skip_serializing_if = "Option::is_none")]
332 pub profile: Option<UserProfileDataPatch>,
333 #[serde(skip_serializing_if = "Option::is_none")]
334 pub avatar: Option<AttachmentId>,
335 #[serde(skip_serializing_if = "Option::is_none")]
336 pub remove: Option<UserField>,
337}