From e438f353affe8934134c2a28bea7fd6d549fb58e Mon Sep 17 00:00:00 2001 From: DrSmoothl <1787882683@qq.com> Date: Wed, 13 May 2026 21:10:10 +0800 Subject: [PATCH] fix(onebot): resolve self nickname via user profile when friend list omits self The session warmup only set qqInfo.nickname when QQ's friend-list response happened to echo self back, which it omits for some accounts / versions / multi-account warmup races. The WebUI online sessions card then rendered a blank nickname row above the UIN. Fall back to a direct user-profile fetch when the friend-list scan misses self, and seed qqInfo.nickname with the UIN at session creation so the panel never paints empty while warmup is in flight. --- packages/core/src/onebot/manager.ts | 31 +++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/core/src/onebot/manager.ts b/packages/core/src/onebot/manager.ts index 6904db6e..0ad6ebf1 100644 --- a/packages/core/src/onebot/manager.ts +++ b/packages/core/src/onebot/manager.ts @@ -60,6 +60,10 @@ export class OneBotManager { instance.addPid(activePid); } + // Seed nickname with the UIN so the WebUI never renders blank while + // warmup is in flight or if warmup never resolves a real nickname. + if (!qqInfo.nickname) qqInfo.nickname = uin; + this.instances.set(uin, instance); log.info('session started: UIN=%s', uin); @@ -81,12 +85,17 @@ export class OneBotManager { } async function warmUpBridgeState(uin: string, qqInfo: QQInfo, bridge: Bridge): Promise { - // Step 1: Fetch friend list + derive self profile + const selfUin = parseInt(uin, 10) || 0; + let selfResolved = false; + + // Step 1: Fetch friend list + derive self profile when QQ happens to + // include self in the response. Some accounts / versions omit self, + // which used to leave qqInfo.nickname empty — see step 1b for the + // explicit fallback. try { const friends = await bridge.fetchFriendList(); log.info('friends loaded: UIN=%s count=%d', uin, friends.length); - const selfUin = parseInt(uin, 10) || 0; for (const f of friends) { if (f.uin === selfUin) { qqInfo.setSelfProfile({ @@ -96,6 +105,7 @@ async function warmUpBridgeState(uin: string, qqInfo: QQInfo, bridge: Bridge): P }); qqInfo.nickname = f.nickname || uin; log.debug('self info: UIN=%s uid=%s nickname=%s', uin, f.uid, f.nickname ?? ''); + selfResolved = true; break; } } @@ -103,6 +113,23 @@ async function warmUpBridgeState(uin: string, qqInfo: QQInfo, bridge: Bridge): P log.warn('failed to load friends for UIN %s: %s', uin, e instanceof Error ? e.message : String(e)); } + // Step 1b: friend-list path didn't resolve self → fetch user profile + // directly via OIDB 0xFE1_2 so multi-account WebUI shows a nickname + // for every injected session, not just the ones where QQ echoed self + // back in the friend list. + if (!selfResolved && selfUin > 0) { + try { + const profile = await bridge.fetchUserProfile(selfUin); + qqInfo.setSelfProfile(profile); + qqInfo.nickname = profile.nickname || uin; + log.debug('self info via profile: UIN=%s uid=%s nickname=%s', + uin, profile.uid, profile.nickname); + } catch (e) { + log.warn('failed to load self profile for UIN %s: %s', + uin, e instanceof Error ? e.message : String(e)); + } + } + // Step 2: Fetch group list let groups: { groupId: number }[] = []; try {