diff --git a/crates/projection-irc/src/handler.rs b/crates/projection-irc/src/handler.rs index 15a1e56..3d54626 100644 --- a/crates/projection-irc/src/handler.rs +++ b/crates/projection-irc/src/handler.rs @@ -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 -where - T: AsyncWrite + Unpin, -{ - fn handle(&self, arg: IrcConnection) -> impl Future>; +/// 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 Future>; } diff --git a/crates/projection-irc/src/lib.rs b/crates/projection-irc/src/lib.rs index 0dbfda0..080ee69 100644 --- a/crates/projection-irc/src/lib.rs +++ b/crates/projection-irc/src/lib.rs @@ -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 } => { diff --git a/crates/projection-irc/src/whois.rs b/crates/projection-irc/src/whois.rs index f48b90f..888ef0e 100644 --- a/crates/projection-irc/src/whois.rs +++ b/crates/projection-irc/src/whois.rs @@ -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 Handler 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 Handler 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? - { - IrcResponseMessage::empty_tags( - Some(server_name.clone()), - ErrNoSuchNick401::new(client.clone(), nick.clone()), - ) - .write_response(&mut writer) - .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(conn.server_name.clone()), + ErrNoSuchNick401::new(conn.client.clone(), nick.clone()), + ) + .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(()) } diff --git a/crates/proto-irc/src/client.rs b/crates/proto-irc/src/client.rs index ab83822..17e8376 100644 --- a/crates/proto-irc/src/client.rs +++ b/crates/proto-irc/src/client.rs @@ -43,9 +43,7 @@ pub enum ClientMessage { target: Recipient, // aka mask }, /// WHOIS [] - Whois { - arg: command_args::Whois, - }, + Whois(Whois), /// `TOPIC :` Topic { chan: Chan, @@ -71,15 +69,11 @@ 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, - } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Whois { + Nick(Str), + TargetNick(Str, Str), + EmptyArgs, } pub fn client_message(input: &str) -> Result { @@ -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));