forked from jmug/stoatchat
feat(core): separate limits for new user accounts
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user