Compare commits

...

11 Commits

Author SHA1 Message Date
手瓜一十雪
cba9c78ab1 release: v2.6.21 2024-10-02 10:05:01 +08:00
手瓜一十雪
c32db4a881 fix: rkey v2 2024-10-02 10:03:48 +08:00
手瓜一十雪
871add3071 Merge pull request #419 from hguandl/macos
Fix Protobuf Dependencies & macOS Support
2024-10-01 22:59:07 +08:00
Hao Guan
e661c617a3 update: macOS support 2024-10-01 22:48:51 +08:00
Hao Guan
d4bf721540 fix: protobuf dependencies 2024-10-01 22:48:31 +08:00
Wesley F. Young
d91b55faed update: log group name & sender nickname onto console 2024-10-01 11:01:32 +08:00
Alen
9687832d4d chore: 拉高linuxQQ版本 2024-10-01 02:37:44 +08:00
手瓜一十雪
fc3e436744 fix: log 2024-09-30 17:07:30 +08:00
手瓜一十雪
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
15 changed files with 232 additions and 155 deletions

View File

@@ -2,8 +2,8 @@
"name": "qq-chat", "name": "qq-chat",
"version": "9.9.15-28418", "version": "9.9.15-28418",
"verHash": "206bfa62", "verHash": "206bfa62",
"linuxVersion": "3.2.12-28327", "linuxVersion": "3.2.12-28418",
"linuxVerHash": "f60e8252", "linuxVerHash": "0256c948",
"type": "module", "type": "module",
"private": true, "private": true,
"description": "QQ", "description": "QQ",

View File

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

View File

@@ -1,52 +1,53 @@
{ {
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "2.6.18", "version": "2.6.21",
"scripts": { "scripts": {
"build:framework": "vite build --mode framework", "build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell", "build:shell": "vite build --mode shell",
"build:webui": "cd ./src/webui && vite build", "build:webui": "cd ./src/webui && vite build",
"lint": "eslint --fix src/**/*.{js,ts}", "lint": "eslint --fix src/**/*.{js,ts}",
"depend": "cd dist && npm install --omit=dev" "depend": "cd dist && npm install --omit=dev"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-typescript": "^7.24.7", "@babel/preset-typescript": "^7.24.7",
"@log4js-node/log4js-api": "^1.0.2", "@log4js-node/log4js-api": "^1.0.2",
"@rollup/plugin-node-resolve": "^15.2.3", "@protobuf-ts/runtime": "^2.9.4",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-node-resolve": "^15.2.3",
"@types/cors": "^2.8.17", "@rollup/plugin-typescript": "^11.1.6",
"@types/express": "^5.0.0", "@types/cors": "^2.8.17",
"@types/fluent-ffmpeg": "^2.1.24", "@types/express": "^5.0.0",
"@types/node": "^22.0.1", "@types/fluent-ffmpeg": "^2.1.24",
"@types/qrcode-terminal": "^0.12.2", "@types/node": "^22.0.1",
"@types/ws": "^8.5.12", "@types/qrcode-terminal": "^0.12.2",
"@typescript-eslint/eslint-plugin": "^8.3.0", "@types/ws": "^8.5.12",
"@typescript-eslint/parser": "^8.3.0", "@typescript-eslint/eslint-plugin": "^8.3.0",
"eslint": "^8.57.0", "@typescript-eslint/parser": "^8.3.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1", "eslint-import-resolver-typescript": "^3.6.1",
"typescript": "^5.3.3", "eslint-plugin-import": "^2.29.1",
"vite": "^5.2.6", "typescript": "^5.3.3",
"vite-plugin-cp": "^4.0.8", "vite": "^5.2.6",
"vite-tsconfig-paths": "^4.3.2" "vite-plugin-cp": "^4.0.8",
}, "vite-tsconfig-paths": "^4.3.2"
"dependencies": { },
"ajv": "^8.13.0", "dependencies": {
"@protobuf-ts/plugin": "^2.9.4", "ajv": "^8.13.0",
"async-mutex": "^0.5.0", "@protobuf-ts/plugin": "^2.9.4",
"chalk": "^5.3.0", "async-mutex": "^0.5.0",
"commander": "^12.1.0", "chalk": "^5.3.0",
"cors": "^2.8.5", "commander": "^12.1.0",
"express": "^5.0.0-beta.2", "cors": "^2.8.5",
"fast-xml-parser": "^4.3.6", "express": "^5.0.0-beta.2",
"file-type": "^19.0.0", "fast-xml-parser": "^4.3.6",
"fluent-ffmpeg": "^2.1.2", "file-type": "^19.0.0",
"image-size": "^1.1.1", "fluent-ffmpeg": "^2.1.2",
"json-schema-to-ts": "^3.1.0", "image-size": "^1.1.1",
"log4js": "^6.9.1", "json-schema-to-ts": "^3.1.0",
"qrcode-terminal": "^0.12.0", "log4js": "^6.9.1",
"silk-wasm": "^3.6.1", "qrcode-terminal": "^0.12.0",
"ws": "^8.18.0" "silk-wasm": "^3.6.1",
} "ws": "^8.18.0"
} }
}

View File

@@ -139,8 +139,13 @@ export class LogWrapper {
logMessage(msg: RawMessage, selfInfo: SelfInfo) { logMessage(msg: RawMessage, selfInfo: SelfInfo) {
const isSelfSent = msg.senderUin === selfInfo.uin; const isSelfSent = msg.senderUin === selfInfo.uin;
this.log(`${isSelfSent ? '发送 ->' : '接收 <-'
} ${rawMessageToText(msg)}`); // Intercept grey tip
if (msg.elements[0]?.elementType === ElementType.GreyTip) {
return;
}
this.log(`${isSelfSent ? '发送 ->' : '接收 <-' } ${rawMessageToText(msg)}`);
} }
} }
@@ -154,7 +159,12 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
if (msg.chatType == ChatType.KCHATTYPEC2C) { if (msg.chatType == ChatType.KCHATTYPEC2C) {
tokens.push(`私聊 (${msg.peerUin})`); tokens.push(`私聊 (${msg.peerUin})`);
} else if (msg.chatType == ChatType.KCHATTYPEGROUP) { } else if (msg.chatType == ChatType.KCHATTYPEGROUP) {
tokens.push(`群聊 (群 ${msg.peerUin}${msg.senderUin})`); if (recursiveLevel < 1) {
tokens.push(`群聊 [${msg.peerName}(${msg.peerUin})]`);
}
if (msg.senderUin !== '0') {
tokens.push(`[${msg.sendMemberName || msg.sendRemarkName || msg.sendNickName}(${msg.senderUin})]`);
}
} else if (msg.chatType == ChatType.KCHATTYPEDATALINE) { } else if (msg.chatType == ChatType.KCHATTYPEDATALINE) {
tokens.push('移动设备'); tokens.push('移动设备');
} else /* temp */ { } else /* temp */ {

View File

@@ -1 +1 @@
export const napCatVersion = '2.6.18'; export const napCatVersion = '2.6.21';

View File

@@ -365,22 +365,41 @@ export class NTQQFileApi {
if (url) { if (url) {
const parsedUrl = new URL(IMAGE_HTTP_HOST + url); const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
const urlRkey = parsedUrl.searchParams.get('rkey');
const imageAppid = parsedUrl.searchParams.get('appid'); const imageAppid = parsedUrl.searchParams.get('appid');
const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid); const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid);
if (isNTV2) { const imageFileId = parsedUrl.searchParams.get('fileid');
let rkey = parsedUrl.searchParams.get('rkey');
if (rkey) { let rkeyData = {
return IMAGE_HTTP_HOST_NT + url; private_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qEc3Rbib9LP4',
} group_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qffcqm614gds',
const rkeyData = await this.rkeyManager.getRkey(); online_rkey: false
rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey; };
return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
} else { try {
return IMAGE_HTTP_HOST + url; let tempRkeyData = await this.rkeyManager.getRkey();
rkeyData.group_rkey = tempRkeyData.group_rkey;
rkeyData.private_rkey = tempRkeyData.private_rkey;
rkeyData.online_rkey = tempRkeyData.expired_time > Date.now() / 1000;
} catch (e) {
this.context.logger.logError.bind(this.context.logger)('获取rkey失败 Fallback Old Mode', e);
} }
if (isNTV2 && urlRkey) {
return IMAGE_HTTP_HOST_NT + urlRkey;
} else if (isNTV2 && rkeyData.online_rkey) {
let rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
return IMAGE_HTTP_HOST_NT + url + `&rkey=${rkey}`;
} else if (isNTV2 && imageFileId) {
let rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
return IMAGE_HTTP_HOST + `/download?appid=${imageAppid}&fileid=${imageFileId}&rkey=${rkey}`;
}
} else if (fileMd5 || md5HexStr) { } else if (fileMd5 || md5HexStr) {
return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`; return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
} }
this.context.logger.logDebug('图片url获取失败', element); this.context.logger.logDebug('图片url获取失败', element);
return ''; return '';
} }

View File

@@ -909,11 +909,26 @@ export interface RawMessage {
*/ */
peerUin: string; peerUin: string;
/**
* 好友备注(如果是好友消息)
*/
remark?: string;
/**
* 群名(如果是群消息)
*/
peerName: string;
/** /**
* 发送者昵称(如果是好友消息) * 发送者昵称(如果是好友消息)
*/ */
sendNickName: string; sendNickName: string;
/**
* 发送者好友备注(如果是群消息并且有发送者好友)
*/
sendRemarkName: string;
/** /**
* 发送者群名片(如果是群消息) * 发送者群名片(如果是群消息)
*/ */
@@ -974,4 +989,4 @@ export interface MsgReqType {
extraCnt: number extraCnt: number
} }
//getMsgsIncludeSelf Peer必须 byType 1 //getMsgsIncludeSelf Peer必须 byType 1
//getMsgsWithMsgTimeAndClientSeqForC2C Peer必须 byType 3 //getMsgsWithMsgTimeAndClientSeqForC2C Peer必须 byType 3

View File

@@ -15,6 +15,10 @@
"appid": 537246140, "appid": 537246140,
"qua": "V1_LNX_NQ_3.2.12_28131_GW_B" "qua": "V1_LNX_NQ_3.2.12_28131_GW_B"
}, },
"6.9.55-28131": {
"appid": 537246115,
"qua": "V1_MAC_NQ_6.9.55_28131_GW_B"
},
"9.9.15-28327":{ "9.9.15-28327":{
"appid": 537249321, "appid": 537249321,
"qua": "V1_WIN_NQ_9.9.15_28327_GW_B" "qua": "V1_WIN_NQ_9.9.15_28327_GW_B"
@@ -30,5 +34,9 @@
"3.2.12-28418":{ "3.2.12-28418":{
"appid": 537249393, "appid": 537249393,
"qua": "V1_LNX_NQ_3.2.12_28418_GW_B" "qua": "V1_LNX_NQ_3.2.12_28418_GW_B"
},
"6.9.56-28418": {
"appid": 537249367,
"qua": "V1_MAC_NQ_6.9.56_28418_GW_B"
} }
} }

View File

@@ -26,7 +26,8 @@ export class RkeyManager {
try { try {
await this.refreshRkey(); await this.refreshRkey();
} catch (e) { } catch (e) {
this.logger.logError.bind(this.logger)('获取rkey失败', e); throw new Error(`获取rkey失败: ${e}`);//外抛
//this.logger.logError.bind(this.logger)('获取rkey失败', e);
} }
} }
return this.rkeyData; return this.rkeyData;
@@ -42,9 +43,18 @@ export class RkeyManager {
//刷新rkey //刷新rkey
for (const url of this.serverUrl) { for (const url of this.serverUrl) {
try { try {
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET'); let temp = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
this.rkeyData = {
group_rkey: temp.group_rkey.slice(6),
private_rkey: temp.private_rkey.slice(6),
expired_time: temp.expired_time
};
} catch (e) { } catch (e) {
this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e); this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e);
//是否为最后一个url
if (url === this.serverUrl[this.serverUrl.length - 1]) {
throw new Error(`获取rkey失败: ${e}`);//外抛
}
} }
} }

View File

@@ -0,0 +1,21 @@
import { MessageType, BinaryReader, ScalarType, BinaryWriter } from '@protobuf-ts/runtime';
export const FileId = new MessageType("FileId", [
{ no: 2, name: "sha1", kind: "scalar", T: ScalarType.BYTES },
{ no: 4, name: "appid", kind: "scalar", T: ScalarType.UINT32 },
]);
export function encodePBFileId(message: any) {
return FileId.internalBinaryWrite(message, new BinaryWriter(), {
writerFactory: () => new BinaryWriter(),
writeUnknownFields: false
}).finish();
}
export function decodePBFileId(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer);
return FileId.internalBinaryRead(reader, reader.len, {
readUnknownField: true,
readerFactory: () => new BinaryReader(buffer)
});
}

View File

@@ -1,59 +1,58 @@
import { MessageType, BinaryReader, ScalarType, RepeatType } from '@protobuf-ts/runtime'; import { MessageType, BinaryReader, ScalarType, RepeatType } from '@protobuf-ts/runtime';
export const LikeDetailType = new MessageType("LikeDetailType", [ export const LikeDetail = new MessageType("likeDetail", [
{ no: 1, name: "txt", kind: "scalar", T: ScalarType.STRING /* string */ }, { no: 1, name: "txt", kind: "scalar", T: ScalarType.STRING /* string */ },
{ no: 2, name: "uin", kind: "scalar", T: ScalarType.INT64 /* int64 */ }, { no: 3, name: "uin", kind: "scalar", T: ScalarType.INT64 /* int64 */ },
{ no: 3, name: "nickname", kind: "scalar", T: ScalarType.STRING /* string */ } { no: 5, name: "nickname", kind: "scalar", T: ScalarType.STRING /* string */ }
]); ]);
export const LikeMsgType = new MessageType("LikeMsgType", [ export const LikeMsg = new MessageType("likeMsg", [
{ no: 1, name: "times", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 1, name: "times", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 2, name: "time", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 2, name: "time", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 3, name: "detail", kind: "message", T: () => LikeDetailType } { no: 3, name: "detail", kind: "message", T: () => LikeDetail }
]); ]);
export const ProfileLikeSubTipType = new MessageType("ProfileLikeSubTipType", [ export const ProfileLikeSubTip = new MessageType("profileLikeSubTip", [
{ no: 1, name: "msg", kind: "message", T: () => LikeMsgType } { no: 14, name: "msg", kind: "message", T: () => LikeMsg }
]); ]);
export const ProfileLikeTip = new MessageType("profileLikeTip", [
export const ProfileLikeTipType = new MessageType("ProfileLikeTipType", [
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 1, name: "msgType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 2, name: "subType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 3, name: "content", kind: "message", T: () => ProfileLikeSubTipType } { 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 SysMessageHeaderType = new MessageType("SysMessageHeaderType", [ export const SysMessageMsgSpec = new MessageType("SysMessageMsgSpec", [
{ no: 1, name: "id", kind: "scalar", T: ScalarType.STRING /* string */ }, { no: 1, name: "msgType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 2, name: "timestamp", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 2, name: "subType", kind: "scalar", T: ScalarType.UINT32 /* uint32 */ },
{ no: 3, name: "sender", kind: "scalar", T: ScalarType.STRING /* string */ } { 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 SysMessageMsgSpecType = new MessageType("SysMessageMsgSpecType", [ export const SysMessageBodyWrapper = new MessageType("SysMessageBodyWrapper", [
{ no: 1, name: "msgType", kind: "scalar", T: ScalarType.INT32 /* int32 */ }, { no: 2, name: "wrappedBody", kind: "scalar", T: ScalarType.BYTES /* bytes */ }
{ no: 2, name: "subType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 3, name: "subSubType", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 4, name: "msgSeq", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 5, name: "time", kind: "scalar", T: ScalarType.INT32 /* int32 */ },
{ no: 6, name: "msgId", kind: "scalar", T: ScalarType.INT64 /* int64 */ },
{ no: 7, name: "other", kind: "scalar", T: ScalarType.INT32 /* int32 */ }
]); ]);
export const SysMessageBodyWrapperType = new MessageType("SysMessageBodyWrapperType", [ export const SysMessage = new MessageType("SysMessage", [
{ no: 1, name: "wrappedBody", kind: "scalar", T: ScalarType.BYTES /* bytes */ } { 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 const SysMessageType = new MessageType("SysMessageType", [
{ no: 1, name: "header", kind: "message", T: () => SysMessageHeaderType, repeat: RepeatType.PACKED },
{ no: 2, name: "msgSpec", kind: "message", T: () => SysMessageMsgSpecType, repeat: RepeatType.PACKED },
{ no: 3, name: "bodyWrapper", kind: "message", T: () => SysMessageBodyWrapperType }
]); ]);
export function decodeProfileLikeTip(buffer: Uint8Array): any { export function decodeProfileLikeTip(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer); const reader = new BinaryReader(buffer);
return ProfileLikeTipType.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) }); return ProfileLikeTip.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
} }
export function decodeSysMessage(buffer: Uint8Array): any { export function decodeSysMessage(buffer: Uint8Array): any {
const reader = new BinaryReader(buffer); const reader = new BinaryReader(buffer);
return SysMessageType.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) }); return SysMessage.internalBinaryRead(reader, reader.len, { readUnknownField: true, readerFactory: () => new BinaryReader(buffer) });
} }

View File

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

View File

@@ -73,53 +73,40 @@ export class NapCatOneBot11Adapter {
}; };
this.actions = createActionMap(this, core); this.actions = createActionMap(this, core);
this.networkManager = new OB11NetworkManager(); this.networkManager = new OB11NetworkManager();
this.registerNative(core, context).then().catch(); this.registerNative(core, context).catch(e => this.context.logger.logWarn.bind(this.context.logger)('初始化Native失败', e)).then();
this.InitOneBot() this.InitOneBot()
.catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e)); .catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e));
} }
async registerNative(core: NapCatCore, context: InstanceContext) { async registerNative(core: NapCatCore, context: InstanceContext) {
this.nativeCore = new Native(context.pathWrapper.binaryPath); try {
this.nativeCore.registerRecallCallback(async (hex: string) => { this.nativeCore = new Native(context.pathWrapper.binaryPath);
try { if (!this.nativeCore.inited) throw new Error('Native Not Init');
let data = decodeMessage(Buffer.from(hex, 'hex')) as any; this.nativeCore.registerRecallCallback(async (hex: string) => {
//data.MsgHead.BodyInner.MsgType SubType try {
let bodyInner = data.msgHead?.bodyInner; let data = decodeMessage(Buffer.from(hex, 'hex')) as any;
//context.logger.log("[appNative] Parse MsgType:" + bodyInner.msgType + " / SubType:" + bodyInner.subType); //data.MsgHead.BodyInner.MsgType SubType
if (bodyInner && bodyInner.msgType == 732 && bodyInner.subType == 17) { let bodyInner = data.msgHead?.bodyInner;
let RecallData = Buffer.from(data.msgHead.noifyData.innerData); //context.logger.log("[appNative] Parse MsgType:" + bodyInner.msgType + " / SubType:" + bodyInner.subType);
//跳过 4字节 群号 + 不知道的1字节 +2字节 长度 if (bodyInner && bodyInner.msgType == 732 && bodyInner.subType == 17) {
let uid = RecallData.readUint32BE(); let RecallData = Buffer.from(data.msgHead.noifyData.innerData);
const buffer = Buffer.from(RecallData.toString('hex').slice(14), 'hex'); //跳过 4字节 群号 + 不知道的1字节 +2字节 长度
let seq: number = decodeRecallGroup(buffer).recallDetails.subDetail.msgSeq; let uid = RecallData.readUint32BE();
let peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: uid.toString() }; const buffer = Buffer.from(RecallData.toString('hex').slice(14), 'hex');
context.logger.log("[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq); let seq: number = decodeRecallGroup(buffer).recallDetails.subDetail.msgSeq;
let msgs = await core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, seq.toString()); let peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: uid.toString() };
this.recallMsgCache.put(msgs.msgList[0].msgId, msgs.msgList[0]); context.logger.log("[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq);
// let ob11 = await this.apis.MsgApi.parseMessage(msgs.msgList[0], 'array') let msgs = await core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, seq.toString());
// .catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e)); this.recallMsgCache.put(msgs.msgList[0].msgId, msgs.msgList[0]);
// if (ob11) { }
// const { sendElements, deleteAfterSentFiles } = await this.apis.MsgApi.createSendElements(ob11.message as OB11MessageData[], peer); } catch (error: any) {
// this.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles); context.logger.logWarn("[Native] Error:", (error as Error).message, ' HEX:', hex);
// }
// this.apis.MsgApi.sendMsg(peer, [{
// elementType: 1,
// elementId: '',
// textElement: {
// content: "[Native] 群消息撤回 Peer: " + uid.toString() + " / MsgSeq:" + seq,
// atType: 0,
// atUid: '',
// atTinyId: '',
// atNtUid: '',
// },
// }]);
} }
} 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() { async InitOneBot() {
const selfInfo = this.core.selfInfo; const selfInfo = this.core.selfInfo;

View File

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

View File

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