fix: list channel members upon joining the correct way

sorry for the slight refactor :/
This commit is contained in:
user0-07161 2025-10-07 19:46:40 +02:00
parent 0c0e2b1cea
commit f6a48453be
9 changed files with 44 additions and 42 deletions

View file

@ -25,6 +25,7 @@ impl Channel {
pub async fn names_list_send( pub async fn names_list_send(
&self, &self,
user: User, user: User,
channel: &Channel,
writer: &mut BufWriter<TcpStream>, writer: &mut BufWriter<TcpStream>,
hostname: &str, hostname: &str,
) -> Result<(), SenderError> { ) -> Result<(), SenderError> {
@ -34,6 +35,13 @@ impl Channel {
members.push(member.nickname.unwrap()); members.push(member.nickname.unwrap());
} }
for member in channel.joined_users.clone() {
members.push(member.nickname.unwrap());
}
members.sort();
members.dedup();
IrcResponseCodes::NameReply IrcResponseCodes::NameReply
.into_irc_response( .into_irc_response(
user.nickname.clone().unwrap(), user.nickname.clone().unwrap(),

View file

@ -1,9 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
commands::{IrcAction, IrcHandler}, commands::{IrcAction, IrcHandler},
messages::Message,
user::User, user::User,
}; };
@ -16,7 +14,6 @@ impl IrcHandler for Cap {
_arguments: Vec<String>, _arguments: Vec<String>,
_authenticated: bool, _authenticated: bool,
_user_state: &mut User, _user_state: &mut User,
_sender: Sender<Message>,
) -> super::IrcAction { ) -> super::IrcAction {
IrcAction::DoNothing IrcAction::DoNothing
} }

View file

@ -1,11 +1,9 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
JOINED_CHANNELS, JOINED_CHANNELS,
channels::Channel, channels::Channel,
commands::{IrcAction, IrcHandler}, commands::{IrcAction, IrcHandler},
messages::{JoinMessage, Message},
user::User, user::User,
}; };
@ -18,7 +16,6 @@ impl IrcHandler for Join {
arguments: Vec<String>, arguments: Vec<String>,
authenticated: bool, authenticated: bool,
user_state: &mut User, user_state: &mut User,
sender: Sender<Message>,
) -> super::IrcAction { ) -> super::IrcAction {
let mut joined_channels = JOINED_CHANNELS.lock().await; let mut joined_channels = JOINED_CHANNELS.lock().await;
let mut channels = Vec::new(); let mut channels = Vec::new();
@ -56,14 +53,6 @@ impl IrcHandler for Join {
} }
} }
for channel in channels.clone() {
let join_message = JoinMessage {
sender: user_state.clone().unwrap_all(),
channel: channel.clone(),
};
sender.send(Message::JoinMessage(join_message)).unwrap();
}
IrcAction::JoinChannels(channels) IrcAction::JoinChannels(channels)
} }
} }

View file

@ -11,7 +11,7 @@ use crate::{
cap::Cap, join::Join, nick::Nick, ping::Ping, privmsg::PrivMsg, user::User as UserHandler, cap::Cap, join::Join, nick::Nick, ping::Ping, privmsg::PrivMsg, user::User as UserHandler,
}, },
error_structs::CommandExecError, error_structs::CommandExecError,
messages::Message, messages::{JoinMessage, Message},
sender::IrcResponse, sender::IrcResponse,
user::User, user::User,
}; };
@ -36,6 +36,7 @@ pub struct IrcMessage {
pub enum IrcAction { pub enum IrcAction {
SendText(IrcResponse), SendText(IrcResponse),
SendMessage(Message),
JoinChannels(Vec<Channel>), JoinChannels(Vec<Channel>),
ErrorAuthenticateFirst, ErrorAuthenticateFirst,
DoNothing, DoNothing,
@ -50,7 +51,6 @@ pub trait IrcHandler: Send + Sync {
command: Vec<String>, command: Vec<String>,
authenticated: bool, authenticated: bool,
user_state: &mut User, user_state: &mut User,
sender: Sender<Message>,
) -> IrcAction; ) -> IrcAction;
} }
@ -118,10 +118,11 @@ impl IrcCommand {
self.arguments.clone(), self.arguments.clone(),
user_state.is_populated(), user_state.is_populated(),
user_state, user_state,
broadcast_sender,
) )
.await; .await;
action.execute(writer, hostname, &user_state).await; action
.execute(writer, hostname, &user_state, broadcast_sender)
.await;
Ok(()) Ok(())
} }
@ -133,6 +134,7 @@ impl IrcAction {
writer: &mut BufWriter<TcpStream>, writer: &mut BufWriter<TcpStream>,
hostname: &str, hostname: &str,
user_state: &User, user_state: &User,
sender: Sender<Message>,
) { ) {
match self { match self {
IrcAction::SendText(msg) => { IrcAction::SendText(msg) => {
@ -141,18 +143,18 @@ impl IrcAction {
IrcAction::JoinChannels(channels) => { IrcAction::JoinChannels(channels) => {
for channel in channels { for channel in channels {
channel let join_message = JoinMessage {
.send_topic(user_state.clone(), writer, hostname) sender: user_state.clone().unwrap_all(),
.await channel: channel.clone(),
.unwrap(); };
sender.send(Message::JoinMessage(join_message)).unwrap();
channel
.names_list_send(user_state.clone(), writer, hostname)
.await
.unwrap();
} }
} }
IrcAction::SendMessage(msg) => {
sender.send(msg.clone()).unwrap();
}
_ => {} _ => {}
} }
} }

View file

@ -1,9 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
commands::{IrcAction, IrcHandler}, commands::{IrcAction, IrcHandler},
messages::Message,
user::User, user::User,
}; };
@ -16,7 +14,6 @@ impl IrcHandler for Nick {
command: Vec<String>, command: Vec<String>,
_authenticated: bool, _authenticated: bool,
user_state: &mut User, user_state: &mut User,
_sender: Sender<Message>,
) -> IrcAction { ) -> IrcAction {
user_state.nickname = Some(command[0].clone()); user_state.nickname = Some(command[0].clone());

View file

@ -1,9 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
commands::{IrcAction, IrcHandler}, commands::{IrcAction, IrcHandler},
messages::Message,
sender::IrcResponse, sender::IrcResponse,
user::User, user::User,
}; };
@ -17,7 +15,6 @@ impl IrcHandler for Ping {
command: Vec<String>, command: Vec<String>,
authenticated: bool, authenticated: bool,
user_state: &mut User, user_state: &mut User,
_sender: Sender<Message>,
) -> IrcAction { ) -> IrcAction {
if authenticated { if authenticated {
IrcAction::SendText(IrcResponse { IrcAction::SendText(IrcResponse {

View file

@ -1,5 +1,4 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
CONNECTED_USERS, CONNECTED_USERS,
@ -17,7 +16,6 @@ impl IrcHandler for PrivMsg {
command: Vec<String>, command: Vec<String>,
authenticated: bool, authenticated: bool,
user_state: &mut User, user_state: &mut User,
sender: Sender<Message>,
) -> IrcAction { ) -> IrcAction {
if !authenticated { if !authenticated {
return IrcAction::ErrorAuthenticateFirst; return IrcAction::ErrorAuthenticateFirst;
@ -32,9 +30,7 @@ impl IrcHandler for PrivMsg {
receiver: command[0].clone(), receiver: command[0].clone(),
text: command[1].clone(), text: command[1].clone(),
}; };
println!("SENDING: {message:#?}");
sender.send(Message::PrivMessage(message)).unwrap();
IrcAction::DoNothing IrcAction::SendMessage(Message::PrivMessage(message))
} }
} }

View file

@ -1,9 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use tokio::sync::broadcast::Sender;
use crate::{ use crate::{
commands::{IrcAction, IrcHandler}, commands::{IrcAction, IrcHandler},
messages::Message,
user::User as UserState, user::User as UserState,
}; };
@ -16,7 +14,6 @@ impl IrcHandler for User {
command: Vec<String>, command: Vec<String>,
_authenticated: bool, _authenticated: bool,
user_state: &mut UserState, user_state: &mut UserState,
_sender: Sender<Message>,
) -> IrcAction { ) -> IrcAction {
if command.len() < 4 { if command.len() < 4 {
return IrcAction::DoNothing; // XXX: return an error return IrcAction::DoNothing; // XXX: return an error

View file

@ -2,6 +2,7 @@ use std::{
collections::HashSet, collections::HashSet,
net::{SocketAddr, TcpListener, TcpStream}, net::{SocketAddr, TcpListener, TcpStream},
str::FromStr, str::FromStr,
time::Duration,
}; };
use anyhow::Error as AnyhowError; use anyhow::Error as AnyhowError;
@ -14,6 +15,7 @@ use tokio::{
Mutex, Mutex,
broadcast::{self, Receiver, Sender}, broadcast::{self, Receiver, Sender},
}, },
time::sleep,
}; };
use tracing::instrument; use tracing::instrument;
@ -96,6 +98,8 @@ async fn handle_connection(
let mut tcp_writer = TokioBufWriter::new(TokioTcpStream::from_std(stream)?); let mut tcp_writer = TokioBufWriter::new(TokioTcpStream::from_std(stream)?);
let mut state = User::default(); let mut state = User::default();
let hostname = info.server_hostname.clone();
loop { loop {
tokio::select! { tokio::select! {
result = tcp_listener(&stream_tcp, state.clone(), &info, &mut tcp_reader) => { result = tcp_listener(&stream_tcp, state.clone(), &info, &mut tcp_reader) => {
@ -109,7 +113,7 @@ async fn handle_connection(
} }
} }
}, },
result = message_listener(&state, &mut message_receiver, &mut tcp_writer) => { result = message_listener(&state, &mut message_receiver, &mut tcp_writer, &hostname) => {
match result { match result {
Ok(_) => {}, Ok(_) => {},
Err(err) => { Err(err) => {
@ -189,8 +193,11 @@ async fn message_listener(
user_wrapped: &User, user_wrapped: &User,
receiver: &mut Receiver<Message>, receiver: &mut Receiver<Message>,
writer: &mut TokioBufWriter<TokioTcpStream>, writer: &mut TokioBufWriter<TokioTcpStream>,
hostname: &str,
) -> Result<(), ListenerError> { ) -> Result<(), ListenerError> {
if !user_wrapped.is_populated() { if !user_wrapped.is_populated() {
sleep(Duration::from_millis(250)).await; // avoid immediately returns b'cuz they result in high
// cpu usage
return Err(ListenerError::UserIsUnidentified); return Err(ListenerError::UserIsUnidentified);
} }
@ -237,6 +244,8 @@ async fn message_listener(
Message::JoinMessage(message) => { Message::JoinMessage(message) => {
if message.channel.joined_users.contains(user_wrapped) || message.sender == user { if message.channel.joined_users.contains(user_wrapped) || message.sender == user {
let channel = message.channel.clone();
IrcResponse { IrcResponse {
sender: Some(message.sender.hostmask().clone()), sender: Some(message.sender.hostmask().clone()),
command: "JOIN".into(), command: "JOIN".into(),
@ -246,6 +255,16 @@ async fn message_listener(
} }
.send("", writer, true) .send("", writer, true)
.await?; .await?;
channel
.send_topic(user_wrapped.clone(), writer, hostname)
.await
.unwrap();
channel
.names_list_send(user_wrapped.clone(), &channel, writer, hostname)
.await
.unwrap();
} }
} }
} }