forked from lavina/lavina
implement WHO irc command for queries on self
This commit is contained in:
parent
30db029390
commit
81ee1c1044
|
@ -79,7 +79,12 @@ impl PlayerConnection {
|
|||
|
||||
pub async fn leave_room(&mut self, room_id: RoomId) -> Result<()> {
|
||||
let (promise, deferred) = oneshot();
|
||||
self.player_handle.send(PlayerCommand::Cmd(Cmd::LeaveRoom { room_id, promise }, self.connection_id.clone())).await;
|
||||
self.player_handle
|
||||
.send(PlayerCommand::Cmd(
|
||||
Cmd::LeaveRoom { room_id, promise },
|
||||
self.connection_id.clone(),
|
||||
))
|
||||
.await;
|
||||
Ok(deferred.await?)
|
||||
}
|
||||
|
||||
|
@ -346,7 +351,8 @@ impl Player {
|
|||
}
|
||||
promise.send(());
|
||||
let update = Updates::RoomLeft {
|
||||
room_id, former_member_id: self.player_id.clone(),
|
||||
room_id,
|
||||
former_member_id: self.player_id.clone(),
|
||||
};
|
||||
self.broadcast_update(update, connection_id).await;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::core::player::{PlayerConnection, PlayerId, PlayerRegistry, Updates};
|
|||
use crate::core::room::{RoomId, RoomInfo, RoomRegistry};
|
||||
use crate::prelude::*;
|
||||
use crate::protos::irc::client::{client_message, ClientMessage};
|
||||
use crate::protos::irc::server::{ServerMessage, ServerMessageBody};
|
||||
use crate::protos::irc::server::{AwayStatus, ServerMessage, ServerMessageBody};
|
||||
use crate::protos::irc::{Chan, Recipient};
|
||||
use crate::util::Terminator;
|
||||
|
||||
|
@ -244,10 +244,13 @@ async fn handle_update(
|
|||
player_id: &PlayerId,
|
||||
writer: &mut (impl AsyncWrite + Unpin),
|
||||
rooms: &RoomRegistry,
|
||||
update: Updates
|
||||
update: Updates,
|
||||
) -> Result<()> {
|
||||
match update {
|
||||
Updates::RoomJoined { new_member_id, room_id } => {
|
||||
Updates::RoomJoined {
|
||||
new_member_id,
|
||||
room_id,
|
||||
} => {
|
||||
if player_id == &new_member_id {
|
||||
if let Some(room) = rooms.get_room(&room_id) {
|
||||
let room_info = room.get_room_info().await;
|
||||
|
@ -262,26 +265,42 @@ async fn handle_update(
|
|||
tags: vec![],
|
||||
sender: Some(new_member_id.as_bytes().clone()),
|
||||
body: ServerMessageBody::Join(Chan::Global(room_id.as_bytes().clone())),
|
||||
}.write_async(writer).await?;
|
||||
}
|
||||
.write_async(writer)
|
||||
.await?;
|
||||
writer.flush().await?
|
||||
}
|
||||
},
|
||||
Updates::RoomLeft { room_id, former_member_id } => {
|
||||
}
|
||||
Updates::RoomLeft {
|
||||
room_id,
|
||||
former_member_id,
|
||||
} => {
|
||||
ServerMessage {
|
||||
tags: vec![],
|
||||
sender: Some(former_member_id.as_bytes().clone()),
|
||||
body: ServerMessageBody::Part(Chan::Global(room_id.as_bytes().clone())),
|
||||
}.write_async(writer).await?;
|
||||
}
|
||||
.write_async(writer)
|
||||
.await?;
|
||||
writer.flush().await?
|
||||
},
|
||||
Updates::NewMessage { author_id, room_id, body } => {
|
||||
}
|
||||
Updates::NewMessage {
|
||||
author_id,
|
||||
room_id,
|
||||
body,
|
||||
} => {
|
||||
ServerMessage {
|
||||
tags: vec![],
|
||||
sender: Some(author_id.as_bytes().clone()),
|
||||
body: ServerMessageBody::PrivateMessage { target: Recipient::Chan(Chan::Global(room_id.as_bytes().clone())), body: body.as_bytes().to_vec() }
|
||||
}.write_async(writer).await?;
|
||||
writer.flush().await?
|
||||
body: ServerMessageBody::PrivateMessage {
|
||||
target: Recipient::Chan(Chan::Global(room_id.as_bytes().clone())),
|
||||
body: body.as_bytes().to_vec(),
|
||||
},
|
||||
}
|
||||
.write_async(writer)
|
||||
.await?;
|
||||
writer.flush().await?
|
||||
}
|
||||
Updates::RoomTopicChanged { room_id, new_topic } => {
|
||||
ServerMessage {
|
||||
tags: vec![],
|
||||
|
@ -291,9 +310,11 @@ async fn handle_update(
|
|||
chat: Chan::Global(room_id.as_bytes().clone()),
|
||||
topic: new_topic,
|
||||
},
|
||||
}.write_async(writer).await?;
|
||||
}
|
||||
.write_async(writer)
|
||||
.await?;
|
||||
writer.flush().await?
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -360,6 +381,46 @@ async fn handle_incoming_message(
|
|||
Chan::Local(_) => {}
|
||||
};
|
||||
}
|
||||
ClientMessage::Who { target } => match &target {
|
||||
Recipient::Nick(nick) => {
|
||||
if nick == &user.nickname {
|
||||
let mut username = Vec::with_capacity(user.username.len() + 1);
|
||||
username.push(b'~');
|
||||
username.extend_from_slice(user.username.as_slice());
|
||||
ServerMessage {
|
||||
tags: vec![],
|
||||
sender: Some(config.server_name.as_bytes().to_vec()),
|
||||
body: ServerMessageBody::N352WhoReply {
|
||||
client: user.nickname.clone(),
|
||||
username,
|
||||
host: b"*".to_vec(), // TODO need to decide what to send as user's host
|
||||
server: config.server_name.as_bytes().to_vec(),
|
||||
flags: AwayStatus::Here,
|
||||
hops: 0,
|
||||
realname: user.realname.clone(),
|
||||
},
|
||||
}
|
||||
.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?;
|
||||
}
|
||||
log::warn!("WHO for other users is not implemented")
|
||||
}
|
||||
Recipient::Chan(_) => {
|
||||
log::warn!("WHO for chans not implemented")
|
||||
}
|
||||
},
|
||||
cmd => {
|
||||
log::warn!("Not implemented handler for client command: {cmd:?}");
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ pub enum ClientMessage {
|
|||
/// MODE <target>
|
||||
Mode(Chan), // TODO support not only chan
|
||||
/// WHO <target>
|
||||
Who(Chan), // TODO support not only chan
|
||||
Who {
|
||||
target: Recipient, // aka mask
|
||||
},
|
||||
/// TOPIC <chan> :<topic>
|
||||
Topic {
|
||||
chan: Chan,
|
||||
|
@ -144,9 +146,9 @@ fn client_message_mode(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
|||
|
||||
fn client_message_who(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||
let (input, _) = tag("WHO ")(input)?;
|
||||
let (input, chan) = chan(input)?;
|
||||
let (input, target) = recipient(input)?;
|
||||
|
||||
Ok((input, ClientMessage::Who(chan)))
|
||||
Ok((input, ClientMessage::Who { target }))
|
||||
}
|
||||
|
||||
fn client_message_topic(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||
|
|
|
@ -83,11 +83,32 @@ pub enum ServerMessageBody {
|
|||
client: ByteVec,
|
||||
params: ByteVec, // TODO make this a datatype
|
||||
},
|
||||
/// Final reply to a client's [Who](crate::protos::irc::client::ClientMessage::Who) request.
|
||||
N315EndOfWho {
|
||||
client: ByteVec,
|
||||
mask: Recipient,
|
||||
/// Usually `b"End of WHO list"`
|
||||
msg: ByteVec,
|
||||
},
|
||||
N332Topic {
|
||||
client: ByteVec,
|
||||
chat: Chan,
|
||||
topic: ByteVec,
|
||||
},
|
||||
/// A reply to a client's [Who](crate::protos::irc::client::ClientMessage::Who) request.
|
||||
N352WhoReply {
|
||||
client: ByteVec,
|
||||
// chan = *
|
||||
username: ByteVec,
|
||||
/// User's hostname
|
||||
host: ByteVec,
|
||||
/// Hostname of the server the user is connected to
|
||||
server: ByteVec,
|
||||
/// Flags
|
||||
flags: AwayStatus,
|
||||
hops: u8,
|
||||
realname: ByteVec,
|
||||
},
|
||||
N353NamesReply {
|
||||
client: ByteVec,
|
||||
chan: Chan,
|
||||
|
@ -177,6 +198,14 @@ impl ServerMessageBody {
|
|||
writer.write_all(¶ms).await?;
|
||||
writer.write_all(b" :are supported by this server").await?;
|
||||
}
|
||||
ServerMessageBody::N315EndOfWho { client, mask, msg } => {
|
||||
writer.write_all(b"315 ").await?;
|
||||
writer.write_all(&client).await?;
|
||||
writer.write_all(b" ").await?;
|
||||
mask.write_async(writer).await?;
|
||||
writer.write_all(b" :").await?;
|
||||
writer.write_all(&msg).await?;
|
||||
}
|
||||
ServerMessageBody::N332Topic {
|
||||
client,
|
||||
chat,
|
||||
|
@ -189,6 +218,33 @@ impl ServerMessageBody {
|
|||
writer.write_all(b" :").await?;
|
||||
writer.write_all(&topic).await?;
|
||||
}
|
||||
ServerMessageBody::N352WhoReply {
|
||||
client,
|
||||
username,
|
||||
host,
|
||||
server,
|
||||
flags,
|
||||
hops,
|
||||
realname,
|
||||
} => {
|
||||
writer.write_all(b"352 ").await?;
|
||||
writer.write_all(&client).await?;
|
||||
writer.write_all(b" * ").await?;
|
||||
writer.write_all(&username).await?;
|
||||
writer.write_all(b" ").await?;
|
||||
writer.write_all(&host).await?;
|
||||
writer.write_all(b" ").await?;
|
||||
writer.write_all(&server).await?;
|
||||
writer.write_all(b" ").await?;
|
||||
match flags {
|
||||
AwayStatus::Here => writer.write_all(b"H").await?,
|
||||
AwayStatus::Gone => writer.write_all(b"G").await?,
|
||||
}
|
||||
writer.write_all(b" :").await?;
|
||||
writer.write_all(hops.to_string().as_bytes()).await?;
|
||||
writer.write_all(b" ").await?;
|
||||
writer.write_all(&realname).await?;
|
||||
}
|
||||
ServerMessageBody::N353NamesReply {
|
||||
client,
|
||||
chan,
|
||||
|
@ -213,6 +269,12 @@ impl ServerMessageBody {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum AwayStatus {
|
||||
Here,
|
||||
Gone,
|
||||
}
|
||||
|
||||
fn server_message_body(input: &[u8]) -> IResult<&[u8], ServerMessageBody> {
|
||||
alt((
|
||||
server_message_body_notice,
|
||||
|
|
Loading…
Reference in New Issue