Silently ignore unknown in-channel fantasy commands
All checks were successful
CI / check (push) Successful in 4m15s
All checks were successful
CI / check (push) Successful in 4m15s
This commit is contained in:
parent
d6b681c972
commit
bfff7dba91
3 changed files with 35 additions and 1 deletions
|
|
@ -79,6 +79,23 @@ const TOPICS: &[HelpEntry] = &[
|
||||||
HelpEntry { cmd: "NOEXPIRE", summary: "pin against expiry (operator)", detail: "Syntax: \x02NOEXPIRE <#channel> {ON|OFF}\x02\nPins a channel so inactivity expiry never drops it. Operators only." },
|
HelpEntry { cmd: "NOEXPIRE", summary: "pin against expiry (operator)", detail: "Syntax: \x02NOEXPIRE <#channel> {ON|OFF}\x02\nPins a channel so inactivity expiry never drops it. Operators only." },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Every command the dispatcher below recognizes. The fantasy router consults
|
||||||
|
// this so an unknown in-channel `!word` — another bot's command sharing the `!`
|
||||||
|
// prefix — is silently ignored rather than drawing a "don't know that command"
|
||||||
|
// reply from the assigned bot. Keep in sync with the `on_command` match.
|
||||||
|
pub const COMMANDS: &[&str] = &[
|
||||||
|
"REGISTER", "INFO", "DROP", "MLOCK", "MODE", "ACCESS", "FLAGS", "OP", "DEOP", "VOICE",
|
||||||
|
"DEVOICE", "UP", "DOWN", "OWNER", "DEOWNER", "PROTECT", "ADMIN", "DEPROTECT", "DEADMIN",
|
||||||
|
"HALFOP", "DEHALFOP", "KICK", "BAN", "UNBAN", "TOPIC", "INVITE", "AKICK", "LEVELS",
|
||||||
|
"STATUS", "SUSPEND", "UNSUSPEND", "NOEXPIRE", "LIST", "SET", "ENTRYMSG", "GETKEY",
|
||||||
|
"SEEN", "ENFORCE", "SYNC", "CLONE", "SOP", "AOP", "HOP", "VOP", "HELP",
|
||||||
|
];
|
||||||
|
|
||||||
|
/// True if `cmd` (any case) is a command ChanServ handles.
|
||||||
|
pub fn is_command(cmd: &str) -> bool {
|
||||||
|
COMMANDS.iter().any(|c| cmd.eq_ignore_ascii_case(c))
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ChanServ {
|
pub struct ChanServ {
|
||||||
pub uid: String,
|
pub uid: String,
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +332,8 @@ impl Service for ChanServ {
|
||||||
Some("HOP") => xop::handle(me, from, "HOP", "halfop", args, ctx, db),
|
Some("HOP") => xop::handle(me, from, "HOP", "halfop", args, ctx, db),
|
||||||
Some("VOP") => xop::handle(me, from, "VOP", "voice", args, ctx, db),
|
Some("VOP") => xop::handle(me, from, "VOP", "voice", args, ctx, db),
|
||||||
Some("HELP") => echo_api::help(me, from, ctx, BLURB, TOPICS, args.get(1).copied()),
|
Some("HELP") => echo_api::help(me, from, ctx, BLURB, TOPICS, args.get(1).copied()),
|
||||||
|
// Direct `/msg ChanServ FOO` earns this reply; the fantasy router
|
||||||
|
// gates on COMMANDS first so an in-channel `!foo` stays silent.
|
||||||
Some(other) => ctx.notice(me, from.uid, format!("I don't know the command \x02{other}\x02. Try \x02HELP\x02.")),
|
Some(other) => ctx.notice(me, from.uid, format!("I don't know the command \x02{other}\x02. Try \x02HELP\x02.")),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,12 @@ impl Engine {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only ChanServ's own verbs are fantasy commands. An unknown `!word` is
|
||||||
|
// some other bot's command sharing the `!` prefix, not ours, so ignore it
|
||||||
|
// silently instead of the bot barking "I don't know that command".
|
||||||
|
if !echo_chanserv::is_command(cmd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let Some(csuid) = self.service_uid("ChanServ") else { return };
|
let Some(csuid) = self.service_uid("ChanServ") else { return };
|
||||||
// Rewrite `!cmd args…` into `CMD #channel args…` for ChanServ.
|
// Rewrite `!cmd args…` into `CMD #channel args…` for ChanServ.
|
||||||
let mark = ctx.actions.len();
|
let mark = ctx.actions.len();
|
||||||
|
|
|
||||||
|
|
@ -3469,6 +3469,11 @@
|
||||||
assert!(chan(&mut e, "000AAAAAB", "#c", "hello everyone").is_empty(), "chatter ignored");
|
assert!(chan(&mut e, "000AAAAAB", "#c", "hello everyone").is_empty(), "chatter ignored");
|
||||||
// Fantasy in a channel with no bot does nothing.
|
// Fantasy in a channel with no bot does nothing.
|
||||||
assert!(chan(&mut e, "000AAAAAB", "#d", "!op").is_empty(), "no bot, no fantasy");
|
assert!(chan(&mut e, "000AAAAAB", "#d", "!op").is_empty(), "no bot, no fantasy");
|
||||||
|
|
||||||
|
// An unknown `!word` (another bot's command sharing the `!` prefix) draws
|
||||||
|
// no reply from the assigned bot — not even "I don't know that command".
|
||||||
|
let out = chan(&mut e, "000AAAAAB", "#c", "!cissue \"CERT LIST\" fix it");
|
||||||
|
assert!(out.is_empty(), "unknown fantasy command stays silent: {out:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemoServ delivers a memo to an offline account and notifies them on login.
|
// MemoServ delivers a memo to an offline account and notifies them on login.
|
||||||
|
|
@ -3539,8 +3544,12 @@
|
||||||
assert!(notice(&cs(&mut e, "000AAAAAB", "SUSPEND #c"), "Access denied"));
|
assert!(notice(&cs(&mut e, "000AAAAAB", "SUSPEND #c"), "Access denied"));
|
||||||
// The oper suspends it.
|
// The oper suspends it.
|
||||||
assert!(notice(&cs(&mut e, "000AAAAAC", "SUSPEND #c raided"), "now suspended"));
|
assert!(notice(&cs(&mut e, "000AAAAAC", "SUSPEND #c raided"), "now suspended"));
|
||||||
// The founder can no longer manage it.
|
// The founder can no longer manage it — including MODE/ACCESS/FLAGS, which
|
||||||
|
// used to bypass the suspension freeze.
|
||||||
assert!(notice(&cs(&mut e, "000AAAAAB", "SET #c SIGNKICK ON"), "suspended"));
|
assert!(notice(&cs(&mut e, "000AAAAAB", "SET #c SIGNKICK ON"), "suspended"));
|
||||||
|
assert!(notice(&cs(&mut e, "000AAAAAB", "MODE #c +m"), "suspended"), "MODE frozen while suspended");
|
||||||
|
assert!(notice(&cs(&mut e, "000AAAAAB", "ACCESS #c ADD someone sop"), "suspended"), "ACCESS frozen while suspended");
|
||||||
|
assert!(notice(&cs(&mut e, "000AAAAAB", "FLAGS #c someone +o"), "suspended"), "FLAGS frozen while suspended");
|
||||||
// UNSUSPEND restores management.
|
// UNSUSPEND restores management.
|
||||||
assert!(notice(&cs(&mut e, "000AAAAAC", "UNSUSPEND #c"), "no longer suspended"));
|
assert!(notice(&cs(&mut e, "000AAAAAC", "UNSUSPEND #c"), "no longer suspended"));
|
||||||
assert!(notice(&cs(&mut e, "000AAAAAB", "SET #c SIGNKICK ON"), "is now"));
|
assert!(notice(&cs(&mut e, "000AAAAAB", "SET #c SIGNKICK ON"), "is now"));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue