use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::{
autumn::Attachment,
channels::ChannelPermissions,
id::{CategoryId, ChannelId, MemberId, RoleId, ServerId, UserId},
};
pub type MemberCompositeKey = MemberId;
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Member {
#[serde(rename = "_id")]
pub id: MemberCompositeKey,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nickname: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avatar: Option<Attachment>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub roles: Vec<RoleId>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Ban {
#[serde(rename = "_id")]
pub id: MemberCompositeKey,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
pub type PermissionTuple = (ServerPermissions, ChannelPermissions);
bitflags::bitflags! {
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
#[doc = "Server permissions"]
pub struct ServerPermissions: u32 {
const VIEW = 0b00000000000000000000000000000001; const MANAGE_ROLES = 0b00000000000000000000000000000010; const MANAGE_CHANNELS = 0b00000000000000000000000000000100; const MANAGE_SERVER = 0b00000000000000000000000000001000; const KICK_MEMBERS = 0b00000000000000000000000000010000; const BAN_MEMBERS = 0b00000000000000000000000000100000; const CHANGE_NICKNAME = 0b00000000000000000001000000000000; const MANAGE_NICKNAMES = 0b00000000000000000010000000000000; const CHANGE_AVATAR = 0b00000000000000000100000000000000; const REMOVE_AVATARS = 0b00000000000000001000000000000000; }
}
pub type Color = String;
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Role {
pub name: String,
pub permissions: PermissionTuple,
#[serde(rename = "colour", default, skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hoist: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rank: Option<usize>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct RoleInformation {
pub name: String,
#[serde(rename = "colour", default, skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hoist: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rank: Option<usize>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct Category {
pub id: CategoryId,
pub title: String,
pub channels: Vec<ChannelId>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct SystemMessageChannels {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_joined: Option<ChannelId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_left: Option<ChannelId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_kicked: Option<ChannelId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_banned: Option<ChannelId>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Server {
#[serde(rename = "_id")]
pub id: ServerId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nonce: Option<String>,
pub owner: UserId,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub channels: Vec<ChannelId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub categories: Vec<Category>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub system_messages: Option<SystemMessageChannels>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub roles: Option<RolesObject>,
pub default_permissions: PermissionTuple,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub icon: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub banner: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nsfw: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flags: Option<ServerFlags>,
}
bitflags::bitflags! {
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct ServerFlags: u32 {
const OFFICIAL_REVOLT_SERVER = 1;
const VERIFIED_COMMUNITY_SERVER = 2;
}
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct PartialMember {
#[serde(rename = "_id", default, skip_serializing_if = "Option::is_none")]
pub id: Option<MemberId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nickname: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub avatar: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub roles: Option<Vec<RoleId>>,
}
impl PartialMember {
pub fn patch(self, member: &mut Member) {
let PartialMember {
id: pid,
nickname: pnickname,
avatar: pavatar,
roles: proles,
} = self;
let Member {
id,
nickname,
avatar,
roles,
} = member;
if let Some(pid) = pid {
*id = pid;
}
if let Some(pnickname) = pnickname {
*nickname = Some(pnickname);
}
if let Some(pavatar) = pavatar {
*avatar = Some(pavatar);
}
if let Some(proles) = proles {
*roles = proles;
}
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum MemberField {
Nickname,
Avatar,
}
impl MemberField {
pub fn remove_patch(self, member: &mut Member) {
match self {
Self::Nickname => member.nickname = None,
Self::Avatar => member.avatar = None,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(transparent)]
pub struct RolesObject(HashMap<RoleId, Role>);
impl RolesObject {
pub fn iter(&self) -> RolesIter {
RolesIter(self.0.iter())
}
pub fn get(&self, id: &RoleId) -> Option<&Role> {
self.0.get(id)
}
pub fn patch_role(&mut self, role_id: &RoleId, patch: PartialRole, remove: Option<RoleField>) {
if let Some(refr) = self.0.get_mut(role_id) {
patch.patch(refr);
if let Some(remove) = remove {
remove.remove_patch(refr);
}
}
}
pub fn remove(&mut self, id: &RoleId) {
self.0.remove(id);
}
}
pub struct RolesIter<'a>(std::collections::hash_map::Iter<'a, RoleId, Role>);
impl<'a> Iterator for RolesIter<'a> {
type Item = (&'a RoleId, &'a Role);
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(deny_unknown_fields)]
pub struct PartialRole {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub permissions: Option<(ServerPermissions, ChannelPermissions)>,
#[serde(rename = "colour", default, skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hoist: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rank: Option<usize>,
}
impl PartialRole {
pub fn patch(self, role: &mut Role) {
let PartialRole {
name: pname,
permissions: ppermissions,
color: pcolor,
hoist: phoist,
rank: prank,
} = self;
let Role {
name,
permissions,
color,
hoist,
rank,
} = role;
if let Some(pname) = pname {
*name = pname;
}
if let Some(ppermissions) = ppermissions {
*permissions = ppermissions;
}
if let Some(pcolor) = pcolor {
*color = Some(pcolor);
}
if let Some(phoist) = phoist {
*hoist = Some(phoist);
}
if let Some(prank) = prank {
*rank = Some(prank);
}
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum RoleField {
#[serde(rename = "Colour")]
Color,
}
impl RoleField {
pub fn remove_patch(self, role: &mut Role) {
match self {
Self::Color => role.color = None,
}
}
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PartialServer {
#[serde(rename = "_id", default, skip_serializing_if = "Option::is_none")]
pub id: Option<ServerId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nonce: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owner: Option<UserId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub channels: Option<Vec<ChannelId>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub categories: Option<Vec<Category>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub system_messages: Option<SystemMessageChannels>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub roles: Option<RolesObject>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_permissions: Option<(ServerPermissions, ChannelPermissions)>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub icon: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub banner: Option<Attachment>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nsfw: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flags: Option<ServerFlags>,
}
impl PartialServer {
pub fn patch(self, serv: &mut Server) {
let PartialServer {
id: pid,
nonce: pnonce,
owner: powner,
name: pname,
description: pdescription,
channels: pchannels,
categories: pcategories,
system_messages: psystem_messages,
roles: proles,
default_permissions: pdefault_permissions,
icon: picon,
banner: pbanner,
nsfw: pnsfw,
flags: pflags,
} = self;
let Server {
id,
nonce,
owner,
name,
description,
channels,
categories,
system_messages,
roles,
default_permissions,
icon,
banner,
nsfw,
flags,
} = serv;
if let Some(pid) = pid {
*id = pid;
}
if let Some(pnonce) = pnonce {
*nonce = Some(pnonce);
}
if let Some(powner) = powner {
*owner = powner;
}
if let Some(pname) = pname {
*name = pname;
}
if let Some(pdescription) = pdescription {
*description = Some(pdescription);
}
if let Some(pchannels) = pchannels {
*channels = pchannels;
}
if let Some(pcategories) = pcategories {
*categories = pcategories;
}
if let Some(psystem_messages) = psystem_messages {
*system_messages = Some(psystem_messages);
}
if let Some(proles) = proles {
*roles = Some(proles);
}
if let Some(pdefault_permissions) = pdefault_permissions {
*default_permissions = pdefault_permissions;
}
if let Some(picon) = picon {
*icon = Some(picon);
}
if let Some(pbanner) = pbanner {
*banner = Some(pbanner);
}
if let Some(pnsfw) = pnsfw {
*nsfw = Some(pnsfw);
}
if let Some(pflags) = pflags {
*flags = Some(pflags);
}
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum ServerField {
Icon,
Banner,
Description,
}
impl ServerField {
pub fn remove_patch(self, server: &mut Server) {
match self {
Self::Icon => server.icon = None,
Self::Banner => server.banner = None,
Self::Description => server.description = None,
}
}
}