From c6b302d5a8a2c8843c084bfbafe26a746cae5a12 Mon Sep 17 00:00:00 2001 From: Alen Date: Tue, 16 Jul 2024 20:27:44 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E6=88=B3=E4=B8=80=E6=88=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 取缔FriendAddEvent,并入Private Event处理 --- src/main/main.ts | 18 +++++--- src/onebot11/constructor.ts | 51 +++++++++++++++++----- src/onebot11/event/notice/OB11PokeEvent.ts | 9 ++-- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index f7b6019..cb86fa6 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -191,12 +191,20 @@ function onLoad() { postOb11Event(groupEvent) } }) - OB11Constructor.FriendAddEvent(message).then((friendAddEvent) => { - if (friendAddEvent) { - // log("post friend add event", friendAddEvent); - postOb11Event(friendAddEvent) + OB11Constructor.PrivateEvent(message).then((privateEvent) => { + log(message) + if (privateEvent) { + // log("post private event", privateEvent); + postOb11Event(privateEvent) } }) + // OB11Constructor.FriendAddEvent(message).then((friendAddEvent) => { + // log(message) + // if (friendAddEvent) { + // // log("post friend add event", friendAddEvent); + // postOb11Event(friendAddEvent) + // } + // }) } } @@ -215,7 +223,7 @@ function onLoad() { pokeEvent = new OB11GroupPokeEvent(parseInt(id)) } else { - pokeEvent = new OB11FriendPokeEvent(parseInt(id)) + pokeEvent = new OB11FriendPokeEvent(parseInt(selfInfo.uin), parseInt(id)) } postOb11Event(pokeEvent) }) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index e3120d7..67af8f3 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -47,7 +47,8 @@ import { mFaceCache } from '../ntqqapi/constructor' import { OB11FriendAddNoticeEvent } from './event/notice/OB11FriendAddNoticeEvent' import { OB11FriendRecallNoticeEvent } from './event/notice/OB11FriendRecallNoticeEvent' import { OB11GroupRecallNoticeEvent } from './event/notice/OB11GroupRecallNoticeEvent' -import { OB11GroupPokeEvent } from './event/notice/OB11PokeEvent' +import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent' +import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent'; let lastRKeyUpdateTime = 0 @@ -308,7 +309,33 @@ export class OB11Constructor { resMsg.raw_message = resMsg.raw_message.trim() return resMsg } - + static async PrivateEvent(msg: RawMessage): Promise { + if (msg.chatType !== ChatType.friend) { + return; + } + for (const element of msg.elements) { + if (element.grayTipElement) { + if (element.grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) { + const json = JSON.parse(element.grayTipElement.jsonGrayTipElement.jsonStr); + if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) { + //判断业务类型 + //Poke事件 + let pokedetail: any[] = json.items; + //筛选item带有uid的元素 + pokedetail = pokedetail.filter(item => item.uid); + if (pokedetail.length == 2) { + return new OB11FriendPokeEvent(parseInt((uidMaps[pokedetail[0].uid])!), parseInt((uidMaps[pokedetail[1].uid]))); + } + } + //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE + } + } + } + if (msg.msgType === 5 && msg.subMsgType === 12) { + const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin)) + return event + } + } static async GroupEvent(msg: RawMessage): Promise { if (msg.chatType !== ChatType.group) { return @@ -515,16 +542,16 @@ export class OB11Constructor { } } - static async FriendAddEvent(msg: RawMessage): Promise { - if (msg.chatType !== ChatType.friend) { - return - } - if (msg.msgType === 5 && msg.subMsgType === 12) { - const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin)) - return event - } - return - } + // static async FriendAddEvent(msg: RawMessage): Promise { + // if (msg.chatType !== ChatType.friend) { + // return + // } + // if (msg.msgType === 5 && msg.subMsgType === 12) { + // const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin)) + // return event + // } + // return + // } static async RecallEvent( msg: RawMessage, diff --git a/src/onebot11/event/notice/OB11PokeEvent.ts b/src/onebot11/event/notice/OB11PokeEvent.ts index 1c8f964..4811a35 100644 --- a/src/onebot11/event/notice/OB11PokeEvent.ts +++ b/src/onebot11/event/notice/OB11PokeEvent.ts @@ -10,11 +10,10 @@ class OB11PokeEvent extends OB11BaseNoticeEvent { } export class OB11FriendPokeEvent extends OB11PokeEvent { - sender_id: number - constructor(user_id: number) { - super() - this.user_id = user_id - this.sender_id = user_id + constructor(user_id: number, target_id: number) { + super(); + this.target_id = target_id; + this.user_id = user_id; } } From f9454039a1fffd5da5e3a5925fba834c64c2fc8f Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 16 Jul 2024 21:52:15 +0800 Subject: [PATCH 02/11] fix: old poke event --- src/onebot11/event/notice/OB11PokeEvent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/onebot11/event/notice/OB11PokeEvent.ts b/src/onebot11/event/notice/OB11PokeEvent.ts index 4811a35..68adb78 100644 --- a/src/onebot11/event/notice/OB11PokeEvent.ts +++ b/src/onebot11/event/notice/OB11PokeEvent.ts @@ -10,7 +10,7 @@ class OB11PokeEvent extends OB11BaseNoticeEvent { } export class OB11FriendPokeEvent extends OB11PokeEvent { - constructor(user_id: number, target_id: number) { + constructor(user_id: number, target_id: number=0) { super(); this.target_id = target_id; this.user_id = user_id; From 7a33a36f443bd64545afb633dc2d88f37e9ebc29 Mon Sep 17 00:00:00 2001 From: super1207 Date: Sat, 20 Jul 2024 17:58:00 +0800 Subject: [PATCH 03/11] add get_event api --- src/onebot11/action/index.ts | 2 + src/onebot11/action/llonebot/GetEvent.ts | 23 ++++++++ src/onebot11/action/types.ts | 1 + src/onebot11/server/event-for-http.ts | 68 ++++++++++++++++++++++++ src/onebot11/server/post-ob11-event.ts | 6 +++ 5 files changed, 100 insertions(+) create mode 100644 src/onebot11/action/llonebot/GetEvent.ts create mode 100644 src/onebot11/server/event-for-http.ts diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index 3785082..ad57dc1 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -50,6 +50,7 @@ import { ForwardFriendSingleMsg, ForwardGroupSingleMsg } from './msg/ForwardSing import { GetGroupEssence } from './group/GetGroupEssence' import { GetGroupHonorInfo } from './group/GetGroupHonorInfo' import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation' +import GetEvent from './llonebot/GetEvent' export const actionHandlers = [ new GetFile(), @@ -59,6 +60,7 @@ export const actionHandlers = [ new GetGroupAddRequest(), new SetQQAvatar(), new GetFriendWithCategory(), + new GetEvent(), // onebot11 new SendLike(), new GetMsg(), diff --git a/src/onebot11/action/llonebot/GetEvent.ts b/src/onebot11/action/llonebot/GetEvent.ts new file mode 100644 index 0000000..09827b1 --- /dev/null +++ b/src/onebot11/action/llonebot/GetEvent.ts @@ -0,0 +1,23 @@ +import BaseAction from '../BaseAction' +import { ActionName } from '../types' +import { getHttpEvent } from '../../server/event-for-http' +import { PostEventType } from '../../server/post-ob11-event' +// import { log } from "../../../common/utils"; + +interface Payload { + key: string + timeout: number +} + +export default class GetEvent extends BaseAction { + actionName = ActionName.GetEvent + protected async _handle(payload: Payload): Promise { + let key = '' + if (payload.key) { + key = payload.key; + } + let timeout = parseInt(payload.timeout?.toString()) || 0; + let evts = await getHttpEvent(key,timeout); + return evts; + } +} diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index 1b61ecc..f5b1abb 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -22,6 +22,7 @@ export enum ActionName { Debug = 'llonebot_debug', GetFile = 'get_file', GetFriendsWithCategory = 'get_friends_with_category', + GetEvent = 'get_event', // onebot 11 SendLike = 'send_like', GetLoginInfo = 'get_login_info', diff --git a/src/onebot11/server/event-for-http.ts b/src/onebot11/server/event-for-http.ts new file mode 100644 index 0000000..086aa2a --- /dev/null +++ b/src/onebot11/server/event-for-http.ts @@ -0,0 +1,68 @@ +import { PostEventType } from "./post-ob11-event" + + +interface HttpEventType { + seq: number + event: PostEventType +} + +interface HttpUserType { + lastAccessTime: number + userSeq: number +} + +let curentSeq:number = 0; +let eventList:HttpEventType[] = []; +let httpUser:Record = {}; + + +export function postHttpEvent(event: PostEventType) { + curentSeq += 1; + eventList.push({ + seq: curentSeq, + event: event + }); + while(eventList.length > 100) { + eventList.shift(); + } +} + + +export async function getHttpEvent(userKey:string,timeout = 0) { + let toRetEvent = []; + + // 清除过时的user,5分钟没访问过的user将被删除 + let now = Date.now(); + for(let key in httpUser) { + let user = httpUser[key]; + if(now - user.lastAccessTime > 1000 * 60 * 5) { + delete httpUser[key]; + } + } + + // 增加新的user + if(!httpUser[userKey] ) { + httpUser[userKey] = { + lastAccessTime: now, + userSeq: curentSeq + } + } + + let user = httpUser[userKey]; + // 等待数据到来,暂时先这么写吧...... + while(curentSeq == user.userSeq && Date.now() - now < timeout) { + await new Promise( resolve => setTimeout(resolve, 10) ); + } + // 取数据 + for(let i = 0; i < eventList.length; i++) { + let evt = eventList[i]; + if(evt.seq > user.userSeq) { + toRetEvent.push(evt.event); + } + } + + // 更新user数据 + user.lastAccessTime = Date.now(); + user.userSeq = curentSeq; + return toRetEvent; +} diff --git a/src/onebot11/server/post-ob11-event.ts b/src/onebot11/server/post-ob11-event.ts index d78f130..c781ea6 100644 --- a/src/onebot11/server/post-ob11-event.ts +++ b/src/onebot11/server/post-ob11-event.ts @@ -8,6 +8,7 @@ import { log } from '@/common/utils' import { getConfigUtil } from '@/common/config' import crypto from 'crypto' import { handleQuickOperation, QuickOperationEvent } from '../action/quick-operation' +import { postHttpEvent } from './event-for-http' export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent @@ -78,4 +79,9 @@ export function postOb11Event(msg: PostEventType, reportSelf = false, postWs = t if (postWs) { postWsEvent(msg) } + if(!(msg.post_type == 'meta_event' && (msg as OB11BaseMetaEvent).meta_event_type == 'heartbeat')) { + // 不上报心跳 + postHttpEvent(msg) + } + } From 5fa2427c51b035fe47a287c51faa97f84ee0aa2f Mon Sep 17 00:00:00 2001 From: Alen Date: Wed, 24 Jul 2024 19:04:07 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9poke=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增poke事件支持上传raw信息 --- src/onebot11/constructor.ts | 16 ++++++++-------- src/onebot11/event/notice/OB11PokeEvent.ts | 10 ++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index addc4fb..dc3e159 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -321,11 +321,11 @@ export class OB11Constructor { if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) { //判断业务类型 //Poke事件 - let pokedetail: any[] = json.items; + const pokedetail: any[] = json.items; //筛选item带有uid的元素 - pokedetail = pokedetail.filter(item => item.uid); - if (pokedetail.length == 2) { - return new OB11FriendPokeEvent(parseInt((uidMaps[pokedetail[0].uid])!), parseInt((uidMaps[pokedetail[1].uid]))); + const poke_uid = pokedetail.filter(item => item.uid); + if (poke_uid.length == 2) { + return new OB11FriendPokeEvent(parseInt((uidMaps[poke_uid[0].uid])!), parseInt((uidMaps[poke_uid[1].uid])), pokedetail); } } //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE @@ -526,11 +526,11 @@ export class OB11Constructor { if (grayTipElement.jsonGrayTipElement.busiId == 1061) { //判断业务类型 //Poke事件 - let pokedetail: any[] = json.items; + const pokedetail: any[] = json.items; //筛选item带有uid的元素 - pokedetail = pokedetail.filter(item => item.uid); - if (pokedetail.length == 2) { - return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((uidMaps[pokedetail[0].uid])!), parseInt((uidMaps[pokedetail[1].uid]))); + const poke_uid = pokedetail.filter(item => item.uid); + if (poke_uid.length == 2) { + return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((uidMaps[poke_uid[0].uid])!), parseInt((uidMaps[poke_uid[1].uid])), pokedetail); } } const memberUin = json.items[1].param[0] diff --git a/src/onebot11/event/notice/OB11PokeEvent.ts b/src/onebot11/event/notice/OB11PokeEvent.ts index 4811a35..4e6917f 100644 --- a/src/onebot11/event/notice/OB11PokeEvent.ts +++ b/src/onebot11/event/notice/OB11PokeEvent.ts @@ -5,25 +5,27 @@ import { OB11BaseEvent } from '../OB11BaseEvent' class OB11PokeEvent extends OB11BaseNoticeEvent { notice_type = 'notify' sub_type = 'poke' - target_id = parseInt(selfInfo.uin) + target_id = 0 user_id: number + raw_message: any } export class OB11FriendPokeEvent extends OB11PokeEvent { - constructor(user_id: number, target_id: number) { + constructor(user_id: number, target_id: number, raw_message: any) { super(); this.target_id = target_id; this.user_id = user_id; + this.raw_message = raw_message; } } export class OB11GroupPokeEvent extends OB11PokeEvent { group_id: number - - constructor(group_id: number, user_id: number = 0, target_id: number = 0) { + constructor(group_id: number, user_id: number = 0, target_id: number = 0, raw_message: any) { super() this.group_id = group_id this.target_id = target_id this.user_id = user_id + this.raw_message = raw_message } } From 8ba47635d3da39af11118a39b082b3ebc89a3115 Mon Sep 17 00:00:00 2001 From: Alen Date: Thu, 25 Jul 2024 01:02:48 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.增加设精事件上报(目前上报的shortId经常出错,实际消息体却是正确的,待解决) 2.增加设精/取消设精api接口 3.poke事件增加raw信息上报 --- src/ntqqapi/api/group.ts | 25 ++++++++++++ src/ntqqapi/api/msg.ts | 12 +++--- src/ntqqapi/types/msg.ts | 6 +++ .../action/go-cqhttp/DelEssenceMsg.ts | 24 ++++++++++++ .../action/go-cqhttp/SetEssenceMsg.ts | 23 +++++++++++ src/onebot11/action/index.ts | 6 ++- src/onebot11/action/types.ts | 2 + src/onebot11/constructor.ts | 38 +++++++++++++++---- .../event/notice/OB11GroupEssenceEvent.ts | 14 +++++++ 9 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 src/onebot11/action/go-cqhttp/DelEssenceMsg.ts create mode 100644 src/onebot11/action/go-cqhttp/SetEssenceMsg.ts create mode 100644 src/onebot11/event/notice/OB11GroupEssenceEvent.ts diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 06d00c5..6617dcc 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -5,6 +5,7 @@ import { deleteGroup, uidMaps } from '../../common/data' import { dbUtil } from '../../common/db' import { log } from '../../common/utils/log' import { NTQQWindowApi, NTQQWindows } from './window' +import { wrapperApi } from '../native/wrapper' export class NTQQGroupApi { @@ -282,4 +283,28 @@ export class NTQQGroupApi { }) } static publishGroupBulletin(groupQQ: string, title: string, content: string) {} + static async removeGroupEssence(GroupCode: string, msgId: string) { + // 代码没测过 + // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom + let MsgData = await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); + let param = { + groupCode: GroupCode, + msgRandom: parseInt(MsgData.msgList[0].msgRandom), + msgSeq: parseInt(MsgData.msgList[0].msgSeq) + }; + // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 + return wrapperApi.NodeIQQNTWrapperSession.getGroupService().removeGroupEssence(param); + } + static async addGroupEssence(GroupCode: string, msgId: string) { + // 代码没测过 + // 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom + let MsgData = await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: GroupCode }, msgId, 1, false); + let param = { + groupCode: GroupCode, + msgRandom: parseInt(MsgData.msgList[0].msgRandom), + msgSeq: parseInt(MsgData.msgList[0].msgSeq) + }; + // GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数 + return wrapperApi.NodeIQQNTWrapperSession.getGroupService().addGroupEssence(param); + } } diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index 54ca551..1bd2da8 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -1,22 +1,17 @@ import { callNTQQApi, GeneralCallResult, NTQQApiMethod } from '../ntcall' -import { ChatType, RawMessage, SendMessageElement } from '../types' +import { ChatType, RawMessage, SendMessageElement, Peer } from '../types' import { dbUtil } from '../../common/db' import { selfInfo } from '../../common/data' import { ReceiveCmdS, registerReceiveHook } from '../hook' import { log } from '../../common/utils/log' import { sleep } from '../../common/utils/helper' import { isQQ998 } from '../../common/utils' +import { wrapperApi } from '@/ntqqapi/native/wrapper' export let sendMessagePool: Record void) | null> = {} // peerUid: callbackFunc export let sentMessages: Record = {} // msgId: RawMessage -export interface Peer { - chatType: ChatType - peerUid: string // 如果是群聊uid为群号,私聊uid就是加密的字符串 - guildId?: '' -} - async function sendWaiter(peer: Peer, waitComplete = true, timeout: number = 10000) { // 等待上一个相同的peer发送完 const peerUid = peer.peerUid @@ -293,4 +288,7 @@ export class NTQQMsgApi { }) }) } + static async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) { + return await wrapperApi.NodeIQQNTWrapperSession.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z); + } } diff --git a/src/ntqqapi/types/msg.ts b/src/ntqqapi/types/msg.ts index 1e74520..e50295f 100644 --- a/src/ntqqapi/types/msg.ts +++ b/src/ntqqapi/types/msg.ts @@ -415,3 +415,9 @@ export interface RawMessage { multiForwardMsgElement: MultiForwardMsgElement }[] } + +export interface Peer { + chatType: ChatType; + peerUid: string; // 如果是群聊uid为群号,私聊uid就是加密的字符串 + guildId?: string; +} \ No newline at end of file diff --git a/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts b/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts new file mode 100644 index 0000000..2bc5c3b --- /dev/null +++ b/src/onebot11/action/go-cqhttp/DelEssenceMsg.ts @@ -0,0 +1,24 @@ + +import BaseAction from '../BaseAction'; +import { ActionName } from '../types'; +import { NTQQGroupApi } from '../../../ntqqapi/api/group' +import { dbUtil } from '@/common/db'; + +interface Payload { + message_id: number | string; +} + +export default class GoCQHTTPDelEssenceMsg extends BaseAction { + actionName = ActionName.GoCQHTTP_DelEssenceMsg; + + protected async _handle(payload: Payload): Promise { + const msg = await dbUtil.getMsgByShortId(parseInt(payload.message_id.toString())); + if (!msg) { + throw new Error('msg not found'); + } + return await NTQQGroupApi.removeGroupEssence( + msg.peerUid, + msg.msgId + ); + } +} diff --git a/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts b/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts new file mode 100644 index 0000000..682eddd --- /dev/null +++ b/src/onebot11/action/go-cqhttp/SetEssenceMsg.ts @@ -0,0 +1,23 @@ +import BaseAction from '../BaseAction'; +import { ActionName } from '../types'; +import { NTQQGroupApi } from '../../../ntqqapi/api/group' +import { dbUtil } from '@/common/db'; + +interface Payload { + message_id: number | string; +} + +export default class GoCQHTTPSetEssenceMsg extends BaseAction { + actionName = ActionName.GoCQHTTP_SetEssenceMsg; + + protected async _handle(payload: Payload): Promise { + const msg = await dbUtil.getMsgByShortId(parseInt(payload.message_id.toString())); + if (!msg) { + throw new Error('msg not found'); + } + return await NTQQGroupApi.addGroupEssence( + msg.peerUid, + msg.msgId + ); + } +} diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index 3785082..efe1523 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -50,6 +50,8 @@ import { ForwardFriendSingleMsg, ForwardGroupSingleMsg } from './msg/ForwardSing import { GetGroupEssence } from './group/GetGroupEssence' import { GetGroupHonorInfo } from './group/GetGroupHonorInfo' import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation' +import GoCQHTTPSetEssenceMsg from './go-cqhttp/SetEssenceMsg' +import GoCQHTTPDelEssenceMsg from './go-cqhttp/DelEssenceMsg' export const actionHandlers = [ new GetFile(), @@ -106,7 +108,9 @@ export const actionHandlers = [ new GoCQHTTPUploadPrivateFile(), new GoCQHTTPGetGroupMsgHistory(), new GoCQHTTGetForwardMsgAction(), - new GoCQHTTHandleQuickOperation() + new GoCQHTTHandleQuickOperation(), + new GoCQHTTPSetEssenceMsg(), + new GoCQHTTPDelEssenceMsg() ] function initActionMap() { diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index 1b61ecc..ec38c6e 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -70,4 +70,6 @@ export enum ActionName { GoCQHTTP_GetEssenceMsg = "get_essence_msg_list", GoCQHTTP_HandleQuickOperation = ".handle_quick_operation", GetGroupHonorInfo = "get_group_honor_info", + GoCQHTTP_SetEssenceMsg = 'set_essence_msg', + GoCQHTTP_DelEssenceMsg = 'delete_essence_msg', } diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index dc3e159..eaae427 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -15,6 +15,7 @@ import { FaceIndex, GrayTipElementSubType, Group, + Peer, GroupMember, PicType, RawMessage, @@ -34,6 +35,7 @@ import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNotice import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent' import { NTQQUserApi } from '../ntqqapi/api/user' import { NTQQFileApi } from '../ntqqapi/api/file' +import { NTQQMsgApi } from '../ntqqapi/api/msg' import { calcQQLevel } from '../common/utils/qqlevel' import { log } from '../common/utils/log' import { sleep } from '../common/utils/helper' @@ -49,6 +51,7 @@ import { OB11FriendRecallNoticeEvent } from './event/notice/OB11FriendRecallNoti import { OB11GroupRecallNoticeEvent } from './event/notice/OB11GroupRecallNoticeEvent' import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent' import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent'; +import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent'; let lastRKeyUpdateTime = 0 @@ -533,13 +536,34 @@ export class OB11Constructor { return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((uidMaps[poke_uid[0].uid])!), parseInt((uidMaps[poke_uid[1].uid])), pokedetail); } } - const memberUin = json.items[1].param[0] - const title = json.items[3].txt - log('收到群成员新头衔消息', json) - getGroupMember(msg.peerUid, memberUin).then((member) => { - member.memberSpecialTitle = title - }) - return new OB11GroupTitleEvent(parseInt(msg.peerUid), parseInt(memberUin), title) + if (grayTipElement.jsonGrayTipElement.busiId == 2401) { + log('收到群精华消息', json) + const searchParams = new URL(json.items[0].jp).searchParams; + const msgSeq = searchParams.get('msgSeq')!; + const Group = searchParams.get('groupCode'); + const Businessid = searchParams.get('businessid'); + const Peer: Peer = { + guildId: '', + chatType: ChatType.group, + peerUid: Group! + }; + const msgList = (await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true)).msgList; + // (待解决) getMsgByLongId 拿到的 ShortId 经常跟实际 Msg 对不上(但msgId是一致的)。 + // 不过引用消息拿到的 ShortId 是对的。 + //console.log("原始消息: ", msgList); + //console.log("本地缓存: ", await dbUtil.getMsgByLongId(msgList[0].msgId)); + return new OB11GroupEssenceEvent(parseInt(msg.peerUid), Number(((await dbUtil.getMsgByLongId(msgList[0].msgId)).msgShortId)!), parseInt(msgList[0].senderUin)); + // 获取MsgSeq+Peer可获取具体消息 + } + if (grayTipElement.jsonGrayTipElement.busiId == 2407) { + const memberUin = json.items[1].param[0] + const title = json.items[3].txt + log('收到群成员新头衔消息', json) + getGroupMember(msg.peerUid, memberUin).then((member) => { + member.memberSpecialTitle = title + }) + return new OB11GroupTitleEvent(parseInt(msg.peerUid), parseInt(memberUin), title) + } } } } diff --git a/src/onebot11/event/notice/OB11GroupEssenceEvent.ts b/src/onebot11/event/notice/OB11GroupEssenceEvent.ts new file mode 100644 index 0000000..ae1053e --- /dev/null +++ b/src/onebot11/event/notice/OB11GroupEssenceEvent.ts @@ -0,0 +1,14 @@ +import { OB11GroupNoticeEvent } from './OB11GroupNoticeEvent'; +export class OB11GroupEssenceEvent extends OB11GroupNoticeEvent { + notice_type = 'essence'; + message_id: number; + sender_id: number; + sub_type: 'add' | 'delete' = 'add'; + + constructor(groupId: number, message_id: number, sender_id: number) { + super(); + this.group_id = groupId; + this.message_id = message_id; + this.sender_id = sender_id; + } +} From 9f1d4c4db2646d389224e90b430c61a41758bf40 Mon Sep 17 00:00:00 2001 From: Alen <33656288+cnxysoft@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:25:40 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改群管变更事件获取渠道,让所有群角色都能收到群管变更通知 --- src/main/main.ts | 58 +++++++++++++++++++++++---------------------- src/ntqqapi/hook.ts | 8 +++++++ 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index cb86fa6..c103f37 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -318,34 +318,36 @@ function onLoad() { // if (notify.user2.uid) { // member2 = await getGroupMember(notify.group.groupCode, null, notify.user2.uid); // } - if ( - [GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes( - notify.type, - ) - ) { - const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid) - log('有管理员变动通知') - refreshGroupMembers(notify.group.groupCode).then() - let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() - groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode) - log('开始获取变动的管理员') - if (member1) { - log('变动管理员获取成功') - groupAdminNoticeEvent.user_id = parseInt(member1.uin) - groupAdminNoticeEvent.sub_type = [ - GroupNotifyTypes.ADMIN_UNSET, - GroupNotifyTypes.ADMIN_UNSET_OTHER, - ].includes(notify.type) - ? 'unset' - : 'set' - // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; - postOb11Event(groupAdminNoticeEvent, true) - } - else { - log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode)) - } - } - else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { + // 原本的群管变更通知事件处理 + // if ( + // [GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes( + // notify.type, + // ) + // ) { + // const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid) + // log('有管理员变动通知') + // refreshGroupMembers(notify.group.groupCode).then() + // let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() + // groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode) + // log('开始获取变动的管理员') + // if (member1) { + // log('变动管理员获取成功') + // groupAdminNoticeEvent.user_id = parseInt(member1.uin) + // groupAdminNoticeEvent.sub_type = [ + // GroupNotifyTypes.ADMIN_UNSET, + // GroupNotifyTypes.ADMIN_UNSET_OTHER, + // ].includes(notify.type) + // ? 'unset' + // : 'set' + // // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; + // postOb11Event(groupAdminNoticeEvent, true) + // } + // else { + // log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode)) + // } + // } + // else + if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { log('有成员退出通知', notify) try { const member1 = await NTQQUserApi.getUserDetailInfo(notify.user1.uid) diff --git a/src/ntqqapi/hook.ts b/src/ntqqapi/hook.ts index ca2708d..3e9fee6 100644 --- a/src/ntqqapi/hook.ts +++ b/src/ntqqapi/hook.ts @@ -23,6 +23,7 @@ import { log } from '@/common/utils' import { isNumeric, sleep } from '@/common/utils' import { OB11Constructor } from '../onebot11/constructor' import { OB11GroupCardEvent } from '../onebot11/event/notice/OB11GroupCardEvent' +import { OB11GroupAdminNoticeEvent } from '../onebot11/event/notice/OB11GroupAdminNoticeEvent' export let hookApiCallbacks: Record void> = {} @@ -369,6 +370,13 @@ export async function startHook() { postOb11Event( new OB11GroupCardEvent(parseInt(groupCode), parseInt(member.uin), member.cardName, existMember.cardName), ) + } else if (member.role != existMember.role) { + log('有管理员变动通知') + let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() + groupAdminNoticeEvent.group_id = parseInt(groupCode) + groupAdminNoticeEvent.user_id = parseInt(member.uin) + groupAdminNoticeEvent.sub_type = member.role == GroupMemberRole.admin ? 'set' : 'unset' + postOb11Event(groupAdminNoticeEvent, true) } Object.assign(existMember, member) } From 641068954972c85889a9e63d1534b2b1c14f0a88 Mon Sep 17 00:00:00 2001 From: Alen Date: Thu, 1 Aug 2024 21:56:44 +0800 Subject: [PATCH 07/11] =?UTF-8?q?BUG=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 尝试修复设精事件shortId和senderId --- src/onebot11/constructor.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index eaae427..a3eacbe 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -547,12 +547,14 @@ export class OB11Constructor { chatType: ChatType.group, peerUid: Group! }; - const msgList = (await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true)).msgList; - // (待解决) getMsgByLongId 拿到的 ShortId 经常跟实际 Msg 对不上(但msgId是一致的)。 - // 不过引用消息拿到的 ShortId 是对的。 - //console.log("原始消息: ", msgList); - //console.log("本地缓存: ", await dbUtil.getMsgByLongId(msgList[0].msgId)); - return new OB11GroupEssenceEvent(parseInt(msg.peerUid), Number(((await dbUtil.getMsgByLongId(msgList[0].msgId)).msgShortId)!), parseInt(msgList[0].senderUin)); + let msgList = (await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true)).msgList; + const origMsg = await dbUtil.getMsgByLongId(msgList[0].msgId); + const postMsg = await dbUtil.getMsgBySeqId(origMsg.msgSeq) ?? origMsg; + // 如果 senderUin 为 0,可能是 历史消息 或 自身消息 + if (msgList[0].senderUin === '0') { + msgList[0].senderUin = postMsg?.senderUin ?? selfInfo.uin; + } + return new OB11GroupEssenceEvent(parseInt(msg.peerUid), postMsg.msgShortId, parseInt(msgList[0].senderUin)); // 获取MsgSeq+Peer可获取具体消息 } if (grayTipElement.jsonGrayTipElement.busiId == 2407) { From 71aedca4c65f4240537a48111f5c287249b469c8 Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:23:48 +0000 Subject: [PATCH 08/11] feat: the name attribute of the at message segment --- src/onebot11/constructor.ts | 39 +++++++++++++++++++++++-------------- src/onebot11/cqcode.ts | 10 +++++----- src/onebot11/types.ts | 17 ++++++++++++++++ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index addc4fb..544f657 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -109,33 +109,42 @@ export class OB11Constructor { } for (let element of msg.elements) { - let message_data: OB11MessageData | any = { - data: {}, - type: 'unknown', + let message_data: OB11MessageData = { + data: {} as any, + type: 'unknown' as any, } if (element.textElement && element.textElement?.atType !== AtType.notAt) { - message_data['type'] = OB11MessageDataType.at + let qq: string + let name: string | undefined if (element.textElement.atType == AtType.atAll) { // message_data["data"]["mention"] = "all" - message_data['data']['qq'] = 'all' + qq = 'all' } else { - let atUid = element.textElement.atNtUid + const { atNtUid, content } = element.textElement let atQQ = element.textElement.atUid if (!atQQ || atQQ === '0') { - const atMember = await getGroupMember(msg.peerUin, atUid) + const atMember = await getGroupMember(msg.peerUin, atNtUid) if (atMember) { atQQ = atMember.uin } } if (atQQ) { // message_data["data"]["mention"] = atQQ - message_data['data']['qq'] = atQQ + qq = atQQ + name = content.replace('@', '') + } + } + message_data = { + type: OB11MessageDataType.at, + data: { + qq, + name } } } else if (element.textElement) { - message_data['type'] = 'text' + message_data['type'] = OB11MessageDataType.text let text = element.textElement.content if (!text.trim()) { continue @@ -143,7 +152,7 @@ export class OB11Constructor { message_data['data']['text'] = text } else if (element.replyElement) { - message_data['type'] = 'reply' + message_data['type'] = OB11MessageDataType.reply // log("收到回复消息", element.replyElement.replayMsgSeq) try { const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq) @@ -159,7 +168,7 @@ export class OB11Constructor { } } else if (element.picElement) { - message_data['type'] = 'image' + message_data['type'] = OB11MessageDataType.image // message_data["data"]["file"] = element.picElement.sourcePath let fileName = element.picElement.fileName const sourcePath = element.picElement.sourcePath @@ -204,9 +213,9 @@ export class OB11Constructor { message_data['data']['file_size'] = videoOrFileElement.fileSize if (element.videoElement) { message_data['data']['url'] = await NTQQFileApi.getVideoUrl({ - chatType: msg.chatType, - peerUid: msg.peerUid, - }, msg.msgId, element.elementId, + chatType: msg.chatType, + peerUid: msg.peerUid, + }, msg.msgId, element.elementId, ) } dbUtil @@ -296,7 +305,7 @@ export class OB11Constructor { message_data['type'] = OB11MessageDataType.forward message_data['data']['id'] = msg.msgId } - if (message_data.type !== 'unknown' && message_data.data) { + if ((message_data.type as string) !== 'unknown' && message_data.data) { const cqCode = encodeCQCode(message_data) if (messagePostFormat === 'string') { (resMsg.message as string) += cqCode diff --git a/src/onebot11/cqcode.ts b/src/onebot11/cqcode.ts index 6b61160..3e9bfc5 100644 --- a/src/onebot11/cqcode.ts +++ b/src/onebot11/cqcode.ts @@ -61,15 +61,15 @@ export function encodeCQCode(data: OB11MessageData) { let result = '[CQ:' + data.type for (const name in data.data) { const value = data.data[name] + if (value === undefined) { + continue + } try { - // Check if the value can be converted to a string - value.toString(); + result += `,${name}=${CQCodeEscape(value)}` } catch (error) { // If it can't be converted, skip this name-value pair - // console.warn(`Skipping problematic name-value pair. Name: ${name}, Value: ${value}`); - continue; + continue } - result += `,${name}=${CQCodeEscape(value)}` } result += ']' return result diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts index de9c2ed..90a9f3c 100644 --- a/src/onebot11/types.ts +++ b/src/onebot11/types.ts @@ -195,6 +195,7 @@ export interface OB11MessageAt { type: OB11MessageDataType.at data: { qq: string | 'all' + name?: string } } @@ -241,6 +242,20 @@ export interface OB11MessageJson { data: { data: string /* , config: { token: string } */ } } +export interface OB11MessageMarkdown { + type: OB11MessageDataType.markdown + data: { + data: string + } +} + +export interface OB11MessageForward { + type: OB11MessageDataType.forward + data: { + id: string + } +} + export type OB11MessageData = | OB11MessageText | OB11MessageFace @@ -258,6 +273,8 @@ export type OB11MessageData = | OB11MessagePoke | OB11MessageDice | OB11MessageRPS + | OB11MessageMarkdown + | OB11MessageForward export interface OB11PostSendMsg { message_type?: 'private' | 'group' From 6e8389e833ded6e2d5c5a549981dbfc6aaf8b345 Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:26:18 +0000 Subject: [PATCH 09/11] chore --- src/onebot11/constructor.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index 544f657..59f2c93 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -117,7 +117,6 @@ export class OB11Constructor { let qq: string let name: string | undefined if (element.textElement.atType == AtType.atAll) { - // message_data["data"]["mention"] = "all" qq = 'all' } else { @@ -130,7 +129,6 @@ export class OB11Constructor { } } if (atQQ) { - // message_data["data"]["mention"] = atQQ qq = atQQ name = content.replace('@', '') } From 3f5ca8ebfab58d3585c4516a5156e1a73e73f073 Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:31:37 +0000 Subject: [PATCH 10/11] chore --- src/onebot11/cqcode.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/onebot11/cqcode.ts b/src/onebot11/cqcode.ts index 3e9bfc5..1cfdd04 100644 --- a/src/onebot11/cqcode.ts +++ b/src/onebot11/cqcode.ts @@ -68,7 +68,6 @@ export function encodeCQCode(data: OB11MessageData) { result += `,${name}=${CQCodeEscape(value)}` } catch (error) { // If it can't be converted, skip this name-value pair - continue } } result += ']' From 406e3c7e6b0c1b8555727b4f2598156d89aee076 Mon Sep 17 00:00:00 2001 From: idranme <96647698+idranme@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:49:30 +0000 Subject: [PATCH 11/11] opt --- src/onebot11/cqcode.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/onebot11/cqcode.ts b/src/onebot11/cqcode.ts index 1cfdd04..6ffcddb 100644 --- a/src/onebot11/cqcode.ts +++ b/src/onebot11/cqcode.ts @@ -50,7 +50,6 @@ export function encodeCQCode(data: OB11MessageData) { } const CQCodeEscape = (text: string) => { - text = text.toString() return text.replace(/\&/g, '&').replace(/\[/g, '[').replace(/\]/g, ']').replace(/,/g, ',') } @@ -65,7 +64,8 @@ export function encodeCQCode(data: OB11MessageData) { continue } try { - result += `,${name}=${CQCodeEscape(value)}` + const text = value.toString() + result += `,${name}=${CQCodeEscape(text)}` } catch (error) { // If it can't be converted, skip this name-value pair }