use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use crate::{
autumn::{Attachment, AttachmentId},
id::UserId,
};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(transparent)]
pub struct Username(pub String);
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum RelationshipStatus {
None,
User,
Friend,
Outgoing,
Incoming,
Blocked,
BlockedOther,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Relationship {
pub status: RelationshipStatus,
#[serde(rename = "_id")]
pub id: UserId,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub enum UserPresence {
Online,
Idle,
Busy,
Invisible,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Status {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub presence: Option<UserPresence>,
}
bitflags! {
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
#[doc = "User badges"]
pub struct Badges: u32 {
const DEVELOPER = 1;
const TRANSLATOR = 2;
const SUPPORTER = 4;
const RESPONSIBLE_DISCLOSURE = 8;
const REVOLT_TEAM = 16;
const EARLY_ADOPTER = 256;
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct BotInformation {
pub owner: UserId,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct User {
#[serde(rename = "_id")]
pub id: UserId,
pub username: Username,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avatar: Option<Attachment>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub relations: Vec<Relationship>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub badges: Option<Badges>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub relationship: Option<RelationshipStatus>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub online: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flags: Option<UserFlags>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bot: Option<BotInformation>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub profile: Option<Profile>,
}
bitflags! {
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
#[doc = "User flags"]
pub struct UserFlags: u32 {
const SUSPENDED = 0x1;
const DELETED = 0x2;
const BANNED = 0x4;
}
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Profile {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub background: Option<Attachment>,
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct UserPatch {
#[serde(rename = "_id", default, skip_serializing_if = "Option::is_none")]
pub id: Option<UserId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub username: Option<Username>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avatar: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub relations: Option<Vec<Relationship>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub badges: Option<Badges>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub relationship: Option<RelationshipStatus>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub online: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flags: Option<UserFlags>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bot: Option<BotInformation>,
#[serde(
rename = "profile.content",
default,
skip_serializing_if = "Option::is_none"
)]
pub profile_content: Option<String>,
#[serde(
rename = "profile.background",
default,
skip_serializing_if = "Option::is_none"
)]
pub profile_background: Option<Attachment>,
}
impl UserPatch {
pub fn patch(self, user: &mut User) {
let UserPatch {
id: pid,
username: pusername,
avatar: pavatar,
relations: prelations,
badges: pbadges,
status: pstatus,
relationship: prelationship,
online: ponline,
flags: pflags,
bot: pbot,
profile_content: pprofile_content,
profile_background: pprofile_background,
} = self;
let User {
id,
username,
avatar,
relations,
badges,
status,
relationship,
online,
flags,
bot,
profile,
} = user;
if let Some(pid) = pid {
*id = pid;
}
if let Some(pusername) = pusername {
*username = pusername;
}
if let Some(pavatar) = pavatar {
*avatar = Some(pavatar);
}
if let Some(prelations) = prelations {
*relations = prelations;
}
if let Some(pbadges) = pbadges {
*badges = Some(pbadges);
}
if let Some(pstatus) = pstatus {
*status = Some(pstatus);
}
if let Some(prelationship) = prelationship {
*relationship = Some(prelationship);
}
if let Some(ponline) = ponline {
*online = Some(ponline);
}
if let Some(pflags) = pflags {
*flags = Some(pflags);
}
if let Some(pbot) = pbot {
*bot = Some(pbot);
}
if let Some(pprofile_content) = pprofile_content {
profile.get_or_insert(Default::default()).content = Some(pprofile_content);
}
if let Some(pprofile_background) = pprofile_background {
profile.get_or_insert(Default::default()).background = Some(pprofile_background);
}
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum UserField {
Avatar,
ProfileBackground,
ProfileContent,
StatusText,
}
impl UserField {
pub fn remove_patch(self, user: &mut User) {
match self {
Self::Avatar => user.avatar = None,
Self::ProfileBackground => {}
Self::ProfileContent => {}
Self::StatusText => {
if let Some(Status { text, .. }) = &mut user.status {
*text = None
}
}
}
}
}
#[derive(Serialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct UserProfileDataPatch {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub background: Option<AttachmentId>,
}
#[derive(Serialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[non_exhaustive]
pub struct UserEditPatch {
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(skip_serializing_if = "Option::is_none")]
pub profile: Option<UserProfileDataPatch>,
#[serde(skip_serializing_if = "Option::is_none")]
pub avatar: Option<AttachmentId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub remove: Option<UserField>,
}