feat: initial category permissions and rework of category crud routes
This commit is contained in:
@@ -200,6 +200,7 @@ message_reactions = 20
|
||||
server_emoji = 100
|
||||
server_roles = 200
|
||||
server_channels = 200
|
||||
server_categories = 50
|
||||
|
||||
# How many hours since creation a user is considered new
|
||||
new_user_hours = 72
|
||||
|
||||
@@ -281,6 +281,7 @@ pub struct GlobalLimits {
|
||||
pub server_emoji: usize,
|
||||
pub server_roles: usize,
|
||||
pub server_channels: usize,
|
||||
pub server_categories: usize,
|
||||
|
||||
pub new_user_hours: usize,
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use revolt_models::v0::{self, DataCreateServerChannel};
|
||||
use revolt_models::v0::{self, DataCreateCategory, DataCreateServerChannel, DataEditCategory};
|
||||
use revolt_permissions::{OverrideField, DEFAULT_PERMISSION_SERVER};
|
||||
use revolt_result::Result;
|
||||
use ulid::Ulid;
|
||||
@@ -26,8 +26,8 @@ auto_derived_partial!(
|
||||
// TODO: investigate if this is redundant and can be removed
|
||||
pub channels: Vec<String>,
|
||||
/// Categories for this server
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub categories: Option<Vec<Category>>,
|
||||
#[serde(skip_serializing_if = "HashMap::is_empty")]
|
||||
pub categories: HashMap<String, Category>,
|
||||
/// Configuration for sending system event messages
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub system_messages: Option<SystemMessageChannels>,
|
||||
@@ -87,17 +87,29 @@ auto_derived_partial!(
|
||||
"PartialRole"
|
||||
);
|
||||
|
||||
auto_derived!(
|
||||
auto_derived_partial!(
|
||||
/// Channel category
|
||||
pub struct Category {
|
||||
/// Unique ID for this category
|
||||
pub id: String,
|
||||
/// Title for this category
|
||||
pub title: String,
|
||||
/// Default permissions assigned to users in this category
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub default_permissions: Option<OverrideField>,
|
||||
/// Permissions assigned based on role to this category
|
||||
#[serde(
|
||||
default = "HashMap::<String, OverrideField>::new",
|
||||
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||
)]
|
||||
pub role_permissions: HashMap<String, OverrideField>,
|
||||
/// Channels in this category
|
||||
pub channels: Vec<String>,
|
||||
}
|
||||
},
|
||||
"PartialCategory"
|
||||
);
|
||||
|
||||
auto_derived!(
|
||||
/// System message channel assignments
|
||||
pub struct SystemMessageChannels {
|
||||
/// ID of channel to send user join messages in
|
||||
@@ -127,6 +139,10 @@ auto_derived!(
|
||||
pub enum FieldsRole {
|
||||
Colour,
|
||||
}
|
||||
|
||||
pub enum FieldsCategory {
|
||||
DefaultPermissions
|
||||
}
|
||||
);
|
||||
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
@@ -149,7 +165,7 @@ impl Server {
|
||||
|
||||
analytics: false,
|
||||
banner: None,
|
||||
categories: None,
|
||||
categories: HashMap::new(),
|
||||
discoverable: false,
|
||||
flags: None,
|
||||
icon: None,
|
||||
@@ -221,7 +237,7 @@ impl Server {
|
||||
pub fn remove_field(&mut self, field: &FieldsServer) {
|
||||
match field {
|
||||
FieldsServer::Description => self.description = None,
|
||||
FieldsServer::Categories => self.categories = None,
|
||||
FieldsServer::Categories => self.categories.clear(),
|
||||
FieldsServer::SystemMessages => self.system_messages = None,
|
||||
FieldsServer::Icon => self.icon = None,
|
||||
FieldsServer::Banner => self.banner = None,
|
||||
@@ -334,6 +350,110 @@ impl Role {
|
||||
}
|
||||
}
|
||||
|
||||
impl Category {
|
||||
pub fn remove_field(&mut self, field: FieldsCategory) {
|
||||
match field {
|
||||
FieldsCategory::DefaultPermissions => self.default_permissions = None
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn create(db: &Database, server: &mut Server, data: DataCreateCategory) -> Result<Category> {
|
||||
let channels = data.channels.clone().unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|c| server.channels.contains(&c))
|
||||
.collect();
|
||||
|
||||
let category = Category {
|
||||
id: Ulid::new().to_string(),
|
||||
title: data.title,
|
||||
channels: channels,
|
||||
default_permissions: None,
|
||||
role_permissions: HashMap::new()
|
||||
};
|
||||
|
||||
server.categories.insert(category.id.clone(), category.clone());
|
||||
|
||||
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||
|
||||
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||
|
||||
EventV1::ServerUpdate {
|
||||
id: server.id.clone(),
|
||||
data: partial_server.into(),
|
||||
clear: Vec::new(),
|
||||
}
|
||||
.p(server.id.clone())
|
||||
.await;
|
||||
|
||||
Ok(category)
|
||||
}
|
||||
|
||||
pub async fn delete(&self, db: &Database, server: &mut Server) -> Result<()> {
|
||||
// update the parent server model with the new category
|
||||
server.categories.remove(&self.id);
|
||||
|
||||
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||
|
||||
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||
|
||||
EventV1::ServerUpdate {
|
||||
id: server.id.clone(),
|
||||
data: partial_server.into(),
|
||||
clear: Vec::new(),
|
||||
}
|
||||
.p(server.id.clone())
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update(&mut self, db: &Database, server: &mut Server, partial: PartialCategory, remove: Vec<FieldsCategory>) -> Result<()> {
|
||||
for field in remove {
|
||||
self.remove_field(field);
|
||||
};
|
||||
|
||||
self.apply_options(partial);
|
||||
|
||||
// update the parent server model with the new category
|
||||
server.categories.insert(self.id.clone(), self.clone());
|
||||
|
||||
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||
|
||||
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||
|
||||
EventV1::ServerUpdate {
|
||||
id: server.id.clone(),
|
||||
data: partial_server.into(),
|
||||
clear: Vec::new(),
|
||||
}
|
||||
.p(server.id.clone())
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_role_permission(&mut self, db: &Database, server: &mut Server, role_id: String, role_override: OverrideField) -> Result<()> {
|
||||
self.role_permissions.insert(role_id, role_override);
|
||||
|
||||
// update the parent server model with the new category
|
||||
server.categories.insert(self.id.clone(), self.clone());
|
||||
|
||||
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||
|
||||
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||
|
||||
EventV1::ServerUpdate {
|
||||
id: server.id.clone(),
|
||||
data: partial_server.into(),
|
||||
clear: Vec::new(),
|
||||
}
|
||||
.p(server.id.clone())
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemMessageChannels {
|
||||
pub fn into_channel_ids(self) -> HashSet<String> {
|
||||
let mut ids = HashSet::new();
|
||||
|
||||
@@ -729,9 +729,7 @@ impl From<crate::Server> for Server {
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
channels: value.channels,
|
||||
categories: value
|
||||
.categories
|
||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
||||
categories: value.categories.into_iter().map(|(k, v)| (k, v.into())).collect(),
|
||||
system_messages: value.system_messages.map(|v| v.into()),
|
||||
roles: value
|
||||
.roles
|
||||
@@ -757,9 +755,7 @@ impl From<Server> for crate::Server {
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
channels: value.channels,
|
||||
categories: value
|
||||
.categories
|
||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
||||
categories: value.categories.into_iter().map(|(k, v)| (k, v.into())).collect(),
|
||||
system_messages: value.system_messages.map(|v| v.into()),
|
||||
roles: value
|
||||
.roles
|
||||
@@ -785,9 +781,7 @@ impl From<crate::PartialServer> for PartialServer {
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
channels: value.channels,
|
||||
categories: value
|
||||
.categories
|
||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
||||
categories: value.categories.map(|x| x.into_iter().map(|(k, v)| (k, v.into())).collect()),
|
||||
system_messages: value.system_messages.map(|v| v.into()),
|
||||
roles: value
|
||||
.roles
|
||||
@@ -811,9 +805,7 @@ impl From<PartialServer> for crate::PartialServer {
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
channels: value.channels,
|
||||
categories: value
|
||||
.categories
|
||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
||||
categories: value.categories.map(|x| x.into_iter().map(|(k, v)| (k, v.into())).collect()),
|
||||
system_messages: value.system_messages.map(|v| v.into()),
|
||||
roles: value
|
||||
.roles
|
||||
@@ -859,6 +851,8 @@ impl From<crate::Category> for Category {
|
||||
id: value.id,
|
||||
title: value.title,
|
||||
channels: value.channels,
|
||||
role_permissions: value.role_permissions,
|
||||
default_permissions: value.default_permissions,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -869,6 +863,24 @@ impl From<Category> for crate::Category {
|
||||
id: value.id,
|
||||
title: value.title,
|
||||
channels: value.channels,
|
||||
role_permissions: value.role_permissions,
|
||||
default_permissions: value.default_permissions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::FieldsCategory> for FieldsCategory {
|
||||
fn from(value: crate::FieldsCategory) -> Self {
|
||||
match value {
|
||||
crate::FieldsCategory::DefaultPermissions => FieldsCategory::DefaultPermissions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FieldsCategory> for crate::FieldsCategory {
|
||||
fn from(value: FieldsCategory) -> crate::FieldsCategory {
|
||||
match value {
|
||||
FieldsCategory::DefaultPermissions => crate::FieldsCategory::DefaultPermissions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use revolt_permissions::{
|
||||
RelationshipStatus, DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||
};
|
||||
|
||||
use crate::{Channel, Database, Member, Server, User};
|
||||
use crate::{Category, Channel, Database, Member, Server, User};
|
||||
|
||||
/// Permissions calculator
|
||||
#[derive(Clone)]
|
||||
@@ -16,6 +16,7 @@ pub struct DatabasePermissionQuery<'a> {
|
||||
perspective: &'a User,
|
||||
user: Option<Cow<'a, User>>,
|
||||
channel: Option<Cow<'a, Channel>>,
|
||||
category: Option<Cow<'a, Category>>,
|
||||
server: Option<Cow<'a, Server>>,
|
||||
member: Option<Cow<'a, Member>>,
|
||||
|
||||
@@ -288,6 +289,40 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_default_category_permissions(&mut self) -> Override {
|
||||
if let Some(category) = &self.category {
|
||||
category.default_permissions.unwrap_or_default().into()
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||
if let Some((server, category)) = self.server.as_ref().zip(self.category.as_ref()) {
|
||||
let member_roles = self
|
||||
.member
|
||||
.as_ref()
|
||||
.map(|member| member.roles.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut roles = category.role_permissions
|
||||
.iter()
|
||||
.filter(|(id, _)| member_roles.contains(id))
|
||||
.filter_map(|(id, permission)| {
|
||||
server.roles.get(id).map(|role| {
|
||||
let v: Override = (*permission).into();
|
||||
(role.rank, v)
|
||||
})
|
||||
})
|
||||
.collect::<Vec<(i64, Override)>>();
|
||||
|
||||
roles.sort_by(|a, b| b.0.cmp(&a.0));
|
||||
roles.into_iter().map(|(_, v)| v).collect()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
/// Do we own this group or saved messages channel if it is one of those?
|
||||
async fn do_we_own_the_channel(&mut self) -> bool {
|
||||
if let Some(channel) = &self.channel {
|
||||
@@ -375,6 +410,14 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn set_category_from_channel(&mut self) {
|
||||
if let Some((server, channel)) = self.server.as_ref().zip(self.channel.as_ref()) {
|
||||
let category = server.categories.values().find(|c| c.channels.contains(&channel.id().to_string())).cloned();
|
||||
|
||||
self.category = category.map(Cow::Owned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DatabasePermissionQuery<'a> {
|
||||
@@ -385,6 +428,7 @@ impl<'a> DatabasePermissionQuery<'a> {
|
||||
perspective,
|
||||
user: None,
|
||||
channel: None,
|
||||
category: None,
|
||||
server: None,
|
||||
member: None,
|
||||
|
||||
@@ -443,6 +487,13 @@ impl<'a> DatabasePermissionQuery<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn category(self, category: &'a Category) -> DatabasePermissionQuery<'a> {
|
||||
DatabasePermissionQuery {
|
||||
category: Some(Cow::Borrowed(category)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Use member
|
||||
pub fn member(self, member: &'a Member) -> DatabasePermissionQuery {
|
||||
DatabasePermissionQuery {
|
||||
|
||||
@@ -10,7 +10,7 @@ use schemars::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Bot, Channel, Database, Emoji, Invite, Member, Message, Server, ServerBan, User, Webhook,
|
||||
Bot, Category, Channel, Database, Emoji, Invite, Member, Message, Server, ServerBan, User, Webhook
|
||||
};
|
||||
|
||||
/// Reference to some object in the database
|
||||
|
||||
@@ -28,8 +28,8 @@ auto_derived_partial!(
|
||||
// TODO: investigate if this is redundant and can be removed
|
||||
pub channels: Vec<String>,
|
||||
/// Categories for this server
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub categories: Option<Vec<Category>>,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "HashMap::is_empty"))]
|
||||
pub categories: HashMap<String, Category>,
|
||||
/// Configuration for sending system event messages
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub system_messages: Option<SystemMessageChannels>,
|
||||
@@ -126,15 +126,52 @@ auto_derived!(
|
||||
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||
pub struct Category {
|
||||
/// Unique ID for this category
|
||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||
pub id: String,
|
||||
/// Title for this category
|
||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||
pub title: String,
|
||||
/// Default permissions assigned to users in this channel
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub default_permissions: Option<OverrideField>,
|
||||
/// Permissions assigned based on role to this channel
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(
|
||||
default = "HashMap::<String, OverrideField>::new",
|
||||
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||
)
|
||||
)]
|
||||
pub role_permissions: HashMap<String, OverrideField>,
|
||||
/// Channels in this category
|
||||
pub channels: Vec<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||
pub struct DataCreateCategory {
|
||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||
pub title: String,
|
||||
/// Channels in this category
|
||||
pub channels: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||
pub struct DataEditCategory {
|
||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||
pub title: Option<String>,
|
||||
/// Channels in this category
|
||||
pub channels: Option<Vec<String>>,
|
||||
/// Fields to remove from category object
|
||||
pub remove: Option<Vec<FieldsCategory>>,
|
||||
}
|
||||
|
||||
pub enum FieldsCategory {
|
||||
DefaultPermissions
|
||||
}
|
||||
|
||||
pub struct DataDefaultCategoryPermissions {
|
||||
pub permissions: Override
|
||||
}
|
||||
|
||||
/// System message channel assignments
|
||||
pub struct SystemMessageChannels {
|
||||
/// ID of channel to send user join messages in
|
||||
@@ -226,10 +263,6 @@ auto_derived!(
|
||||
pub icon: Option<String>,
|
||||
/// Attachment Id for banner
|
||||
pub banner: Option<String>,
|
||||
|
||||
/// Category structure for server
|
||||
#[cfg_attr(feature = "validator", validate)]
|
||||
pub categories: Option<Vec<Category>>,
|
||||
/// System message configuration
|
||||
pub system_messages: Option<SystemMessageChannels>,
|
||||
|
||||
|
||||
@@ -68,6 +68,26 @@ pub async fn calculate_server_permissions<P: PermissionQuery>(query: &mut P) ->
|
||||
permissions
|
||||
}
|
||||
|
||||
pub async fn calculate_category_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
|
||||
let mut permissions = calculate_server_permissions(query).await;
|
||||
|
||||
permissions.apply(query.get_default_category_permissions().await);
|
||||
|
||||
for role_override in query.get_our_category_role_overrides().await {
|
||||
permissions.apply(role_override)
|
||||
}
|
||||
|
||||
if !permissions.has_channel_permission(ChannelPermission::ViewChannel) {
|
||||
permissions.revoke_all();
|
||||
}
|
||||
|
||||
if query.are_we_timed_out().await {
|
||||
permissions.restrict(*ALLOW_IN_TIMEOUT);
|
||||
}
|
||||
|
||||
permissions
|
||||
}
|
||||
|
||||
/// Calculate permissions against a channel
|
||||
pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
|
||||
if query.are_we_privileged().await {
|
||||
@@ -109,11 +129,19 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
|
||||
}
|
||||
ChannelType::ServerChannel => {
|
||||
query.set_server_from_channel().await;
|
||||
query.set_category_from_channel().await;
|
||||
|
||||
if query.are_we_server_owner().await {
|
||||
ChannelPermission::GrantAllSafe.into()
|
||||
} else if query.are_we_a_member().await {
|
||||
let mut permissions = calculate_server_permissions(query).await;
|
||||
|
||||
permissions.apply(query.get_default_category_permissions().await);
|
||||
|
||||
for role_override in query.get_our_category_role_overrides().await {
|
||||
permissions.apply(role_override)
|
||||
}
|
||||
|
||||
permissions.apply(query.get_default_channel_permissions().await);
|
||||
|
||||
for role_override in query.get_our_channel_role_overrides().await {
|
||||
@@ -135,4 +163,4 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
|
||||
}
|
||||
ChannelType::Unknown => 0_u64.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,12 @@ pub trait PermissionQuery {
|
||||
/// Get the ordered role overrides (from lowest to highest) for this member in this channel
|
||||
async fn get_our_channel_role_overrides(&mut self) -> Vec<Override>;
|
||||
|
||||
/// Get the default category permissions
|
||||
async fn get_default_category_permissions(&mut self) -> Override;
|
||||
|
||||
/// Get the ordered role overrides (from lowest to highest) for this member in this category
|
||||
async fn get_our_category_role_overrides(&mut self) -> Vec<Override>;
|
||||
|
||||
/// Do we own this group or saved messages channel if it is one of those?
|
||||
async fn do_we_own_the_channel(&mut self) -> bool;
|
||||
|
||||
@@ -64,4 +70,7 @@ pub trait PermissionQuery {
|
||||
/// Set the current server as the server owning this channel
|
||||
/// (this will only ever be called for server channels, use unimplemented!() for other code paths)
|
||||
async fn set_server_from_channel(&mut self);
|
||||
|
||||
//// SEts the current category as the category the channel is in
|
||||
async fn set_category_from_channel(&mut self);
|
||||
}
|
||||
|
||||
@@ -42,12 +42,14 @@ impl IntoResponse for Error {
|
||||
ErrorType::Banned => StatusCode::FORBIDDEN,
|
||||
ErrorType::AlreadyInServer => StatusCode::CONFLICT,
|
||||
ErrorType::CannotTimeoutYourself => StatusCode::BAD_REQUEST,
|
||||
ErrorType::UnknownCategory => StatusCode::NOT_FOUND,
|
||||
|
||||
ErrorType::TooManyServers { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyEmbeds { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyEmoji { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyChannels { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyRoles { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyCategories { .. } => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::ReachedMaximumBots => StatusCode::BAD_REQUEST,
|
||||
ErrorType::IsBot => StatusCode::BAD_REQUEST,
|
||||
|
||||
@@ -115,6 +115,10 @@ pub enum ErrorType {
|
||||
TooManyRoles {
|
||||
max: usize,
|
||||
},
|
||||
TooManyCategories {
|
||||
max: usize,
|
||||
},
|
||||
UnknownCategory,
|
||||
AlreadyInServer,
|
||||
CannotTimeoutYourself,
|
||||
|
||||
|
||||
@@ -49,12 +49,14 @@ impl<'r> Responder<'r, 'static> for Error {
|
||||
ErrorType::Banned => Status::Forbidden,
|
||||
ErrorType::AlreadyInServer => Status::Conflict,
|
||||
ErrorType::CannotTimeoutYourself => Status::BadRequest,
|
||||
|
||||
ErrorType::UnknownCategory => Status::NotFound,
|
||||
|
||||
ErrorType::TooManyServers { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyEmbeds { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyEmoji { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyChannels { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyRoles { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyCategories { .. } => Status::BadRequest,
|
||||
|
||||
ErrorType::ReachedMaximumBots => Status::BadRequest,
|
||||
ErrorType::IsBot => Status::BadRequest,
|
||||
|
||||
Reference in New Issue
Block a user