feat: show speaker nickname instead of raw user ID in voice logs

Resolve the Discord user ID to a server nickname / global name (cached) and
display that in the transcript channel + console logs.
This commit is contained in:
javis-bot
2026-06-14 22:39:06 +09:00
parent d970bf276e
commit 54c3ce7d1b
2 changed files with 35 additions and 2 deletions

View File

@@ -81,6 +81,9 @@ export class VoiceSession {
* diagnosable. `note` says why (e.g. "음성 아님(VAD 차단)", "너무 짧음", "ok"). */
onTurn?: (info: {
user: string;
/** Resolved display name (server nickname / global name) for the speaker,
* so logs show a human name instead of the raw Discord user ID. */
userName?: string;
transcript: string;
reply: string;
note?: string;
@@ -164,6 +167,31 @@ export class VoiceSession {
});
}
/** Resolve a speaker's Discord user ID to a human display name (server
* nickname, else global name / username), cached so we don't refetch every
* utterance. Falls back to the ID if lookup fails. */
private nameCache = new Map<string, string>();
private async displayName(userId: string): Promise<string> {
const cached = this.nameCache.get(userId);
if (cached) return cached;
let name = userId;
try {
const guild: any = this.client?.guilds?.cache?.get(this.guildId);
let member: any = guild?.members?.cache?.get(userId);
if (!member && guild?.members?.fetch) member = await guild.members.fetch(userId).catch(() => null);
if (member) {
name = member.displayName || member.nickname || member.user?.globalName || member.user?.username || userId;
} else {
const u: any = this.client?.users?.cache?.get(userId) || (await this.client?.users?.fetch?.(userId).catch(() => null));
name = u?.globalName || u?.username || userId;
}
} catch {
/* fall back to id */
}
this.nameCache.set(userId, name);
return name;
}
private async captureUtterance(userId: string): Promise<void> {
// Don't start a new capture once we're tearing down (user left).
if (this.destroyed) return;
@@ -199,6 +227,7 @@ export class VoiceSession {
if (mono.length < DISCORD_RATE * 0.3 * 2) {
this.onTurn?.({
user: userId,
userName: await this.displayName(userId),
transcript: "",
reply: "",
note: "너무 짧음(<300ms)",
@@ -247,6 +276,7 @@ export class VoiceSession {
// explains why a turn did or didn't answer, with full stage timing.
this.onTurn?.({
user: userId,
userName: await this.displayName(userId),
transcript: metaSeen?.transcript ?? "",
reply: metaSeen?.reply ?? "",
note: metaSeen?.note,