add callerid (+g) with ACCEPT allow-list, plus msgid and extended-monitor
This commit is contained in:
parent
9b12791774
commit
1581bc15d2
7 changed files with 187 additions and 5 deletions
|
|
@ -376,6 +376,50 @@ fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool) -> CmdResu
|
|||
}
|
||||
return CmdResult::Fail;
|
||||
}
|
||||
// +g callerid: a +g user only accepts PMs from users on their ACCEPT list.
|
||||
// Others are blocked; the target is told someone tried (718), and a PRIVMSG
|
||||
// sender is told the target is in +g and has been informed (716 + 717).
|
||||
let sender_nick = s
|
||||
.users
|
||||
.get(&uid)
|
||||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default();
|
||||
let target_g = s
|
||||
.users
|
||||
.get(&tuid)
|
||||
.map(|u| u.flags.callerid)
|
||||
.unwrap_or(false);
|
||||
if target_g && uid != tuid && !s.is_accepted(tuid, &sender_nick) {
|
||||
let (tnick, sident, shost) = {
|
||||
let t = s.users.get(&tuid);
|
||||
let u = s.users.get(&uid);
|
||||
(
|
||||
t.map(|x| x.nick.clone()).unwrap_or_default(),
|
||||
u.map(|x| x.ident.clone()).unwrap_or_default(),
|
||||
u.map(|x| x.host_display().to_string()).unwrap_or_default(),
|
||||
)
|
||||
};
|
||||
s.numeric(
|
||||
tuid,
|
||||
RPL_UMODEGMSG,
|
||||
&format!(
|
||||
"{sender_nick} {sident}@{shost} :is messaging you, and you have umode +g."
|
||||
),
|
||||
);
|
||||
if !notice {
|
||||
s.numeric(
|
||||
uid,
|
||||
RPL_TARGUMODEG,
|
||||
&format!("{tnick} :is in +g mode (server-side ignore)."),
|
||||
);
|
||||
s.numeric(
|
||||
uid,
|
||||
RPL_TARGNOTIFY,
|
||||
&format!("{tnick} :has been informed that you messaged them."),
|
||||
);
|
||||
}
|
||||
return CmdResult::Ok;
|
||||
}
|
||||
// SILENCE: if the recipient silenced the sender, drop it silently — the
|
||||
// sender is never told (that's the point), but still gets their own echo.
|
||||
let silenced = s.is_silenced(tuid, &prefix);
|
||||
|
|
@ -398,6 +442,20 @@ fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool) -> CmdResu
|
|||
s.numeric(uid, RPL_AWAY, &format!("{target} :{msg}"));
|
||||
}
|
||||
}
|
||||
// callerid convenience: if the SENDER is +g, auto-accept whoever they
|
||||
// message so that person can reply without being blocked.
|
||||
if s.users.get(&uid).map(|u| u.flags.callerid).unwrap_or(false) {
|
||||
let tnick = s
|
||||
.users
|
||||
.get(&tuid)
|
||||
.map(|u| u.nick.to_ascii_lowercase())
|
||||
.unwrap_or_default();
|
||||
if let Some(su) = s.users.get_mut(&uid) {
|
||||
if !tnick.is_empty() && !su.accept.contains(&tnick) {
|
||||
su.accept.push(tnick);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some((uuid, via)) = s.find_remote(target) {
|
||||
// the target is a user on another server — route it across the link
|
||||
s.send_to_remote(uid, &uuid, via, cmd, text);
|
||||
|
|
|
|||
|
|
@ -7,11 +7,16 @@ use crate::channels::normalize_mask;
|
|||
use crate::command::{CmdResult, Command};
|
||||
use crate::numeric::*;
|
||||
use crate::server::Server;
|
||||
use crate::watch::{MONITOR_MAX, SILENCE_MAX, WATCH_MAX};
|
||||
use crate::watch::{ACCEPT_MAX, MONITOR_MAX, SILENCE_MAX, WATCH_MAX};
|
||||
use crate::Uid;
|
||||
|
||||
pub fn commands() -> Vec<Box<dyn Command>> {
|
||||
vec![Box::new(Watch), Box::new(Monitor), Box::new(Silence)]
|
||||
vec![
|
||||
Box::new(Watch),
|
||||
Box::new(Monitor),
|
||||
Box::new(Silence),
|
||||
Box::new(Accept),
|
||||
]
|
||||
}
|
||||
|
||||
// --- WATCH ------------------------------------------------------------------
|
||||
|
|
@ -304,3 +309,87 @@ impl Command for Silence {
|
|||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
||||
// --- ACCEPT (callerid +g allow-list) ----------------------------------------
|
||||
|
||||
fn accept_list(s: &Server, uid: Uid) {
|
||||
let list = s
|
||||
.users
|
||||
.get(&uid)
|
||||
.map(|u| u.accept.clone())
|
||||
.unwrap_or_default();
|
||||
for n in list {
|
||||
s.numeric(uid, RPL_ACCEPTLIST, &n);
|
||||
}
|
||||
s.numeric(uid, RPL_ENDOFACCEPT, ":End of ACCEPT list");
|
||||
}
|
||||
|
||||
struct Accept;
|
||||
impl Command for Accept {
|
||||
fn name(&self) -> &'static str {
|
||||
"ACCEPT"
|
||||
}
|
||||
fn handle(&self, s: &mut Server, uid: Uid, params: &[String]) -> CmdResult {
|
||||
let first = params.first().map(|a| a.as_str()).unwrap_or("");
|
||||
if first.is_empty() || first == "*" {
|
||||
accept_list(s, uid);
|
||||
return CmdResult::Ok;
|
||||
}
|
||||
for tok in params
|
||||
.iter()
|
||||
.flat_map(|p| p.split([',', ' ']))
|
||||
.filter(|t| !t.is_empty())
|
||||
{
|
||||
if tok == "*" {
|
||||
accept_list(s, uid);
|
||||
continue;
|
||||
}
|
||||
let (adding, name) = match tok.strip_prefix('-') {
|
||||
Some(n) => (false, n),
|
||||
None => (true, tok.strip_prefix('+').unwrap_or(tok)),
|
||||
};
|
||||
if name.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let low = name.to_ascii_lowercase();
|
||||
if adding {
|
||||
let (full, exists) = s
|
||||
.users
|
||||
.get(&uid)
|
||||
.map(|u| (u.accept.len() >= ACCEPT_MAX, u.accept.contains(&low)))
|
||||
.unwrap_or((true, false));
|
||||
if exists {
|
||||
s.numeric(
|
||||
uid,
|
||||
ERR_ACCEPTEXIST,
|
||||
&format!("{name} :is already on your accept list"),
|
||||
);
|
||||
} else if full {
|
||||
s.numeric(
|
||||
uid,
|
||||
ERR_ACCEPTFULL,
|
||||
&format!("{name} :Your accept list is full"),
|
||||
);
|
||||
} else if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.accept.push(low);
|
||||
}
|
||||
} else {
|
||||
let existed = s
|
||||
.users
|
||||
.get(&uid)
|
||||
.map(|u| u.accept.contains(&low))
|
||||
.unwrap_or(false);
|
||||
if !existed {
|
||||
s.numeric(
|
||||
uid,
|
||||
ERR_ACCEPTNOT,
|
||||
&format!("{name} :is not on your accept list"),
|
||||
);
|
||||
} else if let Some(u) = s.users.get_mut(&uid) {
|
||||
u.accept.retain(|x| x != &low);
|
||||
}
|
||||
}
|
||||
}
|
||||
CmdResult::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue