Re-assert +r when a registered channel is created
fedserv now handles FJOIN (channel create/burst) and sets +r on any channel that is registered, so a registered channel regains the mode after it empties and is recreated, and after a services relink. Single joins arrive as IJOIN and are ignored.
This commit is contained in:
parent
64500906d8
commit
eb22612da8
3 changed files with 45 additions and 0 deletions
|
|
@ -170,6 +170,16 @@ impl Engine {
|
||||||
self.network.user_nick_change(&uid, nick);
|
self.network.user_nick_change(&uid, nick);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
// A registered channel just (re)appeared: re-assert +r. Fires on
|
||||||
|
// creation and on the uplink burst, so registered channels regain the
|
||||||
|
// mode after emptying, and after a services relink.
|
||||||
|
NetEvent::ChannelCreate { channel } => {
|
||||||
|
if self.db.channel(&channel).is_some() {
|
||||||
|
vec![NetAction::ChannelMode { channel, modes: "+r".to_string() }]
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
NetEvent::Quit { uid } => {
|
NetEvent::Quit { uid } => {
|
||||||
self.network.user_quit(&uid);
|
self.network.user_quit(&uid);
|
||||||
self.sasl_sessions.remove(&uid); // drop any half-finished exchange
|
self.sasl_sessions.remove(&uid); // drop any half-finished exchange
|
||||||
|
|
@ -938,4 +948,21 @@ mod tests {
|
||||||
assert!(notice(&out, "dropped"));
|
assert!(notice(&out, "dropped"));
|
||||||
assert!(out.iter().any(|a| matches!(a, NetAction::ChannelMode { channel, modes } if channel == "#room" && modes == "-r")), "drop clears +r: {out:?}");
|
assert!(out.iter().any(|a| matches!(a, NetAction::ChannelMode { channel, modes } if channel == "#room" && modes == "-r")), "drop clears +r: {out:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A registered channel (re)appearing re-asserts +r; an unregistered one does not.
|
||||||
|
#[test]
|
||||||
|
fn channel_create_reasserts_registered_mode() {
|
||||||
|
let path = std::env::temp_dir().join("fedserv-chancreate.jsonl");
|
||||||
|
let _ = std::fs::remove_file(&path);
|
||||||
|
let mut db = Db::open(&path, "42S");
|
||||||
|
db.register_channel("#reg", "alice").unwrap();
|
||||||
|
let ns = NickServ { uid: "42SAAAAAA".into(), guest_nick: "Guest".into(), guest_seq: 0 };
|
||||||
|
let mut e = Engine::new(vec![Box::new(ns)], db);
|
||||||
|
|
||||||
|
let out = e.handle(NetEvent::ChannelCreate { channel: "#reg".into() });
|
||||||
|
assert!(out.iter().any(|a| matches!(a, NetAction::ChannelMode { channel, modes } if channel == "#reg" && modes == "+r")), "registered channel regains +r: {out:?}");
|
||||||
|
|
||||||
|
let out = e.handle(NetEvent::ChannelCreate { channel: "#other".into() });
|
||||||
|
assert!(out.is_empty(), "unregistered channel is left alone: {out:?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,11 @@ impl Protocol for InspIrcd {
|
||||||
}
|
}
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
},
|
},
|
||||||
|
// FJOIN <chan> <ts> <modes> [params] :<members> — channel create/burst.
|
||||||
|
"FJOIN" => match tokens.next() {
|
||||||
|
Some(chan) if !chan.is_empty() => vec![NetEvent::ChannelCreate { channel: chan.to_string() }],
|
||||||
|
_ => vec![],
|
||||||
|
},
|
||||||
"QUIT" => vec![NetEvent::Quit { uid: source.unwrap_or_default() }],
|
"QUIT" => vec![NetEvent::Quit { uid: source.unwrap_or_default() }],
|
||||||
// account-registration relay from an ircd:
|
// account-registration relay from an ircd:
|
||||||
// ACCTREGISTER <reqid> <origin> <kind> <account> <p2> :<p3>
|
// ACCTREGISTER <reqid> <origin> <kind> <account> <p2> :<p3>
|
||||||
|
|
@ -232,4 +237,14 @@ mod tests {
|
||||||
"{ev:?}"
|
"{ev:?}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FJOIN (channel create/burst) surfaces as ChannelCreate for the channel.
|
||||||
|
#[test]
|
||||||
|
fn parses_fjoin_as_channel_create() {
|
||||||
|
let ev = proto().parse(":0IR FJOIN #chan 1783845132 +tn :o,0IRAAAAAB:0");
|
||||||
|
assert!(
|
||||||
|
matches!(ev.as_slice(), [NetEvent::ChannelCreate { channel }] if channel == "#chan"),
|
||||||
|
"{ev:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ pub enum NetEvent {
|
||||||
Privmsg { from: String, to: String, text: String },
|
Privmsg { from: String, to: String, text: String },
|
||||||
UserConnect { uid: String, nick: String },
|
UserConnect { uid: String, nick: String },
|
||||||
NickChange { uid: String, nick: String },
|
NickChange { uid: String, nick: String },
|
||||||
|
// A channel was created or bursted (InspIRCd FJOIN). Subsequent single joins
|
||||||
|
// arrive as IJOIN and are not surfaced.
|
||||||
|
ChannelCreate { channel: String },
|
||||||
Quit { uid: String },
|
Quit { uid: String },
|
||||||
// An ircd relaying an IRCv3 account-registration request to us as the authority.
|
// An ircd relaying an IRCv3 account-registration request to us as the authority.
|
||||||
AccountRequest { reqid: String, origin: String, kind: String, account: String, p2: String, p3: String },
|
AccountRequest { reqid: String, origin: String, kind: String, account: String, p2: String, p3: String },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue