mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-26 02:31:20 +08:00
napcat.protobuf test
This commit is contained in:
parent
cf5e0e0f14
commit
be2e2e86f0
@ -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"
|
||||
|
||||
@ -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);
|
||||
|
||||
74
src/core/external/appid.json
vendored
74
src/core/external/appid.json
vendored
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
@ -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();
|
||||
@ -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();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user