support who for global channels

This commit is contained in:
Nikita Vilunov 2023-02-16 19:47:51 +01:00
parent 69bccef3bf
commit 63f31aa42f
1 changed files with 56 additions and 14 deletions

View File

@ -29,7 +29,7 @@ struct RegisteredUser {
nickname: Vec<u8>, nickname: Vec<u8>,
/** /**
* Username is mostly unused in modern IRC. * 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] * [https://stackoverflow.com/questions/31666247/what-is-the-difference-between-the-nick-username-and-real-name-in-irc-and-wha]
*/ */
username: Vec<u8>, username: Vec<u8>,
@ -226,7 +226,7 @@ async fn handle_registered_socket<'a>(
} else { } else {
len 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(); buffer.clear();
}, },
update = connection.receiver.recv() => { update = connection.receiver.recv() => {
@ -328,6 +328,7 @@ async fn handle_incoming_message(
buffer: &[u8], buffer: &[u8],
config: &ServerConfig, config: &ServerConfig,
user: &RegisteredUser, user: &RegisteredUser,
rooms: &RoomRegistry,
user_handle: &mut PlayerConnection, user_handle: &mut PlayerConnection,
writer: &mut (impl AsyncWrite + Unpin), writer: &mut (impl AsyncWrite + Unpin),
) -> Result<()> { ) -> Result<()> {
@ -397,16 +398,7 @@ async fn handle_incoming_message(
ServerMessage { ServerMessage {
tags: vec![], tags: vec![],
sender: Some(config.server_name.as_bytes().to_vec()), sender: Some(config.server_name.as_bytes().to_vec()),
body: ServerMessageBody::N352WhoReply { body: user_to_who_msg(config, user, nick),
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(),
},
} }
.write_async(writer) .write_async(writer)
.await?; .await?;
@ -423,8 +415,35 @@ async fn handle_incoming_message(
.await?; .await?;
writer.flush().await?; writer.flush().await?;
} }
Recipient::Chan(_) => { Recipient::Chan(Chan::Global(chan)) => {
log::warn!("WHO for chans not implemented") 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 => { cmd => {
@ -438,6 +457,29 @@ async fn handle_incoming_message(
Ok(()) 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/<nickname>` 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( async fn handle_join(
config: &ServerConfig, config: &ServerConfig,
user: &RegisteredUser, user: &RegisteredUser,