showfile: serve a text file as its own command (e.g. /RULES), config-driven like aliases

This commit is contained in:
Jean Chevronnet 2026-08-09 23:00:07 +00:00
parent 61584a545b
commit e0d849b4c9
4 changed files with 51 additions and 0 deletions

View file

@ -48,6 +48,7 @@ pub mod rpc;
pub mod securelist;
pub mod securitygroups;
pub mod serverban;
pub mod showfile;
pub mod snoop;
pub mod tline;
pub mod whoisport;

41
src/modules/showfile.rs Normal file
View file

@ -0,0 +1,41 @@
//! showfile — serve a text file as its own command (InspIRCd's `m_showfile`).
//! Config, one line per file:
//!
//! ```text
//! showfile = <COMMAND> <path> # e.g. showfile = RULES /etc/echoircd/rules.txt
//! ```
//!
//! makes `/RULES` stream the file to the client. Dispatched from the same place as
//! command aliases (an unknown, config-named command), so no static registration is
//! needed. The file is read fresh on each use, so edits show without a REHASH.
//! Original native Rust.
use crate::server::Server;
use crate::Uid;
/// If `cmd` names a configured `showfile`, stream that file to `uid` (one NOTICE
/// per line) and return `true`. Returns `false` if no showfile matches `cmd`, so
/// the caller can fall through to the normal unknown-command handling.
pub fn maybe_show(s: &mut Server, uid: Uid, cmd: &str) -> bool {
let path = s.conf_all("showfile").iter().find_map(|line| {
let (name, path) = line.split_once(char::is_whitespace)?;
name.eq_ignore_ascii_case(cmd)
.then(|| path.trim().to_string())
});
let Some(path) = path else {
return false;
};
let nick = s.users.get(&uid).map(|u| u.nick.clone()).unwrap_or_default();
match std::fs::read_to_string(&path) {
Ok(body) => {
for line in body.lines() {
s.send(uid, format!(":{} NOTICE {nick} :{line}", s.name));
}
}
Err(_) => s.send(
uid,
format!(":{} NOTICE {nick} :*** {cmd}: file not available.", s.name),
),
}
true
}