From 20bc7ae85b73163bd6d31a6b69fac68f8af876dc Mon Sep 17 00:00:00 2001 From: harrylyu2006 Date: Thu, 5 Mar 2026 20:53:09 +0800 Subject: [PATCH] fix: NapCat friend list compatibility and crash fixes 1. NapCat API returns `user_id` instead of `uin` and `nickname` instead of `nick` in friend list responses, causing friend uin to be NaN and nickname to be undefined. 2. `onSelectChatPersonal` crashes when avatar loading fails, unlike `addExact` which already handles this. Added the same try-catch pattern. 3. `fetchFile` crashes on empty URL (e.g. when `getAvatarUrl` returns empty string for falsy room id). Added early return guard. 4. `generateRichHeaderUrl` crashes with `Invalid URL` when `WEB_ENDPOINT` is not configured, unlike `generateTelegramAvatarUrl` which already has this guard. Co-Authored-By: Claude Opus 4.6 --- main/src/client/NapCatClient/client.ts | 6 +++--- main/src/helpers/forwardHelper.ts | 1 + main/src/services/ConfigService.ts | 10 ++++++++-- main/src/utils/urls.ts | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/main/src/client/NapCatClient/client.ts b/main/src/client/NapCatClient/client.ts index c9c05a90..9053c92b 100644 --- a/main/src/client/NapCatClient/client.ts +++ b/main/src/client/NapCatClient/client.ts @@ -216,7 +216,7 @@ export class NapCatClient extends QQClient { } category.friends.push(NapCatFriend.createExisted(this, { nickname: it.nick || it.nickname, - uid: parseInt(it.uin), + uid: parseInt(it.uin || it.user_id), remark: it.remark, })); } @@ -225,8 +225,8 @@ export class NapCatClient extends QQClient { return data.map(it => ({ name: it.categoryName || (it as any).categroyName, // typo in API friends: it.buddyList.map(friend => NapCatFriend.createExisted(this, { - nickname: friend.nick, - uid: parseInt(friend.uin), + nickname: friend.nick || friend.nickname, + uid: parseInt(friend.uin || friend.user_id), remark: friend.remark, })), })); diff --git a/main/src/helpers/forwardHelper.ts b/main/src/helpers/forwardHelper.ts index 543d5972..f4b87e60 100644 --- a/main/src/helpers/forwardHelper.ts +++ b/main/src/helpers/forwardHelper.ts @@ -241,6 +241,7 @@ export default { }, generateRichHeaderUrl(apiKey: string, userId: number, messageHeader = '') { + if (!env.WEB_ENDPOINT) return ''; const url = new URL(`${env.WEB_ENDPOINT}/richHeader/${apiKey}/${userId}`); // 防止群名片刷新慢 messageHeader && url.searchParams.set('hash', md5Hex(messageHeader).substring(0, 10)); diff --git a/main/src/services/ConfigService.ts b/main/src/services/ConfigService.ts index 11dff649..0892a6cb 100644 --- a/main/src/services/ConfigService.ts +++ b/main/src/services/ConfigService.ts @@ -74,7 +74,13 @@ export default class ConfigService { private async onSelectChatPersonal(entity: Friend | Group) { const roomId = 'uin' in entity ? entity.uin : -entity.gid; const name = 'uin' in entity ? entity.remark || entity.nickname : entity.name; - const avatar = await getAvatar(roomId); + let avatar: Buffer; + try { + avatar = await getAvatar(roomId); + } + catch (e) { + avatar = null; + } const message = await (await this.owner).sendMessage({ message: await getAboutText(entity, true), buttons: [ @@ -85,7 +91,7 @@ export default class ConfigService { }))], [Button.url('手动选择现有群组', this.getAssociateLink(roomId))], ], - file: new CustomFile('avatar.png', avatar.length, '', avatar), + file: avatar ? new CustomFile('avatar.png', avatar.length, '', avatar) : undefined, }); } diff --git a/main/src/utils/urls.ts b/main/src/utils/urls.ts index 0c53dc1c..229d11cb 100644 --- a/main/src/utils/urls.ts +++ b/main/src/utils/urls.ts @@ -28,6 +28,7 @@ const httpsAgent = new https.Agent({ }); export async function fetchFile(url: string): Promise { + if (!url) return Buffer.alloc(0); const res = await axios.get(url, { responseType: 'arraybuffer', httpsAgent,