Compare commits

...

16 Commits

Author SHA1 Message Date
手瓜一十雪
da90245f7b release: v2.6.20 2024-09-30 17:05:02 +08:00
手瓜一十雪
410d6a85d7 fix: protobuf #417 2024-09-30 08:30:39 +08:00
手瓜一十雪
b693342e4f fix 2024-09-30 08:18:02 +08:00
手瓜一十雪
acca361f2e release: v2.6.18 2024-09-29 20:11:30 +08:00
手瓜一十雪
b663f47713 style: ScalarType 2024-09-29 20:10:14 +08:00
手瓜一十雪
d332b199b5 refactor: protobufjs给我似! 2024-09-29 20:06:11 +08:00
Alen
78bac1dbd1 Merge pull request #416 from cnxysoft/upmain
fix: 28418下载HASH
2024-09-29 16:21:52 +08:00
Alen
724ff215f9 fix: 28418下载HASH 2024-09-29 16:20:01 +08:00
手瓜一十雪
68ea146469 release: v2.6.17 2024-09-29 13:07:52 +08:00
手瓜一十雪
82583e616f fix: #415 2024-09-29 12:57:50 +08:00
手瓜一十雪
bfc339c58d refactor: #415 2024-09-29 12:53:18 +08:00
手瓜一十雪
fe4427c076 feat: message字段返回 #415 2024-09-29 12:30:29 +08:00
手瓜一十雪
5745f388a9 feat: 简化代码 #415 2024-09-29 12:19:04 +08:00
手瓜一十雪
377e3c253f feat: parseForward for array 2024-09-29 11:26:45 +08:00
手瓜一十雪
3007a0c00e feat: nativeNode 2024-09-28 23:00:47 +08:00
手瓜一十雪
f51ffc091d Merge pull request #410 from NapNeko/hook
[Hook] NapcatNative
2024-09-28 21:38:04 +08:00
13 changed files with 219 additions and 202 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "qq-chat",
"version": "9.9.15-28418",
"verHash": "512caf78",
"verHash": "206bfa62",
"linuxVersion": "3.2.12-28327",
"linuxVerHash": "f60e8252",
"type": "module",

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ",
"slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现",
"version": "2.6.16",
"version": "2.6.20",
"icon": "./logo.png",
"authors": [
{

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "2.6.16",
"version": "2.6.20",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",
@@ -13,7 +13,6 @@
"devDependencies": {
"@babel/preset-typescript": "^7.24.7",
"@log4js-node/log4js-api": "^1.0.2",
"@protobuf-ts/plugin": "^2.9.4",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@types/cors": "^2.8.17",
@@ -34,6 +33,7 @@
},
"dependencies": {
"ajv": "^8.13.0",
"@protobuf-ts/plugin": "^2.9.4",
"async-mutex": "^0.5.0",
"chalk": "^5.3.0",
"commander": "^12.1.0",
@@ -45,7 +45,6 @@
"image-size": "^1.1.1",
"json-schema-to-ts": "^3.1.0",
"log4js": "^6.9.1",
"protobufjs": "~7.4.0",
"qrcode-terminal": "^0.12.0",
"silk-wasm": "^3.6.1",
"ws": "^8.18.0"

View File

@@ -1 +1 @@
export const napCatVersion = '2.6.16';
export const napCatVersion = '2.6.20';

View File

@@ -1,37 +1,48 @@
import * as pb from 'protobufjs';
import { MessageType, BinaryReader, ScalarType } from '@protobuf-ts/runtime';
export const BodyInner = new MessageType("BodyInner", [
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */, opt: true },
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */, opt: true }
]);
export const BodyInner = new pb.Type("BodyInner")
.add(new pb.Field("msgType", 1, "uint32", "optional"))
.add(new pb.Field("subType", 2, "uint32", "optional"))
export const NoifyData = new MessageType("NoifyData", [
{ no: 1, name: "skip", kind: "scalar", T: ScalarType.BYTES /* bytes */, opt: true },
{ no: 2, name: "innerData", kind: "scalar", T: ScalarType.BYTES /* bytes */, opt: true }
]);
export const NoifyData = new pb.Type("NoifyData")
.add(new pb.Field("skip", 1, "bytes", "optional"))
.add(new pb.Field("innerData", 2, "bytes", "optional"))
export const MsgHead = new MessageType("MsgHead", [
{ no: 2, name: "bodyInner", kind: "message", T: () => BodyInner, opt: true },
{ no: 3, name: "noifyData", kind: "message", T: () => NoifyData, opt: true }
]);
export const MsgHead = new pb.Type("MsgHead")
.add(BodyInner)
.add(NoifyData)
.add(new pb.Field("bodyInner", 2, "BodyInner", "optional"))
.add(new pb.Field("noifyData", 3, "NoifyData", "optional"));
export const Message = new MessageType("Message", [
{ no: 1, name: "msgHead", kind: "message", T: () => MsgHead }
]);
export const Message = new pb.Type("Message")
.add(MsgHead)
.add(new pb.Field("msgHead", 1, "MsgHead"))
export const SubDetail = new MessageType("SubDetail", [
{ no: 1, name: "msgSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 2, name: "msgTime", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 6, name: "senderUid", kind: "scalar", T: ScalarType.STRING /* string */ }
]);
export const SubDetail = new pb.Type("SubDetail")
.add(new pb.Field("msgSeq", 1, "uint32"))
.add(new pb.Field("msgTime", 2, "uint32"))
.add(new pb.Field("senderUid", 6, "string"))
export const RecallDetails = new MessageType("RecallDetails", [
{ no: 1, name: "operatorUid", kind: "scalar", T: ScalarType.STRING /* string */ },
{ no: 3, name: "subDetail", kind: "message", T: () => SubDetail }
]);
export const RecallDetails = new pb.Type("RecallDetails")
.add(SubDetail)
.add(new pb.Field("operatorUid", 1, "string"))
.add(new pb.Field("subDetail", 3, "SubDetail"))
export const RecallGroup = new MessageType("RecallGroup", [
{ no: 1, name: "type", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 4, name: "peerUid", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 11, name: "recallDetails", kind: "message", T: () => RecallDetails },
{ no: 37, name: "grayTipsSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ }
]);
export const RecallGroup = new pb.Type("RecallGroup")
.add(RecallDetails)
.add(new pb.Field("type", 1, "int32"))
.add(new pb.Field("peerUid", 4, "uint32"))
.add(new pb.Field("recallDetails", 11, "RecallDetails"))
.add(new pb.Field("grayTipsSeq", 37, "uint32"))
export function decodeMessage(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer);
return Message.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
}
export function decodeRecallGroup(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer);
return RecallGroup.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
}

View File

@@ -1,95 +1,58 @@
import * as pb from 'protobufjs';
import { MessageType, BinaryReader, ScalarType, RepeatType } from '@protobuf-ts/runtime';
// Proto: from src/core/proto/ProfileLike.proto
// Author: Mlikiowa
export const LikeDetail = new MessageType("likeDetail", [
{ no: 1, name: "txt", kind: "scalar", T: ScalarType.STRING /* string */ },
{ no: 3, name: "uin", kind: "scalar", T: ScalarType.INT64 /* int64 */ },
{ no: 5, name: "nickname", kind: "scalar", T: ScalarType.STRING /* string */ }
]);
export interface LikeDetailType {
txt: string;
uin: pb.Long;
nickname: string;
}
export interface LikeMsgType {
times: number;
time: number;
detail: LikeDetailType;
export const LikeMsg = new MessageType("likeMsg", [
{ no: 1, name: "times", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 2, name: "time", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 3, name: "detail", kind: "message", T: () => LikeDetail }
]);
export const ProfileLikeSubTip = new MessageType("profileLikeSubTip", [
{ no: 14, name: "msg", kind: "message", T: () => LikeMsg }
]);
export const ProfileLikeTip = new MessageType("profileLikeTip", [
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 203, name: "content", kind: "message", T: () => ProfileLikeSubTip }
]);
export const SysMessageHeader = new MessageType("SysMessageHeader", [
{ no: 1, name: "PeerNumber", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 2, name: "PeerString", kind: "scalar", T: ScalarType.STRING /* string */ },
{ no: 5, name: "Uin", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 6, name: "Uid", kind: "scalar", T: ScalarType.STRING /* string */, opt: true }
]);
export const SysMessageMsgSpec = new MessageType("SysMessageMsgSpec", [
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 3, name: "subSubType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 5, name: "msgSeq", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 6, name: "time", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 12, name: "msgId", kind: "scalar", T: ScalarType.UINT64 /* uint64 */ },
{ no: 13, name: "other", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ }
]);
export const SysMessageBodyWrapper = new MessageType("SysMessageBodyWrapper", [
{ no: 2, name: "wrappedBody", kind: "scalar", T: ScalarType.BYTES /* bytes */ }
]);
export const SysMessage = new MessageType("SysMessage", [
{ no: 1, name: "header", kind: "message", T: () => SysMessageHeader, repeat: RepeatType.UNPACKED },
{ no: 2, name: "msgSpec", kind: "message", T: () => SysMessageMsgSpec, repeat: RepeatType.UNPACKED },
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapper }
]);
export function decodeProfileLikeTip(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer);
return ProfileLikeTip.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
}
export interface profileLikeSubTipType {
msg: LikeMsgType;
}
export interface ProfileLikeTipType {
msgType: number;
subType: number;
content: profileLikeSubTipType;
}
export interface SysMessageHeaderType {
id: string;
timestamp: number;
sender: string;
}
export interface SysMessageMsgSpecType {
msgType: number;
subType: number;
subSubType: number;
msgSeq: number;
time: number;
msgId: pb.Long;
other: number;
}
export interface SysMessageBodyWrapperType {
wrappedBody: Uint8Array;
}
export interface SysMessageType {
header: SysMessageHeaderType[];
msgSpec: SysMessageMsgSpecType[];
bodyWrapper: SysMessageBodyWrapperType;
}
export const SysMessageHeader = new pb.Type("SysMessageHeader")
.add(new pb.Field("PeerNumber", 1, "uint32"))
.add(new pb.Field("PeerString", 2, "string"))
.add(new pb.Field("Uin", 5, "uint32"))
.add(new pb.Field("Uid", 6, "string", "optional"));
export const SysMessageMsgSpec = new pb.Type("SysMessageMsgSpec")
.add(new pb.Field("msgType", 1, "uint32"))
.add(new pb.Field("subType", 2, "uint32"))
.add(new pb.Field("subSubType", 3, "uint32"))
.add(new pb.Field("msgSeq", 5, "uint32"))
.add(new pb.Field("time", 6, "uint32"))
.add(new pb.Field("msgId", 12, "uint64"))
.add(new pb.Field("other", 13, "uint32"));
export const SysMessageBodyWrapper = new pb.Type("SysMessageBodyWrapper")
.add(new pb.Field("wrappedBody", 2, "bytes"));
export const SysMessage = new pb.Type("SysMessage")
.add(SysMessageHeader)
.add(SysMessageMsgSpec)
.add(SysMessageBodyWrapper)
.add(new pb.Field("header", 1, "SysMessageHeader", "repeated"))
.add(new pb.Field("msgSpec", 2, "SysMessageMsgSpec", "repeated"))
.add(new pb.Field("bodyWrapper", 3, "SysMessageBodyWrapper"));
export const likeDetail = new pb.Type("likeDetail")
.add(new pb.Field("txt", 1, "string"))
.add(new pb.Field("uin", 3, "int64"))
.add(new pb.Field("nickname", 5, "string"));
export const likeMsg = new pb.Type("likeMsg")
.add(likeDetail)
.add(new pb.Field("times", 1, "int32"))
.add(new pb.Field("time", 2, "int32"))
.add(new pb.Field("detail", 3, "likeDetail"));
export const profileLikeSubTip = new pb.Type("profileLikeSubTip")
.add(likeMsg)
.add(new pb.Field("msg", 14, "likeMsg"))
export const profileLikeTip = new pb.Type("profileLikeTip")
.add(profileLikeSubTip)
.add(new pb.Field("msgType", 1, "int32"))
.add(new pb.Field("subType", 2, "int32"))
.add(new pb.Field("content", 203, "profileLikeSubTip"));
export function decodeSysMessage(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer);
return SysMessage.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
}

View File

@@ -1,23 +1,40 @@
import { constants } from "node:os";
import path from "path";
import { dlopen } from "process";
import fs from "fs";
export class Native {
platform: string;
supportedPlatforms = ['win32'];
MoeHooExport: any = { exports: {} };
recallHookEnabled: boolean = false;
inited = true;
constructor(nodePath: string, platform: string = process.platform) {
this.platform = platform;
if (!this.supportedPlatforms.includes(this.platform)) {
throw new Error(`Platform ${this.platform} is not supported`);
try {
if (!this.supportedPlatforms.includes(this.platform)) {
throw new Error(`Platform ${this.platform} is not supported`);
}
let nativeNode = path.join(nodePath, './native/MoeHoo.win32.node');
if (fs.existsSync(nativeNode)) {
dlopen(this.MoeHooExport, nativeNode, constants.dlopen.RTLD_LAZY);
}
} catch (error) {
this.inited = false;
}
dlopen(this.MoeHooExport, path.join(nodePath, './native/MoeHoo.win32.node'), constants.dlopen.RTLD_LAZY);
}
isSetReCallEnabled(): boolean {
return this.recallHookEnabled;
return this.recallHookEnabled && this.inited;
}
registerRecallCallback(callback: (hex: string) => any): void {
this.recallHookEnabled = true;
return this.MoeHooExport.exports.registMsgPush(callback);
try {
if (!this.inited) throw new Error('Native Not Init');
if (this.MoeHooExport.exports?.registMsgPush) {
this.MoeHooExport.exports.registMsgPush(callback);
this.recallHookEnabled = true;
}
} catch (error) {
this.recallHookEnabled = false;
}
}
}

View File

@@ -1,9 +1,16 @@
import BaseAction from '../BaseAction';
import { OB11ForwardMessage } from '@/onebot';
import { OB11Message, OB11MessageData, OB11MessageDataType, OB11MessageForward, OB11MessageNode as OriginalOB11MessageNode } from '@/onebot';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique';
type OB11MessageNode = OriginalOB11MessageNode & {
data: {
content?: Array<OB11MessageData>;
message: Array<OB11MessageData>;
};
};
const SchemaData = {
type: 'object',
properties: {
@@ -18,36 +25,69 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetForwardMsg;
payloadSchema = SchemaData;
private createTemplateNode(message: OB11Message): OB11MessageNode {
return {
type: OB11MessageDataType.node,
data: {
user_id: message.user_id,
nickname: message.sender.nickname,
message: [],
content: []
}
};
}
async parseForward(messages: OB11Message[]): Promise<OB11MessageNode[]> {
const retMsg: OB11MessageNode[] = [];
for (const message of messages) {
const templateNode = this.createTemplateNode(message);
for (const msgdata of message.message) {
if ((msgdata as OB11MessageData).type === OB11MessageDataType.forward) {
const newNode = this.createTemplateNode(message);
newNode.data.message = await this.parseForward((msgdata as OB11MessageForward).data.content);
templateNode.data.message.push(newNode);
} else {
templateNode.data.message.push(msgdata as OB11MessageData);
}
}
retMsg.push(templateNode);
}
return retMsg;
}
async _handle(payload: Payload): Promise<any> {
const msgId = payload.message_id || payload.id;
if (!msgId) {
throw Error('message_id is required');
throw new Error('message_id is required');
}
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId);
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || parseInt(msgId));
if (!rootMsg) {
throw Error('msg not found');
throw new Error('msg not found');
}
const data = await this.core.apis.MsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId);
const data = await this.core.apis.MsgApi.getMsgsByMsgId(rootMsg.Peer, [rootMsg.MsgId]);
if (!data || data.result !== 0) {
throw Error('找不到相关的聊天记录' + data?.errMsg);
throw new Error('找不到相关的聊天记录' + data?.errMsg);
}
const msgList = data.msgList;
const messages = (await Promise.all(msgList.map(async msg => {
const resMsg = await this.obContext.apis.MsgApi
.parseMessage(msg);
if (!resMsg) return;
resMsg.message_id = MessageUnique.createUniqueMsgId({
guildId: '',
chatType: msg.chatType,
peerUid: msg.peerUid,
}, msg.msgId)!;
return resMsg;
}))).filter(msg => !!msg);
messages.map(msg => {
(<OB11ForwardMessage>msg).content = msg.message;
delete (<any>msg).message;
});
return { messages };
const singleMsg = data.msgList[0];
const resMsg = await this.obContext.apis.MsgApi.parseMessage(singleMsg, 'array');//强制array 以便处理
if (!resMsg) {
throw new Error('找不到相关的聊天记录');
}
//if (this.obContext.configLoader.configData.messagePostFormat === 'array') {
//提取
let realmsg = ((await this.parseForward([resMsg]))[0].data.message as OB11MessageNode[])[0].data.message;
//里面都是offline消息 id都是0 没得说话
return { message: realmsg };
//}
// return { message: resMsg };
}
}
}

View File

@@ -34,7 +34,7 @@ import { RequestUtil } from '@/common/request';
import fs from 'node:fs';
import fsPromise from 'node:fs/promises';
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
import { SysMessage, SysMessageType } from '@/core/proto/ProfileLike';
import { decodeSysMessage } from '@/core/proto/ProfileLike';
type RawToOb11Converters = {
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
@@ -841,7 +841,7 @@ export class OneBotMsgApi {
return { path, fileName: inputdata.name ?? fileName };
}
async parseSysMessage(msg: number[]) {
const sysMsg = SysMessage.decode(Uint8Array.from(msg)) as unknown as SysMessageType;
const sysMsg = decodeSysMessage(Uint8Array.from(msg));
if (sysMsg.msgSpec.length === 0) {
return;
}

View File

@@ -1,5 +1,5 @@
import { NapCatCore } from '@/core';
import { profileLikeTip, ProfileLikeTipType } from '@/core/proto/ProfileLike';
import { decodeProfileLikeTip } from '@/core/proto/ProfileLike';
import { NapCatOneBot11Adapter } from '@/onebot';
import { OB11ProfileLikeEvent } from '../event/notice/OB11ProfileLikeEvent';
@@ -13,7 +13,7 @@ export class OneBotUserApi {
this.core = core;
}
async parseLikeEvent(wrappedBody: Uint8Array): Promise<OB11ProfileLikeEvent | undefined> {
const likeTip = profileLikeTip.decode(Uint8Array.from(wrappedBody)) as unknown as ProfileLikeTipType;
const likeTip = decodeProfileLikeTip(Uint8Array.from(wrappedBody));
if (likeTip?.msgType !== 0 || likeTip?.subType !== 203) return;
this.core.context.logger.logDebug("收到点赞通知消息");
const likeMsg = likeTip.content.msg;

View File

@@ -45,7 +45,7 @@ import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecal
import { LRUCache } from '@/common/lru-cache';
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
import { Native } from '@/native';
import { Message, RecallGroup } from '@/core/proto/Message';
import { decodeMessage, decodeRecallGroup, Message, RecallGroup } from '@/core/proto/Message';
//OneBot实现类
export class NapCatOneBot11Adapter {
@@ -79,47 +79,34 @@ export class NapCatOneBot11Adapter {
}
async registerNative(core: NapCatCore, context: InstanceContext) {
this.nativeCore = new Native(context.pathWrapper.binaryPath);
this.nativeCore.registerRecallCallback(async (hex: string) => {
try {
let data = Message.decode(Buffer.from(hex, 'hex')) as any;
//data.MsgHead.BodyInner.MsgType SubType
let bodyInner = data.msgHead?.bodyInner;
//context.logger.log("[appNative] Parse MsgType:" + bodyInner.msgType + " / SubType:" + bodyInner.subType);
if (bodyInner && bodyInner.msgType == 732 && bodyInner.subType == 17) {
let RecallData = Buffer.from(data.msgHead.noifyData.innerData);
//跳过 4字节 群号 + 不知道的1字节 +2字节 长度
let uid = RecallData.readUint32BE();
const buffer = Buffer.from(RecallData.toString('hex').slice(14), 'hex');
let seq: number = (RecallGroup.decode(buffer) as any).recallDetails.subDetail.msgSeq;
let peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: uid.toString() };
context.logger.log("[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq);
let msgs = await core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, seq.toString());
this.recallMsgCache.put(msgs.msgList[0].msgId, msgs.msgList[0]);
// let ob11 = await this.apis.MsgApi.parseMessage(msgs.msgList[0], 'array')
// .catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
// if (ob11) {
// const { sendElements, deleteAfterSentFiles } = await this.apis.MsgApi.createSendElements(ob11.message as OB11MessageData[], peer);
// this.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles);
// }
// this.apis.MsgApi.sendMsg(peer, [{
// elementType: 1,
// elementId: '',
// textElement: {
// content: "[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq,
// atType: 0,
// atUid: '',
// atTinyId: '',
// atNtUid: '',
// },
// }]);
try {
this.nativeCore = new Native(context.pathWrapper.binaryPath);
if (!this.nativeCore.inited) throw new Error('Native Not Init');
this.nativeCore.registerRecallCallback(async (hex: string) => {
try {
let data = decodeMessage(Buffer.from(hex, 'hex')) as any;
//data.MsgHead.BodyInner.MsgType SubType
let bodyInner = data.msgHead?.bodyInner;
//context.logger.log("[appNative] Parse MsgType:" + bodyInner.msgType + " / SubType:" + bodyInner.subType);
if (bodyInner && bodyInner.msgType == 732 && bodyInner.subType == 17) {
let RecallData = Buffer.from(data.msgHead.noifyData.innerData);
//跳过 4字节 群号 + 不知道的1字节 +2字节 长度
let uid = RecallData.readUint32BE();
const buffer = Buffer.from(RecallData.toString('hex').slice(14), 'hex');
let seq: number = decodeRecallGroup(buffer).recallDetails.subDetail.msgSeq;
let peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: uid.toString() };
context.logger.log("[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq);
let msgs = await core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, seq.toString());
this.recallMsgCache.put(msgs.msgList[0].msgId, msgs.msgList[0]);
}
} catch (error: any) {
context.logger.logWarn("[Native] Error:", (error as Error).message, ' HEX:', hex);
}
} catch (error: any) {
context.logger.logWarn("[Native] Error:", (error as Error).message, ' HEX:', hex);
}
});
});
} catch (error) {
context.logger.logWarn("[Native] Error:", (error as Error).message);
return;
}
}
async InitOneBot() {
const selfInfo = this.core.selfInfo;

View File

@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
undefined,
SettingButton('V2.6.16', 'napcat-update-button', 'secondary'),
SettingButton('V2.6.20', 'napcat-update-button', 'secondary'),
),
]),
SettingList([

View File

@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
SettingItem(
'<span id="napcat-update-title">Napcat</span>',
void 0,
SettingButton("V2.6.16", "napcat-update-button", "secondary")
SettingButton("V2.6.20", "napcat-update-button", "secondary")
)
]),
SettingList([