🏡 index : ~doyle/titanirc.git

author Jordan Doyle <jordan@doyle.la> 2024-01-29 0:30:27.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-29 0:30:27.0 +00:00:00
commit
3f29387fd57b56444a82272e53a656f7bdd164b6 [patch]
tree
0df39f4e7ab333ce0d1c549329d1a9ac1a1832ae
parent
26f9b995091690eb9c9fd242ccd829632c1e74cd
download
3f29387fd57b56444a82272e53a656f7bdd164b6.tar.gz

Implement admin command



Diff

 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<Result<irc_proto::Message, ProtocolError>> 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<Result<irc_proto::Message, ProtocolError>> 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<Result<irc_proto::Message, ProtocolError>> 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<ServerListUsers> for Server {
    }
}

impl Handler<ServerAdminInfo> for Server {
    type Result = MessageResult<ServerAdminInfo>;

    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<PrivateMessage> 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<Message> {
        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,