NICKLOCK / NICKUNLOCK (services hold a user's nick)
This commit is contained in:
parent
4d6525cac2
commit
e2a4a3e248
3 changed files with 95 additions and 0 deletions
|
|
@ -50,6 +50,8 @@ pub fn commands() -> Vec<Box<dyn Command>> {
|
||||||
Box::new(AllTime),
|
Box::new(AllTime),
|
||||||
Box::new(SwhoisCmd),
|
Box::new(SwhoisCmd),
|
||||||
Box::new(SetIdle),
|
Box::new(SetIdle),
|
||||||
|
Box::new(NickLock),
|
||||||
|
Box::new(NickUnlock),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -699,6 +701,84 @@ impl Command for Cban {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NICKLOCK — force a user's nick and lock it so they can't change it (InspIRCd
|
||||||
|
/// `m_nicklock`). `NICKLOCK <nick> <newnick>`; opers/services still can.
|
||||||
|
struct NickLock;
|
||||||
|
impl Command for NickLock {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"NICKLOCK"
|
||||||
|
}
|
||||||
|
fn min_params(&self) -> usize {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
fn handle(&self, s: &mut Server, uid: Uid, params: &[String]) -> CmdResult {
|
||||||
|
if !require_oper(s, uid) {
|
||||||
|
return CmdResult::Fail;
|
||||||
|
}
|
||||||
|
let Some(tuid) = oper_target(s, uid, ¶ms[0]) else {
|
||||||
|
return CmdResult::Fail;
|
||||||
|
};
|
||||||
|
let newnick = ¶ms[1];
|
||||||
|
if !valid_nick(newnick) {
|
||||||
|
s.numeric(
|
||||||
|
uid,
|
||||||
|
ERR_ERRONEUSNICKNAME,
|
||||||
|
&format!("{newnick} :Erroneous nickname"),
|
||||||
|
);
|
||||||
|
return CmdResult::Fail;
|
||||||
|
}
|
||||||
|
let cur = s
|
||||||
|
.users
|
||||||
|
.get(&tuid)
|
||||||
|
.map(|u| u.nick.clone())
|
||||||
|
.unwrap_or_default();
|
||||||
|
if !newnick.eq_ignore_ascii_case(&cur) {
|
||||||
|
if s.find_nick(newnick).is_some()
|
||||||
|
|| s.remote_nick.contains_key(&newnick.to_ascii_lowercase())
|
||||||
|
{
|
||||||
|
s.numeric(
|
||||||
|
uid,
|
||||||
|
ERR_NICKNAMEINUSE,
|
||||||
|
&format!("{newnick} :Nickname is already in use"),
|
||||||
|
);
|
||||||
|
return CmdResult::Fail;
|
||||||
|
}
|
||||||
|
s.set_nick(tuid, newnick);
|
||||||
|
}
|
||||||
|
if let Some(u) = s.users.get_mut(&tuid) {
|
||||||
|
u.flags.nick_locked = true;
|
||||||
|
}
|
||||||
|
let by = oper_nick(s, uid);
|
||||||
|
s.snotice(&format!("{by} used NICKLOCK on {newnick}"));
|
||||||
|
CmdResult::Ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NICKUNLOCK — release a NICKLOCK so the user may change nick again.
|
||||||
|
struct NickUnlock;
|
||||||
|
impl Command for NickUnlock {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"NICKUNLOCK"
|
||||||
|
}
|
||||||
|
fn min_params(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
fn handle(&self, s: &mut Server, uid: Uid, params: &[String]) -> CmdResult {
|
||||||
|
if !require_oper(s, uid) {
|
||||||
|
return CmdResult::Fail;
|
||||||
|
}
|
||||||
|
let Some(tuid) = oper_target(s, uid, ¶ms[0]) else {
|
||||||
|
return CmdResult::Fail;
|
||||||
|
};
|
||||||
|
if let Some(u) = s.users.get_mut(&tuid) {
|
||||||
|
u.flags.nick_locked = false;
|
||||||
|
}
|
||||||
|
let by = oper_nick(s, uid);
|
||||||
|
s.snotice(&format!("{by} used NICKUNLOCK on {}", params[0]));
|
||||||
|
CmdResult::Ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// CONNECT — dial a configured server link on demand. `CONNECT <servername>`.
|
/// CONNECT — dial a configured server link on demand. `CONNECT <servername>`.
|
||||||
struct Connect;
|
struct Connect;
|
||||||
impl Command for Connect {
|
impl Command for Connect {
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,20 @@ impl Command for Nick {
|
||||||
);
|
);
|
||||||
return CmdResult::Fail;
|
return CmdResult::Fail;
|
||||||
}
|
}
|
||||||
|
// NICKLOCK: a services-held nick can't be changed by the user (opers bypass)
|
||||||
|
if s.users
|
||||||
|
.get(&uid)
|
||||||
|
.map(|u| u.flags.nick_locked)
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& !s.is_oper(uid)
|
||||||
|
{
|
||||||
|
s.numeric(
|
||||||
|
uid,
|
||||||
|
ERR_CANTCHANGENICK,
|
||||||
|
":Your nickname is locked and cannot be changed",
|
||||||
|
);
|
||||||
|
return CmdResult::Fail;
|
||||||
|
}
|
||||||
// Q-line: a reserved nick is refused (opers and services bypass)
|
// Q-line: a reserved nick is refused (opers and services bypass)
|
||||||
if !s.is_oper(uid) {
|
if !s.is_oper(uid) {
|
||||||
if let Some(reason) = s.matched_qline(newnick) {
|
if let Some(reason) = s.matched_qline(newnick) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ pub struct UserFlags {
|
||||||
pub callerid: bool, // +g (only accept PMs from users on the ACCEPT list)
|
pub callerid: bool, // +g (only accept PMs from users on the ACCEPT list)
|
||||||
pub showwhois: bool, // +W (get a notice when someone WHOISes you)
|
pub showwhois: bool, // +W (get a notice when someone WHOISes you)
|
||||||
pub deny_uncommon: bool, // +c (only users sharing a channel may PM you)
|
pub deny_uncommon: bool, // +c (only users sharing a channel may PM you)
|
||||||
|
pub nick_locked: bool, // NICKLOCK: services/oper holds this nick (no self-change)
|
||||||
pub away: Option<String>, // AWAY message, if set
|
pub away: Option<String>, // AWAY message, if set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue