napcat.protobuf test

This commit is contained in:
手瓜一十雪 2025-02-21 21:12:46 +08:00
parent cf5e0e0f14
commit be2e2e86f0
9 changed files with 247 additions and 14 deletions

View File

@ -63,8 +63,10 @@
},
"dependencies": {
"@ffmpeg.wasm/core-mt": "^0.13.2",
"@napi-rs/canvas": "^0.1.67",
"compressing": "^1.10.1",
"express": "^5.0.0",
"napcat.protobuf": "^1.1.2",
"piscina": "^4.7.0",
"silk-wasm": "^3.6.1",
"ws": "^8.18.0"

View File

@ -109,7 +109,6 @@ export class RequestUtil {
req.end();
});
}
// 请求返回都是原始内容
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}) {
return this.HttpGetJson<string>(url, method, data, headers, false, false);

View File

@ -1,4 +1,76 @@
{
"3.1.2-13107": {
"appid": 537146866,
"qua": "V1_LNX_NQ_3.1.2-13107_RDM_B"
},
"3.2.10-25765": {
"appid": 537234773,
"qua": "V1_LNX_NQ_3.2.10_25765_GW_B"
},
"3.2.12-26702": {
"appid": 537237950,
"qua": "V1_LNX_NQ_3.2.12_26702_GW_B"
},
"3.2.12-26740": {
"appid": 537237950,
"qua": "V1_LNX_NQ_3.2.12_26740_GW_B"
},
"3.2.12-26909": {
"appid": 537237923,
"qua": "V1_LNX_NQ_3.2.12_26909_GW_B"
},
"3.2.12-27187": {
"appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27187_GW_B"
},
"3.2.12-27206": {
"appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B"
},
"3.2.12-27254": {
"appid": 537240795,
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
},
"9.9.11-24815": {
"appid": 537226656,
"qua": "V1_WIN_NQ_9.9.11_24815_GW_B"
},
"9.9.12-25493": {
"appid": 537231759,
"qua": "V1_WIN_NQ_9.9.12_25493_GW_B"
},
"9.9.12-25765": {
"appid": 537234702,
"qua": "V1_WIN_NQ_9.9.12_25765_GW_B"
},
"9.9.12-26299": {
"appid": 537234826,
"qua": "V1_WIN_NQ_9.9.12_26299_GW_B"
},
"9.9.12-26339": {
"appid": 537234826,
"qua": "V1_WIN_NQ_9.9.12_26339_GW_B"
},
"9.9.12-26466": {
"appid": 537234826,
"qua": "V1_WIN_NQ_9.9.12_26466_GW_B"
},
"9.9.15-26702": {
"appid": 537237765,
"qua": "V1_WIN_NQ_9.9.15_26702_GW_B"
},
"9.9.15-26740": {
"appid": 537237765,
"qua": "V1_WIN_NQ_9.9.15_26740_GW_B"
},
"3.2.12-27556": {
"appid": 537243600,
"qua": "V1_LNX_NQ_3.2.12_27556_GW_B"
},
"3.2.12-27597": {
"appid": 537243600,
"qua": "V1_LNX_NQ_3.2.12_27597_GW_B"
},
"9.9.15-28060": {
"appid": 537246092,
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
@ -187,4 +259,4 @@
"appid": 537266500,
"qua": "V1_WIN_NQ_9.9.17_31363_GW_B"
}
}
}

View File

@ -8,7 +8,8 @@ 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';
import { ProtoBufDecode } from 'napcat.protobuf';
export const MsgData = new LRUCache<string, string>(5000);
// 0 send 1 recv
export interface NativePacketExportType {
InitHook?: (send: string, recv: string, callback: (type: number, uin: string, cmd: string, seq: number, hex_data: string) => void) => boolean;
@ -55,6 +56,19 @@ export class NativePacketClient extends IPacketClient {
// console.log('callback:', callback, trace_id);
callback?.({ seq, cmd, hex_data });
}
if (cmd === 'trpc.msg.olpush.OlPushService.MsgPush') {
try {
let msg_info = ProtoBufDecode(Buffer.from(hex_data, 'hex')) as any;
let group_id = (msg_info['1']['1']['8']['1'] as number).toString()
let msg_seq = (msg_info['1']['2']['5'] as number).toString()
let msg_id = group_id + '_' + msg_seq;
MsgData.put(msg_id, hex_data);
console.log('add msgid:', msg_id);
} catch (error) {
console.log('error:', error);
}
}
});
this.available = true;
}

View File

@ -50,6 +50,7 @@ import {
import { OB11Message } from './types';
import { IOB11NetworkAdapter } from '@/onebot/network/adapter';
import { OB11HttpSSEServerAdapter } from './network/http-server-sse';
import { OB11PluginAdapter } from './network/plugin';
//OneBot实现类
export class NapCatOneBot11Adapter {
@ -113,9 +114,9 @@ export class NapCatOneBot11Adapter {
//创建NetWork服务
// 注册Plugin 如果需要基于NapCat进行快速开发
// this.networkManager.registerAdapter(
// new OB11PluginAdapter('myPlugin', this.core, this,this.actions)
// );
this.networkManager.registerAdapter(
new OB11PluginAdapter('myPlugin', this.core, this, this.actions)
);
for (const key of ob11Config.network.httpServers) {
if (key.enable) {
this.networkManager.registerAdapter(

View File

@ -15,14 +15,14 @@ export class OB11PluginAdapter extends IOB11NetworkAdapter<PluginConfig> {
messagePostFormat: 'array',
reportSelfMessage: false,
enable: true,
debug: false,
debug: true,
};
super(name, config, core, obContext, actions);
}
onEvent<T extends OB11EmitEventContent>(event: T) {
if (event.post_type === 'message') {
plugin_onmessage(this.config.name, this.core, this.obContext, event as OB11Message, this.actions, this).then().catch();
plugin_onmessage(this.config.name, this.core, this.obContext, event as OB11Message, this.actions, this).then().catch(console.log);
}
}

View File

@ -1,11 +1,75 @@
import { NapCatOneBot11Adapter, OB11Message } from '@/onebot';
import { NapCatOneBot11Adapter, OB11Message, OB11MessageDataType } from '@/onebot';
import { NapCatCore } from '@/core';
import { ActionMap } from '@/onebot/action';
import { OB11PluginAdapter } from '@/onebot/network/plugin';
import { MsgData } from '@/core/packet/client/nativeClient';
import { ProtoBufDecode } from 'napcat.protobuf';
import { drawJsonContent } from '@/shell/napcat';
import appidList from "@/core/external/appid.json";
export const plugin_onmessage = async (adapter: string, _core: NapCatCore, _obCtx: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap, instance: OB11PluginAdapter) => {
if (message.raw_message === 'ping') {
const ret = await action.get('send_group_msg')?.handle({ group_id: String(message.group_id), message: 'pong' }, adapter, instance.config);
console.log(ret);
if (typeof message.message === 'string' || !message.raw) return;
if (!message.message.find(e => e.type == 'text' && e.data.text == '#取')) return;
let reply = message.raw.elements.find(e => e.replyElement)?.replyElement?.replayMsgSeq;
if (!reply) return;
let msg_id = message.group_id?.toString() + "_" + reply;
let hex_data = MsgData.get(msg_id);
if (!hex_data) {
console.log('未找到' + msg_id);
return;
}
};
let decodedData: any = ProtoBufDecode(new Uint8Array(Buffer.from(hex_data, 'hex')), (data) => Buffer.from(data).toString('hex'));
let msgList = [];
for (const keyData of decodedData['1']['3']['1']['2']) {
let mdInner = JSON.stringify(keyData, (_key, value) => typeof value === 'bigint' ? value.toString() : value, 2);
msgList.push({
type: OB11MessageDataType.node,
data: {
content: [
{
type: OB11MessageDataType.image,
data: {
file: await drawJsonContent(mdInner)
}
}
]
}
});
}
let now_appid = decodedData['1']['1']['4'];
console.log(now_appid);
let versionList = Object.entries(appidList).filter(([_, appidData]) => appidData.appid == now_appid).map(([version, appidData]) => ({ version, appidData }));
if (versionList.length > 0) {
let msg = `用户应用号: ${now_appid}`;
if (versionList.length > 1) {
versionList.forEach(version => {
msg += `\n可能的客户端版本: ${version.version}\n可能的客户端识别码: ${version.appidData.qua}`;
});
} else {
msg += `\n客户端版本: ${versionList[0]?.version}\n客户端识别码: ${versionList[0]?.appidData.qua}`;
}
msgList.push({
type: OB11MessageDataType.node,
data: {
content: [
{
type: OB11MessageDataType.image,
data: {
file: await drawJsonContent(msg)
}
}
]
}
});
}
await action.get('send_group_msg')?.handle({
group_id: String(message.group_id),
message: msgList as any
}, adapter, instance.config);
};

View File

@ -1,2 +1,82 @@
import { NCoreInitShell } from './base';
import { createCanvas, GlobalFonts, loadImage } from '@napi-rs/canvas';
GlobalFonts.registerFromPath('F:\\fonts\\JetBrainsMono.ttf', 'JetBrains Mono');
GlobalFonts.registerFromPath('F:\\fonts\\AaCute.ttf', 'Aa偷吃可爱长大的');
export async function drawJsonContent(jsonContent: string) {
const lines = jsonContent.split('\n');
const padding = 40;
const lineHeight = 30;
const canvas = createCanvas(1, 1);
const ctx = canvas.getContext('2d');
let maxLineWidth = 0;
for (const line of lines) {
let lineWidth = 0;
for (const char of line) {
const isChinese = /[\u4e00-\u9fa5]/.test(char);
ctx.font = isChinese ? '20px "Aa偷吃可爱长大的"' : '20px "JetBrains Mono"';
lineWidth += ctx.measureText(char).width;
}
if (lineWidth > maxLineWidth) {
maxLineWidth = lineWidth;
}
}
const width = maxLineWidth + padding * 2;
const height = lines.length * lineHeight + padding * 2;
const finalCanvas = createCanvas(width, height);
const finalCtx = finalCanvas.getContext('2d');
const backgroundImage = await loadImage('F:\\BVideo\\Dev\\post.jpg');
const pattern = finalCtx.createPattern(backgroundImage, 'repeat');
finalCtx.fillStyle = pattern;
finalCtx.fillRect(0, 0, width, height);
finalCtx.filter = 'blur(5px)';
finalCtx.drawImage(finalCanvas, 0, 0);
finalCtx.filter = 'none';
const cardWidth = width - padding;
const cardHeight = height - padding;
const cardX = padding / 2;
const cardY = padding / 2;
const radius = 20;
finalCtx.fillStyle = 'rgba(255, 255, 255, 0.8)';
finalCtx.beginPath();
finalCtx.moveTo(cardX + radius, cardY);
finalCtx.lineTo(cardX + cardWidth - radius, cardY);
finalCtx.quadraticCurveTo(cardX + cardWidth, cardY, cardX + cardWidth, cardY + radius);
finalCtx.lineTo(cardX + cardWidth, cardY + cardHeight - radius);
finalCtx.quadraticCurveTo(cardX + cardWidth, cardY + cardHeight, cardX + cardWidth - radius, cardY + cardHeight);
finalCtx.lineTo(cardX + radius, cardY + cardHeight);
finalCtx.quadraticCurveTo(cardX, cardY + cardHeight, cardX, cardY + cardHeight - radius);
finalCtx.lineTo(cardX, cardY + radius);
finalCtx.quadraticCurveTo(cardX, cardY, cardX + radius, cardY);
finalCtx.closePath();
finalCtx.fill();
// 绘制 JSON 内容
finalCtx.fillStyle = 'black';
let textY = cardY + 40;
for (const line of lines) {
let x = cardX + 20;
for (const char of line) {
const isChinese = /[\u4e00-\u9fa5]/.test(char);
finalCtx.font = isChinese ? '20px "Aa偷吃可爱长大的"' : '20px "JetBrains Mono"';
finalCtx.fillText(char, x, textY);
x += finalCtx.measureText(char).width;
}
textY += 30;
}
// 保存图像
const buffer = finalCanvas.toBuffer('image/png');
return "base64://" + buffer.toString('base64');
}
NCoreInitShell();

View File

@ -9,7 +9,8 @@ const external = [
'ws',
'express',
'@ffmpeg.wasm/core-mt',
'piscina'
'piscina',
'@napi-rs/canvas'
];
const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)].flat();