mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-29 13:01:27 +08:00
Refactor packet client and update message history actions
Replaced LRUCache with Map for callback and event management in packet clients, and standardized callback hash usage. Updated GetFriendMsgHistory and GetGroupMsgHistory actions to use snake_case for payload keys. Modified OneBotMsgApi to support disabling URL retrieval for ptt elements via a new parameter.
This commit is contained in:
parent
6200097f7c
commit
4d200de6b7
@ -1,4 +1,3 @@
|
||||
import { LRUCache } from '@/common/lru-cache';
|
||||
import crypto, { createHash } from 'crypto';
|
||||
import { OidbPacket, PacketHexStr } from '@/core/packet/transformer/base';
|
||||
import { LogStack } from '@/core/packet/context/clientContext';
|
||||
@ -7,7 +6,6 @@ import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
|
||||
export interface RecvPacket {
|
||||
type: string, // 仅recv
|
||||
trace_id_md5?: string,
|
||||
data: RecvPacketData
|
||||
}
|
||||
|
||||
@ -30,7 +28,7 @@ function randText(len: number): string {
|
||||
export abstract class IPacketClient {
|
||||
protected readonly napcore: NapCoreContext;
|
||||
protected readonly logger: PacketLogger;
|
||||
protected readonly cb = new LRUCache<string, (json: RecvPacketData) => Promise<void>>(500); // trace_id-type callback
|
||||
protected readonly cb = new Map<string, (json: RecvPacketData) => Promise<any> | any>(); // hash-type callback
|
||||
logStack: LogStack;
|
||||
available: boolean = false;
|
||||
|
||||
@ -44,24 +42,21 @@ export abstract class IPacketClient {
|
||||
|
||||
abstract init(pid: number, recv: string, send: string): Promise<void>;
|
||||
|
||||
abstract sendCommandImpl(cmd: string, data: string, trace_id: string): void;
|
||||
abstract sendCommandImpl(cmd: string, data: string, hash: string, timeout: number): void;
|
||||
|
||||
private async registerCallback(trace_id: string, type: string, callback: (json: RecvPacketData) => Promise<void>): Promise<void> {
|
||||
this.cb.put(createHash('md5').update(trace_id).digest('hex') + type, callback);
|
||||
}
|
||||
|
||||
private async sendCommand(cmd: string, data: string, trace_id: string, rsp: boolean = false, timeout: number = 20000, sendcb: (json: RecvPacketData) => void = () => {
|
||||
private async sendCommand(cmd: string, data: string, trace_data: string, rsp: boolean = false, timeout: number = 20000, sendcb: (json: RecvPacketData) => void = () => {
|
||||
}): Promise<RecvPacketData> {
|
||||
return new Promise<RecvPacketData>((resolve, reject) => {
|
||||
if (!this.available) {
|
||||
reject(new Error('packetBackend 当前不可用!'));
|
||||
}
|
||||
|
||||
let hash = createHash('md5').update(trace_data).digest('hex');
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
reject(new Error(`sendCommand timed out after ${timeout} ms for ${cmd} with trace_id ${trace_id}`));
|
||||
this.cb.delete(hash + 'send');
|
||||
this.cb.delete(hash + 'recv');
|
||||
reject(new Error(`sendCommand timed out after ${timeout} ms for ${cmd} with hash ${hash}`));
|
||||
}, timeout);
|
||||
|
||||
this.registerCallback(trace_id, 'send', async (json: RecvPacketData) => {
|
||||
this.cb.set(hash + 'send', async (json: RecvPacketData) => {
|
||||
sendcb(json);
|
||||
if (!rsp) {
|
||||
clearTimeout(timeoutHandle);
|
||||
@ -70,21 +65,20 @@ export abstract class IPacketClient {
|
||||
});
|
||||
|
||||
if (rsp) {
|
||||
this.registerCallback(trace_id, 'recv', async (json: RecvPacketData) => {
|
||||
this.cb.set(hash + 'recv', async (json: RecvPacketData) => {
|
||||
clearTimeout(timeoutHandle);
|
||||
resolve(json);
|
||||
});
|
||||
}
|
||||
|
||||
this.sendCommandImpl(cmd, data, trace_id);
|
||||
this.sendCommandImpl(cmd, data, hash, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
async sendPacket(cmd: string, data: PacketHexStr, rsp = false, timeout = 20000): Promise<RecvPacketData> {
|
||||
const md5 = crypto.createHash('md5').update(data).digest('hex');
|
||||
const trace_id = (randText(4) + md5 + data).slice(0, data.length / 2);
|
||||
return this.sendCommand(cmd, data, trace_id, rsp, timeout, async () => {
|
||||
await this.napcore.sendSsoCmdReqByContend(cmd, trace_id);
|
||||
const trace_data = (randText(4) + md5 + data).slice(0, data.length / 2);// trace_data
|
||||
return this.sendCommand(cmd, data, trace_data, rsp, timeout, async () => {
|
||||
await this.napcore.sendSsoCmdReqByContend(cmd, trace_data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import { fileURLToPath } from 'url';
|
||||
import fs from 'fs';
|
||||
import { IPacketClient } from '@/core/packet/client/baseClient';
|
||||
import { constants } from 'node:os';
|
||||
import { LRUCache } from '@/common/lru-cache';
|
||||
import { LogStack } from '@/core/packet/context/clientContext';
|
||||
import { NapCoreContext } from '@/core/packet/context/napCoreContext';
|
||||
import { PacketLogger } from '@/core/packet/context/loggerContext';
|
||||
@ -18,7 +17,8 @@ export interface NativePacketExportType {
|
||||
export class NativePacketClient extends IPacketClient {
|
||||
private readonly supportedPlatforms = ['win32.x64', 'linux.x64', 'linux.arm64', 'darwin.x64', 'darwin.arm64'];
|
||||
private readonly MoeHooExport: { exports: NativePacketExportType } = { exports: {} };
|
||||
private readonly sendEvent = new LRUCache<number, string>(500); // seq->trace_id
|
||||
private readonly sendEvent = new Map<number, string>(); // seq - hash
|
||||
private readonly timeEvent = new Map<string, NodeJS.Timeout>(); // hash - timeout
|
||||
|
||||
constructor(napCore: NapCoreContext, logger: PacketLogger, logStack: LogStack) {
|
||||
super(napCore, logger, logStack);
|
||||
@ -45,25 +45,31 @@ export class NativePacketClient extends IPacketClient {
|
||||
process.dlopen(this.MoeHooExport, moehoo_path, constants.dlopen.RTLD_LAZY);
|
||||
|
||||
this.MoeHooExport.exports.InitHook?.(send, recv, (type: number, _uin: string, cmd: string, seq: number, hex_data: string) => {
|
||||
const trace_id = createHash('md5').update(Buffer.from(hex_data, 'hex')).digest('hex');
|
||||
if (type === 0 && this.cb.get(trace_id + 'recv')) {
|
||||
const hash = createHash('md5').update(Buffer.from(hex_data, 'hex')).digest('hex');
|
||||
if (type === 0 && this.cb.get(hash + 'recv')) {
|
||||
//此时为send 提取seq
|
||||
this.sendEvent.put(seq, trace_id);
|
||||
this.sendEvent.set(seq, hash);
|
||||
setTimeout(() => {
|
||||
this.sendEvent.delete(seq);
|
||||
this.timeEvent.delete(hash);
|
||||
}, +(this.timeEvent.get(hash) ?? 20000));
|
||||
//正式send完成 无recv v
|
||||
//均无异常 v
|
||||
}
|
||||
if (type === 1 && this.sendEvent.get(seq)) {
|
||||
//此时为recv 调用callback
|
||||
const trace_id = this.sendEvent.get(seq);
|
||||
const callback = this.cb.get(trace_id + 'recv');
|
||||
// console.log('callback:', callback, trace_id);
|
||||
const hash = this.sendEvent.get(seq);
|
||||
const callback = this.cb.get(hash + 'recv');
|
||||
callback?.({ seq, cmd, hex_data });
|
||||
}
|
||||
}, this.napcore.config.o3HookMode == 1);
|
||||
this.available = true;
|
||||
}
|
||||
|
||||
sendCommandImpl(cmd: string, data: string, trace_id: string): void {
|
||||
const trace_id_md5 = createHash('md5').update(trace_id).digest('hex');
|
||||
this.MoeHooExport.exports.SendPacket?.(cmd, data, trace_id_md5);
|
||||
this.cb.get(trace_id_md5 + 'send')?.({ seq: 0, cmd, hex_data: '' });
|
||||
sendCommandImpl(cmd: string, data: string, hash: string, timeout: number): void {
|
||||
this.timeEvent.set(hash, setTimeout(() => {
|
||||
this.timeEvent.delete(hash);//考虑情况为正式send都没进
|
||||
}, timeout));
|
||||
this.MoeHooExport.exports.SendPacket?.(cmd, data, hash);
|
||||
this.cb.get(hash + 'send')?.({ seq: 0, cmd, hex_data: '' });
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,8 +15,8 @@ const SchemaData = Type.Object({
|
||||
message_seq: Type.Optional(Type.String()),
|
||||
count: Type.Number({ default: 20 }),
|
||||
reverseOrder: Type.Boolean({ default: false }),
|
||||
disableGetUrl: Type.Boolean({ default: false }),
|
||||
parseMultMsg: Type.Boolean({ default: true })
|
||||
disable_get_url: Type.Boolean({ default: false }),
|
||||
parse_mult_msg: Type.Boolean({ default: true })
|
||||
});
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ export default class GetFriendMsgHistory extends OneBotAction<Payload, Response>
|
||||
}));
|
||||
//烘焙消息
|
||||
const ob11MsgList = (await Promise.all(
|
||||
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parseMultMsg, payload.disableGetUrl)))
|
||||
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parse_mult_msg, payload.disable_get_url)))
|
||||
).filter(msg => msg !== undefined);
|
||||
return { 'messages': ob11MsgList };
|
||||
}
|
||||
|
||||
@ -15,8 +15,8 @@ const SchemaData = Type.Object({
|
||||
message_seq: Type.Optional(Type.String()),
|
||||
count: Type.Number({ default: 20 }),
|
||||
reverseOrder: Type.Boolean({ default: false }),
|
||||
disableGetUrl: Type.Boolean({ default: false }),
|
||||
parseMultMsg: Type.Boolean({ default: true }),
|
||||
disable_get_url: Type.Boolean({ default: false }),
|
||||
parse_mult_msg: Type.Boolean({ default: true }),
|
||||
});
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Re
|
||||
}));
|
||||
//烘焙消息
|
||||
const ob11MsgList = (await Promise.all(
|
||||
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parseMultMsg, payload.disableGetUrl)))
|
||||
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parse_mult_msg, payload.disable_get_url)))
|
||||
).filter(msg => msg !== undefined);
|
||||
return { 'messages': ob11MsgList };
|
||||
}
|
||||
|
||||
@ -444,7 +444,7 @@ export class OneBotMsgApi {
|
||||
};
|
||||
},
|
||||
|
||||
pttElement: async (element, msg, elementWrapper) => {
|
||||
pttElement: async (element, msg, elementWrapper, { disableGetUrl }) => {
|
||||
const peer = {
|
||||
chatType: msg.chatType,
|
||||
peerUid: msg.peerUid,
|
||||
@ -452,7 +452,7 @@ export class OneBotMsgApi {
|
||||
};
|
||||
const fileCode = FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, '', element.fileName);
|
||||
let pttUrl = '';
|
||||
if (this.core.apis.PacketApi.packetStatus) {
|
||||
if (this.core.apis.PacketApi.packetStatus && !disableGetUrl) {
|
||||
try {
|
||||
pttUrl = await registerResource(
|
||||
'ptt-url-get',
|
||||
|
||||
@ -62,7 +62,6 @@ export class NapCatOneBot11Adapter {
|
||||
networkManager: OB11NetworkManager;
|
||||
actions: ActionMap;
|
||||
private readonly bootTime = Date.now() / 1000;
|
||||
//recallMsgCache = new LRUCache<string, boolean>(100);
|
||||
recallEventCache = new Map<string, any>();
|
||||
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
|
||||
this.core = core;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user