invite: route INVITE for a remote target to its server and deliver inbound INVITE

This commit is contained in:
Jean Chevronnet 2026-08-16 19:11:57 +00:00
parent 559a102e48
commit ef84846267
2 changed files with 44 additions and 0 deletions

View file

@ -281,6 +281,18 @@ impl Command for Invite {
return CmdResult::Fail; return CmdResult::Fail;
} }
let Some(tuid) = s.find_nick(tnick) else { let Some(tuid) = s.find_nick(tnick) else {
// remote target: route the invite to the server that owns it
if let Some((tuuid, _)) = s.find_remote(tnick) {
let iuuid = s.users[&uid].uuid.clone();
s.route_invite(&iuuid, &tuuid, chan);
let rnick = s
.remote_users
.get(&tuuid)
.map(|r| r.nick.clone())
.unwrap_or_else(|| tnick.to_string());
s.numeric(uid, RPL_INVITING, &format!("{rnick} {chan}"));
return CmdResult::Ok;
}
s.numeric( s.numeric(
uid, uid,
ERR_NOSUCHNICK, ERR_NOSUCHNICK,

View file

@ -168,6 +168,7 @@ impl Server {
"QUIT" if registered => self.link_quit_recv(uid, msg), "QUIT" if registered => self.link_quit_recv(uid, msg),
"KILL" if registered => self.link_kill_recv(uid, msg), "KILL" if registered => self.link_kill_recv(uid, msg),
"SAVE" if registered => self.link_save_recv(uid, msg), "SAVE" if registered => self.link_save_recv(uid, msg),
"INVITE" if registered => self.link_invite_recv(uid, msg),
"ADDLINE" if registered => self.link_addline_recv(uid, msg), "ADDLINE" if registered => self.link_addline_recv(uid, msg),
"DELLINE" if registered => self.link_delline_recv(uid, msg), "DELLINE" if registered => self.link_delline_recv(uid, msg),
"PRIVMSG" if registered => self.link_message_recv(uid, msg, false), "PRIVMSG" if registered => self.link_message_recv(uid, msg, false),
@ -1141,6 +1142,37 @@ impl Server {
} }
} }
/// Route an INVITE toward the server that owns a remote `target` uuid.
pub fn route_invite(&self, inviter: &str, target: &str, chan: &str) {
if let Some(v) = self.link_toward(target) {
self.link_out(v, format!(":{inviter} INVITE {target} {chan}"));
}
}
/// `:<src> INVITE <target> <chan>` — deliver an invite to a local target (record
/// it so they bypass +i, and notify them), or forward toward a remote one.
fn link_invite_recv(&mut self, via: Uid, msg: &Message) {
let Some(src) = msg.source.clone() else {
return;
};
let (Some(target), Some(chan)) =
(msg.params.first().cloned(), msg.params.get(1).cloned())
else {
return;
};
if let Some(&luid) = self.uuid_local.get(&target) {
let key = chan.to_ascii_lowercase();
if let Some(ch) = self.channels.get_mut(&key) {
ch.invites.insert(luid);
}
let prefix = self.uuid_prefix(&src).unwrap_or_else(|| src.clone());
let nick = self.users.get(&luid).map(|u| u.nick.clone()).unwrap_or_default();
self.send(luid, format!(":{prefix} INVITE {nick} :{chan}"));
} else {
self.forward_to_target(&target, msg, via);
}
}
/// `:<src> ADDLINE <type> <mask> <setter> <settime> <duration> :<reason>` — a /// `:<src> ADDLINE <type> <mask> <setter> <settime> <duration> :<reason>` — a
/// network ban set on a peer (e.g. a services akill). Apply and relay onward. /// network ban set on a peer (e.g. a services akill). Apply and relay onward.
fn link_addline_recv(&mut self, via: Uid, msg: &Message) { fn link_addline_recv(&mut self, via: Uid, msg: &Message) {