irc: rename Handler to IrcCommand and its method to handle_with

This commit is contained in:
Nikita Vilunov 2024-06-05 02:39:11 +02:00
parent 59528909c7
commit a22cde0ea8
4 changed files with 61 additions and 112 deletions

View File

@ -1,5 +1,6 @@
use std::future::Future;
use anyhow::Result;
use tokio::io::AsyncWrite;
use lavina_core::player::PlayerConnection;
@ -13,9 +14,7 @@ pub struct IrcConnection<'a, T: AsyncWrite + Unpin> {
pub player_connection: &'a mut PlayerConnection,
}
pub trait Handler<T>
where
T: AsyncWrite + Unpin,
{
fn handle(&self, arg: IrcConnection<T>) -> impl Future<Output = anyhow::Result<()>>;
/// Represents a client-to-server IRC message that can be handled by the server.
pub trait IrcCommand {
fn handle_with(&self, conn: &mut IrcConnection<impl AsyncWrite + Unpin>) -> impl Future<Output = Result<()>>;
}

View File

@ -30,7 +30,7 @@ use sasl::AuthBody;
mod cap;
use handler::Handler;
use handler::{IrcCommand, IrcConnection};
mod whois;
@ -826,15 +826,14 @@ async fn handle_incoming_message(
log::warn!("Local chans not supported");
}
},
ClientMessage::Whois { arg } => {
arg.handle(handler::IrcConnection {
ClientMessage::Whois(cmd) => {
let mut conn = IrcConnection {
server_name: config.server_name.clone(),
client: user.nickname.clone(),
writer,
player_connection: user_handle,
})
.await?;
};
cmd.handle_with(&mut conn).await?;
writer.flush().await?;
}
ClientMessage::Mode { target } => {

View File

@ -1,35 +1,27 @@
use lavina_core::{
player::{GetInfoResult, PlayerId},
prelude::Str,
};
use proto_irc::{
client::command_args::Whois,
commands::whois::{
error::{ErrNoNicknameGiven431, ErrNoSuchNick401},
response::RplEndOfWhois318,
},
response::{IrcResponseMessage, WriteResponse},
};
use anyhow::Result;
use tokio::io::AsyncWrite;
use crate::handler::{Handler, IrcConnection};
use crate::handler::{IrcCommand, IrcConnection};
use lavina_core::player::GetInfoResult;
use lavina_core::player::PlayerId;
use lavina_core::prelude::Str;
use proto_irc::client::Whois;
use proto_irc::commands::whois::error::{ErrNoNicknameGiven431, ErrNoSuchNick401};
use proto_irc::commands::whois::response::RplEndOfWhois318;
use proto_irc::response::IrcResponseMessage;
use proto_irc::response::WriteResponse;
impl<T: AsyncWrite + Unpin> Handler<T> for Whois {
async fn handle(&self, body: IrcConnection<'_, T>) -> anyhow::Result<()> {
impl IrcCommand for Whois {
async fn handle_with(&self, conn: &mut IrcConnection<'_, impl AsyncWrite + Unpin>) -> Result<()> {
match self {
Whois::Nick(nick) => handle_nick_target(nick.clone(), body).await?,
Whois::TargetNick(_, nick) => handle_nick_target(nick.clone(), body).await?,
Whois::Nick(nick) => handle_nick_target(nick.clone(), conn).await?,
Whois::TargetNick(_, nick) => handle_nick_target(nick.clone(), conn).await?,
Whois::EmptyArgs => {
let IrcConnection {
server_name,
mut writer,
..
} = body;
IrcResponseMessage::empty_tags(
Some(server_name.clone()),
ErrNoNicknameGiven431::new(server_name.clone()),
Some(conn.server_name.clone()),
ErrNoNicknameGiven431::new(conn.server_name.clone()),
)
.write_response(&mut writer)
.write_response(conn.writer)
.await?
}
}
@ -37,31 +29,23 @@ impl<T: AsyncWrite + Unpin> Handler<T> for Whois {
}
}
async fn handle_nick_target(nick: Str, body: IrcConnection<'_, impl AsyncWrite + Unpin>) -> anyhow::Result<()> {
let IrcConnection {
server_name,
mut writer,
client,
player_connection,
} = body;
if let GetInfoResult::UserDoesntExist =
player_connection.check_user_existence(PlayerId::from(nick.clone())?).await?
{
async fn handle_nick_target(nick: Str, conn: &mut IrcConnection<'_, impl AsyncWrite + Unpin>) -> Result<()> {
match conn.player_connection.check_user_existence(PlayerId::from(nick.clone())?).await? {
GetInfoResult::UserExists => {}
GetInfoResult::UserDoesntExist => {
IrcResponseMessage::empty_tags(
Some(server_name.clone()),
ErrNoSuchNick401::new(client.clone(), nick.clone()),
Some(conn.server_name.clone()),
ErrNoSuchNick401::new(conn.client.clone(), nick.clone()),
)
.write_response(&mut writer)
.write_response(conn.writer)
.await?
}
}
IrcResponseMessage::empty_tags(
Some(server_name.clone()),
RplEndOfWhois318::new(client.clone(), nick.clone()),
Some(conn.server_name.clone()),
RplEndOfWhois318::new(conn.client.clone(), nick.clone()),
)
.write_response(&mut writer)
.write_response(conn.writer)
.await?;
Ok(())
}

View File

@ -43,9 +43,7 @@ pub enum ClientMessage {
target: Recipient, // aka mask
},
/// WHOIS [<target>] <nick>
Whois {
arg: command_args::Whois,
},
Whois(Whois),
/// `TOPIC <chan> :<topic>`
Topic {
chan: Chan,
@ -71,16 +69,12 @@ pub enum ClientMessage {
},
}
pub mod command_args {
use crate::prelude::Str;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Whois {
Nick(Str),
TargetNick(Str, Str),
EmptyArgs,
}
}
pub fn client_message(input: &str) -> Result<ClientMessage> {
let res = all_consuming(alt((
@ -204,24 +198,9 @@ fn client_message_whois(input: &str) -> IResult<&str, ClientMessage> {
let (input, _) = tag("WHOIS ")(input)?;
let args: Vec<_> = input.split_whitespace().collect();
match args.as_slice()[..] {
[nick] => Ok((
"",
ClientMessage::Whois {
arg: command_args::Whois::Nick(nick.into()),
},
)),
[target, nick, ..] => Ok((
"",
ClientMessage::Whois {
arg: command_args::Whois::TargetNick(target.into(), nick.into()),
},
)),
[] => Ok((
"",
ClientMessage::Whois {
arg: command_args::Whois::EmptyArgs,
},
)),
[nick] => Ok(("", ClientMessage::Whois(Whois::Nick(nick.into())))),
[target, nick, ..] => Ok(("", ClientMessage::Whois(Whois::TargetNick(target.into(), nick.into())))),
[] => Ok(("", ClientMessage::Whois(Whois::EmptyArgs))),
}
}
@ -448,35 +427,23 @@ mod test {
let res_more_than_two_params = client_message(test_more_than_two_params);
let res_none_none_params = client_message(test_none_none_params);
let expected_arg = ClientMessage::Whois {
arg: command_args::Whois::Nick("val".into()),
};
let expected_user_user = ClientMessage::Whois {
arg: command_args::Whois::TargetNick("val".into(), "val".into()),
};
let expected_arg = ClientMessage::Whois(Whois::Nick("val".into()));
let expected_user_user = ClientMessage::Whois(Whois::TargetNick("val".into(), "val".into()));
let expected_server_user = ClientMessage::Whois {
arg: command_args::Whois::TargetNick("com.test.server".into(), "user".into()),
};
let expected_server_user = ClientMessage::Whois(Whois::TargetNick("com.test.server".into(), "user".into()));
let expected_user_server = ClientMessage::Whois {
arg: command_args::Whois::TargetNick("user".into(), "com.test.server".into()),
};
let expected_user_server = ClientMessage::Whois(Whois::TargetNick("user".into(), "com.test.server".into()));
let expected_user_list = ClientMessage::Whois {
arg: command_args::Whois::Nick("user_1,user_2,user_3".into()),
};
let expected_server_user_list = ClientMessage::Whois {
arg: command_args::Whois::TargetNick("com.test.server".into(), "user_1,user_2,user_3".into()),
};
let expected_user_list = ClientMessage::Whois(Whois::Nick("user_1,user_2,user_3".into()));
let expected_server_user_list = ClientMessage::Whois(Whois::TargetNick(
"com.test.server".into(),
"user_1,user_2,user_3".into(),
));
let expected_more_than_two_params = ClientMessage::Whois {
arg: command_args::Whois::TargetNick("test.server".into(), "user_1,user_2,user_3".into()),
};
let expected_more_than_two_params =
ClientMessage::Whois(Whois::TargetNick("test.server".into(), "user_1,user_2,user_3".into()));
let expected_none_none_params = ClientMessage::Whois {
arg: command_args::Whois::EmptyArgs,
};
let expected_none_none_params = ClientMessage::Whois(Whois::EmptyArgs);
assert_matches!(res_one_arg, Ok(result) => assert_eq!(expected_arg, result));
assert_matches!(res_user_user, Ok(result) => assert_eq!(expected_user_user, result));