From 7e838cee49e948bbea49f6eca7880b6fcca67613 Mon Sep 17 00:00:00 2001 From: Jean Date: Thu, 16 Jul 2026 19:15:48 +0000 Subject: [PATCH] server: brand the service pseudo-client host (was services.local) The service pseudo-clients (NickServ etc.) wore a hardcoded services.local host, so they showed as services@services.local. Add a configurable [server] service_host (empty defaults to the server name), used when introducing them, so they appear as services@services.tchatou.fr. --- src/config.rs | 5 +++++ src/engine/mod.rs | 11 ++++++++++- src/main.rs | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 6442ba7..0384770 100644 --- a/src/config.rs +++ b/src/config.rs @@ -261,6 +261,11 @@ pub struct Server { // ircd rejects a digit-leading SVSNICK and falls back to the raw uuid. #[serde(default = "default_guest_nick")] pub guest_nick: String, + // Hostname the service pseudo-clients wear (NickServ!services@). Empty + // falls back to the server name, so NickServ shows as ...@services.tchatou.fr + // rather than the generic default. + #[serde(default)] + pub service_host: String, } fn default_protocol() -> u32 { diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 3013e65..3dc6a5b 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -102,6 +102,7 @@ pub struct Engine { // burst is done, so a relink doesn't enforce every already-online user. synced: bool, guest_nick: String, // base for the Guest#### rename on enforcement + service_host: String, // hostname the service pseudo-clients wear enforce_seq: u32, // counter appended to guest_nick pending_enforce: Vec, // registered nicks awaiting identify-or-rename bot_uids: HashMap, // casefolded bot nick -> live uid (per connection) @@ -229,6 +230,7 @@ impl Engine { sid: String::new(), synced: false, guest_nick: "Guest".to_string(), + service_host: "services.local".to_string(), enforce_seq: 0, pending_enforce: Vec::new(), bot_uids: HashMap::new(), @@ -677,6 +679,13 @@ impl Engine { } } + // The hostname the service pseudo-clients wear (NickServ!services@). + pub fn set_service_host(&mut self, host: &str) { + if !host.is_empty() { + self.service_host = host.to_string(); + } + } + // A user arrived on (or changed to) a registered nick: if they aren't logged // into that account, prompt them to IDENTIFY and schedule a rename. Gated on // `synced` so a netburst can't enforce every already-online user; a user who @@ -808,7 +817,7 @@ impl Engine { uid: svc.uid().to_string(), nick: svc.nick().to_string(), ident: "services".to_string(), - host: svc.host().to_string(), + host: self.service_host.clone(), gecos: svc.gecos().to_string(), }); } diff --git a/src/main.rs b/src/main.rs index cd78da3..db792c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -178,6 +178,9 @@ async fn main() -> Result<()> { engine.lock().await.set_opers(cfg.opers()); engine.lock().await.set_sid(cfg.server.sid.clone()); engine.lock().await.set_guest_nick(&cfg.server.guest_nick); + // Service pseudo-clients wear the configured host, or the server name. + let service_host = if cfg.server.service_host.is_empty() { &cfg.server.name } else { &cfg.server.service_host }; + engine.lock().await.set_service_host(service_host); engine.lock().await.set_log_channel(cfg.log.as_ref().map(|l| l.channel.clone())); if let Some(expire) = &cfg.expire { engine.lock().await.set_expiry(expire.account_ttl(), expire.channel_ttl(), expire.warn_ttl());