feat(core): separate limits for new user accounts

This commit is contained in:
Paul Makles
2024-06-25 19:20:34 +01:00
parent e5eea267cf
commit 6ec8007e4e
9 changed files with 38 additions and 22 deletions

View File

@@ -48,6 +48,7 @@ webhooks_enabled = false
[features.limits.global] [features.limits.global]
group_size = 100 group_size = 100
message_embeds = 5
message_replies = 5 message_replies = 5
message_reactions = 20 message_reactions = 20
server_emoji = 100 server_emoji = 100
@@ -61,7 +62,6 @@ outgoing_friend_requests = 5
bots = 2 bots = 2
message_length = 2000 message_length = 2000
message_embeds = 5
message_attachments = 5 message_attachments = 5
servers = 100 servers = 100
@@ -77,7 +77,6 @@ outgoing_friend_requests = 10
bots = 5 bots = 5
message_length = 2000 message_length = 2000
message_embeds = 5
message_attachments = 5 message_attachments = 5
servers = 100 servers = 100

View File

@@ -107,6 +107,7 @@ pub struct Api {
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct GlobalLimits { pub struct GlobalLimits {
pub group_size: usize, pub group_size: usize,
pub message_embeds: usize,
pub message_replies: usize, pub message_replies: usize,
pub message_reactions: usize, pub message_reactions: usize,
pub server_emoji: usize, pub server_emoji: usize,
@@ -123,7 +124,6 @@ pub struct FeaturesLimits {
pub bots: usize, pub bots: usize,
pub message_length: usize, pub message_length: usize,
pub message_attachments: usize, pub message_attachments: usize,
pub message_embeds: usize,
pub servers: usize, pub servers: usize,
pub attachment_size: usize, pub attachment_size: usize,

View File

@@ -80,8 +80,7 @@ impl Bot {
return Err(create_error!(IsBot)); return Err(create_error!(IsBot));
} }
let config = config().await; if db.get_number_of_bots_by_user(&owner.id).await? >= owner.limits().await.bots {
if db.get_number_of_bots_by_user(&owner.id).await? >= config.features.limits.default.bots {
return Err(create_error!(ReachedMaximumBots)); return Err(create_error!(ReachedMaximumBots));
} }

View File

@@ -2,7 +2,7 @@ use std::collections::HashSet;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use iso8601_timestamp::Timestamp; use iso8601_timestamp::Timestamp;
use revolt_config::config; use revolt_config::{config, FeaturesLimits};
use revolt_models::v0::{ use revolt_models::v0::{
self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageSort, MessageWebhook, self, BulkMessageResponse, DataMessageSend, Embed, MessageAuthor, MessageSort, MessageWebhook,
PushNotification, ReplyIntent, SendableEmbed, Text, RE_MENTION, PushNotification, ReplyIntent, SendableEmbed, Text, RE_MENTION,
@@ -207,11 +207,13 @@ impl Default for Message {
#[allow(clippy::disallowed_methods)] #[allow(clippy::disallowed_methods)]
impl Message { impl Message {
/// Create message from API data /// Create message from API data
#[allow(clippy::too_many_arguments)]
pub async fn create_from_api( pub async fn create_from_api(
db: &Database, db: &Database,
channel: Channel, channel: Channel,
data: DataMessageSend, data: DataMessageSend,
author: MessageAuthor<'_>, author: MessageAuthor<'_>,
limits: FeaturesLimits,
mut idempotency: IdempotencyKey, mut idempotency: IdempotencyKey,
generate_embeds: bool, generate_embeds: bool,
allow_mentions: bool, allow_mentions: bool,
@@ -221,7 +223,7 @@ impl Message {
Message::validate_sum( Message::validate_sum(
&data.content, &data.content,
data.embeds.as_deref().unwrap_or_default(), data.embeds.as_deref().unwrap_or_default(),
config.features.limits.default.message_length, limits.message_length,
)?; )?;
idempotency idempotency
@@ -320,20 +322,20 @@ impl Message {
if data if data
.attachments .attachments
.as_ref() .as_ref()
.is_some_and(|v| v.len() > config.features.limits.default.message_attachments) .is_some_and(|v| v.len() > limits.message_attachments)
{ {
return Err(create_error!(TooManyAttachments { return Err(create_error!(TooManyAttachments {
max: config.features.limits.default.message_attachments, max: limits.message_attachments,
})); }));
} }
if data if data
.embeds .embeds
.as_ref() .as_ref()
.is_some_and(|v| v.len() > config.features.limits.default.message_embeds) .is_some_and(|v| v.len() > config.features.limits.global.message_embeds)
{ {
return Err(create_error!(TooManyEmbeds { return Err(create_error!(TooManyEmbeds {
max: config.features.limits.default.message_embeds, max: config.features.limits.global.message_embeds,
})); }));
} }

View File

@@ -1,10 +1,10 @@
use std::{collections::HashSet, time::Duration}; use std::{collections::HashSet, str::FromStr, time::Duration};
use crate::{events::client::EventV1, Database, File, RatelimitEvent}; use crate::{events::client::EventV1, Database, File, RatelimitEvent};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use revolt_config::config; use revolt_config::{config, FeaturesLimits};
use revolt_models::v0; use revolt_models::v0;
use revolt_presence::filter_online; use revolt_presence::filter_online;
use revolt_result::{create_error, Result}; use revolt_result::{create_error, Result};
@@ -197,6 +197,22 @@ impl User {
Ok(user) Ok(user)
} }
/// Get limits for this user
pub async fn limits(&self) -> FeaturesLimits {
let config = config().await;
if ulid::Ulid::from_str(&self.id)
.expect("`ulid`")
.datetime()
.elapsed()
.expect("time went backwards")
<= Duration::from_secs(86400u64 * config.features.limits.global.new_user_days as u64)
{
config.features.limits.new_user
} else {
config.features.limits.default
}
}
/// Get the relationship with another user /// Get the relationship with another user
pub fn relationship_with(&self, user_b: &str) -> RelationshipStatus { pub fn relationship_with(&self, user_b: &str) -> RelationshipStatus {
if self.id == user_b { if self.id == user_b {
@@ -235,12 +251,11 @@ impl User {
/// Check if this user can acquire another server /// Check if this user can acquire another server
pub async fn can_acquire_server(&self, db: &Database) -> Result<()> { pub async fn can_acquire_server(&self, db: &Database) -> Result<()> {
let config = config().await; if db.fetch_server_count(&self.id).await? <= self.limits().await.servers {
if db.fetch_server_count(&self.id).await? <= config.features.limits.default.servers {
Ok(()) Ok(())
} else { } else {
Err(create_error!(TooManyServers { Err(create_error!(TooManyServers {
max: config.features.limits.default.servers max: self.limits().await.servers
})) }))
} }
} }
@@ -500,10 +515,9 @@ impl User {
.unwrap_or_default(); .unwrap_or_default();
// If we're over the limit, don't allow creating more requests // If we're over the limit, don't allow creating more requests
let config = config().await; if count >= self.limits().await.outgoing_friend_requests {
if count >= config.features.limits.default.outgoing_friend_requests {
return Err(create_error!(TooManyPendingFriendRequests { return Err(create_error!(TooManyPendingFriendRequests {
max: config.features.limits.default.outgoing_friend_requests max: self.limits().await.outgoing_friend_requests
})); }));
} }

View File

@@ -56,7 +56,7 @@ pub async fn worker(db: Database) {
let embeds = generate( let embeds = generate(
task.content, task.content,
&config.hosts.january, &config.hosts.january,
config.features.limits.default.message_embeds, config.features.limits.global.message_embeds,
semaphore, semaphore,
) )
.await; .await;

View File

@@ -30,11 +30,10 @@ pub async fn edit(
}) })
})?; })?;
let config = config().await;
Message::validate_sum( Message::validate_sum(
&edit.content, &edit.content,
edit.embeds.as_deref().unwrap_or_default(), edit.embeds.as_deref().unwrap_or_default(),
config.features.limits.default.message_length, user.limits().await.message_length,
)?; )?;
// Ensure we have permissions to send a message // Ensure we have permissions to send a message

View File

@@ -81,6 +81,7 @@ pub async fn message_send(
channel, channel,
data, data,
v0::MessageAuthor::User(&author), v0::MessageAuthor::User(&author),
user.limits().await,
idempotency, idempotency,
permissions.has_channel_permission(ChannelPermission::SendEmbeds), permissions.has_channel_permission(ChannelPermission::SendEmbeds),
allow_mentions, allow_mentions,

View File

@@ -1,3 +1,4 @@
use revolt_config::config;
use revolt_database::{ use revolt_database::{
util::{idempotency::IdempotencyKey, reference::Reference}, util::{idempotency::IdempotencyKey, reference::Reference},
Database, Message, Database, Message,
@@ -58,6 +59,7 @@ pub async fn webhook_execute(
channel, channel,
data, data,
v0::MessageAuthor::Webhook(&webhook.into()), v0::MessageAuthor::Webhook(&webhook.into()),
config().await.features.limits.default,
idempotency, idempotency,
true, true,
true, true,