From 400f9b14da4eafbd961d5a4047f27a3f4fd92f32 Mon Sep 17 00:00:00 2001 From: user0-07161 Date: Mon, 16 Feb 2026 12:24:38 +0100 Subject: [PATCH] feat: implement NAMES --- src/client/commands/mod.rs | 11 +++++++++++ src/client/commands/names.rs | 37 ++++++++++++++++++++++++++++++++++++ src/user.rs | 14 +++++++++++++- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/client/commands/names.rs diff --git a/src/client/commands/mod.rs b/src/client/commands/mod.rs index ad783bb..c0859e8 100644 --- a/src/client/commands/mod.rs +++ b/src/client/commands/mod.rs @@ -12,6 +12,7 @@ use super::commands::{ use crate::{ SENDER, channels::Channel, + client::commands::names::Names, config::ServerInfo, error_structs::CommandExecError, messages::{ChanJoinMessage, Message}, @@ -21,6 +22,7 @@ use crate::{ mod cap; mod join; +mod names; mod nick; mod pass; mod ping; @@ -45,6 +47,7 @@ pub enum ClientAction { JoinChannels(Vec), UpgradeToServerConn, ErrorAuthenticateFirst, + ListNames(Channel), DoNothing, } @@ -126,6 +129,7 @@ impl ClientCommand { command_map.insert("JOIN".to_owned(), &Join); command_map.insert("WHO".to_owned(), &Who); command_map.insert("PASS".to_owned(), &Pass); + command_map.insert("NAMES".to_owned(), &Names); debug!("executing IrcCommand: {self:?}"); @@ -190,6 +194,13 @@ impl ClientAction { return ReturnAction::ServerConn; } + ClientAction::ListNames(channel) => { + channel + .names_list_send(user_state.clone().unwrap_all(), channel, writer, hostname) + .await + .unwrap(); + } + _ => {} } diff --git a/src/client/commands/names.rs b/src/client/commands/names.rs new file mode 100644 index 0000000..f39e39c --- /dev/null +++ b/src/client/commands/names.rs @@ -0,0 +1,37 @@ +use async_trait::async_trait; + +use super::{ClientAction, ClientHandler}; +use crate::{JOINED_CHANNELS, user::User}; + +pub struct Names; + +#[async_trait] +impl ClientHandler for Names { + async fn handle( + &self, + arguments: Vec, + _authenticated: bool, + _user_state: &mut User, + _server_outgoing_password: String, + _server_incoming_passwords: Vec, + _user_passwords: Vec, + ) -> Vec { + let mut actions = Vec::new(); + + let channels_lock = JOINED_CHANNELS.lock().await; + let channel_names = arguments[0] + .split(',') + .map(|x| x.to_owned()) + .collect::>(); + + for channel in channel_names { + for channel_lock in channels_lock.iter() { + if channel == channel_lock.name { + actions.push(super::ClientAction::ListNames(channel_lock.clone())); + } + } + } + + actions + } +} diff --git a/src/user.rs b/src/user.rs index ad1ec22..5140538 100644 --- a/src/user.rs +++ b/src/user.rs @@ -21,7 +21,7 @@ pub struct User { // pub hostname: Option, } -#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] +#[derive(Clone, Debug, Hash, PartialOrd, Ord)] pub struct UserUnwrapped { pub nickname: String, pub username: String, @@ -35,6 +35,18 @@ pub struct UserUnwrapped { // pub hostname: Option, } +impl PartialEq for UserUnwrapped { + fn eq(&self, other: &Self) -> bool { + self.nickname == other.nickname && self.username == other.username + } + + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +impl Eq for UserUnwrapped {} + impl User { pub fn is_populated_without_uid(&self) -> bool { self.realname.is_some() && self.username.is_some() && self.nickname.is_some()