i18n: sweep all remaining dynamic prose (oper commands, XLINE/FILTER/DNSBL notices, whois/vhost/knock/dcc/title/reputation/tline/rmode, hash, rename) through trf; +\xNN catalog escape; fr+es now 236 entries each
This commit is contained in:
parent
ef96bcbd06
commit
9b51db07f5
32 changed files with 295 additions and 128 deletions
|
|
@ -66,12 +66,10 @@ impl Command for Tban {
|
|||
(u.nick.clone(), u.prefix())
|
||||
};
|
||||
if s.channels[&key].bans.iter().any(|b| b.mask == mask) {
|
||||
let m = s.trf("{0} is already banned on {1}", &[mask.as_str(), chan.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :{mask} is already banned on {chan}",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {nick} :{m}", s.name),
|
||||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
|
|
@ -127,12 +125,10 @@ impl Command for Knock {
|
|||
.cloned()
|
||||
.unwrap_or_else(|| "requesting an invite".to_string());
|
||||
let who = s.users[&uid].prefix();
|
||||
let m = s.trf("[Knock] {0} is knocking: {1}", &[who.as_str(), reason.as_str()]);
|
||||
s.to_channel(
|
||||
&key,
|
||||
&format!(
|
||||
":{} NOTICE {chan} :[Knock] {who} is knocking: {reason}",
|
||||
s.name
|
||||
),
|
||||
&format!(":{} NOTICE {chan} :{m}", s.name),
|
||||
None,
|
||||
);
|
||||
s.numeric(
|
||||
|
|
@ -314,9 +310,10 @@ impl Command for Invite {
|
|||
let maxinv = s.conf_num("maxinvites", 100usize);
|
||||
if s.channels[&key].invites.len() >= maxinv && !s.channels[&key].invites.contains(&tuid) {
|
||||
let nick = s.users.get(&uid).map(|u| u.nick.clone()).unwrap_or_default();
|
||||
let m = s.trf("Channel invite list is full", &[]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :{chan} :Channel invite list is full", s.name),
|
||||
format!(":{} NOTICE {nick} :{chan} :{m}", s.name),
|
||||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
|
|
@ -408,12 +405,10 @@ impl Command for Uninvite {
|
|||
format!(":{} NOTICE {nick} :{who} {word} {chan}", s.name),
|
||||
);
|
||||
if removed {
|
||||
let m = s.trf("Your invite to {0} was revoked", &[chan.as_str()]);
|
||||
s.send(
|
||||
tuid,
|
||||
format!(
|
||||
":{} NOTICE {who} :Your invite to {chan} was revoked",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {who} :{m}", s.name),
|
||||
);
|
||||
}
|
||||
CmdResult::Ok
|
||||
|
|
@ -563,7 +558,8 @@ impl Command for Rename {
|
|||
s.fail(uid, "RENAME", "CANNOT_RENAME", "The channel cannot be renamed.");
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
s.snotice_c('a', &format!("{oldname} renamed to {new} by {prefix}"));
|
||||
let m = s.trf("{0} renamed to {1} by {2}", &[oldname.as_str(), new.as_str(), prefix.as_str()]);
|
||||
s.snotice_c('a', &m);
|
||||
s.propagate_rename(&uuid, &oldname, new, &reason, None);
|
||||
CmdResult::Ok
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,9 @@ impl Command for Admin {
|
|||
RPL_ADMINME,
|
||||
&format!("{} :Administrative info", s.name),
|
||||
);
|
||||
s.numeric(uid, RPL_ADMINLOC1, &format!(":{} IRC network", s.network));
|
||||
let network = s.network.clone();
|
||||
let m = s.trf("{0} IRC network", &[network.as_str()]);
|
||||
s.numeric(uid, RPL_ADMINLOC1, &format!(":{m}"));
|
||||
s.numeric(
|
||||
uid,
|
||||
RPL_ADMINLOC2,
|
||||
|
|
|
|||
|
|
@ -53,12 +53,10 @@ impl Command for SslInfo {
|
|||
};
|
||||
let tls = if secure { "yes" } else { "no" };
|
||||
let fp = certfp.unwrap_or_else(|| "none".to_string());
|
||||
let m = s.trf("SSLINFO {0}: TLS={1} certfp={2}", &[nick.as_str(), tls, fp.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {asker} :SSLINFO {nick}: TLS={tls} certfp={fp}",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {asker} :{m}", s.name),
|
||||
);
|
||||
CmdResult::Ok
|
||||
}
|
||||
|
|
@ -437,9 +435,10 @@ impl Command for Whois {
|
|||
// +W showwhois — tell the target that someone looked them up
|
||||
if showwhois && !is_self {
|
||||
let by = s.users.get(&uid).map(|u| u.prefix()).unwrap_or_default();
|
||||
let m = s.trf("{0} did a /WHOIS on you", &[by.as_str()]);
|
||||
s.send(
|
||||
tuid,
|
||||
format!(":{} NOTICE {nick} :*** {by} did a /WHOIS on you", s.name),
|
||||
format!(":{} NOTICE {nick} :*** {m}", s.name),
|
||||
);
|
||||
}
|
||||
s.numeric(uid, RPL_ENDOFWHOIS, &format!("{nick} :End of /WHOIS list"));
|
||||
|
|
|
|||
|
|
@ -543,12 +543,10 @@ pub(crate) fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool)
|
|||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
let m = s.trf("Cannot message {0}: a TLS connection is required (+z)", &[tn.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {sn} :Cannot message {tn}: a TLS connection is required (+z)",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {sn} :{m}", s.name),
|
||||
);
|
||||
}
|
||||
return CmdResult::Fail;
|
||||
|
|
|
|||
|
|
@ -398,14 +398,12 @@ impl Command for GlobOps {
|
|||
.filter(|(_, u)| u.flags.oper)
|
||||
.map(|(&u, _)| u)
|
||||
.collect();
|
||||
let m = s.trf("GLOBOPS from {0}: {1}", &[from.as_str(), params[0].as_str()]);
|
||||
for o in opers {
|
||||
let nick = s.users.get(&o).map(|u| u.nick.clone()).unwrap_or_default();
|
||||
s.send(
|
||||
o,
|
||||
format!(
|
||||
":{} NOTICE {nick} :*** GLOBOPS from {from}: {}",
|
||||
s.name, params[0]
|
||||
),
|
||||
format!(":{} NOTICE {nick} :*** {m}", s.name),
|
||||
);
|
||||
}
|
||||
CmdResult::Ok
|
||||
|
|
@ -731,9 +729,10 @@ fn do_xline(s: &mut Server, uid: Uid, params: &[String], kind: XKind) -> CmdResu
|
|||
if s.remove_xline(kind, &mask, &nick) {
|
||||
s.propagate_delline(kind.tag(), &mask);
|
||||
} else {
|
||||
let m = s.trf("{0}-line not found: {1}", &[kind.tag(), mask.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :{}-line not found: {mask}", s.name, kind.tag()),
|
||||
format!(":{} NOTICE {nick} :{m}", s.name),
|
||||
);
|
||||
}
|
||||
return CmdResult::Ok;
|
||||
|
|
@ -878,17 +877,20 @@ impl Command for Rline {
|
|||
if s.remove_xline(XKind::Rline, &pattern, &nick) {
|
||||
s.propagate_delline("R", &pattern);
|
||||
} else {
|
||||
let m = s.trf("R-line not found: {0}", &[pattern.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :R-line not found: {pattern}", s.name),
|
||||
format!(":{} NOTICE {nick} :{m}", s.name),
|
||||
);
|
||||
}
|
||||
return CmdResult::Ok;
|
||||
}
|
||||
if let Err(e) = crate::regex::Regex::new(&pattern) {
|
||||
let e = e.to_string();
|
||||
let m = s.trf("Invalid RLINE regex: {0}", &[e.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :Invalid RLINE regex: {e}", s.name),
|
||||
format!(":{} NOTICE {nick} :{m}", s.name),
|
||||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
|
|
@ -952,7 +954,8 @@ impl Command for NickLock {
|
|||
u.flags.nick_locked = true;
|
||||
}
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used NICKLOCK on {newnick}"));
|
||||
let m = s.trf("{0} used NICKLOCK on {1}", &[by.as_str(), newnick.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -977,7 +980,8 @@ impl Command for NickUnlock {
|
|||
u.flags.nick_locked = false;
|
||||
}
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used NICKUNLOCK on {}", params[0]));
|
||||
let m = s.trf("{0} used NICKUNLOCK on {1}", &[by.as_str(), params[0].as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1049,7 +1053,8 @@ impl Command for Squit {
|
|||
return CmdResult::Fail;
|
||||
};
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('l', &format!("{by} used SQUIT on {name}"));
|
||||
let m = s.trf("{0} used SQUIT on {1}", &[by.as_str(), name.as_str()]);
|
||||
s.snotice_c('l', &m);
|
||||
s.close_link(via, &format!("SQUIT from {by}"));
|
||||
CmdResult::Ok
|
||||
}
|
||||
|
|
@ -1209,7 +1214,9 @@ impl Command for SaMode {
|
|||
let r = apply_mode(s, uid, params);
|
||||
s.mode_sudo = false;
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used SAMODE: {}", params.join(" ")));
|
||||
let joined = params.join(" ");
|
||||
let m = s.trf("{0} used SAMODE: {1}", &[by.as_str(), joined.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
r
|
||||
}
|
||||
}
|
||||
|
|
@ -1248,7 +1255,8 @@ impl Command for SaTopic {
|
|||
s.to_channel(&key, &format!(":{prefix} TOPIC {chan} :{text}"), None);
|
||||
s.propagate_topic(uid, chan, &text);
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used SATOPIC on {chan}"));
|
||||
let m = s.trf("{0} used SATOPIC on {1}", &[by.as_str(), chan.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1313,7 +1321,8 @@ impl Command for SaKick {
|
|||
s.events
|
||||
.push_back(Hook::Part(tuid, key, "kicked".to_string()));
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used SAKICK on {victim} in {chan}"));
|
||||
let m = s.trf("{0} used SAKICK on {1} in {2}", &[by.as_str(), victim.as_str(), chan.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1343,7 +1352,8 @@ impl Command for SaQuit {
|
|||
s.send(tuid, format!("ERROR :Closing link: (SAQUIT: {reason})"));
|
||||
s.remove_user(tuid, &format!("Quit: {reason}"));
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used SAQUIT on {}: {reason}", params[0]));
|
||||
let m = s.trf("{0} used SAQUIT on {1}: {2}", &[by.as_str(), params[0].as_str(), reason.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1379,7 +1389,8 @@ impl Command for ChgName {
|
|||
}
|
||||
s.notify_peers(t, &line, |c| c.setname);
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used CHGNAME on {}: {realname}", params[0]));
|
||||
let m = s.trf("{0} used CHGNAME on {1}: {2}", &[by.as_str(), params[0].as_str(), realname.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1436,7 +1447,8 @@ impl Command for ClearChan {
|
|||
}
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used CLEARCHAN on {chan}"));
|
||||
let m = s.trf("{0} used CLEARCHAN on {1}", &[by.as_str(), chan.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -1553,7 +1565,8 @@ impl Command for SwhoisCmd {
|
|||
}
|
||||
}
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice_c('v', &format!("{by} used SWHOIS on {}: {text}", params[0]));
|
||||
let m = s.trf("{0} used SWHOIS on {1}: {2}", &[by.as_str(), params[0].as_str(), text.as_str()]);
|
||||
s.snotice_c('v', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,9 +60,10 @@ impl Command for Vhost {
|
|||
match host {
|
||||
Some(h) => {
|
||||
s.change_host_ident(uid, None, Some(&h));
|
||||
let m = s.trf("Your vhost is now {0}", &[h.as_str()]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :Your vhost is now {h}", s.name),
|
||||
format!(":{} NOTICE {nick} :{m}", s.name),
|
||||
);
|
||||
}
|
||||
None => {
|
||||
|
|
|
|||
|
|
@ -351,7 +351,9 @@ impl Command for Signore {
|
|||
.map(|u| u.signore.len() >= max && !u.signore.contains(&mask))
|
||||
.unwrap_or(true);
|
||||
if full {
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :Your SIGNORE list is full ({max} max)."));
|
||||
let maxs = max.to_string();
|
||||
let m = s.trf("Your SIGNORE list is full ({0} max).", &[maxs.as_str()]);
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
|
|
@ -359,12 +361,14 @@ impl Command for Signore {
|
|||
u.signore.push(mask.clone());
|
||||
}
|
||||
}
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :SIGNORE \x02{mask}\x02 added — you and they can no longer see each other's messages."));
|
||||
let m = s.trf("SIGNORE \x02{0}\x02 added — you and they can no longer see each other's messages.", &[mask.as_str()]);
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
|
||||
} else {
|
||||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.signore.retain(|x| x != &mask);
|
||||
}
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :SIGNORE \x02{mask}\x02 removed."));
|
||||
let m = s.trf("SIGNORE \x02{0}\x02 removed.", &[mask.as_str()]);
|
||||
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
|
||||
}
|
||||
// Persist the change to the user's services account (no-op if not logged in).
|
||||
s.push_signore_to_services(uid);
|
||||
|
|
|
|||
14
src/i18n.rs
14
src/i18n.rs
|
|
@ -231,6 +231,20 @@ fn read_quoted(s: &str) -> Option<(String, &str)> {
|
|||
't' => out.push('\t'),
|
||||
'"' => out.push('"'),
|
||||
'\\' => out.push('\\'),
|
||||
// \xNN — a raw byte, so IRC formatting controls (e.g. \x02 bold) in a
|
||||
// msgid match the literal byte the source `"\x02"` compiles to.
|
||||
'x' => {
|
||||
let (h1, h2) = (chars.next()?.1, chars.next()?.1);
|
||||
match u8::from_str_radix(&format!("{h1}{h2}"), 16) {
|
||||
Ok(b) => out.push(b as char),
|
||||
Err(_) => {
|
||||
out.push('\\');
|
||||
out.push('x');
|
||||
out.push(h1);
|
||||
out.push(h2);
|
||||
}
|
||||
}
|
||||
}
|
||||
other => {
|
||||
out.push('\\');
|
||||
out.push(other);
|
||||
|
|
|
|||
22
src/ircd.rs
22
src/ircd.rs
|
|
@ -175,8 +175,11 @@ impl Ircd {
|
|||
busy.store(0, Ordering::Relaxed);
|
||||
let ms = start.elapsed().as_millis() as u64;
|
||||
if slow_ms != 0 && ms >= slow_ms {
|
||||
self.server
|
||||
.snotice(&format!("slow event: a command took {ms}ms on the core thread"));
|
||||
let ms_s = ms.to_string();
|
||||
let m = self
|
||||
.server
|
||||
.trf("slow event: a command took {0}ms on the core thread", &[ms_s.as_str()]);
|
||||
self.server.snotice(&m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -260,11 +263,16 @@ impl Ircd {
|
|||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default();
|
||||
let line = match hash {
|
||||
Some(h) => format!(
|
||||
":{} NOTICE {nick} :{algo} hashed password: {h}",
|
||||
self.server.name
|
||||
),
|
||||
None => format!(":{} NOTICE {nick} :Could not hash with '{algo}'", self.server.name),
|
||||
Some(h) => {
|
||||
let m = self
|
||||
.server
|
||||
.trf("{0} hashed password: {1}", &[algo.as_str(), h.as_str()]);
|
||||
format!(":{} NOTICE {nick} :{m}", self.server.name)
|
||||
}
|
||||
None => {
|
||||
let m = self.server.trf("Could not hash with '{0}'", &[algo.as_str()]);
|
||||
format!(":{} NOTICE {nick} :{m}", self.server.name)
|
||||
}
|
||||
};
|
||||
self.server.send(uid, line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,7 +340,8 @@ impl Server {
|
|||
}
|
||||
|
||||
fn reject_link(&mut self, uid: Uid, why: &str) {
|
||||
self.link_out(uid, format!("ERROR :Link denied: {why}"));
|
||||
let m = self.trf("Link denied: {0}", &[why]);
|
||||
self.link_out(uid, format!("ERROR :{m}"));
|
||||
eprintln!("[link] rejected {uid}: {why}");
|
||||
self.close_link(uid, why);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -726,7 +726,8 @@ impl ChanMode for ListMode {
|
|||
for (m, setter, ts) in rows {
|
||||
s.numeric(uid, entry_num, &format!("{chan} {m} {setter} {ts}"));
|
||||
}
|
||||
s.numeric(uid, end_num, &format!("{chan} :End of channel {noun}"));
|
||||
let m = s.trf("End of channel {0}", &[noun]);
|
||||
s.numeric(uid, end_num, &format!("{chan} :{m}"));
|
||||
return Applied::No;
|
||||
};
|
||||
// autoop (+w) embeds a status prefix to grant on join, applied under server
|
||||
|
|
|
|||
|
|
@ -285,12 +285,14 @@ impl Module for AntiMixedUtf8 {
|
|||
|
||||
// Notify the sender even for punitive actions: the writer flushes queued
|
||||
// lines before a disconnect.
|
||||
let block_msg = srv.amu.block_msg.clone();
|
||||
let m = srv.trf(
|
||||
"{0} (Flagged by the spam filter; network operators have been notified.)",
|
||||
&[block_msg.as_str()],
|
||||
);
|
||||
srv.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :*** {} (Flagged by the spam filter; network operators have been notified.)",
|
||||
srv.name, srv.amu.block_msg
|
||||
),
|
||||
format!(":{} NOTICE {nick} :*** {m}", srv.name),
|
||||
);
|
||||
|
||||
let action = srv.amu.action.to_ascii_lowercase();
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ impl Module for BlockAmsg {
|
|||
let notify_opers = matches!(action.as_str(), "killopers" | "noticeopers" | "zlineopers");
|
||||
if notify_opers {
|
||||
let mask = srv.users.get(&uid).map(|u| u.prefix()).unwrap_or_default();
|
||||
srv.snotice(&format!("User {mask} had an /amsg or /ame blocked"));
|
||||
let m = srv.trf("User {0} had an /amsg or /ame blocked", &[mask.as_str()]);
|
||||
srv.snotice(&m);
|
||||
}
|
||||
let reason = "Attempted to global message (/amsg or /ame)";
|
||||
match action.as_str() {
|
||||
|
|
|
|||
|
|
@ -158,9 +158,10 @@ impl Command for VerifyChallenge {
|
|||
.unwrap_or_default();
|
||||
|
||||
let fail = |s: &mut Server, why: &str| {
|
||||
let m = s.trf("Cloudflare Challenge: {0}", &[why]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :*** Cloudflare Challenge: {why}", s.name),
|
||||
format!(":{} NOTICE {nick} :*** {m}", s.name),
|
||||
);
|
||||
CmdResult::Fail
|
||||
};
|
||||
|
|
|
|||
|
|
@ -289,7 +289,9 @@ fn pick(
|
|||
if let Some(max) = c.limit {
|
||||
if class_count(s, &c.name, uid) >= max {
|
||||
if c.maxconnwarn {
|
||||
s.snotice_c('c', &format!("connect class {} is full ({max})", c.name));
|
||||
let max_s = max.to_string();
|
||||
let m = s.trf("connect class {0} is full ({1})", &[c.name.as_str(), max_s.as_str()]);
|
||||
s.snotice_c('c', &m);
|
||||
}
|
||||
continue; // full — try the next class
|
||||
}
|
||||
|
|
@ -355,7 +357,11 @@ pub fn assign(s: &mut Server, uid: Uid) -> Option<String> {
|
|||
};
|
||||
let warn = |s: &Server, why: &str| {
|
||||
if class.maxconnwarn {
|
||||
s.snotice_c('c', &format!("connect class {} refused {ip}: {why}", class.name));
|
||||
let m = s.trf(
|
||||
"connect class {0} refused {1}: {2}",
|
||||
&[class.name.as_str(), ip.as_str(), why],
|
||||
);
|
||||
s.snotice_c('c', &m);
|
||||
}
|
||||
};
|
||||
if let Some(max) = class.localmax {
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ pub fn grant(s: &mut Server, uid: Uid, title: &str, vhost: &str) {
|
|||
s.change_host_ident(uid, None, Some(vhost));
|
||||
}
|
||||
let nick = nick(s, uid);
|
||||
let m = s.trf("TITLE: you are now known as \"{0}\".", &[title]);
|
||||
s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :*** TITLE: you are now known as \"{title}\".", s.name),
|
||||
format!(":{} NOTICE {nick} :*** {m}", s.name),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,19 +117,21 @@ impl Module for DccAllow {
|
|||
return ModResult::Passthru;
|
||||
}
|
||||
let tnick = s.users.get(&tuid).map(|u| u.nick.clone()).unwrap_or_default();
|
||||
let m1 = s.trf(
|
||||
"Your DCC to {0} was blocked; they must /DCCALLOW +{1} first.",
|
||||
&[tnick.as_str(), sender.as_str()],
|
||||
);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {sender} :*** Your DCC to {tnick} was blocked; they must /DCCALLOW +{sender} first.",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {sender} :*** {m1}", s.name),
|
||||
);
|
||||
let m2 = s.trf(
|
||||
"{0} tried to send you {1} — blocked. /DCCALLOW +{2} to allow it, then ask them to resend.",
|
||||
&[sender.as_str(), what.as_str(), sender.as_str()],
|
||||
);
|
||||
s.send(
|
||||
tuid,
|
||||
format!(
|
||||
":{} NOTICE {tnick} :*** {sender} tried to send you {what} — blocked. /DCCALLOW +{sender} to allow it, then ask them to resend.",
|
||||
s.name
|
||||
),
|
||||
format!(":{} NOTICE {tnick} :*** {m2}", s.name),
|
||||
);
|
||||
ModResult::Deny
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,14 +185,20 @@ impl Command for FilterCmd {
|
|||
let filter = match SpamFilter::new(pattern.clone(), engine.clone(), action.clone(), duration, reason) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
s.send(uid, format!(":{} NOTICE {nick} :FILTER rejected ({e})", s.name));
|
||||
let e_s = e.to_string();
|
||||
let m = s.trf("FILTER rejected ({0})", &[e_s.as_str()]);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
};
|
||||
let f = s.ext.get_or_insert_with::<Filters>(Filters::default);
|
||||
f.0.retain(|r| r.pattern != pattern);
|
||||
f.0.push(filter);
|
||||
s.snotice_c('f', &format!("{nick} added FILTER {pattern} (engine={engine} action={action})"));
|
||||
let m = s.trf(
|
||||
"{0} added FILTER {1} (engine={2} action={3})",
|
||||
&[nick.as_str(), pattern.as_str(), engine.as_str(), action.as_str()],
|
||||
);
|
||||
s.snotice_c('f', &m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ impl Command for GlobopsCmd {
|
|||
return CmdResult::Fail;
|
||||
}
|
||||
let nick = s.users.get(&uid).map(|u| u.nick.clone()).unwrap_or_default();
|
||||
s.snotice_c('g', &format!("GLOBOPS from {nick}: {}", params.join(" ")));
|
||||
let body = params.join(" ");
|
||||
let m = s.trf("GLOBOPS from {0}: {1}", &[nick.as_str(), body.as_str()]);
|
||||
s.snotice_c('g', &m);
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ pub fn apply(s: &mut Server, uid: Uid, type_id: Option<&str>) {
|
|||
return;
|
||||
};
|
||||
let Some(r) = with_resolved(s, |m| m.get(&id).cloned()) else {
|
||||
s.snotice_c('o', &format!("oper type '{id}' is not defined — granting full access"));
|
||||
let m = s.trf("oper type '{0}' is not defined — granting full access", &[id.as_str()]);
|
||||
s.snotice_c('o', &m);
|
||||
return;
|
||||
};
|
||||
if !r.modes.is_empty() {
|
||||
|
|
|
|||
|
|
@ -199,23 +199,16 @@ impl Command for MkPasswd {
|
|||
}
|
||||
match make(&algo, &pass) {
|
||||
Some(hashed) => {
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :{algo} hashed password: {hashed}",
|
||||
s.name
|
||||
),
|
||||
);
|
||||
let m = s.trf("{0} hashed password: {1}", &[algo.as_str(), hashed.as_str()]);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
|
||||
CmdResult::Ok
|
||||
}
|
||||
None => {
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :Unknown hash '{algo}' (try md5, sha1, sha256, sha512, pbkdf2, bcrypt)",
|
||||
s.name
|
||||
),
|
||||
let m = s.trf(
|
||||
"Unknown hash '{0}' (try md5, sha1, sha256, sha512, pbkdf2, bcrypt)",
|
||||
&[algo.as_str()],
|
||||
);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
|
||||
CmdResult::Fail
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,13 +289,13 @@ impl Command for ReputationCmd {
|
|||
e.score = val.min(cap);
|
||||
e.last_seen = n;
|
||||
save(s);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {anick} :REPUTATION {nick} ({k}) set to {val}",
|
||||
s.name
|
||||
),
|
||||
let ks = k.to_string();
|
||||
let vals = val.to_string();
|
||||
let m = s.trf(
|
||||
"REPUTATION {0} ({1}) set to {2}",
|
||||
&[nick.as_str(), ks.as_str(), vals.as_str()],
|
||||
);
|
||||
s.send(uid, format!(":{} NOTICE {anick} :{m}", s.name));
|
||||
} else {
|
||||
let score = score_of(s, tuid);
|
||||
s.send(
|
||||
|
|
|
|||
|
|
@ -99,13 +99,13 @@ impl Command for RMode {
|
|||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default();
|
||||
let plural = if removed == 1 { "y" } else { "ies" };
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :RMODE: removed {removed} +{mode} entr{plural} from {chan}",
|
||||
s.name
|
||||
),
|
||||
let removeds = removed.to_string();
|
||||
let modes = mode.to_string();
|
||||
let m = s.trf(
|
||||
"RMODE: removed {0} +{1} entr{2} from {3}",
|
||||
&[removeds.as_str(), modes.as_str(), plural, chan.as_str()],
|
||||
);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ pub fn handle(s: &mut Server, action: &str, params: &str) -> Result<String, RpcE
|
|||
std::thread::spawn(move || {
|
||||
crate::socketengine::connect_link(&addr, tx, counter, max_line)
|
||||
});
|
||||
s.snotice_c('l', &format!("RPC initiated a link to {}", b.name));
|
||||
let m = s.trf("RPC initiated a link to {0}", &[b.name.as_str()]);
|
||||
s.snotice_c('l', &m);
|
||||
Ok(obj(&[("result", "true".into())]))
|
||||
}
|
||||
"disconnect" => {
|
||||
|
|
|
|||
|
|
@ -221,13 +221,8 @@ impl Command for SecGroupsCmd {
|
|||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {anick} :{tnick} is in security groups: {list}",
|
||||
s.name
|
||||
),
|
||||
);
|
||||
let m = s.trf("{0} is in security groups: {1}", &[tnick.as_str(), list.as_str()]);
|
||||
s.send(uid, format!(":{} NOTICE {anick} :{m}", s.name));
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ pub fn maybe_show(s: &mut Server, uid: Uid, cmd: &str) -> bool {
|
|||
s.send(uid, format!(":{} NOTICE {nick} :{line}", s.name));
|
||||
}
|
||||
}
|
||||
None => s.send(
|
||||
uid,
|
||||
format!(":{} NOTICE {nick} :*** {cmd}: file not available.", s.name),
|
||||
),
|
||||
None => {
|
||||
let m = s.trf("{0}: file not available.", &[cmd]);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ impl Module for SolveMsg {
|
|||
answer: Some(ans),
|
||||
});
|
||||
}
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :*** To cut spam, answer this to send your message — what is {a} {sym} {b} ?",
|
||||
s.name
|
||||
),
|
||||
let as_ = a.to_string();
|
||||
let bs = b.to_string();
|
||||
let m = s.trf(
|
||||
"To cut spam, answer this to send your message — what is {0} {1} {2} ?",
|
||||
&[as_.as_str(), sym, bs.as_str()],
|
||||
);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
|
||||
ModResult::Deny
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,13 +48,14 @@ impl Command for TLine {
|
|||
.get(&uid)
|
||||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default();
|
||||
s.send(
|
||||
uid,
|
||||
format!(
|
||||
":{} NOTICE {nick} :*** TLINE: {mask} matches {matched} of {total} local users ({pct}%)",
|
||||
s.name
|
||||
),
|
||||
let matcheds = matched.to_string();
|
||||
let totals = total.to_string();
|
||||
let pcts = pct.to_string();
|
||||
let m = s.trf(
|
||||
"TLINE: {0} matches {1} of {2} local users ({3}%)",
|
||||
&[mask.as_str(), matcheds.as_str(), totals.as_str(), pcts.as_str()],
|
||||
);
|
||||
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -438,7 +438,8 @@ impl Server {
|
|||
self.send(t, line.clone());
|
||||
}
|
||||
if self.conf_bool("seenicks", false) {
|
||||
self.snotice_c('n', &format!("{old} is now known as {newnick}"));
|
||||
let m = self.trf("{0} is now known as {1}", &[old.as_str(), newnick]);
|
||||
self.snotice_c('n', &m);
|
||||
}
|
||||
// WATCH/MONITOR: the old nick is now gone, the new one is here
|
||||
self.watch_notify_offline(&old);
|
||||
|
|
|
|||
|
|
@ -304,7 +304,8 @@ impl Server {
|
|||
crate::server::long_date(expires)
|
||||
)
|
||||
};
|
||||
self.snotice_c('x', &format!("XLINE: {setter} added a {detail}: {reason}"));
|
||||
let m = self.trf("XLINE: {0} added a {1}: {2}", &[setter, detail.as_str(), reason]);
|
||||
self.snotice_c('x', &m);
|
||||
self.save_xlines();
|
||||
self.enforce_xlines();
|
||||
}
|
||||
|
|
@ -335,7 +336,8 @@ impl Server {
|
|||
Some(e) if e != 0 => format!("timed {tag}-line on {mask} (already expired)"),
|
||||
_ => format!("permanent {tag}-line on {mask}"),
|
||||
};
|
||||
self.snotice_c('x', &format!("XLINE: {remover} removed a {detail}"));
|
||||
let m = self.trf("XLINE: {0} removed a {1}", &[remover, detail.as_str()]);
|
||||
self.snotice_c('x', &m);
|
||||
self.save_xlines();
|
||||
}
|
||||
removed
|
||||
|
|
@ -383,7 +385,8 @@ impl Server {
|
|||
}
|
||||
self.xlines.retain(|x| x.expires == 0 || x.expires > n);
|
||||
for (kind, mask) in &expired {
|
||||
self.snotice_c('x', &format!("XLINE: {}-line on {mask} expired", kind.tag()));
|
||||
let m = self.trf("XLINE: {0}-line on {1} expired", &[kind.tag(), mask.as_str()]);
|
||||
self.snotice_c('x', &m);
|
||||
}
|
||||
self.save_xlines(); // an expiry changed the set — persist it
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue