From c4d7d5a0d40ea210d82f9491047b99f444700a53 Mon Sep 17 00:00:00 2001 From: Alen Date: Tue, 20 Aug 2024 01:02:03 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E5=A4=9A=E5=A4=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修改(疑似)旧设备回复消息验证失败的解决方案 2.修复Base64发送文件失败 3.修复群时间监听器未注册 --- src/core/core.ts | 3 +++ src/onebot/helper/data.ts | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/core.ts b/src/core/core.ts index 9069a603..8599bf87 100644 --- a/src/core/core.ts +++ b/src/core/core.ts @@ -196,6 +196,9 @@ export class NapCatCore { this.apis.GroupApi.groupMemberCache.set(groupCode, members); } }; + this.context.session.getGroupService().addKernelGroupListener( + new this.context.wrapper.NodeIKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger)), + ); } checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean { if (memberNew.role !== memberOld?.role) { diff --git a/src/onebot/helper/data.ts b/src/onebot/helper/data.ts index 7cb7e9e2..44dbe87f 100644 --- a/src/onebot/helper/data.ts +++ b/src/onebot/helper/data.ts @@ -149,7 +149,6 @@ export class OB11Constructor { message_data['type'] = OB11MessageDataType.reply; //log("收到回复消息", element.replyElement); try { - let oldMsgFlag = false; const records = msg.records.find(msgRecord => msgRecord.msgId === element?.replyElement?.sourceMsgIdInRecords); const peer = { chatType: msg.chatType, @@ -164,14 +163,17 @@ export class OB11Constructor { chatType: msg.chatType, }, element.replyElement.replayMsgSeq, 1, true, true)).msgList.find(msg => msg.msgRandom === records.msgRandom); if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) { - if (!replyMsg && records.msgRandom === '0') oldMsgFlag = true; replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replyElement.replayMsgSeq)).msgList[0]; } if (msg.peerUin == '284840486') { //合并消息内侧 消息具体定位不到 } - if ((!replyMsg || (records.msgRandom !== replyMsg.msgRandom && !oldMsgFlag || (oldMsgFlag && records.msgSeq !== replyMsg.msgSeq))) && msg.peerUin !== '284840486') { - throw new Error('回复消息消息验证失败'); + if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') { + const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList; + if (replyMsgList.length < 1) { + throw new Error('回复消息消息验证失败'); + } + replyMsg = replyMsgList.filter(e => e.msgSeq == records.msgSeq).sort((a, b) => parseInt(a.msgTime) - parseInt(b.msgTime))[0]; } message_data['data']['id'] = MessageUnique.createMsg({ peerUid: msg.peerUid, From 7a08187c5f85d885781f471add003fb03cae1350 Mon Sep 17 00:00:00 2001 From: Alen Date: Tue, 20 Aug 2024 07:28:25 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20Uid=E8=BD=ACUin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复Uid转Uin兜底逻辑 --- src/core/apis/user.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/apis/user.ts b/src/core/apis/user.ts index bf09fd77..ab231863 100644 --- a/src/core/apis/user.ts +++ b/src/core/apis/user.ts @@ -127,13 +127,16 @@ export class NTQQUserApi { return RetUser; } - async getUserDetailInfo(uid: string) { - const ret = await this.fetchUserDetailInfo(uid, UserDetailSource.KDB); - if (ret.uin === '0') { - this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.') - return await this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); + async getUserDetailInfo(uid: string): Promise { + try { + let retUser = await this.fetchUserDetailInfo(uid, UserDetailSource.KDB); + if (retUser.uin !== '0') { + return retUser; + } + } catch (e) { } - return ret; + this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.'); + return this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); } async modifySelfProfile(param: ModifyProfileParams) { From f484c6e5feb14aff01a181833e9bd6e9b37456df Mon Sep 17 00:00:00 2001 From: Alen <33656288+cnxysoft@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:28:32 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E5=A4=9A=E5=A4=84=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修复group_card事件上报 2.修复group_admin事件上报 --- src/onebot/helper/data.ts | 20 ++++++++++---------- src/onebot/index.ts | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/onebot/helper/data.ts b/src/onebot/helper/data.ts index 44dbe87f..9c3aaa10 100644 --- a/src/onebot/helper/data.ts +++ b/src/onebot/helper/data.ts @@ -30,6 +30,7 @@ import { EventType } from '../event/OB11BaseEvent'; import { encodeCQCode } from './cqcode'; import { OB11GroupIncreaseEvent } from '../event/notice/OB11GroupIncreaseEvent'; import { OB11GroupBanEvent } from '../event/notice/OB11GroupBanEvent'; +import { OB11GroupCardEvent } from '../event/notice/OB11GroupCardEvent'; import { OB11GroupUploadNoticeEvent } from '../event/notice/OB11GroupUploadNoticeEvent'; import { OB11GroupNoticeEvent } from '../event/notice/OB11GroupNoticeEvent'; import { calcQQLevel, sleep, UUIDConverter } from '@/common/utils/helper'; @@ -421,16 +422,15 @@ export class OB11Constructor { return; } //log("group msg", msg); - // Mlikiowa V2.0.34 Refactor Todo - // if (msg.senderUin && msg.senderUin !== '0') { - // const member = await getGroupMember(msg.peerUid, msg.senderUin); - // if (member && member.cardName !== msg.sendMemberName) { - // const newCardName = msg.sendMemberName || ''; - // const event = new OB11GroupCardEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName); - // member.cardName = newCardName; - // return event; - // } - // } + if (msg.senderUin && msg.senderUin !== '0') { + const member = await NTQQGroupApi.getGroupMember(msg.peerUid, msg.senderUin); + if (member && member.cardName !== msg.sendMemberName) { + const newCardName = msg.sendMemberName || ''; + const event = new OB11GroupCardEvent(core, parseInt(msg.peerUid), parseInt(msg.senderUin), newCardName, member.cardName); + member.cardName = newCardName; + return event; + } + } for (const element of msg.elements) { const grayTipElement = element.grayTipElement; diff --git a/src/onebot/index.ts b/src/onebot/index.ts index f5472b14..b12ba056 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -9,6 +9,7 @@ import { NapCatCore, RawMessage, SendStatusType, + GroupMemberRole, } from '@/core'; import { OB11Config, OB11ConfigLoader } from '@/onebot/helper/config'; import { OneBotApiContextType } from '@/onebot/types'; @@ -413,6 +414,29 @@ export class NapCatOneBot11Adapter { } }; + groupListener.onMemberInfoChange = async (groupCode, changeType, members) => { + //this.context.logger.logDebug('收到群成员信息变动通知', groupCode, changeType); + if (changeType === 0) { + const existMembers = this.core.apis.GroupApi.groupMemberCache.get(groupCode); + if (!existMembers) return; + members.forEach((member) => { + const existMember = existMembers.get(member.uid); + if (!existMember?.isChangeRole) return; + this.context.logger.logDebug('变动管理员获取成功'); + const groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent( + this.core, + parseInt(groupCode), + parseInt(member.uin), + member.role === GroupMemberRole.admin ? 'set' : 'unset', + ); + this.networkManager.emitEvent(groupAdminNoticeEvent) + .catch(e => this.context.logger.logError('处理群管理员变动失败', e)); + existMember.isChangeRole = false; + this.context.logger.logDebug('群管理员变动处理完毕'); + }); + } + }; + this.context.session.getGroupService().addKernelGroupListener( new this.context.wrapper.NodeIKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger)), ); From 1bee811312f80d3c4e4b19f3610ed9b43f06fd9e Mon Sep 17 00:00:00 2001 From: Alen <33656288+cnxysoft@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:05:23 +0800 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=E6=8E=A5=E5=8F=A3=E5=85=BC?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 调整SetSelfProfile接口为SetQQProfile,使其兼容gocq标准 --- src/onebot/action/extends/SetSelfProfile.ts | 32 ------------------- src/onebot/action/go-cqhttp/SetQQProfile.ts | 34 +++++++++++++++++++++ src/onebot/action/index.ts | 4 +-- src/onebot/action/types.ts | 2 +- 4 files changed, 37 insertions(+), 35 deletions(-) delete mode 100644 src/onebot/action/extends/SetSelfProfile.ts create mode 100644 src/onebot/action/go-cqhttp/SetQQProfile.ts diff --git a/src/onebot/action/extends/SetSelfProfile.ts b/src/onebot/action/extends/SetSelfProfile.ts deleted file mode 100644 index 4c60f0ea..00000000 --- a/src/onebot/action/extends/SetSelfProfile.ts +++ /dev/null @@ -1,32 +0,0 @@ -import BaseAction from '../BaseAction'; -import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; - -const SchemaData = { - type: 'object', - properties: { - nick: { type: 'string' }, - longNick: { type: 'string' }, - sex: { type: ['number', 'string'] },//传Sex值?建议传0 - }, - required: ['nick', 'longNick', 'sex'], -} as const satisfies JSONSchema; - -type Payload = FromSchema; - -export class SetSelfProfile extends BaseAction { - actionName = ActionName.SetSelfProfile; - PayloadSchema = SchemaData; - - async _handle(payload: Payload) { - const NTQQUserApi = this.CoreContext.apis.UserApi; - const ret = await NTQQUserApi.modifySelfProfile({ - nick: payload.nick, - longNick: payload.longNick, - sex: parseInt(payload.sex.toString()), - birthday: { birthday_year: '', birthday_month: '', birthday_day: '' }, - location: undefined, - }); - return ret; - } -} diff --git a/src/onebot/action/go-cqhttp/SetQQProfile.ts b/src/onebot/action/go-cqhttp/SetQQProfile.ts new file mode 100644 index 00000000..73334115 --- /dev/null +++ b/src/onebot/action/go-cqhttp/SetQQProfile.ts @@ -0,0 +1,34 @@ +import BaseAction from '../BaseAction'; +import { ActionName } from '../types'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +const SchemaData = { + type: 'object', + properties: { + nickname: { type: 'string' }, + personal_note: { type: 'string' }, + sex: { type: ['number', 'string'] },//传Sex值?建议传0 + }, + required: ['nickname'], +} as const satisfies JSONSchema; + +type Payload = FromSchema; + +export class SetQQProfile extends BaseAction { + actionName = ActionName.SetQQProfile; + PayloadSchema = SchemaData; + + async _handle(payload: Payload) { + const NTQQUserApi = this.CoreContext.apis.UserApi; + const self = this.CoreContext.selfInfo; + const OldProfile = await NTQQUserApi.getUserDetailInfo(self.uid); + const ret = await NTQQUserApi.modifySelfProfile({ + nick: payload.nickname, + longNick: payload?.personal_note ?? OldProfile?.longNick!, + sex: parseInt(payload?.sex ? payload?.sex.toString() : OldProfile?.sex!.toString()), + birthday: { birthday_year: OldProfile?.birthday_year!.toString(), birthday_month: OldProfile?.birthday_month!.toString(), birthday_day: OldProfile?.birthday_day!.toString() }, + location: undefined, + }); + return ret; + } +} diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index 7ff7da6d..d4d14a02 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -61,7 +61,7 @@ import { TranslateEnWordToZn } from './extends/TranslateEnWordToZn'; import { SetGroupFileFolder } from './file/SetGroupFileFolder'; import { DelGroupFile } from './file/DelGroupFile'; import { DelGroupFileFolder } from './file/DelGroupFileFolder'; -import { SetSelfProfile } from './extends/SetSelfProfile'; +import { SetQQProfile } from './go-cqhttp/SetQQProfile' import { ShareGroupEx, SharePeer } from './extends/ShareContact'; import { CreateCollection } from './extends/CreateCollection'; import { SetLongNick } from './extends/SetLongNick'; @@ -86,7 +86,7 @@ export function createActionMap(onebotContext: NapCatOneBot11Adapter, coreContex const actionHandlers = [ new FetchEmojiLike(onebotContext, coreContext), new GetFile(onebotContext, coreContext), - new SetSelfProfile(onebotContext, coreContext), + new SetQQProfile(onebotContext, coreContext), new ShareGroupEx(onebotContext, coreContext), new SharePeer(onebotContext, coreContext), new CreateCollection(onebotContext, coreContext), diff --git a/src/onebot/action/types.ts b/src/onebot/action/types.ts index 26204339..2cc84873 100644 --- a/src/onebot/action/types.ts +++ b/src/onebot/action/types.ts @@ -91,7 +91,7 @@ export enum ActionName { GetOnlineClient = 'get_online_clients', OCRImage = 'ocr_image', IOCRImage = '.ocr_image', - SetSelfProfile = 'set_self_profile', + SetQQProfile = 'set_qq_profile', CreateCollection = 'create_collection', GetCollectionList = 'get_collection_list', SetLongNick = 'set_self_longnick', From 0c8cf7374665b02d609f0a73fb7d3d57f5d6ab71 Mon Sep 17 00:00:00 2001 From: Alen <33656288+cnxysoft@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:35:23 +0800 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=E6=8E=A5=E5=8F=A3=E5=85=BC?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 调整SetGroupHeader接口为SetGroupPortrait,使其兼容gocq标准 --- .../SetGroupPortrait.ts} | 22 +++++++++---------- src/onebot/action/index.ts | 4 ++-- src/onebot/action/types.ts | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) rename src/onebot/action/{extends/SetGroupHeader.ts => go-cqhttp/SetGroupPortrait.ts} (72%) diff --git a/src/onebot/action/extends/SetGroupHeader.ts b/src/onebot/action/go-cqhttp/SetGroupPortrait.ts similarity index 72% rename from src/onebot/action/extends/SetGroupHeader.ts rename to src/onebot/action/go-cqhttp/SetGroupPortrait.ts index bfd60f4e..7034d40e 100644 --- a/src/onebot/action/extends/SetGroupHeader.ts +++ b/src/onebot/action/go-cqhttp/SetGroupPortrait.ts @@ -7,18 +7,18 @@ import { checkFileReceived, uri2local } from '@/common/utils/file'; interface Payload { file: string, - groupCode: string + group_id: number } -export default class SetGroupHeader extends BaseAction { - actionName = ActionName.SetGroupHeader; +export default class SetGroupPortrait extends BaseAction { + actionName = ActionName.SetGroupPortrait; // 用不着复杂检测 protected async check(payload: Payload): Promise { - if (!payload.file || typeof payload.file != 'string' || !payload.groupCode || typeof payload.groupCode != 'string') { + if (!payload.file || typeof payload.file != 'string' || !payload.group_id || typeof payload.group_id != 'number') { return { valid: false, - message: 'file和groupCode字段不能为空或者类型错误', + message: 'file和group_id字段不能为空或者类型错误', }; } return { @@ -34,7 +34,7 @@ export default class SetGroupHeader extends BaseAction { } if (path) { await checkFileReceived(path, 5000); // 文件不存在QQ会崩溃,需要提前判断 - const ret = await NTQQGroupApi.setGroupAvatar(payload.groupCode, path); + const ret = await NTQQGroupApi.setGroupAvatar(payload.group_id.toString(), path) as any; if (!isLocal) { fs.unlink(path, () => { }); @@ -43,11 +43,11 @@ export default class SetGroupHeader extends BaseAction { throw `头像${payload.file}设置失败,api无返回`; } // log(`头像设置返回:${JSON.stringify(ret)}`) - // if (ret['result'] == 1004022) { - // throw `头像${payload.file}设置失败,文件可能不是图片格式`; - // } else if (ret['result'] != 0) { - // throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`; - // } + if (ret['result'] == 1004022) { + throw `头像${payload.file}设置失败,文件可能不是图片格式或权限不足`; + } else if (ret['result'] != 0) { + throw `头像${payload.file}设置失败,未知的错误,${ret['result']}:${ret['errMsg']}`; + } return ret; } else { if (!isLocal) { diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index d4d14a02..a486c044 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -69,7 +69,7 @@ import DelEssenceMsg from './group/DelEssenceMsg'; import SetEssenceMsg from './group/SetEssenceMsg'; import GetRecentContact from './user/GetRecentContact'; import { GetProfileLike } from './extends/GetProfileLike'; -import SetGroupHeader from './extends/SetGroupHeader'; +import SetGroupPortrait from './go-cqhttp/SetGroupPortrait'; import { FetchCustomFace } from './extends/FetchCustomFace'; import GoCQHTTPUploadPrivateFile from './go-cqhttp/UploadPrivareFile'; import { FetchEmojiLike } from './extends/FetchEmojiLike'; @@ -161,7 +161,7 @@ export function createActionMap(onebotContext: NapCatOneBot11Adapter, coreContex new GetRecentContact(onebotContext, coreContext), new MarkAllMsgAsRead(onebotContext, coreContext), new GetProfileLike(onebotContext, coreContext), - new SetGroupHeader(onebotContext, coreContext), + new SetGroupPortrait(onebotContext, coreContext), new FetchCustomFace(onebotContext, coreContext), new GoCQHTTPUploadPrivateFile(onebotContext, coreContext), new GetGuildProfile(onebotContext, coreContext), diff --git a/src/onebot/action/types.ts b/src/onebot/action/types.ts index 2cc84873..2bfbcd28 100644 --- a/src/onebot/action/types.ts +++ b/src/onebot/action/types.ts @@ -100,7 +100,7 @@ export enum ActionName { GetRecentContact = 'get_recent_contact', _MarkAllMsgAsRead = '_mark_all_as_read', GetProfileLike = 'get_profile_like', - SetGroupHeader = 'set_group_head', + SetGroupPortrait = 'set_group_portrait', FetchCustomFace = 'fetch_custom_face', GOCQHTTP_UploadPrivateFile = 'upload_private_file', TestApi01 = 'test_api_01', From 71ae08706b2774402381bde5b5eeb8439855e328 Mon Sep 17 00:00:00 2001 From: Alen <33656288+cnxysoft@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:49:16 +0800 Subject: [PATCH 6/6] release: v2.0.35 --- manifest.json | 2 +- package.json | 2 +- src/common/framework/napcat.ts | 2 +- src/onebot/action/msg/SendMsg/create-send-elements.ts | 4 ++-- src/webui/ui/NapCat.ts | 2 +- static/assets/renderer.js | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifest.json b/manifest.json index d4b59a65..effd6c28 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "NapCatQQ", "slug": "NapCat.Framework", "description": "高性能的 OneBot 11 协议实现", - "version": "2.0.34", + "version": "2.0.35", "icon": "./logo.png", "authors": [ { diff --git a/package.json b/package.json index 024d4dac..463b1d1d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "napcat", "private": true, "type": "module", - "version": "2.0.34", + "version": "2.0.35", "scripts": { "build:framework": "vite build --mode framework", "build:shell": "vite build --mode shell", diff --git a/src/common/framework/napcat.ts b/src/common/framework/napcat.ts index d9cf1a08..378d0db3 100644 --- a/src/common/framework/napcat.ts +++ b/src/common/framework/napcat.ts @@ -2,7 +2,7 @@ import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; -export const napcat_version = '2.0.34'; +export const napcat_version = '2.0.35'; export class NapCatPathWrapper { binaryPath: string; diff --git a/src/onebot/action/msg/SendMsg/create-send-elements.ts b/src/onebot/action/msg/SendMsg/create-send-elements.ts index d1b51405..ee917267 100644 --- a/src/onebot/action/msg/SendMsg/create-send-elements.ts +++ b/src/onebot/action/msg/SendMsg/create-send-elements.ts @@ -56,7 +56,7 @@ const _handlers: { if (atQQ === 'all') return SendMsgElementConstructor.at(coreContext, atQQ, atQQ, AtType.atAll, '全体成员'); // then the qq is a group member - // Mlikiowa V2.0.34 Refactor Todo + // Mlikiowa V2.0.35 Refactor Todo const uid = await coreContext.apis.UserApi.getUidByUinV2(`${atQQ}`); if (!uid) throw new Error('Get Uid Error'); return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, ''); @@ -161,7 +161,7 @@ const _handlers: { } else { postData = data; } - // Mlikiowa V2.0.34 Refactor Todo + // Mlikiowa V2.0.35 Refactor Todo const signUrl = obContext.configLoader.configData.musicSignUrl; if (!signUrl) { if (data.type === 'qq') { diff --git a/src/webui/ui/NapCat.ts b/src/webui/ui/NapCat.ts index 1e1092e3..b8c4006e 100644 --- a/src/webui/ui/NapCat.ts +++ b/src/webui/ui/NapCat.ts @@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) { SettingItem( 'Napcat', undefined, - SettingButton('V2.0.34', 'napcat-update-button', 'secondary'), + SettingButton('V2.0.35', 'napcat-update-button', 'secondary'), ), ]), SettingList([ diff --git a/static/assets/renderer.js b/static/assets/renderer.js index ad2e5327..ba3c3312 100644 --- a/static/assets/renderer.js +++ b/static/assets/renderer.js @@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) { SettingItem( 'Napcat', void 0, - SettingButton("V2.0.34", "napcat-update-button", "secondary") + SettingButton("V2.0.35", "napcat-update-button", "secondary") ) ]), SettingList([