opmoderated channel mode (+U — route unprivileged messages to ops)
This commit is contained in:
parent
4a53c80d4d
commit
4d6525cac2
4 changed files with 26 additions and 4 deletions
|
|
@ -154,6 +154,7 @@ pub struct ChanModes {
|
|||
pub allowinvite: bool, // +A — any member (not just ops) may INVITE
|
||||
pub permanent: bool, // +P — channel persists with zero members
|
||||
pub kicknorejoin: Option<u32>, // +J <secs> — block rejoin for N secs after a kick
|
||||
pub opmoderated: bool, // +U — unprivileged users' messages go to ops only
|
||||
}
|
||||
|
||||
impl ChanModes {
|
||||
|
|
@ -180,6 +181,7 @@ impl ChanModes {
|
|||
'Q' => self.nokicks = on,
|
||||
'A' => self.allowinvite = on,
|
||||
'P' => self.permanent = on,
|
||||
'U' => self.opmoderated = on,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,13 +176,21 @@ pub(crate) fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool)
|
|||
}
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
// +U opmoderated — an unprivileged user's message isn't blocked; it's routed
|
||||
// to channel ops only (below). It also overrides +m's block for that purpose.
|
||||
let op_only = s
|
||||
.channels
|
||||
.get(&key)
|
||||
.map(|c| c.modes.opmoderated)
|
||||
.unwrap_or(false)
|
||||
&& s.rank(uid, &key) < RANK_VOICE;
|
||||
// +m: only voiced-or-above may speak
|
||||
let moderated = s
|
||||
.channels
|
||||
.get(&key)
|
||||
.map(|c| c.modes.moderated)
|
||||
.unwrap_or(false);
|
||||
if moderated && s.rank(uid, &key) < RANK_VOICE {
|
||||
if moderated && s.rank(uid, &key) < RANK_VOICE && !op_only {
|
||||
if !notice {
|
||||
s.numeric(
|
||||
uid,
|
||||
|
|
@ -347,6 +355,10 @@ pub(crate) fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool)
|
|||
if m == uid || s.users.get(&m).map(|u| u.flags.deaf).unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
// +U: an unprivileged sender's message reaches ops (half-op+) only
|
||||
if op_only && s.rank(m, &key) < RANK_HALFOP {
|
||||
continue;
|
||||
}
|
||||
s.send_tagged(m, uid, &ctags, &msgid, &line);
|
||||
}
|
||||
// echo-message: give the sender their own copy if they asked for one
|
||||
|
|
|
|||
10
src/mode.rs
10
src/mode.rs
|
|
@ -89,6 +89,7 @@ static CHAN_MODES: &[&(dyn ChanMode + Sync)] = &[
|
|||
&ALLOWINVITE,
|
||||
&PERMANENT,
|
||||
&KICKNOREJOIN,
|
||||
&OPMODERATED,
|
||||
];
|
||||
|
||||
// --- prefix modes (+q/+a/+o/+h/+v): a per-member rank, needs a nick ----------
|
||||
|
|
@ -307,6 +308,9 @@ fn set_allowinvite(m: &mut ChanModes, v: bool) {
|
|||
fn set_permanent(m: &mut ChanModes, v: bool) {
|
||||
m.permanent = v;
|
||||
}
|
||||
fn set_opmoderated(m: &mut ChanModes, v: bool) {
|
||||
m.opmoderated = v;
|
||||
}
|
||||
static NOKICKS: Flag = Flag {
|
||||
ch: 'Q',
|
||||
set: set_nokicks,
|
||||
|
|
@ -319,6 +323,10 @@ static PERMANENT: Flag = Flag {
|
|||
ch: 'P',
|
||||
set: set_permanent,
|
||||
};
|
||||
static OPMODERATED: Flag = Flag {
|
||||
ch: 'U',
|
||||
set: set_opmoderated,
|
||||
};
|
||||
|
||||
impl ChanMode for Flag {
|
||||
fn letter(&self) -> char {
|
||||
|
|
@ -1142,7 +1150,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn registry_covers_all_channel_modes() {
|
||||
for c in "qaohvbeIklmntiszpONCTcSRMfjFLgGuBQAPJ".chars() {
|
||||
for c in "qaohvbeIklmntiszpONCTcSRMfjFLgGuBQAPJU".chars() {
|
||||
assert!(chan_mode(c).is_some(), "missing handler for +{c}");
|
||||
}
|
||||
assert!(chan_mode('y').is_none());
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ impl Server {
|
|||
uid,
|
||||
RPL_MYINFO,
|
||||
&format!(
|
||||
"{} echoircd-{VERSION} iowxsgBDIHrRzWc qaohvbeIklimnpstzCTcSNORMfjFLgGuBQAPJ",
|
||||
"{} echoircd-{VERSION} iowxsgBDIHrRzWc qaohvbeIklimnpstzCTcSNORMfjFLgGuBQAPJU",
|
||||
self.name
|
||||
),
|
||||
);
|
||||
|
|
@ -425,7 +425,7 @@ impl Server {
|
|||
uid,
|
||||
RPL_ISUPPORT,
|
||||
&format!(
|
||||
"CHANTYPES=# PREFIX=(qaohv)~&@%+ CHANMODES=beIg,k,lfjFLHBJ,ACGMNOPQRSTcimnpstuz EXTBAN=,cmn WATCH=128 MONITOR=128 SILENCE=32 CALLERID=g WHOX CHATHISTORY=256 MSGREFTYPES=timestamp,msgid UTF8ONLY CASEMAPPING=ascii NICKLEN=30 CHANNELLEN=50 NETWORK={} :are supported by this server",
|
||||
"CHANTYPES=# PREFIX=(qaohv)~&@%+ CHANMODES=beIg,k,lfjFLHBJ,ACGMNOPQRSTUcimnpstuz EXTBAN=,cmn WATCH=128 MONITOR=128 SILENCE=32 CALLERID=g WHOX CHATHISTORY=256 MSGREFTYPES=timestamp,msgid UTF8ONLY CASEMAPPING=ascii NICKLEN=30 CHANNELLEN=50 NETWORK={} :are supported by this server",
|
||||
self.network
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue