From 24535097346c789442e2287abfc961c01de6728c Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:55:56 +0800 Subject: [PATCH 1/3] refactor --- src/ntqqapi/api/msg.ts | 24 +++++-- src/ntqqapi/hook.ts | 13 ++-- src/ntqqapi/ntcall.ts | 21 +++--- src/ntqqapi/types/user.ts | 2 +- .../action/go-cqhttp/GetStrangerInfo.ts | 70 ++++++++----------- .../action/go-cqhttp/UploadGroupFile.ts | 6 +- .../action/go-cqhttp/UploadPrivateFile.ts | 6 +- .../action/group/GetGroupMemberInfo.ts | 6 +- .../action/group/GetGroupMemberList.ts | 18 +++-- src/onebot11/connect/http.ts | 2 +- src/onebot11/entities.ts | 8 +-- src/onebot11/types.ts | 2 - 12 files changed, 95 insertions(+), 83 deletions(-) diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index 5f67c9c..57f22d5 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -62,21 +62,35 @@ export class NTQQMsgApi extends Service { async sendMsg(peer: Peer, msgElements: SendMessageElement[], timeout = 10000) { const uniqueId = await this.generateMsgUniqueId(peer.chatType) - peer.guildId = uniqueId + const msgAttributeInfos = new Map() + msgAttributeInfos.set(0, { + attrType: 0, + attrId: uniqueId, + vasMsgInfo: { + msgNamePlateInfo: {}, + bubbleInfo: {}, + avatarPendantInfo: {}, + vasFont: {}, + iceBreakInfo: {} + } + }) + + let sentMsgId: string const data = await invoke<{ msgList: RawMessage[] }>( 'nodeIKernelMsgService/sendMsg', [{ msgId: '0', peer, msgElements, - msgAttributeInfos: new Map() + msgAttributeInfos }], { cbCmd: 'nodeIKernelMsgListener/onMsgInfoListUpdate', afterFirstCmd: false, cmdCB: payload => { for (const msgRecord of payload.msgList) { - if (msgRecord.guildId === uniqueId && msgRecord.sendStatus === 2) { + if (msgRecord.msgAttrs.get(0)?.attrId === uniqueId && msgRecord.sendStatus === 2) { + sentMsgId = msgRecord.msgId return true } } @@ -85,8 +99,8 @@ export class NTQQMsgApi extends Service { timeout } ) - delete peer.guildId - return data.msgList.find(msgRecord => msgRecord.guildId === uniqueId) + + return data.msgList.find(msgRecord => msgRecord.msgId === sentMsgId) } async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) { diff --git a/src/ntqqapi/hook.ts b/src/ntqqapi/hook.ts index f00a576..104cfbe 100644 --- a/src/ntqqapi/hook.ts +++ b/src/ntqqapi/hook.ts @@ -29,11 +29,10 @@ export enum ReceiveCmdS { const logHook = false -const receiveHooks: Array<{ +const receiveHooks: Map void | Promise - id: string -}> = [] +}> = new Map() const callHooks: Array<{ method: NTMethod[] @@ -72,7 +71,7 @@ export function startHook() { } } else if (args[2]) { for (const receiveData of args[2]) { - for (const hook of receiveHooks) { + for (const hook of receiveHooks.values()) { if (hook.method.includes(receiveData.cmdName)) { Promise.resolve(hook.hookFunc(receiveData.payload)) } @@ -106,10 +105,9 @@ export function registerReceiveHook( if (!Array.isArray(method)) { method = [method] } - receiveHooks.push({ + receiveHooks.set(id, { method: method as ReceiveCmdS[], hookFunc, - id, }) return id } @@ -128,6 +126,5 @@ export function registerCallHook( } export function removeReceiveHook(id: string) { - const index = receiveHooks.findIndex((h) => h.id === id) - receiveHooks.splice(index, 1) + receiveHooks.delete(id) } diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts index 4a18105..87cdfae 100644 --- a/src/ntqqapi/ntcall.ts +++ b/src/ntqqapi/ntcall.ts @@ -147,17 +147,13 @@ export function invoke< const secondCallback = () => { eventId = registerReceiveHook(options.cbCmd!, (payload) => { if (options.cmdCB) { - if (options.cmdCB(payload, result)) { - removeReceiveHook(eventId) - clearTimeout(timeoutId) - resolve(payload) + if (!options.cmdCB(payload, result)) { + return } } - else { - removeReceiveHook(eventId) - clearTimeout(timeoutId) - resolve(payload) - } + removeReceiveHook(eventId) + clearTimeout(timeoutId) + resolve(payload) }) } !afterFirstCmd && secondCallback() @@ -167,9 +163,12 @@ export function invoke< afterFirstCmd && secondCallback() } else { - log('ntqq api call failed,', method, args, res) clearTimeout(timeoutId) - reject(`ntqq api call failed, ${method}, ${res?.errMsg}`) + if (eventId) { + removeReceiveHook(eventId) + } + log('ntqq api call failed,', method, args, res) + reject(`ntqq api call failed, ${method}, ${JSON.stringify(res)}`) } } } diff --git a/src/ntqqapi/types/user.ts b/src/ntqqapi/types/user.ts index 05ef0eb..d33976b 100644 --- a/src/ntqqapi/types/user.ts +++ b/src/ntqqapi/types/user.ts @@ -296,7 +296,7 @@ export interface UserDetailInfoByUin { birthday_year: number birthday_month: number birthday_day: number - sex: number //0 + sex: number topTime: string constellation: number shengXiao: number diff --git a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts index 0557d4e..35a403b 100644 --- a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts +++ b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts @@ -3,59 +3,51 @@ import { OB11User } from '../../types' import { OB11Entities } from '../../entities' import { ActionName } from '../types' import { getBuildVersion } from '@/common/utils' -import { OB11UserSex } from '../../types' import { calcQQLevel } from '@/common/utils/misc' interface Payload { user_id: number | string } -export class GetStrangerInfo extends BaseAction { +interface Response extends OB11User { + reg_time: number + long_nick: string +} + +export class GetStrangerInfo extends BaseAction { actionName = ActionName.GoCQHTTP_GetStrangerInfo payloadSchema = Schema.object({ user_id: Schema.union([Number, String]).required() }) - protected async _handle(payload: Payload): Promise { - if (!(getBuildVersion() >= 26702)) { - const user_id = payload.user_id.toString() - const extendData = await this.ctx.ntUserApi.getUserDetailInfoByUin(user_id) - const uid = (await this.ctx.ntUserApi.getUidByUin(user_id))! - if (!uid || uid.indexOf('*') != -1) { - const ret = { - ...extendData, - user_id: parseInt(extendData.info.uin) || 0, - nickname: extendData.info.nick, - sex: OB11UserSex.Unknown, - age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year, - qid: extendData.info.qid, - level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0, - login_days: 0, - uid: '' - } - return ret + protected async _handle(payload: Payload) { + const uin = payload.user_id.toString() + if (getBuildVersion() >= 26702) { + const data = await this.ctx.ntUserApi.getUserDetailInfoByUinV2(uin) + return { + user_id: parseInt(data.detail.uin) || 0, + nickname: data.detail.simpleInfo.coreInfo.nick, + sex: OB11Entities.sex(data.detail.simpleInfo.baseInfo.sex), + age: data.detail.simpleInfo.baseInfo.age, + qid: data.detail.simpleInfo.baseInfo.qid, + level: data.detail.commonExt.qqLevel && calcQQLevel(data.detail.commonExt.qqLevel) || 0, + login_days: 0, + reg_time: data.detail.commonExt.regTime, + long_nick: data.detail.simpleInfo.baseInfo.longNick } - const data = { ...extendData, ...(await this.ctx.ntUserApi.getUserDetailInfo(uid)) } - return OB11Entities.stranger(data) } else { - const user_id = payload.user_id.toString() - const extendData = await this.ctx.ntUserApi.getUserDetailInfoByUinV2(user_id) - const uid = (await this.ctx.ntUserApi.getUidByUin(user_id))! - if (!uid || uid.indexOf('*') != -1) { - const ret = { - ...extendData, - user_id: parseInt(extendData.detail.uin) || 0, - nickname: extendData.detail.simpleInfo.coreInfo.nick, - sex: OB11UserSex.Unknown, - age: 0, - level: extendData.detail.commonExt.qqLevel && calcQQLevel(extendData.detail.commonExt.qqLevel) || 0, - login_days: 0, - uid: '' - } - return ret + const data = await this.ctx.ntUserApi.getUserDetailInfoByUin(uin) + return { + user_id: parseInt(data.info.uin) || 0, + nickname: data.info.nick, + sex: OB11Entities.sex(data.info.sex), + age: data.info.birthday_year === 0 ? 0 : new Date().getFullYear() - data.info.birthday_year, + qid: data.info.qid, + level: data.info.qqLevel && calcQQLevel(data.info.qqLevel) || 0, + login_days: 0, + reg_time: data.info.regTime, + long_nick: data.info.longNick } - const data = { ...extendData, ...(await this.ctx.ntUserApi.getUserDetailInfo(uid)) } - return OB11Entities.stranger(data) } } } diff --git a/src/onebot11/action/go-cqhttp/UploadGroupFile.ts b/src/onebot11/action/go-cqhttp/UploadGroupFile.ts index 80c4a99..b735ea5 100644 --- a/src/onebot11/action/go-cqhttp/UploadGroupFile.ts +++ b/src/onebot11/action/go-cqhttp/UploadGroupFile.ts @@ -27,7 +27,11 @@ export class UploadGroupFile extends BaseAction { if (!success) { throw new Error(errMsg) } - const file = await SendElement.file(this.ctx, path, payload.name || fileName, payload.folder ?? payload.folder_id) + const name = payload.name || fileName + if (name.includes('/') || name.includes('\\')) { + throw new Error(`文件名 ${name} 不合法`) + } + const file = await SendElement.file(this.ctx, path, name, payload.folder ?? payload.folder_id) const peer = await createPeer(this.ctx, payload, CreatePeerMode.Group) await sendMsg(this.ctx, peer, [file], []) return null diff --git a/src/onebot11/action/go-cqhttp/UploadPrivateFile.ts b/src/onebot11/action/go-cqhttp/UploadPrivateFile.ts index 79e4fa5..56d8eb3 100644 --- a/src/onebot11/action/go-cqhttp/UploadPrivateFile.ts +++ b/src/onebot11/action/go-cqhttp/UploadPrivateFile.ts @@ -23,7 +23,11 @@ export class UploadPrivateFile extends BaseAction { if (!uid) throw new Error('无法获取用户信息') const member = await this.ctx.ntGroupApi.getGroupMember(groupCode, uid, payload.no_cache) if (member) { - const ret = OB11Entities.groupMember(groupCode, member) - const date = Math.round(Date.now() / 1000) + const ret = OB11Entities.groupMember(+groupCode, member) + const date = Math.trunc(Date.now() / 1000) ret.last_sent_time ??= date ret.join_time ??= date const info = await this.ctx.ntUserApi.getUserDetailInfo(member.uid) ret.sex = OB11Entities.sex(info.sex!) - ret.qq_level = (info.qqLevel && calcQQLevel(info.qqLevel)) || 0 + ret.qq_level = info.qqLevel && calcQQLevel(info.qqLevel) || 0 ret.age = info.age ?? 0 return ret } diff --git a/src/onebot11/action/group/GetGroupMemberList.ts b/src/onebot11/action/group/GetGroupMemberList.ts index a6576c7..d4b15e5 100644 --- a/src/onebot11/action/group/GetGroupMemberList.ts +++ b/src/onebot11/action/group/GetGroupMemberList.ts @@ -21,18 +21,22 @@ class GetGroupMemberList extends BaseAction { if (groupMembers.size > 0) { break } - await this.ctx.sleep(100) + await this.ctx.sleep(60) groupMembers = await this.ctx.ntGroupApi.getGroupMembers(groupCode) } - const groupMembersArr = Array.from(groupMembers.values()) - const date = Math.round(Date.now() / 1000) - return groupMembersArr.map(item => { - const member = OB11Entities.groupMember(groupCode, item) + const date = Math.trunc(Date.now() / 1000) + const groupId = Number(payload.group_id) + const ret: OB11GroupMember[] = [] + + for (const item of groupMembers.values()) { + const member = OB11Entities.groupMember(groupId, item) member.join_time ??= date member.last_sent_time ??= date - return member - }) + ret.push(member) + } + + return ret } } diff --git a/src/onebot11/connect/http.ts b/src/onebot11/connect/http.ts index 8eeda4f..2cb6e5c 100644 --- a/src/onebot11/connect/http.ts +++ b/src/onebot11/connect/http.ts @@ -155,7 +155,7 @@ class OB11HttpPost { } public async emitEvent(event: OB11BaseEvent | OB11Message) { - if (!this.activated) { + if (!this.activated || !this.config.hosts.length) { return } const msgStr = JSON.stringify(event) diff --git a/src/onebot11/entities.ts b/src/onebot11/entities.ts index dd32cd7..7b8b3f5 100644 --- a/src/onebot11/entities.ts +++ b/src/onebot11/entities.ts @@ -673,14 +673,14 @@ export namespace OB11Entities { [Sex.female]: OB11UserSex.Female, [Sex.unknown]: OB11UserSex.Unknown, } - return sexMap[sex] || OB11UserSex.Unknown + return sexMap[sex] ?? OB11UserSex.Unknown } - export function groupMember(group_id: string, member: GroupMember): OB11GroupMember { + export function groupMember(groupId: number, member: GroupMember): OB11GroupMember { const titleExpireTime = +member.specialTitleExpireTime - const int32Max = Math.pow(2, 31) - 1 + const int32Max = 2147483647 return { - group_id: parseInt(group_id), + group_id: groupId, user_id: parseInt(member.uin), nickname: member.nick, card: member.cardName || member.nick, diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts index f573d29..9a2c339 100644 --- a/src/onebot11/types.ts +++ b/src/onebot11/types.ts @@ -11,8 +11,6 @@ export interface OB11User { age?: number qid?: string login_days?: number - categroyName?: string - categoryId?: number } export enum OB11UserSex { From 2910b8f4e60366be22cb702741c4494910bdf80c Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:09:51 +0800 Subject: [PATCH 2/3] optimize --- src/ntqqapi/core.ts | 17 ++++---- src/ntqqapi/types/msg.ts | 4 ++ .../action/user/SetFriendAddRequest.ts | 4 +- src/onebot11/entities.ts | 40 +++++++++---------- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/ntqqapi/core.ts b/src/ntqqapi/core.ts index 035c8d9..347e07f 100644 --- a/src/ntqqapi/core.ts +++ b/src/ntqqapi/core.ts @@ -173,9 +173,10 @@ class Core extends Service { }) registerReceiveHook<{ msgList: RawMessage[] }>([ReceiveCmdS.NEW_MSG, ReceiveCmdS.NEW_ACTIVE_MSG], payload => { + const startTime = this.startTime / 1000 for (const message of payload.msgList) { // 过滤启动之前的消息 - if (parseInt(message.msgTime) < this.startTime / 1000) { + if (parseInt(message.msgTime) < startTime) { continue } if (message.senderUin && message.senderUin !== '0') { @@ -202,7 +203,9 @@ class Core extends Service { this.ctx.parallel('nt/message-deleted', msg) } else if (sentMsgIds.get(msg.msgId)) { sentMsgIds.delete(msg.msgId) - this.ctx.parallel('nt/message-sent', msg) + if (msg.sendStatus === 2) { + this.ctx.parallel('nt/message-sent', msg) + } } } }) @@ -211,7 +214,7 @@ class Core extends Service { sentMsgIds.set(payload.msgRecord.msgId, true) }) - const groupNotifyFlags: string[] = [] + const groupNotifyIgnore: string[] = [] registerReceiveHook<{ doubt: boolean oldestUnreadSeq: string @@ -225,13 +228,11 @@ class Core extends Service { return } for (const notify of notifies) { - const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type - const notifyTime = parseInt(notify.seq) / 1000 - if (groupNotifyFlags.includes(flag) || notifyTime < this.startTime) { + const notifyTime = Math.trunc(+notify.seq / 1000) + if (groupNotifyIgnore.includes(notify.seq) || notifyTime < this.startTime) { continue } - groupNotifyFlags.shift() - groupNotifyFlags.push(flag) + groupNotifyIgnore.push(notify.seq) this.ctx.parallel('nt/group-notify', notify) } } diff --git a/src/ntqqapi/types/msg.ts b/src/ntqqapi/types/msg.ts index d8ae0d6..8f1ba94 100644 --- a/src/ntqqapi/types/msg.ts +++ b/src/ntqqapi/types/msg.ts @@ -438,6 +438,10 @@ export interface RawMessage { likesCnt: string isClicked: boolean }[] + msgAttrs: Map } export interface Peer { diff --git a/src/onebot11/action/user/SetFriendAddRequest.ts b/src/onebot11/action/user/SetFriendAddRequest.ts index 864d4d5..9f6cc39 100644 --- a/src/onebot11/action/user/SetFriendAddRequest.ts +++ b/src/onebot11/action/user/SetFriendAddRequest.ts @@ -23,11 +23,11 @@ export default class SetFriendAddRequest extends BaseAction { if (payload.remark) { await this.ctx.ntFriendApi.setBuddyRemark(uid, payload.remark) } - await this.ctx.ntMsgApi.activateChat({ + /*await this.ctx.ntMsgApi.activateChat({ peerUid: uid, chatType: ChatType.C2C, guildId: '' - }) + })*/ return null } } diff --git a/src/onebot11/entities.ts b/src/onebot11/entities.ts index 7b8b3f5..1a84606 100644 --- a/src/onebot11/entities.ts +++ b/src/onebot11/entities.ts @@ -71,7 +71,7 @@ export namespace OB11Entities { sub_type: 'friend', message: messagePostFormat === 'string' ? '' : [], message_format: messagePostFormat === 'string' ? 'string' : 'array', - post_type: selfUin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE, + post_type: selfUin === msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE, } if (debug) { resMsg.raw = msg @@ -376,11 +376,23 @@ export namespace OB11Entities { if (msg.chatType !== ChatType.C2C) { return } + if (msg.msgType !== 5) { + return + } + for (const element of msg.elements) { if (element.grayTipElement) { const { grayTipElement } = element if (grayTipElement.jsonGrayTipElement?.busiId === '1061') { const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr) + const param = grayTipElement.jsonGrayTipElement.xmlToJsonParam + if (param) { + return new OB11FriendPokeEvent( + Number(param.templParam.get('uin_str1')), + Number(param.templParam.get('uin_str2')), + json.items + ) + } const pokedetail: Dict[] = json.items //筛选item带有uid的元素 const poke_uid = pokedetail.filter(item => item.uid) @@ -405,31 +417,15 @@ export namespace OB11Entities { if (msg.chatType !== ChatType.Group) { return } - /**if (msg.senderUin) { - const member = await ctx.ntGroupApi.getGroupMember(msg.peerUid, msg.senderUin) - if (member && member.cardName !== msg.sendMemberName) { - const event = new OB11GroupCardEvent( - parseInt(msg.peerUid), - parseInt(msg.senderUin), - msg.sendMemberName!, - member.cardName, - ) - member.cardName = msg.sendMemberName! - return event - } - }*/ + if (msg.msgType !== 5 && msg.msgType !== 3) { + return + } + for (const element of msg.elements) { const grayTipElement = element.grayTipElement const groupElement = grayTipElement?.groupElement if (groupElement) { - if (groupElement.type === TipGroupElementType.MemberIncrease) { - /*ctx.logger.info('收到群成员增加消息', groupElement) - const { memberUid, adminUid } = groupElement - const memberUin = await ctx.ntUserApi.getUinByUid(memberUid) - const operatorUin = adminUid ? await ctx.ntUserApi.getUinByUid(adminUid) : memberUin - return new OB11GroupIncreaseEvent(+msg.peerUid, +memberUin, +operatorUin)*/ - } - else if (groupElement.type === TipGroupElementType.Ban) { + if (groupElement.type === TipGroupElementType.Ban) { ctx.logger.info('收到群成员禁言提示', groupElement) const memberUid = groupElement.shutUp?.member.uid const adminUid = groupElement.shutUp?.admin.uid From 1b0c9ad57ccb383dd27559dc37e3e40e344d9263 Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:10:57 +0800 Subject: [PATCH 3/3] chore: bump versions --- manifest.json | 2 +- src/version.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index 54fd8ba..873b9ef 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "LLOneBot", "slug": "LLOneBot", "description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发", - "version": "4.0.11", + "version": "4.0.12", "icon": "./icon.webp", "authors": [ { diff --git a/src/version.ts b/src/version.ts index 287e10a..5d09b2a 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const version = '4.0.11' +export const version = '4.0.12'