mode: register +r as a services-only channel mode so a user MODE +r gets a clean rejection instead of 472 unknown-mode (chanserv still sets it via mode_sudo)
This commit is contained in:
parent
b7600ee5aa
commit
636da13a8a
1 changed files with 40 additions and 1 deletions
41
src/mode.rs
41
src/mode.rs
|
|
@ -85,6 +85,7 @@ static CHAN_MODES: &[&(dyn ChanMode + Sync)] = &[
|
||||||
&INVEX,
|
&INVEX,
|
||||||
&KEY,
|
&KEY,
|
||||||
&LIMIT,
|
&LIMIT,
|
||||||
|
®ISTERED_CHAN,
|
||||||
&MODERATED,
|
&MODERATED,
|
||||||
&NOEXTERNAL,
|
&NOEXTERNAL,
|
||||||
&TOPICLOCK,
|
&TOPICLOCK,
|
||||||
|
|
@ -439,6 +440,44 @@ impl ChanMode for OperFlagChan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- +r registered (services-only) ------------------------------------------
|
||||||
|
|
||||||
|
/// `+r` — a registered channel. Set only by services (under `mode_sudo`, e.g. a
|
||||||
|
/// ChanServ FMODE); a client that tries it gets a clean "services-only" rejection
|
||||||
|
/// instead of "unknown mode char".
|
||||||
|
struct RegisteredChan;
|
||||||
|
static REGISTERED_CHAN: RegisteredChan = RegisteredChan;
|
||||||
|
impl ChanMode for RegisteredChan {
|
||||||
|
fn letter(&self) -> char {
|
||||||
|
'r'
|
||||||
|
}
|
||||||
|
fn wants_param(&self, _adding: bool) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn apply(
|
||||||
|
&self,
|
||||||
|
s: &mut Server,
|
||||||
|
chan: &str,
|
||||||
|
key: &str,
|
||||||
|
uid: Uid,
|
||||||
|
adding: bool,
|
||||||
|
_param: Option<&str>,
|
||||||
|
) -> Applied {
|
||||||
|
if !s.mode_sudo {
|
||||||
|
s.numeric(
|
||||||
|
uid,
|
||||||
|
ERR_NOPRIVILEGES,
|
||||||
|
&format!("{chan} :Channel mode +r may only be set by services"),
|
||||||
|
);
|
||||||
|
return Applied::No;
|
||||||
|
}
|
||||||
|
if let Some(c) = s.channels.get_mut(key) {
|
||||||
|
c.modes.registered = adding;
|
||||||
|
}
|
||||||
|
Applied::Yes(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- +k channel key ---------------------------------------------------------
|
// --- +k channel key ---------------------------------------------------------
|
||||||
|
|
||||||
struct Key;
|
struct Key;
|
||||||
|
|
@ -1439,7 +1478,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn registry_covers_all_channel_modes() {
|
fn registry_covers_all_channel_modes() {
|
||||||
for c in "qaohvbeIklmntiszpONCTcSRMfjFLgGuBQAPJUdKXwD".chars() {
|
for c in "qaohvbeIklmntiszpONCTcSRMfjFLgGuBQAPJUdKXwDr".chars() {
|
||||||
assert!(chan_mode(c).is_some(), "missing handler for +{c}");
|
assert!(chan_mode(c).is_some(), "missing handler for +{c}");
|
||||||
}
|
}
|
||||||
assert!(chan_mode('y').is_none());
|
assert!(chan_mode('y').is_none());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue