OperServ: add SHUTDOWN and RESTART
All checks were successful
CI / check (push) Successful in 3m31s

This commit is contained in:
Jean Chevronnet 2026-07-16 01:02:10 +00:00
parent dd43b9a331
commit b2442f85e6
No known key found for this signature in database
6 changed files with 96 additions and 1 deletions

View file

@ -37,6 +37,8 @@ mod chankill;
mod logsearch;
#[path = "defcon.rs"]
mod defcon;
#[path = "shutdown.rs"]
mod shutdown;
pub struct OperServ {
pub uid: String,
@ -88,6 +90,8 @@ impl Service for OperServ {
Some(cmd) if cmd.eq_ignore_ascii_case("CHANKILL") => chankill::handle(me, from, args, ctx, net, db),
Some(cmd) if cmd.eq_ignore_ascii_case("LOGSEARCH") => logsearch::handle(me, from, args, ctx, net),
Some(cmd) if cmd.eq_ignore_ascii_case("DEFCON") => defcon::handle(me, from, args, ctx, db),
Some(cmd) if cmd.eq_ignore_ascii_case("SHUTDOWN") => shutdown::handle(me, from, false, args, ctx),
Some(cmd) if cmd.eq_ignore_ascii_case("RESTART") => shutdown::handle(me, from, true, args, ctx),
Some(cmd) if cmd.eq_ignore_ascii_case("HELP") => echo_api::help(me, from, ctx, BLURB, TOPICS, args.get(1).copied()),
None => echo_api::help(me, from, ctx, BLURB, TOPICS, None),
Some(other) => ctx.notice(me, from.uid, format!("I don't know \x02{other}\x02. Try \x02HELP\x02.")),
@ -121,4 +125,6 @@ const TOPICS: &[HelpEntry] = &[
HelpEntry { cmd: "JUPE", summary: "jupe a server name", detail: "Syntax: \x02JUPE <server.name> [reason] | JUPE DEL <server.name> | JUPE LIST\x02\nBlocks a server name from linking." },
HelpEntry { cmd: "LOGSEARCH", summary: "search the action log", detail: "Syntax: \x02LOGSEARCH [pattern]\x02\nSearches the incident and action log." },
HelpEntry { cmd: "DEFCON", summary: "network defence level", detail: "Syntax: \x02DEFCON [1-5]\x02\nShows or sets the network defence level (5 = normal, 1 = lockdown)." },
HelpEntry { cmd: "SHUTDOWN", summary: "stop services", detail: "Syntax: \x02SHUTDOWN [reason]\x02\nStops the services process. It stays down until restarted." },
HelpEntry { cmd: "RESTART", summary: "restart services", detail: "Syntax: \x02RESTART [reason]\x02\nRestarts the services process (a supervisor respawns it)." },
];

View file

@ -0,0 +1,19 @@
use echo_api::{Priv, Sender, ServiceCtx};
// SHUTDOWN / RESTART [reason]: stop the services process. `restart` selects
// which — a restart exits so a supervisor respawns us, a shutdown stays down.
// Admin-only, and the heaviest command services have. Announced network-wide
// first so users know why services vanished.
pub fn handle(me: &str, from: &Sender, restart: bool, args: &[&str], ctx: &mut ServiceCtx) {
let cmd = if restart { "RESTART" } else { "SHUTDOWN" };
if !from.privs.has(Priv::Admin) {
ctx.notice(me, from.uid, format!("Access denied — {cmd} needs the \x02admin\x02 privilege."));
return;
}
let reason = if args.len() > 1 { args[1..].join(" ") } else { format!("Services {}", if restart { "restarting" } else { "shutting down" }) };
let by = from.account.unwrap_or(from.nick);
ctx.global(me, format!("[\x02Network\x02] Services are {} ({reason}).", if restart { "restarting" } else { "going down" }));
ctx.notice(me, from.uid, format!("Services are {}.", if restart { "restarting" } else { "shutting down" }));
// The action is last, so the notices above are flushed before we exit.
ctx.shutdown(restart, format!("{cmd} by {by}: {reason}"));
}