Relaxed automod somewhat

This commit is contained in:
Joshua Barretto 2022-08-23 10:03:06 +01:00
parent 275b17be57
commit 51d90707b5
3 changed files with 44 additions and 6 deletions

View File

@ -146,6 +146,25 @@ impl<G> ChatType<G> {
ChatType::Meta => None,
}
}
/// `None` means that the chat type is automated.
pub fn is_private(&self) -> Option<bool> {
match self {
ChatType::Online(_)
| ChatType::Offline(_)
| ChatType::CommandInfo
| ChatType::CommandError
| ChatType::FactionMeta(_)
| ChatType::GroupMeta(_)
| ChatType::Npc(_, _)
| ChatType::NpcSay(_, _)
| ChatType::NpcTell(_, _, _)
| ChatType::Meta
| ChatType::Kill(_, _) => None,
ChatType::Tell(_, _) | ChatType::Group(_, _) | ChatType::Faction(_, _) => Some(true),
ChatType::Say(_) | ChatType::Region(_) | ChatType::World(_) => Some(false),
}
}
}
// Stores chat text, type

View File

@ -1,7 +1,7 @@
use crate::settings::ModerationSettings;
use authc::Uuid;
use censor::Censor;
use common::comp::AdminRole;
use common::comp::{AdminRole, ChatType, Group};
use hashbrown::HashMap;
use std::{
fmt,
@ -95,12 +95,18 @@ impl AutoMod {
player: Uuid,
role: Option<AdminRole>,
now: Instant,
chat_type: &ChatType<Group>,
msg: &str,
) -> Result<Option<ActionNote>, ActionErr> {
// TODO: Consider using grapheme cluster count instead of size in bytes
if msg.len() > MAX_BYTES_CHAT_MSG {
Err(ActionErr::TooLong)
} else if !self.settings.automod || (role.is_some() && self.settings.admins_exempt) {
} else if !self.settings.automod
// Is this a private chat message?
|| chat_type.is_private().unwrap_or(true)
// Is the user exempt from automoderation?
|| (role.is_some() && self.settings.admins_exempt)
{
Ok(None)
} else if self.censor.check(msg) {
Err(ActionErr::BannedWord)
@ -123,7 +129,7 @@ impl AutoMod {
const CHAT_VOLUME_PERIOD: f32 = 30.0;
/// The maximum permitted average number of chat messages over the chat volume
/// period.
const MAX_AVG_MSG_PER_SECOND: f32 = 1.0 / 7.0; // No more than a message every 7 seconds on average
const MAX_AVG_MSG_PER_SECOND: f32 = 1.0 / 5.0; // No more than a message every 5 seconds on average
/// The period for which a player should be muted when they exceed the message
/// spam threshold.
const SPAM_MUTE_PERIOD: Duration = Duration::from_secs(180);

View File

@ -114,7 +114,12 @@ pub trait StateExt {
/// Performed after loading component data from the database
fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents);
/// Iterates over registered clients and send each `ServerMsg`
fn validate_chat_msg(&self, player: EcsEntity, msg: &str) -> bool;
fn validate_chat_msg(
&self,
player: EcsEntity,
chat_type: &comp::ChatType<comp::Group>,
msg: &str,
) -> bool;
fn send_chat(&self, msg: comp::UnresolvedChatMsg);
fn notify_players(&self, msg: ServerGeneral);
fn notify_in_game_clients(&self, msg: ServerGeneral);
@ -676,7 +681,12 @@ impl StateExt for State {
}
}
fn validate_chat_msg(&self, entity: EcsEntity, msg: &str) -> bool {
fn validate_chat_msg(
&self,
entity: EcsEntity,
chat_type: &comp::ChatType<comp::Group>,
msg: &str,
) -> bool {
let mut automod = self.ecs().write_resource::<AutoMod>();
let Some(client) = self.ecs().read_storage::<Client>().get(entity) else { return true };
let Some(player) = self.ecs().read_storage::<Player>().get(entity) else { return true };
@ -688,6 +698,7 @@ impl StateExt for State {
.get(entity)
.map(|a| a.0),
Instant::now(),
chat_type,
msg,
) {
Ok(note) => {
@ -727,7 +738,9 @@ impl StateExt for State {
if msg.chat_type.uid().map_or(true, |sender| {
(*ecs.read_resource::<UidAllocator>())
.retrieve_entity_internal(sender.0)
.map_or(false, |e| self.validate_chat_msg(e, &msg.message))
.map_or(false, |e| {
self.validate_chat_msg(e, &msg.chat_type, &msg.message)
})
}) {
match &msg.chat_type {
comp::ChatType::Offline(_)