Say which nick an account is actually using

An IRC session that landed on the alt nick is using that one until GHOST
reclaims the real one, so the configured nick is not an answer to "which
of these people is me". Without that, a client cannot tell which row in a
member list is the local user, and therefore cannot tell whether they hold
op - which is why the moderation menu ended up offered on the strength of
a Matrix-only permissions call and nothing else.

Filled in where a live connection can be seen, and empty for every service
with no such concept.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-02 00:29:08 -04:00
co-authored by Claude Opus 5
parent 043df9bc58
commit cc2650067c
3 changed files with 22 additions and 0 deletions
+7
View File
@@ -688,6 +688,9 @@ pub fn irc_account_to_json(a: &IrcAccountConfig, state: &str) -> Account {
allow_plaintext_sasl: a.allow_plaintext_sasl,
sasl_mechanism: a.sasl_mechanism.clone().unwrap_or_default(),
has_sasl_certificate: a.sasl_cert_path.as_deref().is_some_and(|p| !p.is_empty()),
// Filled in by Runtime::list_accounts, which is the only place that
// can see a live connection.
current_nick: String::new(),
ssl: a.ssl,
has_password: a.password.as_deref().is_some_and(|p| !p.is_empty()),
avatar_url: None,
@@ -716,6 +719,7 @@ pub fn discord_account_to_json(a: &DiscordAccountConfig, state: &str) -> Account
allow_plaintext_sasl: false,
sasl_mechanism: String::new(),
has_sasl_certificate: false,
current_nick: String::new(),
ssl: true,
has_password: !a.token.is_empty(),
avatar_url: a.avatar_url.clone(),
@@ -743,6 +747,7 @@ pub fn sockchat_account_to_json(a: &SockChatAccountConfig, state: &str) -> Accou
allow_plaintext_sasl: false,
sasl_mechanism: String::new(),
has_sasl_certificate: false,
current_nick: String::new(),
ssl: true,
has_password: !a.password.is_empty(),
avatar_url: None,
@@ -779,6 +784,7 @@ pub fn kick_account_to_json(a: &KickAccountConfig, state: &str) -> Account {
allow_plaintext_sasl: false,
sasl_mechanism: String::new(),
has_sasl_certificate: false,
current_nick: String::new(),
ssl: true,
has_password: a.token.as_deref().is_some_and(|t| !t.is_empty()),
avatar_url: None,
@@ -810,6 +816,7 @@ pub fn matrix_account_to_json(a: &MatrixAccountConfig, state: &str, has_key_back
allow_plaintext_sasl: false,
sasl_mechanism: String::new(),
has_sasl_certificate: false,
current_nick: String::new(),
ssl: true,
has_password: !a.password.is_empty(),
avatar_url: None,
+10
View File
@@ -33,6 +33,16 @@ pub struct Account {
/// file on the machine the daemon is running on rather than this one.
#[serde(rename = "hasSaslCertificate")]
pub has_sasl_certificate: bool,
/// The nick this account is actually using right now.
///
/// Not the same as the configured one: a session that landed on the alt
/// nick is using that until GHOST reclaims the real one. Reported because
/// a client cannot otherwise tell which row in a member list is the person
/// using it - and therefore cannot tell whether they hold op.
///
/// Empty for every service that has no such concept.
#[serde(rename = "currentNick")]
pub current_nick: String,
/// Whether this account's connection is encrypted.
///
/// Reported so a frontend can tell the truth about what sending
+5
View File
@@ -594,6 +594,11 @@ impl Runtime {
// runtime is actually holding is filled in here.
for account in &mut out {
account.status = self.account_status(&account.id);
// Only IRC has one, and only while connected - a configured nick
// is not the nick in use if the session landed on the alt.
if let Some(nick) = self.irc_current_nick(&account.id) {
account.current_nick = nick;
}
}
out
}