Restrict accounts to min 30 days to be able to call and start working on masks

This commit is contained in:
2025-08-23 19:56:50 -03:00
parent 134d4e8879
commit 2a2ffd8894
14 changed files with 368 additions and 20 deletions
+17 -6
View File
@@ -14,7 +14,7 @@ use crate::{
},
groups::calls::{
get_display_profile,
permissions::NotBannedPermission,
permissions::{NonNewAccountPermission, NotBannedPermission},
strings::{
get_string_call_answered, get_string_call_hangup_other_party,
get_string_call_hangup_this_party, get_string_call_no_answer,
@@ -53,7 +53,10 @@ impl Command<State, Extras> for CallCommand {
}
fn permissions(&self) -> Vec<Box<dyn Permission<State, Extras> + Send + Sync + 'static>> {
vec![Box::new(NotBannedPermission)]
vec![
Box::new(NotBannedPermission),
Box::new(NonNewAccountPermission),
]
}
async fn execute(
@@ -146,7 +149,10 @@ impl Command<State, Extras> for SkipCommand {
}
fn permissions(&self) -> Vec<Box<dyn Permission<State, Extras> + Send + Sync + 'static>> {
vec![Box::new(NotBannedPermission)]
vec![
Box::new(NotBannedPermission),
Box::new(NonNewAccountPermission),
]
}
async fn execute(
@@ -254,7 +260,10 @@ impl Command<State, Extras> for HangupCommand {
}
fn permissions(&self) -> Vec<Box<dyn Permission<State, Extras> + Send + Sync + 'static>> {
vec![Box::new(NotBannedPermission)]
vec![
Box::new(NotBannedPermission),
Box::new(NonNewAccountPermission),
]
}
async fn execute(
@@ -354,7 +363,10 @@ impl Command<State, Extras> for FriendRequestCommand {
}
fn permissions(&self) -> Vec<Box<dyn Permission<State, Extras> + Send + Sync + 'static>> {
vec![Box::new(NotBannedPermission)]
vec![
Box::new(NotBannedPermission),
Box::new(NonNewAccountPermission),
]
}
async fn execute(
@@ -494,7 +506,6 @@ impl Command<State, Extras> for MaskCommand {
};
if let Some(call_id) = channel.call_id {
} else {
ctx
.send()
+27 -5
View File
@@ -2,12 +2,16 @@ use std::{error::Error, sync::Arc};
use async_trait::async_trait;
use itertools::Itertools;
use time::{Duration, UtcDateTime};
use twilight_http::{api_error::ApiError, error::ErrorType};
use twilight_model::{
gateway::payload::incoming::{MessageCreate, MessageDelete, MessageUpdate},
id::Id,
};
use twilight_util::builder::embed::{EmbedAuthorBuilder, EmbedBuilder, ImageSource};
use twilight_util::{
builder::embed::{EmbedAuthorBuilder, EmbedBuilder, ImageSource},
snowflake::Snowflake,
};
use crate::{
constants::COLOR_WHITE,
@@ -15,14 +19,18 @@ use crate::{
discord::sanitizing::SanitizeDiscordMarkdown,
extras::Extras,
framework::{
commands::extras::ExtrasGetter, events::traits::{
commands::{extras::ExtrasGetter, permissions::Permission},
events::traits::{
EventResult, OnMessageDeleteHandler, OnMessageEditHandler, OnMessageHandler,
}, interactions::components::ActionRow, runtime::Runtime
},
interactions::components::ActionRow,
runtime::Runtime,
},
groups::calls::{
components::{CodeOfConductButton, NeedHelpButton},
embeds, get_display_profile,
moderation::{escape_message, Action, Rule},
moderation::{Action, Rule, escape_message},
permissions::NonNewAccountPermission,
},
state::State,
utils::{ellipse, i64_to_u64},
@@ -96,6 +104,12 @@ impl OnMessageHandler<State, Extras> for CallMessageHandler {
return Ok(());
}
if UtcDateTime::from_unix_timestamp(event.author.id.timestamp() / 1000).unwrap()
> UtcDateTime::now() - Duration::days(30)
{
return Ok(());
}
let prefixes = rt
.get_prefixes(event.guild_id.map(|i| i.get()), Some(event.author.id.get()))
.await;
@@ -239,7 +253,11 @@ impl OnMessageHandler<State, Extras> for CallMessageHandler {
embeds.push(
EmbedBuilder::new()
.author(
EmbedAuthorBuilder::new(format!("Replying to {}", replying_to.data.author_name)).icon_url(
EmbedAuthorBuilder::new(format!(
"Replying to {}",
replying_to.data.author_name
))
.icon_url(
ImageSource::url(replying_to.data.author_avatar_url).unwrap(),
),
)
@@ -323,6 +341,10 @@ impl OnMessageEditHandler<State, Extras> for CallMessageEditHandler {
event: &MessageUpdate,
rt: Arc<Runtime<State, Extras>>,
) -> EventResult {
if event.edited_timestamp.is_none() {
return Ok(());
}
log::trace!(
"Edited message was '{}' sent by {} (bot? {:?})",
event.content,
@@ -1,7 +1,5 @@
scum
idiot
stupid
dumb
moron
fool
stfu
+7
View File
@@ -0,0 +1,7 @@
{
"dinosaur": 1278255435652010014,
"shleepy cat": 1278255475066146816,
"cozy cat": 1278255420124696663,
"coquette cat": 1278255408254816300,
"panic cat": 1278255451993145345
}
+52
View File
@@ -0,0 +1,52 @@
{
"ferret": 1278176917123760139,
"octopus": 1278176904410697880,
"cat": 1278176891290783824,
"monkey": 1278176881195094049,
"panda": 1278176868767629455,
"sheep": 1278176856910073946,
"horse": 1278176842116894760,
"bee": 1278176823846506577,
"wild boar": 1278176806498996235,
"duck": 1278176794591232102,
"chicken": 1278176781790216233,
"elephant": 1278176771413512213,
"cow": 1278176761565413483,
"deer": 1278176744691597312,
"turkey": 1278176730619576321,
"dog": 1278176719932751903,
"beaver": 1278176709530882091,
"camel": 1278176699921465394,
"koala": 1278176687493746709,
"hippo": 1278176675846295603,
"ostrich": 1278176661317095494,
"rhino": 1278176650340864000,
"squirrel": 1278176637627924570,
"chamaleon": 1278176625392877648,
"frog": 1278176614512857088,
"skunk": 1278176604509442079,
"walrus": 1278176554723311678,
"hedgehog": 1278176541750067252,
"pig": 1278176531415564332,
"hen": 1278176518643646485,
"turtle": 1278176507428343891,
"mouse": 1278175957047578696,
"rabbit": 1278175944007487489,
"goat": 1278175933915856938,
"lion": 1278175922964664382,
"wolf": 1278175902047535165,
"snake": 1278175869331968061,
"llama": 1278175850008674325,
"crab": 1278175835634925620,
"owl": 1278175822947029152,
"bat": 1278175813572886550,
"zebra": 1278175799962505216,
"fox": 1278175788818104474,
"gorilla": 1278175775891259456,
"sloth": 1278175765661356175,
"puffer fish": 1278175753497743360,
"bear": 1278175741569142867,
"giraffe": 1278175732601983006,
"penguin": 1278175721956573236,
"parrot": 1278175706798489642
}
+32
View File
@@ -0,0 +1,32 @@
use std::collections::HashMap;
use once_cell::sync::Lazy;
use rand::{SeedableRng, seq::IndexedRandom};
use rand_chacha::ChaCha20Rng;
static MASKS_COMMON: Lazy<HashMap<String, u64>> = Lazy::new(|| {
let (file_name, json) = if cfg!(debug_assertions) {
("dev/common.json", include_str!("dev/common.json"))
} else {
("prod/common.json", include_str!("prod/common.json"))
};
let masks: HashMap<String, u64> =
serde_json::from_str(json).expect(&format!("Failed to parse masks/{file_name} masks"));
assert_ne!(masks.len(), 0, "No masks found in masks/{file_name}");
masks
});
pub fn get_random_mask(not_in: &[String]) -> Option<(String, u64)> {
let mask_names = MASKS_COMMON
.iter()
.filter(|(name, _)| !not_in.contains(name))
.map(|(name, value)| (name.clone(), *value))
.collect::<Vec<_>>();
let mut rng = ChaCha20Rng::from_os_rng();
mask_names.choose(&mut rng).cloned()
}
+7
View File
@@ -0,0 +1,7 @@
{
"dinosaur": 1278254725833297965,
"shleepy cat": 1278254779767984181,
"cozy cat": 1278254704324771893,
"coquette cat": 1278254684200636428,
"panic cat": 1278254760700674098
}
+52
View File
@@ -0,0 +1,52 @@
{
"ferret": 1278173356423909448,
"octopus": 1278173331421397072,
"cat": 1278173317034934282,
"monkey": 1278173297456185344,
"panda": 1278173272390762538,
"sheep": 1278173251914432563,
"horse": 1278173237582237708,
"bee": 1278173216652787826,
"wild boar": 1278173196658413649,
"duck": 1278173181483679918,
"chicken": 1278173167218589726,
"elephant": 1278173150063886346,
"cow": 1278173125024153733,
"deer": 1278173110105014406,
"turkey": 1278173091796877363,
"dog": 1278173070846201856,
"beaver": 1278173051485425705,
"camel": 1278173035018584086,
"koala": 1278173021345021952,
"hippo": 1278173007419932804,
"ostrich": 1278172994669248523,
"rhino": 1278172980848885832,
"squirrel": 1278172965590274088,
"chamaleon": 1278172953305022496,
"frog": 1278172937043710094,
"skunk": 1278172923495976981,
"walrus": 1278172912368619603,
"hedgehog": 1278172899911405678,
"pig": 1278172885239861338,
"hen": 1278172871302184994,
"turtle": 1278172858199314455,
"mouse": 1278172846442414081,
"rabbit": 1278172831921999945,
"goat": 1278172815421472808,
"lion": 1278172803534684235,
"wolf": 1278172791052570687,
"snake": 1278172776259260547,
"llama": 1278172764913799168,
"crab": 1278172752322232330,
"owl": 1278172738309193749,
"bat": 1278172726426865724,
"zebra": 1278172715114565753,
"fox": 1278172702955274292,
"gorilla": 1278172687797194824,
"sloth": 1278172676837343242,
"puffer fish": 1278172665093558294,
"bear": 1278172653076746301,
"giraffe": 1278172640296702073,
"penguin": 1278172627629899808,
"parrot": 1278172600702337074
}
+5 -1
View File
@@ -9,6 +9,7 @@ pub mod commands;
pub(super) mod components;
pub(super) mod embeds;
pub mod events;
pub mod masks;
pub(super) mod moderation;
pub(super) mod permissions;
pub(super) mod strings;
@@ -34,7 +35,10 @@ fn make_name_valid(name: String) -> String {
fn get_display_profile(event: &MessageCreate) -> DisplayProfile {
let member = event.member.clone();
let name = if let Some(nick) = &member.clone().and_then(|member| member.nick.map(make_name_valid)) {
let name = if let Some(nick) = &member
.clone()
.and_then(|member| member.nick.map(make_name_valid))
{
if webhook_username(nick).is_err() {
"Invalid Nickname".to_string()
} else {
+31
View File
@@ -1,4 +1,6 @@
use async_trait::async_trait;
use time::{Duration, UtcDateTime};
use twilight_util::snowflake::{self, Snowflake};
use crate::{
database::models::UserIncident,
@@ -41,3 +43,32 @@ impl Permission<State, Extras> for NotBannedPermission {
Ok(())
}
}
#[derive(Debug)]
pub struct NonNewAccountPermission;
#[async_trait]
impl Permission<State, Extras> for NonNewAccountPermission {
async fn check(&self, ctx: &CommandContext<State, Extras>) -> Result<bool, CommandError> {
Ok(
UtcDateTime::from_unix_timestamp(ctx.event.author.id.timestamp() / 1000).unwrap()
< UtcDateTime::now() - Duration::days(30),
)
}
async fn on_handle_denied(
&self,
ctx: &CommandContext<State, Extras>,
) -> Result<(), CommandError> {
ctx.send()
.content("❌ Your account must be at least 30 days old to use Payphone.")
.component(CodeOfConductButton, 1)
.component(NeedHelpButton, 1)
.await
.inspect_err(|e| {
log::error!("Failed to send message: {e}");
})?;
Ok(())
}
}