From 3f29387fd57b56444a82272e53a656f7bdd164b6 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Mon, 29 Jan 2024 00:30:27 +0000 Subject: [PATCH] Implement admin command --- src/client.rs | 22 ++++++++++++++++------ src/messages.rs | 7 +++++++ src/server.rs | 18 +++++++++++++++--- src/server/response.rs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/client.rs b/src/client.rs index 90027f1..2518045 100644 --- a/src/client.rs +++ b/src/client.rs @@ -23,8 +23,9 @@ use crate::{ messages::{ Broadcast, ChannelFetchTopic, ChannelInvite, ChannelJoin, ChannelKickUser, ChannelList, ChannelMemberList, ChannelMessage, ChannelPart, ChannelSetMode, ChannelUpdateTopic, - FetchClientDetails, MessageKind, PrivateMessage, ServerDisconnect, ServerFetchMotd, - ServerListUsers, UserKickedFromChannel, UserNickChange, UserNickChangeInternal, + FetchClientDetails, MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect, + ServerFetchMotd, ServerListUsers, UserKickedFromChannel, UserNickChange, + UserNickChangeInternal, }, persistence::{ events::{ @@ -487,9 +488,7 @@ impl StreamHandler> for Client { span: Span::current(), }); } - Command::OPER(_, _) => {} Command::UserMODE(_, _) => {} - Command::SERVICE(_, _, _, _, _, _) => {} Command::QUIT(message) => { // set the user's leave reason and request a shutdown of the actor to close the // connection @@ -497,7 +496,6 @@ impl StreamHandler> for Client { self.server_leave_reason = message; ctx.stop(); } - Command::SQUIT(_, _) => {} Command::JOIN(channel_names, _passwords, _real_name) => { // split the list of channel names... let channels = parse_channel_name_list(&channel_names); @@ -706,7 +704,19 @@ impl StreamHandler> for Client { ), }); } - Command::ADMIN(_) => {} + Command::ADMIN(_) => { + let span = Span::current(); + let fut = self + .server + .send(ServerAdminInfo { span }) + .into_actor(self) + .map(|result, this, _ctx| { + for message in result.unwrap().into_messages(&this.connection.nick) { + this.writer.write(message); + } + }); + ctx.spawn(fut); + } Command::INFO(_) => {} Command::SERVLIST(_, _) => {} Command::SQUERY(_, _) => {} diff --git a/src/messages.rs b/src/messages.rs index 15a9d50..cd85bdc 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -122,6 +122,13 @@ pub struct ServerListUsers { pub span: Span, } +/// Returns the result of `ADMIN`. +#[derive(Message)] +#[rtype(result = "super::server::response::AdminInfo")] +pub struct ServerAdminInfo { + pub span: Span, +} + /// Sent from channels to users when a user is removed from the channel. #[derive(Message)] #[rtype(result = "()")] diff --git a/src/server.rs b/src/server.rs index f85993f..7926a48 100644 --- a/src/server.rs +++ b/src/server.rs @@ -21,11 +21,11 @@ use crate::{ connection::InitiatedConnection, messages::{ Broadcast, ChannelFetchTopic, ChannelJoin, ChannelList, ChannelMemberList, - FetchClientByNick, MessageKind, PrivateMessage, ServerDisconnect, ServerFetchMotd, - ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal, + FetchClientByNick, MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect, + ServerFetchMotd, ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal, }, persistence::Persistence, - server::response::{ListUsers, Motd}, + server::response::{AdminInfo, ListUsers, Motd}, SERVER_NAME, }; @@ -276,6 +276,18 @@ impl Handler for Server { } } +impl Handler for Server { + type Result = MessageResult; + + fn handle(&mut self, _msg: ServerAdminInfo, _ctx: &mut Self::Context) -> Self::Result { + MessageResult(AdminInfo { + line1: "Name: example name".to_string(), + line2: "Nickname: examplenick".to_string(), + email: "Email: me@example.com".to_string(), + }) + } +} + impl Handler for Server { type Result = (); diff --git a/src/server/response.rs b/src/server/response.rs index 07ec7ab..3960d46 100644 --- a/src/server/response.rs +++ b/src/server/response.rs @@ -2,6 +2,42 @@ use irc_proto::{Command, Message, Prefix, Response}; use crate::{server::Server, SERVER_NAME}; +pub struct AdminInfo { + pub line1: String, + pub line2: String, + pub email: String, +} + +impl AdminInfo { + #[must_use] + pub fn into_messages(self, for_user: &str) -> Vec { + macro_rules! msg { + ($response:ident, $($payload:expr),*) => { + + Message { + tags: None, + prefix: Some(Prefix::ServerName(SERVER_NAME.to_string())), + command: Command::Response( + Response::$response, + vec![for_user.to_string(), $($payload),*], + ), + } + }; + } + + vec![ + msg!( + RPL_ADMINME, + SERVER_NAME.to_string(), + "Administrative info".to_string() + ), + msg!(RPL_ADMINLOC1, self.line1), + msg!(RPL_ADMINLOC2, self.line2), + msg!(RPL_ADMINEMAIL, self.email), + ] + } +} + pub struct ListUsers { pub current_clients: usize, pub max_clients: usize,