diff --git a/src/modules/disable.rs b/src/modules/disable.rs index 5ce3ee4..73f568e 100644 --- a/src/modules/disable.rs +++ b/src/modules/disable.rs @@ -2,11 +2,19 @@ //! `disabled_commands = LIST WHO KNOCK` (space-separated; repeatable). A disabled //! command replies with `421` as if it didn't exist. Off unless configured. +use crate::map::HashSet; use crate::module::{ModResult, Module}; use crate::numeric::ERR_UNKNOWNCOMMAND; use crate::server::Server; use crate::Uid; +/// The disabled-command set, parsed once and re-parsed only when the config changes. +#[derive(Default)] +struct DisabledCache { + gen: u64, + cmds: HashSet, // uppercased command names +} + pub struct Disable; impl Module for Disable { @@ -25,11 +33,22 @@ impl Module for Disable { if srv.is_oper(uid) { return ModResult::Passthru; } + // (re)build the set only when the config generation changes, not per command + let gen = srv.config_gen; + let stale = srv.ext.get::().map(|c| c.gen != gen).unwrap_or(true); + if stale { + let cmds: HashSet = srv + .conf_all("disabled_commands") + .iter() + .flat_map(|line| line.split_whitespace()) + .map(|c| c.to_ascii_uppercase()) + .collect(); + srv.ext.set(DisabledCache { gen, cmds }); + } let disabled = srv - .conf_all("disabled_commands") - .iter() - .flat_map(|line| line.split_whitespace()) - .any(|c| c.eq_ignore_ascii_case(cmd)); + .ext + .get::() + .is_some_and(|c| c.cmds.contains(&cmd.to_ascii_uppercase())); if disabled { srv.numeric( uid,