🏡 index : ~doyle/titanirc.git

author Jordan Doyle <jordan@doyle.la> 2024-01-29 3:03:03.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-29 3:03:03.0 +00:00:00
commit
253e47b477e83cc65e9d151602d695368a2d217f [patch]
tree
4e14ade727740bf4eeb5e64add3db627fc3542ae
parent
58da12f97a7bea6cc31ecf9715dc84f52fb5990f
download
253e47b477e83cc65e9d151602d695368a2d217f.tar.gz

Implement AWAY



Diff

 src/channel.rs  | 23 ++++++++++++++++++++--
 src/client.rs   | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/messages.rs |  9 +++++++++-
 src/server.rs   | 16 ++++++++++++---
 4 files changed, 102 insertions(+), 7 deletions(-)

diff --git a/src/channel.rs b/src/channel.rs
index b7da4cb..377443c 100644
--- a/src/channel.rs
+++ b/src/channel.rs
@@ -25,8 +25,8 @@ use crate::{
    messages::{
        Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelInvite, ChannelJoin,
        ChannelKickUser, ChannelMemberList, ChannelMessage, ChannelPart, ChannelSetMode,
        ChannelUpdateTopic, FetchClientByNick, FetchUserPermission, MessageKind, ServerDisconnect,
        UserKickedFromChannel, UserNickChange,
        ChannelUpdateTopic, ClientAway, FetchClientByNick, FetchUserPermission, MessageKind,
        ServerDisconnect, UserKickedFromChannel, UserNickChange,
    },
    persistence::{
        events::{FetchAllUserChannelPermissions, SetUserChannelPermissions},
@@ -115,6 +115,25 @@ impl Handler<Broadcast> for Channel {
    }
}

impl Handler<ClientAway> for Channel {
    type Result = ();

    #[instrument(parent = &msg.span, skip_all)]
    fn handle(&mut self, msg: ClientAway, ctx: &mut Self::Context) -> Self::Result {
        if let Some(c) = self.clients.get_mut(&msg.handle) {
            c.away = msg.message;
            ctx.notify(Broadcast {
                message: Message {
                    tags: None,
                    prefix: Some(c.to_nick()),
                    command: Command::AWAY(c.away.clone()),
                },
                span: msg.span,
            });
        }
    }
}

/// Fetches the user's permission for the current channel.
impl Handler<FetchUserPermission> for Channel {
    type Result = MessageResult<FetchUserPermission>;
diff --git a/src/client.rs b/src/client.rs
index 8eaecc0..f6163b6 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -23,7 +23,7 @@ use crate::{
    messages::{
        Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelInvite, ChannelJoin,
        ChannelKickUser, ChannelList, ChannelMemberList, ChannelMessage, ChannelPart,
        ChannelSetMode, ChannelUpdateTopic, ConnectedChannels, FetchClientDetails,
        ChannelSetMode, ChannelUpdateTopic, ClientAway, ConnectedChannels, FetchClientDetails,
        FetchUserPermission, FetchWhoList, FetchWhois, MessageKind, PrivateMessage,
        ServerAdminInfo, ServerDisconnect, ServerFetchMotd, ServerListUsers, UserKickedFromChannel,
        UserNickChange, UserNickChangeInternal,
@@ -283,6 +283,50 @@ impl Handler<FetchClientDetails> for Client {
    }
}

impl Handler<SetAway> for Client {
    type Result = ();

    #[instrument(parent = &msg.span, skip_all)]
    fn handle(&mut self, msg: SetAway, ctx: &mut Self::Context) -> Self::Result {
        self.connection.away = msg.msg.filter(|msg| !msg.is_empty());

        let broadcast = ClientAway {
            span: msg.span,
            handle: ctx.address(),
            message: self.connection.away.clone(),
        };

        self.server.do_send(broadcast.clone());
        for channel in self.channels.values() {
            channel.do_send(broadcast.clone());
        }

        let resp = if self.connection.away.is_some() {
            Command::Response(
                Response::RPL_NOWAWAY,
                vec![
                    self.connection.nick.to_string(),
                    "You have been marked as being away".to_string(),
                ],
            )
        } else {
            Command::Response(
                Response::RPL_UNAWAY,
                vec![
                    self.connection.nick.to_string(),
                    "You are no longer marked as being away".to_string(),
                ],
            )
        };

        self.writer.write(Message {
            tags: None,
            prefix: None,
            command: resp,
        });
    }
}

/// A self-message from the Client's [`StreamHandler`] implementation when the user
/// sends a join command out.
///
@@ -838,7 +882,12 @@ impl StreamHandler<Result<irc_proto::Message, ProtocolError>> for Client {
            Command::PONG(_, _) => {
                self.last_active = Instant::now();
            }
            Command::AWAY(_) => {}
            Command::AWAY(msg) => {
                ctx.notify(SetAway {
                    span: Span::current(),
                    msg,
                });
            }
            Command::REHASH => {}
            Command::DIE => {}
            Command::RESTART => {}
@@ -957,3 +1006,11 @@ struct JoinChannelRequest {
    channels: Vec<String>,
    span: Span,
}

/// A [`Client`] internal self-notification to set away status
#[derive(actix::Message, Debug)]
#[rtype(result = "()")]
struct SetAway {
    msg: Option<String>,
    span: Span,
}
diff --git a/src/messages.rs b/src/messages.rs
index 89b573f..33d7158 100644
--- a/src/messages.rs
+++ b/src/messages.rs
@@ -54,6 +54,15 @@ pub struct ConnectedChannels {
    pub span: Span,
}

/// Marks the client as being away (or not away, if `message` is none)
#[derive(Message, Clone)]
#[rtype(result = "()")]
pub struct ClientAway {
    pub span: Span,
    pub handle: Addr<Client>,
    pub message: Option<String>,
}

/// Fetches all the channels visible to the user.
#[derive(Message, Clone)]
#[rtype(result = "super::server::response::ChannelList")]
diff --git a/src/server.rs b/src/server.rs
index 3aa2cbb..7eaf60f 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -25,9 +25,9 @@ use crate::{
    connection::InitiatedConnection,
    messages::{
        Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelJoin, ChannelList,
        ChannelMemberList, ConnectedChannels, FetchClientByNick, FetchWhoList, FetchWhois,
        MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect, ServerFetchMotd,
        ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal,
        ChannelMemberList, ClientAway, ConnectedChannels, FetchClientByNick, FetchWhoList,
        FetchWhois, MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect,
        ServerFetchMotd, ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal,
    },
    persistence::Persistence,
    server::response::{AdminInfo, ListUsers, Motd, WhoList, Whois},
@@ -215,6 +215,16 @@ impl Handler<UserNickChange> for Server {
    }
}

impl Handler<ClientAway> for Server {
    type Result = ();

    fn handle(&mut self, msg: ClientAway, _ctx: &mut Self::Context) -> Self::Result {
        if let Some(c) = self.clients.get_mut(&msg.handle) {
            c.away = msg.message;
        }
    }
}

/// Fetches a client's handle by their nick
impl Handler<FetchClientByNick> for Server {
    type Result = MessageResult<FetchClientByNick>;