hostcycle: PART+JOIN non-chghost clients on host change (prefixes restored)
This commit is contained in:
parent
d4ce5c008f
commit
f022ea5a42
1 changed files with 66 additions and 0 deletions
|
|
@ -709,6 +709,72 @@ impl Server {
|
||||||
if aware {
|
if aware {
|
||||||
self.send(uid, line);
|
self.send(uid, line);
|
||||||
}
|
}
|
||||||
|
// hostcycle — clients WITHOUT the chghost cap only learn the new host via a
|
||||||
|
// PART+JOIN, so cycle them through each shared channel (chghost peers already
|
||||||
|
// got the CHGHOST line above). Prefix modes are re-sent so they don't appear
|
||||||
|
// de-opped. InspIRCd `m_hostcycle`.
|
||||||
|
if new_host.is_some() || new_ident.is_some() {
|
||||||
|
let (nick, new_prefix, acct, realname) = {
|
||||||
|
let u = &self.users[&uid];
|
||||||
|
(
|
||||||
|
u.nick.clone(),
|
||||||
|
u.prefix(),
|
||||||
|
u.account.clone().unwrap_or_else(|| "*".to_string()),
|
||||||
|
u.realname.clone(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let chans: Vec<String> = self.users[&uid].channels.iter().cloned().collect();
|
||||||
|
for key in chans {
|
||||||
|
let Some(ch) = self.channels.get(&key) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let name = ch.name.clone();
|
||||||
|
let modes: String = ch
|
||||||
|
.members
|
||||||
|
.get(&uid)
|
||||||
|
.map(|mem| {
|
||||||
|
let mut s = String::new();
|
||||||
|
for (on, c) in [
|
||||||
|
(mem.owner, 'q'),
|
||||||
|
(mem.admin, 'a'),
|
||||||
|
(mem.op, 'o'),
|
||||||
|
(mem.halfop, 'h'),
|
||||||
|
(mem.voice, 'v'),
|
||||||
|
] {
|
||||||
|
if on {
|
||||||
|
s.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
let recips: Vec<(Uid, bool)> = ch
|
||||||
|
.members
|
||||||
|
.keys()
|
||||||
|
.copied()
|
||||||
|
.filter(|&m| m != uid)
|
||||||
|
.filter_map(|m| {
|
||||||
|
self.users
|
||||||
|
.get(&m)
|
||||||
|
.filter(|u| !u.caps.chghost)
|
||||||
|
.map(|u| (m, u.caps.extended_join))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for (m, extjoin) in recips {
|
||||||
|
self.send(m, format!(":{old_prefix} PART {name} :Changing host"));
|
||||||
|
let joinline = if extjoin {
|
||||||
|
format!(":{new_prefix} JOIN {name} {acct} :{realname}")
|
||||||
|
} else {
|
||||||
|
format!(":{new_prefix} JOIN {name}")
|
||||||
|
};
|
||||||
|
self.send(m, joinline);
|
||||||
|
if !modes.is_empty() {
|
||||||
|
let args = vec![nick.clone(); modes.len()].join(" ");
|
||||||
|
self.send(m, format!(":{} MODE {name} +{modes} {args}", self.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if new_host.is_some() {
|
if new_host.is_some() {
|
||||||
self.numeric(
|
self.numeric(
|
||||||
uid,
|
uid,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue