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<()> {
|
pub async fn leave_room(&mut self, room_id: RoomId) -> Result<()> {
|
||||||
let (promise, deferred) = oneshot();
|
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?)
|
Ok(deferred.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +351,8 @@ impl Player {
|
||||||
}
|
}
|
||||||
promise.send(());
|
promise.send(());
|
||||||
let update = Updates::RoomLeft {
|
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;
|
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::core::room::{RoomId, RoomInfo, RoomRegistry};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::protos::irc::client::{client_message, ClientMessage};
|
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::protos::irc::{Chan, Recipient};
|
||||||
use crate::util::Terminator;
|
use crate::util::Terminator;
|
||||||
|
|
||||||
|
@ -244,10 +244,13 @@ async fn handle_update(
|
||||||
player_id: &PlayerId,
|
player_id: &PlayerId,
|
||||||
writer: &mut (impl AsyncWrite + Unpin),
|
writer: &mut (impl AsyncWrite + Unpin),
|
||||||
rooms: &RoomRegistry,
|
rooms: &RoomRegistry,
|
||||||
update: Updates
|
update: Updates,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match update {
|
match update {
|
||||||
Updates::RoomJoined { new_member_id, room_id } => {
|
Updates::RoomJoined {
|
||||||
|
new_member_id,
|
||||||
|
room_id,
|
||||||
|
} => {
|
||||||
if player_id == &new_member_id {
|
if player_id == &new_member_id {
|
||||||
if let Some(room) = rooms.get_room(&room_id) {
|
if let Some(room) = rooms.get_room(&room_id) {
|
||||||
let room_info = room.get_room_info().await;
|
let room_info = room.get_room_info().await;
|
||||||
|
@ -262,26 +265,42 @@ async fn handle_update(
|
||||||
tags: vec![],
|
tags: vec![],
|
||||||
sender: Some(new_member_id.as_bytes().clone()),
|
sender: Some(new_member_id.as_bytes().clone()),
|
||||||
body: ServerMessageBody::Join(Chan::Global(room_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?
|
writer.flush().await?
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Updates::RoomLeft { room_id, former_member_id } => {
|
Updates::RoomLeft {
|
||||||
|
room_id,
|
||||||
|
former_member_id,
|
||||||
|
} => {
|
||||||
ServerMessage {
|
ServerMessage {
|
||||||
tags: vec![],
|
tags: vec![],
|
||||||
sender: Some(former_member_id.as_bytes().clone()),
|
sender: Some(former_member_id.as_bytes().clone()),
|
||||||
body: ServerMessageBody::Part(Chan::Global(room_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?
|
writer.flush().await?
|
||||||
},
|
}
|
||||||
Updates::NewMessage { author_id, room_id, body } => {
|
Updates::NewMessage {
|
||||||
|
author_id,
|
||||||
|
room_id,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
ServerMessage {
|
ServerMessage {
|
||||||
tags: vec![],
|
tags: vec![],
|
||||||
sender: Some(author_id.as_bytes().clone()),
|
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() }
|
body: ServerMessageBody::PrivateMessage {
|
||||||
}.write_async(writer).await?;
|
target: Recipient::Chan(Chan::Global(room_id.as_bytes().clone())),
|
||||||
|
body: body.as_bytes().to_vec(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
.write_async(writer)
|
||||||
|
.await?;
|
||||||
writer.flush().await?
|
writer.flush().await?
|
||||||
},
|
}
|
||||||
Updates::RoomTopicChanged { room_id, new_topic } => {
|
Updates::RoomTopicChanged { room_id, new_topic } => {
|
||||||
ServerMessage {
|
ServerMessage {
|
||||||
tags: vec![],
|
tags: vec![],
|
||||||
|
@ -291,9 +310,11 @@ async fn handle_update(
|
||||||
chat: Chan::Global(room_id.as_bytes().clone()),
|
chat: Chan::Global(room_id.as_bytes().clone()),
|
||||||
topic: new_topic,
|
topic: new_topic,
|
||||||
},
|
},
|
||||||
}.write_async(writer).await?;
|
}
|
||||||
|
.write_async(writer)
|
||||||
|
.await?;
|
||||||
writer.flush().await?
|
writer.flush().await?
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -360,6 +381,46 @@ async fn handle_incoming_message(
|
||||||
Chan::Local(_) => {}
|
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 => {
|
cmd => {
|
||||||
log::warn!("Not implemented handler for client command: {cmd:?}");
|
log::warn!("Not implemented handler for client command: {cmd:?}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ pub enum ClientMessage {
|
||||||
/// MODE <target>
|
/// MODE <target>
|
||||||
Mode(Chan), // TODO support not only chan
|
Mode(Chan), // TODO support not only chan
|
||||||
/// WHO <target>
|
/// WHO <target>
|
||||||
Who(Chan), // TODO support not only chan
|
Who {
|
||||||
|
target: Recipient, // aka mask
|
||||||
|
},
|
||||||
/// TOPIC <chan> :<topic>
|
/// TOPIC <chan> :<topic>
|
||||||
Topic {
|
Topic {
|
||||||
chan: Chan,
|
chan: Chan,
|
||||||
|
@ -144,9 +146,9 @@ fn client_message_mode(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
|
||||||
fn client_message_who(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
fn client_message_who(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
let (input, _) = tag("WHO ")(input)?;
|
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> {
|
fn client_message_topic(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
|
|
@ -83,11 +83,32 @@ pub enum ServerMessageBody {
|
||||||
client: ByteVec,
|
client: ByteVec,
|
||||||
params: ByteVec, // TODO make this a datatype
|
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 {
|
N332Topic {
|
||||||
client: ByteVec,
|
client: ByteVec,
|
||||||
chat: Chan,
|
chat: Chan,
|
||||||
topic: ByteVec,
|
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 {
|
N353NamesReply {
|
||||||
client: ByteVec,
|
client: ByteVec,
|
||||||
chan: Chan,
|
chan: Chan,
|
||||||
|
@ -177,6 +198,14 @@ impl ServerMessageBody {
|
||||||
writer.write_all(¶ms).await?;
|
writer.write_all(¶ms).await?;
|
||||||
writer.write_all(b" :are supported by this server").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 {
|
ServerMessageBody::N332Topic {
|
||||||
client,
|
client,
|
||||||
chat,
|
chat,
|
||||||
|
@ -189,6 +218,33 @@ impl ServerMessageBody {
|
||||||
writer.write_all(b" :").await?;
|
writer.write_all(b" :").await?;
|
||||||
writer.write_all(&topic).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 {
|
ServerMessageBody::N353NamesReply {
|
||||||
client,
|
client,
|
||||||
chan,
|
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> {
|
fn server_message_body(input: &[u8]) -> IResult<&[u8], ServerMessageBody> {
|
||||||
alt((
|
alt((
|
||||||
server_message_body_notice,
|
server_message_body_notice,
|
||||||
|
|
Loading…
Reference in New Issue