Merge pull request #317 from LLOneBot/dev

chore: v3.27.4
This commit is contained in:
idranme 2024-08-04 17:48:24 +08:00 committed by GitHub
commit 07d9ac823a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 345 additions and 79 deletions

View File

@ -198,6 +198,13 @@ function onLoad() {
postOb11Event(privateEvent) postOb11Event(privateEvent)
} }
}) })
// OB11Constructor.FriendAddEvent(message).then((friendAddEvent) => {
// log(message)
// if (friendAddEvent) {
// // log("post friend add event", friendAddEvent);
// postOb11Event(friendAddEvent)
// }
// })
} }
} }
@ -216,7 +223,7 @@ function onLoad() {
pokeEvent = new OB11GroupPokeEvent(parseInt(id)) pokeEvent = new OB11GroupPokeEvent(parseInt(id))
} }
else { else {
pokeEvent = new OB11FriendPokeEvent(parseInt(id)) pokeEvent = new OB11FriendPokeEvent(parseInt(selfInfo.uin), parseInt(id))
} }
postOb11Event(pokeEvent) postOb11Event(pokeEvent)
}) })
@ -311,34 +318,36 @@ function onLoad() {
// if (notify.user2.uid) { // if (notify.user2.uid) {
// member2 = await getGroupMember(notify.group.groupCode, null, 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( // if (
notify.type, // [GroupNotifyTypes.ADMIN_SET, GroupNotifyTypes.ADMIN_UNSET, GroupNotifyTypes.ADMIN_UNSET_OTHER].includes(
) // notify.type,
) { // )
const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid) // ) {
log('有管理员变动通知') // const member1 = await getGroupMember(notify.group.groupCode, notify.user1.uid)
refreshGroupMembers(notify.group.groupCode).then() // log('有管理员变动通知')
let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent() // refreshGroupMembers(notify.group.groupCode).then()
groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode) // let groupAdminNoticeEvent = new OB11GroupAdminNoticeEvent()
log('开始获取变动的管理员') // groupAdminNoticeEvent.group_id = parseInt(notify.group.groupCode)
if (member1) { // log('开始获取变动的管理员')
log('变动管理员获取成功') // if (member1) {
groupAdminNoticeEvent.user_id = parseInt(member1.uin) // log('变动管理员获取成功')
groupAdminNoticeEvent.sub_type = [ // groupAdminNoticeEvent.user_id = parseInt(member1.uin)
GroupNotifyTypes.ADMIN_UNSET, // groupAdminNoticeEvent.sub_type = [
GroupNotifyTypes.ADMIN_UNSET_OTHER, // GroupNotifyTypes.ADMIN_UNSET,
].includes(notify.type) // GroupNotifyTypes.ADMIN_UNSET_OTHER,
? 'unset' // ].includes(notify.type)
: 'set' // ? 'unset'
// member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal; // : 'set'
postOb11Event(groupAdminNoticeEvent, true) // // member1.role = notify.type == GroupNotifyTypes.ADMIN_SET ? GroupMemberRole.admin : GroupMemberRole.normal;
} // postOb11Event(groupAdminNoticeEvent, true)
else { // }
log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode)) // else {
} // log('获取群通知的成员信息失败', notify, getGroup(notify.group.groupCode))
} // }
else if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) { // }
// else
if (notify.type == GroupNotifyTypes.MEMBER_EXIT || notify.type == GroupNotifyTypes.KICK_MEMBER) {
log('有成员退出通知', notify) log('有成员退出通知', notify)
try { try {
const member1 = await NTQQUserApi.getUserDetailInfo(notify.user1.uid) const member1 = await NTQQUserApi.getUserDetailInfo(notify.user1.uid)

View File

@ -5,6 +5,7 @@ import { deleteGroup, uidMaps } from '../../common/data'
import { dbUtil } from '../../common/db' import { dbUtil } from '../../common/db'
import { log } from '../../common/utils/log' import { log } from '../../common/utils/log'
import { NTQQWindowApi, NTQQWindows } from './window' import { NTQQWindowApi, NTQQWindows } from './window'
import { wrapperApi } from '../native/wrapper'
export class NTQQGroupApi { export class NTQQGroupApi {
@ -282,4 +283,28 @@ export class NTQQGroupApi {
}) })
} }
static publishGroupBulletin(groupQQ: string, title: string, content: string) {} 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);
}
} }

View File

@ -1,22 +1,17 @@
import { callNTQQApi, GeneralCallResult, NTQQApiMethod } from '../ntcall' 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 { dbUtil } from '../../common/db'
import { selfInfo } from '../../common/data' import { selfInfo } from '../../common/data'
import { ReceiveCmdS, registerReceiveHook } from '../hook' import { ReceiveCmdS, registerReceiveHook } from '../hook'
import { log } from '../../common/utils/log' import { log } from '../../common/utils/log'
import { sleep } from '../../common/utils/helper' import { sleep } from '../../common/utils/helper'
import { isQQ998 } from '../../common/utils' import { isQQ998 } from '../../common/utils'
import { wrapperApi } from '@/ntqqapi/native/wrapper'
export let sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void) | null> = {} // peerUid: callbackFunc export let sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void) | null> = {} // peerUid: callbackFunc
export let sentMessages: Record<string, RawMessage> = {} // msgId: RawMessage export let sentMessages: Record<string, RawMessage> = {} // msgId: RawMessage
export interface Peer {
chatType: ChatType
peerUid: string // 如果是群聊uid为群号私聊uid就是加密的字符串
guildId?: ''
}
async function sendWaiter(peer: Peer, waitComplete = true, timeout: number = 10000) { async function sendWaiter(peer: Peer, waitComplete = true, timeout: number = 10000) {
// 等待上一个相同的peer发送完 // 等待上一个相同的peer发送完
const peerUid = peer.peerUid 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);
}
} }

View File

@ -23,6 +23,7 @@ import { log } from '@/common/utils'
import { isNumeric, sleep } from '@/common/utils' import { isNumeric, sleep } from '@/common/utils'
import { OB11Constructor } from '../onebot11/constructor' import { OB11Constructor } from '../onebot11/constructor'
import { OB11GroupCardEvent } from '../onebot11/event/notice/OB11GroupCardEvent' import { OB11GroupCardEvent } from '../onebot11/event/notice/OB11GroupCardEvent'
import { OB11GroupAdminNoticeEvent } from '../onebot11/event/notice/OB11GroupAdminNoticeEvent'
export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {} export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {}
@ -369,6 +370,13 @@ export async function startHook() {
postOb11Event( postOb11Event(
new OB11GroupCardEvent(parseInt(groupCode), parseInt(member.uin), member.cardName, existMember.cardName), 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) Object.assign(existMember, member)
} }

View File

@ -415,3 +415,9 @@ export interface RawMessage {
multiForwardMsgElement: MultiForwardMsgElement multiForwardMsgElement: MultiForwardMsgElement
}[] }[]
} }
export interface Peer {
chatType: ChatType;
peerUid: string; // 如果是群聊uid为群号私聊uid就是加密的字符串
guildId?: string;
}

View File

@ -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<Payload, any> {
actionName = ActionName.GoCQHTTP_DelEssenceMsg;
protected async _handle(payload: Payload): Promise<any> {
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
);
}
}

View File

@ -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<Payload, any> {
actionName = ActionName.GoCQHTTP_SetEssenceMsg;
protected async _handle(payload: Payload): Promise<any> {
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
);
}
}

View File

@ -50,6 +50,10 @@ import { ForwardFriendSingleMsg, ForwardGroupSingleMsg } from './msg/ForwardSing
import { GetGroupEssence } from './group/GetGroupEssence' import { GetGroupEssence } from './group/GetGroupEssence'
import { GetGroupHonorInfo } from './group/GetGroupHonorInfo' import { GetGroupHonorInfo } from './group/GetGroupHonorInfo'
import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation' import { GoCQHTTHandleQuickOperation } from './go-cqhttp/QuickOperation'
import GoCQHTTPSetEssenceMsg from './go-cqhttp/SetEssenceMsg'
import GoCQHTTPDelEssenceMsg from './go-cqhttp/DelEssenceMsg'
import GetEvent from './llonebot/GetEvent'
export const actionHandlers = [ export const actionHandlers = [
new GetFile(), new GetFile(),
@ -59,6 +63,7 @@ export const actionHandlers = [
new GetGroupAddRequest(), new GetGroupAddRequest(),
new SetQQAvatar(), new SetQQAvatar(),
new GetFriendWithCategory(), new GetFriendWithCategory(),
new GetEvent(),
// onebot11 // onebot11
new SendLike(), new SendLike(),
new GetMsg(), new GetMsg(),
@ -106,7 +111,9 @@ export const actionHandlers = [
new GoCQHTTPUploadPrivateFile(), new GoCQHTTPUploadPrivateFile(),
new GoCQHTTPGetGroupMsgHistory(), new GoCQHTTPGetGroupMsgHistory(),
new GoCQHTTGetForwardMsgAction(), new GoCQHTTGetForwardMsgAction(),
new GoCQHTTHandleQuickOperation() new GoCQHTTHandleQuickOperation(),
new GoCQHTTPSetEssenceMsg(),
new GoCQHTTPDelEssenceMsg()
] ]
function initActionMap() { function initActionMap() {

View File

@ -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<Payload, PostEventType[]> {
actionName = ActionName.GetEvent
protected async _handle(payload: Payload): Promise<PostEventType[]> {
let key = ''
if (payload.key) {
key = payload.key;
}
let timeout = parseInt(payload.timeout?.toString()) || 0;
let evts = await getHttpEvent(key,timeout);
return evts;
}
}

View File

@ -22,6 +22,7 @@ export enum ActionName {
Debug = 'llonebot_debug', Debug = 'llonebot_debug',
GetFile = 'get_file', GetFile = 'get_file',
GetFriendsWithCategory = 'get_friends_with_category', GetFriendsWithCategory = 'get_friends_with_category',
GetEvent = 'get_event',
// onebot 11 // onebot 11
SendLike = 'send_like', SendLike = 'send_like',
GetLoginInfo = 'get_login_info', GetLoginInfo = 'get_login_info',
@ -70,4 +71,6 @@ export enum ActionName {
GoCQHTTP_GetEssenceMsg = "get_essence_msg_list", GoCQHTTP_GetEssenceMsg = "get_essence_msg_list",
GoCQHTTP_HandleQuickOperation = ".handle_quick_operation", GoCQHTTP_HandleQuickOperation = ".handle_quick_operation",
GetGroupHonorInfo = "get_group_honor_info", GetGroupHonorInfo = "get_group_honor_info",
GoCQHTTP_SetEssenceMsg = 'set_essence_msg',
GoCQHTTP_DelEssenceMsg = 'delete_essence_msg',
} }

View File

@ -15,6 +15,7 @@ import {
FaceIndex, FaceIndex,
GrayTipElementSubType, GrayTipElementSubType,
Group, Group,
Peer,
GroupMember, GroupMember,
PicType, PicType,
RawMessage, RawMessage,
@ -34,6 +35,7 @@ import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNotice
import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent' import { OB11GroupNoticeEvent } from './event/notice/OB11GroupNoticeEvent'
import { NTQQUserApi } from '../ntqqapi/api/user' import { NTQQUserApi } from '../ntqqapi/api/user'
import { NTQQFileApi } from '../ntqqapi/api/file' import { NTQQFileApi } from '../ntqqapi/api/file'
import { NTQQMsgApi } from '../ntqqapi/api/msg'
import { calcQQLevel } from '../common/utils/qqlevel' import { calcQQLevel } from '../common/utils/qqlevel'
import { log } from '../common/utils/log' import { log } from '../common/utils/log'
import { sleep } from '../common/utils/helper' import { sleep } from '../common/utils/helper'
@ -49,6 +51,7 @@ import { OB11FriendRecallNoticeEvent } from './event/notice/OB11FriendRecallNoti
import { OB11GroupRecallNoticeEvent } from './event/notice/OB11GroupRecallNoticeEvent' import { OB11GroupRecallNoticeEvent } from './event/notice/OB11GroupRecallNoticeEvent'
import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent' import { OB11FriendPokeEvent, OB11GroupPokeEvent } from './event/notice/OB11PokeEvent'
import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent'; import { OB11BaseNoticeEvent } from './event/notice/OB11BaseNoticeEvent';
import { OB11GroupEssenceEvent } from './event/notice/OB11GroupEssenceEvent';
let lastRKeyUpdateTime = 0 let lastRKeyUpdateTime = 0
@ -109,33 +112,40 @@ export class OB11Constructor {
} }
for (let element of msg.elements) { for (let element of msg.elements) {
let message_data: OB11MessageData | any = { let message_data: OB11MessageData = {
data: {}, data: {} as any,
type: 'unknown', type: 'unknown' as any,
} }
if (element.textElement && element.textElement?.atType !== AtType.notAt) { 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) { if (element.textElement.atType == AtType.atAll) {
// message_data["data"]["mention"] = "all" qq = 'all'
message_data['data']['qq'] = 'all'
} }
else { else {
let atUid = element.textElement.atNtUid const { atNtUid, content } = element.textElement
let atQQ = element.textElement.atUid let atQQ = element.textElement.atUid
if (!atQQ || atQQ === '0') { if (!atQQ || atQQ === '0') {
const atMember = await getGroupMember(msg.peerUin, atUid) const atMember = await getGroupMember(msg.peerUin, atNtUid)
if (atMember) { if (atMember) {
atQQ = atMember.uin atQQ = atMember.uin
} }
} }
if (atQQ) { if (atQQ) {
// message_data["data"]["mention"] = atQQ qq = atQQ
message_data['data']['qq'] = atQQ name = content.replace('@', '')
}
}
message_data = {
type: OB11MessageDataType.at,
data: {
qq,
name
} }
} }
} }
else if (element.textElement) { else if (element.textElement) {
message_data['type'] = 'text' message_data['type'] = OB11MessageDataType.text
let text = element.textElement.content let text = element.textElement.content
if (!text.trim()) { if (!text.trim()) {
continue continue
@ -143,7 +153,7 @@ export class OB11Constructor {
message_data['data']['text'] = text message_data['data']['text'] = text
} }
else if (element.replyElement) { else if (element.replyElement) {
message_data['type'] = 'reply' message_data['type'] = OB11MessageDataType.reply
// log("收到回复消息", element.replyElement.replayMsgSeq) // log("收到回复消息", element.replyElement.replayMsgSeq)
try { try {
const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq) const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq)
@ -159,7 +169,7 @@ export class OB11Constructor {
} }
} }
else if (element.picElement) { else if (element.picElement) {
message_data['type'] = 'image' message_data['type'] = OB11MessageDataType.image
// message_data["data"]["file"] = element.picElement.sourcePath // message_data["data"]["file"] = element.picElement.sourcePath
let fileName = element.picElement.fileName let fileName = element.picElement.fileName
const sourcePath = element.picElement.sourcePath const sourcePath = element.picElement.sourcePath
@ -296,7 +306,7 @@ export class OB11Constructor {
message_data['type'] = OB11MessageDataType.forward message_data['type'] = OB11MessageDataType.forward
message_data['data']['id'] = msg.msgId 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) const cqCode = encodeCQCode(message_data)
if (messagePostFormat === 'string') { if (messagePostFormat === 'string') {
(resMsg.message as string) += cqCode (resMsg.message as string) += cqCode
@ -321,11 +331,11 @@ export class OB11Constructor {
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) { if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
//判断业务类型 //判断业务类型
//Poke事件 //Poke事件
let pokedetail: any[] = json.items; const pokedetail: any[] = json.items;
//筛选item带有uid的元素 //筛选item带有uid的元素
pokedetail = pokedetail.filter(item => item.uid); const poke_uid = pokedetail.filter(item => item.uid);
if (pokedetail.length == 2) { if (poke_uid.length == 2) {
return new OB11FriendPokeEvent(parseInt((uidMaps[pokedetail[0].uid])!), parseInt((uidMaps[pokedetail[1].uid]))); return new OB11FriendPokeEvent(parseInt((uidMaps[poke_uid[0].uid])!), parseInt((uidMaps[poke_uid[1].uid])), pokedetail);
} }
} }
//下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE //下面得改 上面也是错的grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE
@ -526,13 +536,35 @@ export class OB11Constructor {
if (grayTipElement.jsonGrayTipElement.busiId == 1061) { if (grayTipElement.jsonGrayTipElement.busiId == 1061) {
//判断业务类型 //判断业务类型
//Poke事件 //Poke事件
let pokedetail: any[] = json.items; const pokedetail: any[] = json.items;
//筛选item带有uid的元素 //筛选item带有uid的元素
pokedetail = pokedetail.filter(item => item.uid); const poke_uid = pokedetail.filter(item => item.uid);
if (pokedetail.length == 2) { if (poke_uid.length == 2) {
return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((uidMaps[pokedetail[0].uid])!), parseInt((uidMaps[pokedetail[1].uid]))); return new OB11GroupPokeEvent(parseInt(msg.peerUid), parseInt((uidMaps[poke_uid[0].uid])!), parseInt((uidMaps[poke_uid[1].uid])), pokedetail);
} }
} }
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!
};
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) {
const memberUin = json.items[1].param[0] const memberUin = json.items[1].param[0]
const title = json.items[3].txt const title = json.items[3].txt
log('收到群成员新头衔消息', json) log('收到群成员新头衔消息', json)
@ -544,6 +576,7 @@ export class OB11Constructor {
} }
} }
} }
}
static async RecallEvent( static async RecallEvent(
msg: RawMessage, msg: RawMessage,

View File

@ -50,7 +50,6 @@ export function encodeCQCode(data: OB11MessageData) {
} }
const CQCodeEscape = (text: string) => { const CQCodeEscape = (text: string) => {
text = text.toString()
return text.replace(/\&/g, '&amp;').replace(/\[/g, '&#91;').replace(/\]/g, '&#93;').replace(/,/g, '&#44;') return text.replace(/\&/g, '&amp;').replace(/\[/g, '&#91;').replace(/\]/g, '&#93;').replace(/,/g, '&#44;')
} }
@ -61,15 +60,15 @@ export function encodeCQCode(data: OB11MessageData) {
let result = '[CQ:' + data.type let result = '[CQ:' + data.type
for (const name in data.data) { for (const name in data.data) {
const value = data.data[name] const value = data.data[name]
if (value === undefined) {
continue
}
try { try {
// Check if the value can be converted to a string const text = value.toString()
value.toString(); result += `,${name}=${CQCodeEscape(text)}`
} catch (error) { } catch (error) {
// If it can't be converted, skip this name-value pair // If it can't be converted, skip this name-value pair
// console.warn(`Skipping problematic name-value pair. Name: ${name}, Value: ${value}`);
continue;
} }
result += `,${name}=${CQCodeEscape(value)}`
} }
result += ']' result += ']'
return result return result

View File

@ -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;
}
}

View File

@ -5,25 +5,28 @@ import { OB11BaseEvent } from '../OB11BaseEvent'
class OB11PokeEvent extends OB11BaseNoticeEvent { class OB11PokeEvent extends OB11BaseNoticeEvent {
notice_type = 'notify' notice_type = 'notify'
sub_type = 'poke' sub_type = 'poke'
target_id = parseInt(selfInfo.uin) target_id = 0
user_id: number user_id: number
raw_message: any
} }
export class OB11FriendPokeEvent extends OB11PokeEvent { export class OB11FriendPokeEvent extends OB11PokeEvent {
constructor(user_id: number, target_id: number) {
constructor(user_id: number, target_id: number, raw_message: any) {
super(); super();
this.target_id = target_id; this.target_id = target_id;
this.user_id = user_id; this.user_id = user_id;
this.raw_message = raw_message;
} }
} }
export class OB11GroupPokeEvent extends OB11PokeEvent { export class OB11GroupPokeEvent extends OB11PokeEvent {
group_id: number group_id: number
constructor(group_id: number, user_id: number = 0, target_id: number = 0, raw_message: any) {
constructor(group_id: number, user_id: number = 0, target_id: number = 0) {
super() super()
this.group_id = group_id this.group_id = group_id
this.target_id = target_id this.target_id = target_id
this.user_id = user_id this.user_id = user_id
this.raw_message = raw_message
} }
} }

View File

@ -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<string,HttpUserType> = {};
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 = [];
// 清除过时的user5分钟没访问过的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;
}

View File

@ -8,6 +8,7 @@ import { log } from '@/common/utils'
import { getConfigUtil } from '@/common/config' import { getConfigUtil } from '@/common/config'
import crypto from 'crypto' import crypto from 'crypto'
import { handleQuickOperation, QuickOperationEvent } from '../action/quick-operation' import { handleQuickOperation, QuickOperationEvent } from '../action/quick-operation'
import { postHttpEvent } from './event-for-http'
export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent export type PostEventType = OB11Message | OB11BaseMetaEvent | OB11BaseNoticeEvent
@ -78,4 +79,9 @@ export function postOb11Event(msg: PostEventType, reportSelf = false, postWs = t
if (postWs) { if (postWs) {
postWsEvent(msg) postWsEvent(msg)
} }
if(!(msg.post_type == 'meta_event' && (msg as OB11BaseMetaEvent).meta_event_type == 'heartbeat')) {
// 不上报心跳
postHttpEvent(msg)
}
} }

View File

@ -195,6 +195,7 @@ export interface OB11MessageAt {
type: OB11MessageDataType.at type: OB11MessageDataType.at
data: { data: {
qq: string | 'all' qq: string | 'all'
name?: string
} }
} }
@ -241,6 +242,20 @@ export interface OB11MessageJson {
data: { data: string /* , config: { token: string } */ } 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 = export type OB11MessageData =
| OB11MessageText | OB11MessageText
| OB11MessageFace | OB11MessageFace
@ -258,6 +273,8 @@ export type OB11MessageData =
| OB11MessagePoke | OB11MessagePoke
| OB11MessageDice | OB11MessageDice
| OB11MessageRPS | OB11MessageRPS
| OB11MessageMarkdown
| OB11MessageForward
export interface OB11PostSendMsg { export interface OB11PostSendMsg {
message_type?: 'private' | 'group' message_type?: 'private' | 'group'