Implement WALLOPS
Diff
rustfmt.toml | 4 ++--
src/client.rs | 14 +++++++++-----
src/connection.rs | 29 +++++++++++++++++++++++++++--
src/messages.rs | 7 +++++++
src/server.rs | 25 +++++++++++++++++++++++++
5 files changed, 64 insertions(+), 15 deletions(-)
@@ -1,7 +1,7 @@
edition = "2021"
imports_granularity = "Crate"
newline_style = "Unix"
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
@@ -18,7 +18,7 @@
channel::Channel,
connection::{
sasl::SaslAlreadyAuthenticated, Capability, InitiatedConnection, MessageSink,
NickNotOwnedByUser,
NickNotOwnedByUser, UserMode,
},
messages::{
Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelInvite, ChannelJoin,
@@ -26,7 +26,7 @@
ChannelSetMode, ChannelUpdateTopic, ClientAway, ConnectedChannels, FetchClientDetails,
FetchUserPermission, FetchWhoList, FetchWhois, MessageKind, PrivateMessage,
ServerAdminInfo, ServerDisconnect, ServerFetchMotd, ServerListUsers, UserKickedFromChannel,
UserNickChange, UserNickChangeInternal,
UserNickChange, UserNickChangeInternal, Wallops,
},
persistence::{
events::{
@@ -624,9 +624,6 @@
#[allow(clippy::match_same_arms)]
match item.command {
Command::USER(_, _, _) | Command::PASS(_) | Command::CAP(_, _, _, _) => {
}
Command::NICK(new_nick) => {
ctx.notify(UserNickChangeInternal {
old_nick: self.connection.nick.to_string(),
@@ -883,7 +880,12 @@
Command::DIE => {}
Command::RESTART => {}
Command::USERS(_) => {}
Command::WALLOPS(_) => {}
Command::WALLOPS(message) if self.connection.mode.contains(UserMode::OPER) => {
self.server.do_send(Wallops {
span: Span::current(),
message,
});
}
Command::USERHOST(_) => {}
Command::SAJOIN(_, _) => {}
Command::SAMODE(_, _, _) => {}
@@ -44,7 +44,6 @@
host: Option<SocketAddr>,
nick: Option<String>,
user: Option<String>,
mode: Option<String>,
real_name: Option<String>,
user_id: Option<UserId>,
capabilities: Capability,
@@ -55,7 +54,7 @@
pub host: SocketAddr,
pub nick: String,
pub user: String,
pub mode: String,
pub mode: UserMode,
pub real_name: String,
pub user_id: UserId,
pub capabilities: Capability,
@@ -82,7 +81,6 @@
host: Some(host),
nick: Some(nick),
user: Some(user),
mode: Some(mode),
real_name: Some(real_name),
user_id: Some(user_id),
capabilities,
@@ -95,7 +93,7 @@
host,
nick,
user,
mode,
mode: UserMode::empty(),
real_name,
user_id,
capabilities,
@@ -138,9 +136,8 @@
match msg.command {
Command::PASS(_) => {}
Command::NICK(nick) => request.nick = Some(nick),
Command::USER(_user, mode, real_name) => {
Command::USER(_user, _mode, real_name) => {
request.mode = Some(mode);
request.real_name = Some(real_name);
}
Command::CAP(_, CapSubCommand::LIST | CapSubCommand::LS, _, _) => {
@@ -278,6 +275,26 @@
pub struct Capability: u32 {
const USERHOST_IN_NAMES = 0b0000_0000_0000_0000_0000_0000_0000_0001;
const SERVER_TIME = 0b0000_0000_0000_0000_0000_0000_0000_0010;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct UserMode: u32 {
const AWAY = 0b0000_0000_0000_0000_0000_0000_0000_0001;
const INVISIBLE = 0b0000_0000_0000_0000_0000_0000_0000_0010;
const WALLOPS = 0b0000_0000_0000_0000_0000_0000_0000_0100;
const RESTRICTED = 0b0000_0000_0000_0000_0000_0000_0000_1000;
const OPER = 0b0000_0000_0000_0000_0000_0000_0001_0000;
const LOCAL_OPER = 0b0000_0000_0000_0000_0000_0000_0010_0000;
const SERVER_NOTICES = 0b0000_0000_0000_0000_0000_0000_0100_0000;
const MASKED_HOST = 0b0000_0000_0000_0000_0000_0000_1000_0000;
}
}
@@ -47,6 +47,13 @@
pub span: Span,
}
#[derive(Message, Clone)]
#[rtype(result = "()")]
pub struct Wallops {
pub message: String,
pub span: Span,
}
#[derive(Message, Clone)]
#[rtype(result = "Vec<(crate::channel::permissions::Permission, String)>")]
@@ -22,12 +22,13 @@
channel::{permissions::Permission, Channel, ChannelId},
client::Client,
config::Config,
connection::InitiatedConnection,
connection::{InitiatedConnection, UserMode},
messages::{
Broadcast, ChannelFetchTopic, ChannelFetchWhoList, ChannelJoin, ChannelList,
ChannelMemberList, ClientAway, ConnectedChannels, FetchClientByNick, FetchWhoList,
FetchWhois, MessageKind, PrivateMessage, ServerAdminInfo, ServerDisconnect,
ServerFetchMotd, ServerListUsers, UserConnected, UserNickChange, UserNickChangeInternal,
Wallops,
},
persistence::Persistence,
server::response::{AdminInfo, ListUsers, Motd, WhoList, Whois},
@@ -132,6 +133,28 @@
self.clients.insert(msg.handle, msg.connection);
self.max_clients = self.clients.len().max(self.max_clients);
}
}
impl Handler<Wallops> for Server {
type Result = ();
#[instrument(parent = &msg.span, skip_all)]
fn handle(&mut self, msg: Wallops, _ctx: &mut Self::Context) -> Self::Result {
for (handle, conn) in &self.clients {
if !conn.mode.contains(UserMode::WALLOPS) {
continue;
}
handle.do_send(Broadcast {
message: Message {
tags: None,
prefix: Some(Prefix::ServerName(SERVER_NAME.to_string())),
command: Command::WALLOPS(msg.message.clone()),
},
span: msg.span.clone(),
});
}
}
}