diff --git a/manifest.json b/manifest.json index 6529520..049c050 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "LLOneBot", "slug": "LLOneBot", "description": "实现 OneBot 11 协议,用于 QQ 机器人开发", - "version": "3.32.6", + "version": "3.32.7", "icon": "./icon.webp", "authors": [ { diff --git a/src/main/log.ts b/src/main/log.ts index a955da6..6347564 100644 --- a/src/main/log.ts +++ b/src/main/log.ts @@ -23,8 +23,7 @@ export default class Log { return } const dateTime = new Date(record.timestamp).toLocaleString() - const userInfo = selfInfo.uin ? `${selfInfo.nick}(${selfInfo.uin})` : '' - const content = `${dateTime} [${record.type}] ${userInfo} | ${record.name} ${record.content}\n\n` + const content = `${dateTime} [${record.type}] ${selfInfo.nick}(${selfInfo.uin}) | ${record.name} ${record.content}\n\n` appendFile(file, content, noop) }, } diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index 3698ac8..c478826 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -183,7 +183,7 @@ export class NTQQMsgApi extends Service { if (!arkElement) { continue } - const forwardData = JSON.parse(arkElement.arkElement.bytesData) + const forwardData = JSON.parse(arkElement.arkElement!.bytesData) if (forwardData.app != 'com.tencent.multimsg') { continue } diff --git a/src/ntqqapi/core.ts b/src/ntqqapi/core.ts index 2d32bc4..8b247fc 100644 --- a/src/ntqqapi/core.ts +++ b/src/ntqqapi/core.ts @@ -27,8 +27,8 @@ declare module 'cordis' { } interface Events { 'nt/message-created': (input: RawMessage[]) => void - 'nt/message-deleted': (input: RawMessage[]) => void - 'nt/message-sent': (input: RawMessage[]) => void + 'nt/message-deleted': (input: RawMessage) => void + 'nt/message-sent': (input: RawMessage) => void 'nt/group-notify': (input: GroupNotify[]) => void 'nt/friend-request': (input: FriendRequest[]) => void 'nt/group-member-info-updated': (input: { groupCode: string, members: GroupMember[] }) => void @@ -96,7 +96,7 @@ class Core extends Service { } for (const path of pathList) { if (path) { - fs.unlink(picPath, () => { + fs.unlink(path, () => { this.ctx.logger.info('删除文件成功', path) }) } @@ -174,23 +174,26 @@ class Core extends Service { this.ctx.parallel('nt/message-created', payload.msgList) }) + const sentMsgIds = new Map() const recallMsgIds: string[] = [] // 避免重复上报 + registerReceiveHook<{ msgList: RawMessage[] }>([ReceiveCmdS.UPDATE_MSG], payload => { - const list = payload.msgList.filter(v => { - if (recallMsgIds.includes(v.msgId)) { - return false + for (const msg of payload.msgList) { + if (msg.recallTime !== '0' && !recallMsgIds.includes(msg.msgId)) { + recallMsgIds.push(msg.msgId) + this.ctx.parallel('nt/message-deleted', msg) + } else if (sentMsgIds.get(msg.msgId)) { + sentMsgIds.delete(msg.msgId) + this.ctx.parallel('nt/message-sent', msg) } - recallMsgIds.push(v.msgId) - return true - }) - this.ctx.parallel('nt/message-deleted', list) + } }) registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmdS.SELF_SEND_MSG, payload => { if (!this.config.reportSelfMessage) { return } - this.ctx.parallel('nt/message-sent', [payload.msgRecord]) + sentMsgIds.set(payload.msgRecord.msgId, true) }) const groupNotifyFlags: string[] = [] diff --git a/src/ntqqapi/types/msg.ts b/src/ntqqapi/types/msg.ts index 977c16b..666a755 100644 --- a/src/ntqqapi/types/msg.ts +++ b/src/ntqqapi/types/msg.ts @@ -102,7 +102,7 @@ export interface SendPicElement { export interface SendReplyElement { elementType: ElementType.REPLY elementId: '' - replyElement: ReplyElement + replyElement: Partial } export interface SendFaceElement { @@ -129,6 +129,12 @@ export interface ReplyElement { replayMsgId: string senderUin: string senderUinStr: string + sourceMsgIdInRecords: string + senderUid: string + senderUidStr: string + sourceMsgIsIncPic: boolean // 原消息是否有图片 + sourceMsgText: string + replyMsgTime: string } export interface FileElement { @@ -303,7 +309,7 @@ export enum GrayTipElementSubType { export interface GrayTipElement { subElementType: GrayTipElementSubType - revokeElement: { + revokeElement?: { operatorRole: string operatorUid: string operatorNick: string @@ -313,14 +319,14 @@ export interface GrayTipElement { isSelfOperate?: boolean wording: string // 自定义的撤回提示语 } - aioOpGrayTipElement: TipAioOpGrayTipElement - groupElement: TipGroupElement - xmlElement: { + aioOpGrayTipElement?: TipAioOpGrayTipElement + groupElement?: TipGroupElement + xmlElement?: { templId: string content: string } - jsonGrayTipElement: { - busiId: number + jsonGrayTipElement?: { + busiId: string jsonStr: string } } @@ -485,36 +491,7 @@ export interface RawMessage { sendStatus?: number // 消息状态,别人发的2是已撤回,自己发的2是已发送 recallTime: string // 撤回时间, "0"是没有撤回 records: RawMessage[] - elements: { - elementId: string - elementType: ElementType - replyElement: { - sourceMsgIdInRecords: string - senderUid: string // 原消息发送者QQ号 - sourceMsgIsIncPic: boolean // 原消息是否有图片 - sourceMsgText: string - replayMsgSeq: string // 源消息的msgSeq,可以通过这个找到源消息的msgId - senderUidStr: string - replyMsgTime: string - } - textElement: { - atType: AtType - atUid: string // QQ号 - content: string - atNtUid: string // uid号 - } - picElement: PicElement - pttElement: PttElement - arkElement: ArkElement - grayTipElement: GrayTipElement - faceElement: FaceElement - videoElement: VideoElement - fileElement: FileElement - marketFaceElement: MarketFaceElement - inlineKeyboardElement: InlineKeyboardElement - markdownElement: MarkdownElement - multiForwardMsgElement: MultiForwardMsgElement - }[] + elements: MessageElement[] } export interface Peer { @@ -529,7 +506,7 @@ export interface MessageElement { extBufForUI: string //"0x" textElement?: TextElement faceElement?: FaceElement - marketFaceElement?: MarkdownElement + marketFaceElement?: MarketFaceElement replyElement?: ReplyElement picElement?: PicElement pttElement?: PttElement diff --git a/src/onebot11/action/file/GetFile.ts b/src/onebot11/action/file/GetFile.ts index 07c37e8..d8bdb56 100644 --- a/src/onebot11/action/file/GetFile.ts +++ b/src/onebot11/action/file/GetFile.ts @@ -59,7 +59,7 @@ export abstract class GetFileBase extends BaseAction { - if (recallEvent) { - this.dispatch(recallEvent) - } - }) - } + private handleRecallMsg(message: RawMessage) { + const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId) + if (!oriMessageId) { + return } + OB11Entities.recallEvent(this.ctx, message, oriMessageId).then((recallEvent) => { + if (recallEvent) { + this.dispatch(recallEvent) + } + }) } private async handleFriendRequest(buddyReqs: FriendRequest[]) { @@ -404,7 +400,7 @@ class OneBot11Adapter extends Service { this.handleRecallMsg(input) }) this.ctx.on('nt/message-sent', input => { - this.handleMsg(input) + this.handleMsg([input]) }) this.ctx.on('nt/group-notify', input => { this.handleGroupNotify(input) diff --git a/src/onebot11/entities.ts b/src/onebot11/entities.ts index 421e74f..ad513b3 100644 --- a/src/onebot11/entities.ts +++ b/src/onebot11/entities.ts @@ -375,29 +375,25 @@ export namespace OB11Entities { for (const element of msg.elements) { if (element.grayTipElement) { const { grayTipElement } = element - if (grayTipElement.subElementType === GrayTipElementSubType.JSON) { + if (grayTipElement.jsonGrayTipElement?.busiId === '1061') { const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr) - if (grayTipElement.jsonGrayTipElement.busiId === 1061) { - const pokedetail: Dict[] = json.items - //筛选item带有uid的元素 - const poke_uid = pokedetail.filter(item => item.uid) - if (poke_uid.length == 2) { - return new OB11FriendPokeEvent( - parseInt(await ctx.ntUserApi.getUinByUid(poke_uid[0].uid)), - parseInt(await ctx.ntUserApi.getUinByUid(poke_uid[1].uid)), - pokedetail - ) - } + const pokedetail: Dict[] = json.items + //筛选item带有uid的元素 + const poke_uid = pokedetail.filter(item => item.uid) + if (poke_uid.length === 2) { + return new OB11FriendPokeEvent( + Number(await ctx.ntUserApi.getUinByUid(poke_uid[0].uid)), + Number(await ctx.ntUserApi.getUinByUid(poke_uid[1].uid)), + pokedetail + ) } } + if (grayTipElement.xmlElement?.templId === '10229') { + const uin = +msg.peerUin || +(await ctx.ntUserApi.getUinByUid(msg.peerUid)) + return new OB11FriendAddNoticeEvent(uin) + } } } - // 好友增加事件 - if (msg.msgType === 5 && msg.subMsgType === 12) { - const uin = +msg.peerUin || +(await ctx.ntUserApi.getUinByUid(msg.peerUid)) - const event = new OB11FriendAddNoticeEvent(uin) - return event - } } export async function groupEvent(ctx: Context, msg: RawMessage): Promise { @@ -564,8 +560,8 @@ export namespace OB11Entities { } } else if (grayTipElement.subElementType == GrayTipElementSubType.JSON) { - const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr) - if (grayTipElement.jsonGrayTipElement.busiId == 1061) { + const json = JSON.parse(grayTipElement.jsonGrayTipElement!.jsonStr) + if (grayTipElement.jsonGrayTipElement?.busiId === '1061') { const pokedetail: Dict[] = json.items //筛选item带有uid的元素 const poke_uid = pokedetail.filter(item => item.uid) @@ -578,7 +574,7 @@ export namespace OB11Entities { ) } } - if (grayTipElement.jsonGrayTipElement.busiId == 2401) { + if (grayTipElement.jsonGrayTipElement?.busiId === '2401') { ctx.logger.info('收到群精华消息', json) const searchParams = new URL(json.items[0].jp).searchParams const msgSeq = searchParams.get('msgSeq')! @@ -605,7 +601,7 @@ export namespace OB11Entities { ) // 获取MsgSeq+Peer可获取具体消息 } - if (grayTipElement.jsonGrayTipElement.busiId == 2407) { + if (grayTipElement.jsonGrayTipElement?.busiId === '2407') { const memberUin = json.items[1].param[0] const title = json.items[3].txt ctx.logger.info('收到群成员新头衔消息', json) @@ -632,9 +628,9 @@ export namespace OB11Entities { if (!msgElement) { return } - const revokeElement = msgElement.grayTipElement.revokeElement + const revokeElement = msgElement.grayTipElement!.revokeElement if (msg.chatType === ChatType.group) { - const operator = await ctx.ntGroupApi.getGroupMember(msg.peerUid, revokeElement.operatorUid) + const operator = await ctx.ntGroupApi.getGroupMember(msg.peerUid, revokeElement!.operatorUid) return new OB11GroupRecallNoticeEvent( parseInt(msg.peerUid), parseInt(msg.senderUin!), diff --git a/src/version.ts b/src/version.ts index 52292a9..3997e97 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const version = '3.32.6' +export const version = '3.32.7'