dictserv: opt-in DICT (RFC 2229) lookup service — bots and /msg answer dict/define/thes/acronym/law/etc via dict.org off-reactor
All checks were successful
CI / check (push) Successful in 4m4s

This commit is contained in:
Jean Chevronnet 2026-07-18 20:21:30 +00:00
parent 76be932131
commit 623750e638
No known key found for this signature in database
15 changed files with 444 additions and 4 deletions

View file

@ -101,10 +101,20 @@ impl Engine {
out.extend(self.reconcile_bots());
// Announce whatever this command changed to the staff audit channel.
out.extend(self.audit_feed(audit_mark, &nick, account.as_deref()));
self.apply_dict_limit(&mut out);
self.apply_msg_style(&mut out);
out
}
// Drop DICT lookups that exceed the global rate budget, so a burst of !dict
// can't hammer the dictionary server. Non-lookup actions pass untouched, and
// the limiter is only consulted when a lookup is actually present.
fn apply_dict_limit(&mut self, out: &mut Vec<NetAction>) {
if out.iter().any(|a| matches!(a, NetAction::DictLookup { .. })) {
out.retain(|a| !matches!(a, NetAction::DictLookup { .. }) || self.dict_limiter.allow());
}
}
// Rewrite each service→user NOTICE to a server-notice (sourced from our
// server) for users who opted into SET SNOTICE; everyone else keeps a normal
// notice from the pseudoclient. A multi-line reply names the service once, on
@ -157,6 +167,19 @@ impl Engine {
return;
}
// A dictionary command (!dict/!define/…) becomes a deferred DICT lookup the
// assigned bot speaks — only when DictServ is loaded. The rate limiter in
// dispatch() drops excess lookups so nobody can hammer the DICT server.
if let Some(l) = echo_dictserv::lookup_for(cmd) {
if self.service_uid("DictServ").is_some() {
let query = words.collect::<Vec<_>>().join(" ");
if !query.trim().is_empty() {
ctx.dict_lookup(botuid.as_str(), chan, l.database, l.label, query);
}
}
return;
}
let Some(csuid) = self.service_uid("ChanServ") else { return };
// Rewrite `!cmd args…` into `CMD #channel args…` for ChanServ.
let mark = ctx.actions.len();