From 63f31aa42f8305488afc666eb0812904ae3e105d Mon Sep 17 00:00:00 2001 From: Nikita Vilunov Date: Thu, 16 Feb 2023 19:47:51 +0100 Subject: [PATCH] support who for global channels --- src/projections/irc/mod.rs | 70 ++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/src/projections/irc/mod.rs b/src/projections/irc/mod.rs index 544694f..bf5bac3 100644 --- a/src/projections/irc/mod.rs +++ b/src/projections/irc/mod.rs @@ -29,7 +29,7 @@ struct RegisteredUser { nickname: Vec, /** * Username is mostly unused in modern IRC. - * + * * [https://stackoverflow.com/questions/31666247/what-is-the-difference-between-the-nick-username-and-real-name-in-irc-and-wha] */ username: Vec, @@ -226,7 +226,7 @@ async fn handle_registered_socket<'a>( } else { len }; - handle_incoming_message(&buffer[0..len], &config, &user, &mut connection, writer).await?; + handle_incoming_message(&buffer[0..len], &config, &user, &rooms, &mut connection, writer).await?; buffer.clear(); }, update = connection.receiver.recv() => { @@ -328,6 +328,7 @@ async fn handle_incoming_message( buffer: &[u8], config: &ServerConfig, user: &RegisteredUser, + rooms: &RoomRegistry, user_handle: &mut PlayerConnection, writer: &mut (impl AsyncWrite + Unpin), ) -> Result<()> { @@ -397,16 +398,7 @@ async fn handle_incoming_message( ServerMessage { tags: vec![], sender: Some(config.server_name.as_bytes().to_vec()), - body: ServerMessageBody::N352WhoReply { - client: user.nickname.clone(), - username, - host, - server: config.server_name.as_bytes().to_vec(), - flags: AwayStatus::Here, - nickname: nick.clone(), - hops: 0, - realname: user.realname.clone(), - }, + body: user_to_who_msg(config, user, nick), } .write_async(writer) .await?; @@ -423,8 +415,35 @@ async fn handle_incoming_message( .await?; writer.flush().await?; } - Recipient::Chan(_) => { - log::warn!("WHO for chans not implemented") + Recipient::Chan(Chan::Global(chan)) => { + let room = rooms.get_room(&RoomId::from_bytes(chan.clone())?); + if let Some(room) = room { + let room_info = room.get_room_info().await; + for member in room_info.members { + ServerMessage { + tags: vec![], + sender: Some(config.server_name.as_bytes().to_vec()), + body: user_to_who_msg(config, user, member.as_bytes()), + } + .write_async(writer) + .await?; + } + } + ServerMessage { + tags: vec![], + sender: Some(config.server_name.as_bytes().to_vec()), + body: ServerMessageBody::N315EndOfWho { + client: user.nickname.clone(), + mask: target.clone(), + msg: b"End of WHO list".to_vec(), + }, + } + .write_async(writer) + .await?; + writer.flush().await?; + } + Recipient::Chan(Chan::Local(_)) => { + log::warn!("Local chans not supported"); } }, cmd => { @@ -438,6 +457,29 @@ async fn handle_incoming_message( Ok(()) } +fn user_to_who_msg(config: &ServerConfig, requestor: &RegisteredUser, target_user_nickname: &ByteVec) -> ServerMessageBody { + // Username is equal to nickname + let mut username = Vec::with_capacity(target_user_nickname.len() + 1); + username.push(b'~'); + username.extend_from_slice(target_user_nickname.as_slice()); + + // User's host is not public, replace it with `user/` pattern + let mut host = b"user/".to_vec(); + host.extend_from_slice(target_user_nickname.as_slice()); + + ServerMessageBody::N352WhoReply { + client: requestor.nickname.clone(), + username, + host, + server: config.server_name.as_bytes().to_vec(), + flags: AwayStatus::Here, + nickname: target_user_nickname.clone(), + hops: 0, + // TODO Realname is not available yet, should be matched to a future core's player field + realname: target_user_nickname.clone(), + } +} + async fn handle_join( config: &ServerConfig, user: &RegisteredUser,