channel modes +Q nokicks / +A allowinvite / +P permchannels; fix SWHOIS (full multi-word text, no doubled nick in WHOIS)
This commit is contained in:
parent
050ce37612
commit
8dc51a281b
8 changed files with 70 additions and 20 deletions
|
|
@ -99,7 +99,7 @@ impl Command for Cycle {
|
|||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.channels.remove(&key);
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
s.join(uid, chan, None);
|
||||
CmdResult::Ok
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ impl Command for Remove {
|
|||
if let Some(u) = s.users.get_mut(&tuid) {
|
||||
u.channels.remove(&key);
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
@ -195,8 +195,11 @@ impl Command for Invite {
|
|||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
// only ops may invite into an +i channel
|
||||
if s.channels[&key].modes.invite_only && !s.is_op(uid, &key) {
|
||||
// only ops may invite into an +i channel — unless +A (allow anyone to invite)
|
||||
if s.channels[&key].modes.invite_only
|
||||
&& !s.channels[&key].modes.allowinvite
|
||||
&& !s.is_op(uid, &key)
|
||||
{
|
||||
s.numeric(
|
||||
uid,
|
||||
ERR_CHANOPRIVSNEEDED,
|
||||
|
|
@ -373,7 +376,7 @@ impl Command for Part {
|
|||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.channels.remove(&key);
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
s.events.push_back(Hook::Part(uid, key, reason.clone()));
|
||||
}
|
||||
CmdResult::Ok
|
||||
|
|
@ -428,6 +431,15 @@ impl Command for Kick {
|
|||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
// +Q — kicks disabled (IRC operators bypass; SAKICK is a separate path)
|
||||
if s.channels[&key].modes.nokicks && !s.is_oper(uid) {
|
||||
s.numeric(
|
||||
uid,
|
||||
ERR_CHANOPRIVSNEEDED,
|
||||
&format!("{chan} :Kicks are disabled here (+Q)"),
|
||||
);
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
let kicker = s.users[&uid].nick.clone();
|
||||
let reason = params.get(2).cloned().unwrap_or(kicker);
|
||||
let prefix = s.users[&uid].prefix();
|
||||
|
|
@ -443,7 +455,7 @@ impl Command for Kick {
|
|||
if let Some(u) = s.users.get_mut(&tuid) {
|
||||
u.channels.remove(&key);
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
s.events
|
||||
.push_back(Hook::Part(tuid, key, "kicked".to_string()));
|
||||
CmdResult::Ok
|
||||
|
|
|
|||
|
|
@ -175,9 +175,10 @@ impl Command for Whois {
|
|||
&format!("{nick} :is an IRC operator"),
|
||||
);
|
||||
}
|
||||
// 320: oper-set SWHOIS line
|
||||
// 320: oper-set SWHOIS line. No redundant target-nick param — just the
|
||||
// text — so clients that don't special-case 320 don't echo the nick.
|
||||
if let Some(line) = &swhois {
|
||||
s.numeric(uid, RPL_WHOISSPECIAL, &format!("{nick} :{line}"));
|
||||
s.numeric(uid, RPL_WHOISSPECIAL, &format!(":{line}"));
|
||||
}
|
||||
// opers can see through the cloak to the real host/ip
|
||||
if asker_oper && disp != realhost {
|
||||
|
|
|
|||
|
|
@ -975,7 +975,7 @@ impl Command for SaKick {
|
|||
if let Some(u) = s.users.get_mut(&tuid) {
|
||||
u.channels.remove(&key);
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
s.events
|
||||
.push_back(Hook::Part(tuid, key, "kicked".to_string()));
|
||||
let by = oper_nick(s, uid);
|
||||
|
|
@ -1099,7 +1099,7 @@ impl Command for ClearChan {
|
|||
s.events
|
||||
.push_back(Hook::Part(tuid, key.clone(), "cleared".to_string()));
|
||||
}
|
||||
s.channels.retain(|_, c| !c.is_empty());
|
||||
s.channels.retain(|_, c| c.keep_alive());
|
||||
let by = oper_nick(s, uid);
|
||||
s.snotice(&format!("{by} used CLEARCHAN on {chan}"));
|
||||
CmdResult::Ok
|
||||
|
|
@ -1208,7 +1208,8 @@ impl Command for SwhoisCmd {
|
|||
let Some(t) = oper_target(s, uid, ¶ms[0]) else {
|
||||
return CmdResult::Fail;
|
||||
};
|
||||
let text = params[1].clone();
|
||||
// everything after the nick is the line — works with or without a `:`
|
||||
let text = params[1..].join(" ");
|
||||
if let Some(u) = s.users.get_mut(&t) {
|
||||
if text.is_empty() {
|
||||
u.ext.take::<Swhois>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue