fix: list channel members upon joining the correct way
sorry for the slight refactor :/
This commit is contained in:
parent
0c0e2b1cea
commit
f6a48453be
9 changed files with 44 additions and 42 deletions
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
21
src/main.rs
21
src/main.rs
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue