Adds the remaining moderation and listing commands. Auto-kick masks are stored in the event log and enforced on join: a matching user is banned and kicked. Topic and invite are sourced from the ChanServ pseudoclient.
120 lines
4.1 KiB
Rust
120 lines
4.1 KiB
Rust
use crate::engine::db::Db;
|
|
use crate::engine::state::Network;
|
|
use crate::proto::{NetAction, RegReply};
|
|
|
|
// Who sent the command, resolved by the engine (UID + current nick + the
|
|
// account they are identified to, if any).
|
|
pub struct Sender<'a> {
|
|
pub uid: &'a str,
|
|
pub nick: &'a str,
|
|
pub account: Option<&'a str>,
|
|
}
|
|
|
|
// A pseudo-client (NickServ, ChanServ, ...). Introduced at burst, receives the
|
|
// commands users message it, reads/writes the account store, and pushes actions.
|
|
pub trait Service: Send {
|
|
fn nick(&self) -> &str;
|
|
fn uid(&self) -> &str;
|
|
fn host(&self) -> &str {
|
|
"services.local"
|
|
}
|
|
fn gecos(&self) -> &str;
|
|
// Whether this service owns channel modes (ChanServ), so the engine can source
|
|
// channel mode changes from it.
|
|
fn manages_channels(&self) -> bool {
|
|
false
|
|
}
|
|
fn on_command(&mut self, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net: &Network, db: &mut Db);
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct ServiceCtx {
|
|
pub actions: Vec<NetAction>,
|
|
}
|
|
|
|
impl ServiceCtx {
|
|
pub fn notice(&mut self, from: &str, to: &str, text: impl Into<String>) {
|
|
self.actions.push(NetAction::Notice {
|
|
from: from.to_string(),
|
|
to: to.to_string(),
|
|
text: text.into(),
|
|
});
|
|
}
|
|
|
|
// Hand a registration to the engine to finish: its password derivation runs
|
|
// off the reactor, then the engine commits it and answers `reply`.
|
|
pub fn defer_register(&mut self, account: impl Into<String>, password: impl Into<String>, email: Option<String>, reply: RegReply) {
|
|
self.actions.push(NetAction::DeferRegister {
|
|
account: account.into(),
|
|
password: password.into(),
|
|
email,
|
|
reply,
|
|
});
|
|
}
|
|
|
|
// Log a user into an account: sets the accountname the ircd turns into
|
|
// RPL_LOGGEDIN (900) and exposes to account-tag / WHOX, the same login the
|
|
// SASL agent applies. Used after a successful REGISTER / IDENTIFY.
|
|
pub fn login(&mut self, uid: &str, account: &str) {
|
|
self.actions.push(NetAction::Metadata {
|
|
target: uid.to_string(),
|
|
key: "accountname".to_string(),
|
|
value: account.to_string(),
|
|
});
|
|
}
|
|
|
|
// Log a user out: clearing the accountname the ircd turns into RPL_LOGGEDOUT
|
|
// (901) and drops from account-tag / WHOX. The inverse of `login`.
|
|
pub fn logout(&mut self, uid: &str) {
|
|
self.actions.push(NetAction::Metadata {
|
|
target: uid.to_string(),
|
|
key: "accountname".to_string(),
|
|
value: String::new(),
|
|
});
|
|
}
|
|
|
|
// Force a user's nick (SVSNICK), e.g. to a guest nick after logout.
|
|
pub fn force_nick(&mut self, uid: &str, nick: &str) {
|
|
self.actions.push(NetAction::ForceNick {
|
|
uid: uid.to_string(),
|
|
nick: nick.to_string(),
|
|
});
|
|
}
|
|
|
|
// Set channel modes, sourced from pseudoclient `from` (e.g. ChanServ).
|
|
pub fn channel_mode(&mut self, from: &str, channel: &str, modes: &str) {
|
|
self.actions.push(NetAction::ChannelMode {
|
|
from: from.to_string(),
|
|
channel: channel.to_string(),
|
|
modes: modes.to_string(),
|
|
});
|
|
}
|
|
|
|
// Kick a user, sourced from pseudoclient `from`.
|
|
pub fn kick(&mut self, from: &str, channel: &str, uid: &str, reason: &str) {
|
|
self.actions.push(NetAction::Kick {
|
|
from: from.to_string(),
|
|
channel: channel.to_string(),
|
|
uid: uid.to_string(),
|
|
reason: reason.to_string(),
|
|
});
|
|
}
|
|
|
|
// Set a channel's topic, sourced from pseudoclient `from`.
|
|
pub fn topic(&mut self, from: &str, channel: &str, topic: &str) {
|
|
self.actions.push(NetAction::Topic {
|
|
from: from.to_string(),
|
|
channel: channel.to_string(),
|
|
topic: topic.to_string(),
|
|
});
|
|
}
|
|
|
|
// Invite a user to a channel, sourced from pseudoclient `from`.
|
|
pub fn invite(&mut self, from: &str, uid: &str, channel: &str) {
|
|
self.actions.push(NetAction::Invite {
|
|
from: from.to_string(),
|
|
uid: uid.to_string(),
|
|
channel: channel.to_string(),
|
|
});
|
|
}
|
|
}
|