channel +H chanhistory: replay recent messages to joiners (m_chanhistory), reuses the history store

This commit is contained in:
Jean Chevronnet 2026-08-08 22:24:29 +00:00
parent d4c4c1a7d0
commit 7bf9e4c0b8
3 changed files with 130 additions and 25 deletions

View file

@ -83,6 +83,7 @@ static CHAN_MODES: &[&(dyn ChanMode + Sync)] = &[
&JOINFLOOD,
&NICKFLOOD,
&REDIRECT,
&CHANHISTORY,
];
// --- prefix modes (+q/+a/+o/+h/+v): a per-member rank, needs a nick ----------
@ -390,6 +391,49 @@ impl ChanMode for Limit {
}
}
// --- +H chanhistory: replay recent messages to joiners ----------------------
struct ChanHistory;
static CHANHISTORY: ChanHistory = ChanHistory;
impl ChanMode for ChanHistory {
fn letter(&self) -> char {
'H'
}
fn wants_param(&self, adding: bool) -> bool {
adding // +H <lines>[:<secs>]; -H takes nothing
}
fn apply(
&self,
s: &mut Server,
_chan: &str,
key: &str,
_uid: Uid,
adding: bool,
param: Option<&str>,
) -> Applied {
if adding {
let Some(p) = param else {
return Applied::No;
};
let (lines_s, secs_s) = p.split_once(':').unwrap_or((p, "0"));
let Some(lines) = lines_s.parse::<u32>().ok().filter(|&n| n > 0) else {
return Applied::No;
};
let lines = lines.min(crate::server::HISTORY_CAP as u32);
let secs = secs_s.parse::<u64>().unwrap_or(0);
if let Some(c) = s.channels.get_mut(key) {
c.modes.history = Some((lines, secs));
}
Applied::Yes(Some(format!("{lines}:{secs}")))
} else {
if let Some(c) = s.channels.get_mut(key) {
c.modes.history = None;
}
Applied::Yes(None)
}
}
}
// --- list modes (+b bans, +e ban exceptions, +I invite exceptions) ----------
#[derive(Clone, Copy)]