NEWS ADD <LOGON|OPER> <text> / DEL <LOGON|OPER> <number> / LIST. Logon news is shown to every user as they connect; oper news is shown to an operator when they log in. Admin-only to manage. Each item carries a stable id assigned at add time and embedded in the log, so deletion is order- independent under replay (DEL by number resolves to that id). Enabling groundwork: the replicated network-wide lists (bans, now news) are consolidated into one NetData struct threaded through apply() as a single parameter — this replaces the akill parameter rather than adding one, so the fold stays within its argument budget as the lists grow.
73 lines
3.4 KiB
Rust
73 lines
3.4 KiB
Rust
//! OperServ gives services operators network-wide tools: AKILL/SQLINE network
|
|
//! bans (event-sourced, lazily expiring, re-asserted at burst), a GLOBAL
|
|
//! announcement to every user, and KILL to disconnect one. `lib.rs` dispatches;
|
|
//! each command family is its own file.
|
|
|
|
use fedserv_api::{NetView, Sender, Service, ServiceCtx, Store};
|
|
|
|
#[path = "xline.rs"]
|
|
mod xline;
|
|
#[path = "global.rs"]
|
|
mod global;
|
|
#[path = "kill.rs"]
|
|
mod kill;
|
|
#[path = "kick.rs"]
|
|
mod kick;
|
|
#[path = "mode.rs"]
|
|
mod mode;
|
|
#[path = "ignore.rs"]
|
|
mod ignore;
|
|
#[path = "stats.rs"]
|
|
mod stats;
|
|
#[path = "svs.rs"]
|
|
mod svs;
|
|
#[path = "info.rs"]
|
|
mod info;
|
|
#[path = "news.rs"]
|
|
mod news;
|
|
|
|
pub struct OperServ {
|
|
pub uid: String,
|
|
}
|
|
|
|
impl Service for OperServ {
|
|
fn nick(&self) -> &str {
|
|
"OperServ"
|
|
}
|
|
fn uid(&self) -> &str {
|
|
&self.uid
|
|
}
|
|
fn gecos(&self) -> &str {
|
|
"Operator Service"
|
|
}
|
|
|
|
fn on_command(&mut self, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &dyn NetView, db: &mut dyn Store) {
|
|
let me = self.uid.as_str();
|
|
// Every OperServ command is operator-only: reveal nothing to others.
|
|
if !from.privs.any() {
|
|
ctx.notice(me, from.uid, "Access denied — OperServ is for services operators.");
|
|
return;
|
|
}
|
|
match args.first().copied() {
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("AKILL") => xline::AKILL.handle(me, from, args, ctx, db),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("SQLINE") => xline::SQLINE.handle(me, from, args, ctx, db),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("GLOBAL") => global::handle(me, from, args, ctx),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("KILL") => kill::handle(me, from, args, ctx, net),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("KICK") => kick::handle(me, from, args, ctx, net),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("MODE") => mode::handle(me, from, args, ctx, net),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("IGNORE") => ignore::handle(me, from, args, ctx, db),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("STATS") => stats::handle(me, from, db, ctx),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("SVSNICK") => svs::nick(me, from, args, ctx, net),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("SVSJOIN") => svs::join(me, from, args, ctx, net),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("INFO") => info::handle(me, from, args, ctx, db),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("NEWS") => news::handle(me, from, args, ctx, db),
|
|
Some(cmd) if cmd.eq_ignore_ascii_case("HELP") => help(me, from, ctx),
|
|
None => help(me, from, ctx),
|
|
Some(other) => ctx.notice(me, from.uid, format!("I don't know \x02{other}\x02. Try \x02HELP\x02.")),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn help(me: &str, from: &Sender, ctx: &mut ServiceCtx) {
|
|
ctx.notice(me, from.uid, "OperServ holds network operator tools (Priv::Admin): \x02AKILL\x02 ADD|DEL|LIST (user@host bans), \x02SQLINE\x02 ADD|DEL|LIST (nick bans), \x02GLOBAL\x02 <message> (announce to everyone), \x02KILL\x02 <nick> [reason] (disconnect a user), \x02KICK\x02 <#chan> <nick> [reason], \x02MODE\x02 <#chan> <modes> [params], \x02IGNORE\x02 ADD|DEL|LIST (silence a user from services), \x02STATS\x02 (enforcement overview), \x02SVSNICK\x02 <nick> <newnick>, \x02SVSJOIN\x02 <nick> <#chan> [key], \x02INFO\x02 ADD|DEL <target> (staff notes), \x02NEWS\x02 ADD|DEL|LIST <LOGON|OPER> (announcements).");
|
|
}
|