mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8569a45114 | ||
![]() |
c790311fc3 | ||
![]() |
3c45c8bd80 | ||
![]() |
d5b7b3ae31 | ||
![]() |
43e73a5f24 | ||
![]() |
f3d967ae07 | ||
![]() |
dbe72fa07e | ||
![]() |
8fe37d1c1e | ||
![]() |
31365505d8 | ||
![]() |
b3fbe9e34a | ||
![]() |
5190b26399 | ||
![]() |
29a8db96f4 | ||
![]() |
1a4c2cabfd | ||
![]() |
ef9189055c | ||
![]() |
5cc3719125 | ||
![]() |
5d46f41348 | ||
![]() |
3c2c1963f4 | ||
![]() |
4896ca9279 | ||
![]() |
f0afba6cd9 | ||
![]() |
bd717c298a | ||
![]() |
baaa8a70dc | ||
![]() |
6d561c6e6f | ||
![]() |
e6b6947d49 | ||
![]() |
52e99a2175 | ||
![]() |
052d17a46f | ||
![]() |
1aa1f4c212 | ||
![]() |
c3a48e3344 | ||
![]() |
1d5483dc28 | ||
![]() |
54277fa0df | ||
![]() |
ab04bd262f | ||
![]() |
fb23087b65 | ||
![]() |
846fee7ac8 | ||
![]() |
977eacc679 | ||
![]() |
dacfefe644 | ||
![]() |
345e941e11 | ||
![]() |
6cb7d45464 | ||
![]() |
e7222653fa | ||
![]() |
014f0758f5 | ||
![]() |
0e8b416f6d | ||
![]() |
09a60a2204 | ||
![]() |
b0eae307c2 | ||
![]() |
f5d2b54cca | ||
![]() |
3eefec3899 |
@@ -1,5 +1,7 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="https://socialify.git.ci/NapNeko/NapCatQQ/image?font=Jost&logo=https%3A%2F%2Fnapneko.github.io%2Fassets%2Flogo.png&name=1&owner=1&pattern=Diagonal%20Stripes&stargazers=1&theme=Auto" alt="NapCatQQ" width="640" height="320" />
|
|
||||||
|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "3.0.3",
|
"version": "3.1.5",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
28
package.json
28
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "3.0.3",
|
"version": "3.1.5",
|
||||||
"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",
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"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",
|
||||||
|
"@protobuf-ts/runtime": "^2.9.4",
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
"@rollup/plugin-typescript": "^11.1.6",
|
"@rollup/plugin-typescript": "^11.1.6",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
@@ -23,29 +24,28 @@
|
|||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.12",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
||||||
"@typescript-eslint/parser": "^8.3.0",
|
"@typescript-eslint/parser": "^8.3.0",
|
||||||
|
"ajv": "^8.13.0",
|
||||||
|
"async-mutex": "^0.5.0",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"commander": "^12.1.0",
|
||||||
|
"cors": "^2.8.5",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
"fast-xml-parser": "^4.3.6",
|
||||||
|
"file-type": "^19.0.0",
|
||||||
|
"image-size": "^1.1.1",
|
||||||
|
"json-schema-to-ts": "^3.1.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.2.6",
|
"vite": "^5.2.6",
|
||||||
"vite-plugin-cp": "^4.0.8",
|
"vite-plugin-cp": "^4.0.8",
|
||||||
"vite-tsconfig-paths": "^4.3.2",
|
"vite-tsconfig-paths": "^4.3.2"
|
||||||
"@protobuf-ts/runtime": "^2.9.4",
|
|
||||||
"ajv": "^8.13.0",
|
|
||||||
"fast-xml-parser": "^4.3.6",
|
|
||||||
"chalk": "^5.3.0",
|
|
||||||
"commander": "^12.1.0",
|
|
||||||
"async-mutex": "^0.5.0",
|
|
||||||
"file-type": "^19.0.0",
|
|
||||||
"json-schema-to-ts": "^3.1.0",
|
|
||||||
"image-size": "^1.1.1",
|
|
||||||
"cors": "^2.8.5"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"qrcode-terminal": "^0.12.0",
|
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
|
||||||
"express": "^5.0.0-beta.2",
|
"express": "^5.0.0-beta.2",
|
||||||
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"log4js": "^6.9.1",
|
"log4js": "^6.9.1",
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
}
|
}
|
||||||
|
106
src/common/forward-msg-builder.ts
Normal file
106
src/common/forward-msg-builder.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import { PacketMsg } from "@/core/packet/msg/message";
|
||||||
|
import * as crypto from "node:crypto";
|
||||||
|
|
||||||
|
interface ForwardMsgJson {
|
||||||
|
app: string
|
||||||
|
config: ForwardMsgJsonConfig,
|
||||||
|
desc: string,
|
||||||
|
extra: ForwardMsgJsonExtra,
|
||||||
|
meta: ForwardMsgJsonMeta,
|
||||||
|
prompt: string,
|
||||||
|
ver: string,
|
||||||
|
view: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardMsgJsonConfig {
|
||||||
|
autosize: number,
|
||||||
|
forward: number,
|
||||||
|
round: number,
|
||||||
|
type: string,
|
||||||
|
width: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardMsgJsonExtra {
|
||||||
|
filename: string,
|
||||||
|
tsum: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardMsgJsonMeta {
|
||||||
|
detail: ForwardMsgJsonMetaDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardMsgJsonMetaDetail {
|
||||||
|
news: {
|
||||||
|
text: string
|
||||||
|
}[],
|
||||||
|
resid: string,
|
||||||
|
source: string,
|
||||||
|
summary: string,
|
||||||
|
uniseq: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardAdaptMsg {
|
||||||
|
senderName?: string;
|
||||||
|
isGroupMsg?: boolean;
|
||||||
|
msg?: ForwardAdaptMsgElement[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ForwardAdaptMsgElement {
|
||||||
|
preview?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ForwardMsgBuilder {
|
||||||
|
private static build(resId: string, msg: ForwardAdaptMsg[]): ForwardMsgJson {
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const isGroupMsg = msg.some(m => m.isGroupMsg);
|
||||||
|
return {
|
||||||
|
app: "com.tencent.multimsg",
|
||||||
|
config: {
|
||||||
|
autosize: 1,
|
||||||
|
forward: 1,
|
||||||
|
round: 1,
|
||||||
|
type: "normal",
|
||||||
|
width: 300
|
||||||
|
},
|
||||||
|
desc: "[聊天记录]",
|
||||||
|
extra: {
|
||||||
|
filename: id,
|
||||||
|
tsum: msg.length,
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
detail: {
|
||||||
|
news: msg.length === 0 ? [{
|
||||||
|
text: "Nya~ This message is send from NapCat.Packet!",
|
||||||
|
}] : msg.map(m => ({
|
||||||
|
text: `${m.senderName}: ${m.msg?.map(msg => msg.preview).join('')}`,
|
||||||
|
})),
|
||||||
|
resid: resId,
|
||||||
|
source: isGroupMsg ? "群聊的聊天记录" :
|
||||||
|
msg.length
|
||||||
|
? Array.from(new Set(msg.map(m => m.senderName)))
|
||||||
|
.join('和') + '的聊天记录'
|
||||||
|
: '聊天记录',
|
||||||
|
summary: `查看${msg.length}条转发消息`,
|
||||||
|
uniseq: id,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prompt: "[聊天记录]",
|
||||||
|
ver: "0.0.0.5",
|
||||||
|
view: "contact",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromResId(resId: string): ForwardMsgJson {
|
||||||
|
return this.build(resId, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromPacketMsg(resId: string, packetMsg: PacketMsg[]): ForwardMsgJson {
|
||||||
|
return this.build(resId, packetMsg.map(msg => ({
|
||||||
|
senderName: msg.senderName,
|
||||||
|
isGroupMsg: msg.groupId !== undefined,
|
||||||
|
msg: msg.msg.map(m => ({
|
||||||
|
preview: m.toPreview(),
|
||||||
|
}))
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '3.0.3';
|
export const napCatVersion = '3.1.5';
|
||||||
|
@@ -30,7 +30,7 @@ export class NTQQFileApi {
|
|||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
rkeyManager: RkeyManager;
|
rkeyManager: RkeyManager;
|
||||||
packetRkey: Array<{ rkey: string; time: number; type: number; }> | undefined;
|
packetRkey: Array<{ rkey: string; time: number; type: number; ttl: bigint }> | undefined;
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -378,10 +378,12 @@ export class NTQQFileApi {
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
if (this.core.apis.PacketApi.available) {
|
if (this.core.apis.PacketApi.available) {
|
||||||
if ((!this.packetRkey || this.packetRkey[0].time > Date.now() / 1000)) {
|
let rkey_expired_private = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||||
|
let rkey_expired_group = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
|
||||||
|
if (rkey_expired_private || rkey_expired_group) {
|
||||||
this.packetRkey = await this.core.apis.PacketApi.sendRkeyPacket();
|
this.packetRkey = await this.core.apis.PacketApi.sendRkeyPacket();
|
||||||
}
|
}
|
||||||
if (this.packetRkey.length > 0) {
|
if (this.packetRkey && this.packetRkey.length > 0) {
|
||||||
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6);
|
rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6);
|
||||||
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
|
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
|
||||||
rkeyData.online_rkey = true;
|
rkeyData.online_rkey = true;
|
||||||
|
@@ -318,7 +318,7 @@ export class NTQQGroupApi {
|
|||||||
|
|
||||||
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||||
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||||
let once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', 1, 2000, (params) => params.sceneId === sceneId)
|
const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', 1, 2000, (params) => params.sceneId === sceneId)
|
||||||
.catch();
|
.catch();
|
||||||
const result = await this.context.session.getGroupService().getNextMemberList(sceneId!, undefined, num);
|
const result = await this.context.session.getGroupService().getNextMemberList(sceneId!, undefined, num);
|
||||||
if (result.errCode !== 0) {
|
if (result.errCode !== 0) {
|
||||||
|
@@ -14,6 +14,7 @@ import {PacketMsg} from "@/core/packet/msg/message";
|
|||||||
import { OidbSvcTrpcTcp0x6D6Response } from "@/core/packet/proto/oidb/Oidb.0x6D6";
|
import { OidbSvcTrpcTcp0x6D6Response } from "@/core/packet/proto/oidb/Oidb.0x6D6";
|
||||||
import { PacketMsgPicElement } from "@/core/packet/msg/element";
|
import { PacketMsgPicElement } from "@/core/packet/msg/element";
|
||||||
|
|
||||||
|
|
||||||
interface OffsetType {
|
interface OffsetType {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
recv: string;
|
recv: string;
|
||||||
@@ -26,7 +27,7 @@ const typedOffset: OffsetType = offset;
|
|||||||
export class NTQQPacketApi {
|
export class NTQQPacketApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
core: NapCatCore;
|
core: NapCatCore;
|
||||||
logger: LogWrapper
|
logger: LogWrapper;
|
||||||
serverUrl: string | undefined;
|
serverUrl: string | undefined;
|
||||||
qqVersion: string | undefined;
|
qqVersion: string | undefined;
|
||||||
packetSession: PacketSession | undefined;
|
packetSession: PacketSession | undefined;
|
||||||
@@ -59,8 +60,12 @@ export class NTQQPacketApi {
|
|||||||
if (!table) return false;
|
if (!table) return false;
|
||||||
const url = 'ws://' + this.serverUrl + '/ws';
|
const url = 'ws://' + this.serverUrl + '/ws';
|
||||||
this.packetSession = new PacketSession(this.core.context.logger, new PacketClient(url, this.core));
|
this.packetSession = new PacketSession(this.core.context.logger, new PacketClient(url, this.core));
|
||||||
await this.packetSession.client.connect();
|
const cb = () => {
|
||||||
await this.packetSession.client.init(process.pid, table.recv, table.send);
|
if (this.packetSession && this.packetSession.client) {
|
||||||
|
this.packetSession.client.init(process.pid, table.recv, table.send).then().catch(this.logger.logError.bind(this.logger));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await this.packetSession.client.connect(cb);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +73,8 @@ export class NTQQPacketApi {
|
|||||||
return this.packetSession!.client.sendPacket(cmd, data, rsp);
|
return this.packetSession!.client.sendPacket(cmd, data, rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendPokePacket(group: number, peer: number) {
|
async sendPokePacket(peer: number, group?: number) {
|
||||||
const data = this.packetSession?.packer.packPokePacket(group, peer);
|
const data = this.packetSession?.packer.packPokePacket(peer, group);
|
||||||
await this.sendPacket('OidbSvcTrpcTcp.0xed3_1', data!, false);
|
await this.sendPacket('OidbSvcTrpcTcp.0xed3_1', data!, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +86,10 @@ export class NTQQPacketApi {
|
|||||||
const retData = new NapProtoMsg(OidbSvcTrpcTcp0X9067_202_Rsp_Body).decode(body);
|
const retData = new NapProtoMsg(OidbSvcTrpcTcp0X9067_202_Rsp_Body).decode(body);
|
||||||
return retData.data.rkeyList;
|
return retData.data.rkeyList;
|
||||||
}
|
}
|
||||||
|
async sendGroupSignPacket(groupCode: string) {
|
||||||
|
const packet = this.packetSession?.packer.packGroupSignReq(this.core.selfInfo.uin, groupCode);
|
||||||
|
await this.sendPacket('OidbSvcTrpcTcp.0xeb7', packet!, true);
|
||||||
|
}
|
||||||
async sendStatusPacket(uin: number): Promise<{ status: number; ext_status: number; } | undefined> {
|
async sendStatusPacket(uin: number): Promise<{ status: number; ext_status: number; } | undefined> {
|
||||||
let status = 0;
|
let status = 0;
|
||||||
try {
|
try {
|
||||||
@@ -107,7 +115,7 @@ export class NTQQPacketApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async uploadResources(msg: PacketMsg[], groupUin: number = 0) {
|
private async uploadResources(msg: PacketMsg[], groupUin: number = 0) {
|
||||||
const reqList = []
|
const reqList = [];
|
||||||
for (const m of msg) {
|
for (const m of msg) {
|
||||||
for (const e of m.msg) {
|
for (const e of m.msg) {
|
||||||
if (e instanceof PacketMsgPicElement) {
|
if (e instanceof PacketMsgPicElement) {
|
||||||
@@ -138,6 +146,6 @@ export class NTQQPacketApi {
|
|||||||
if (resp.download.retCode !== 0) {
|
if (resp.download.retCode !== 0) {
|
||||||
throw new Error(`sendGroupFileDownloadReq error: ${resp.download.clientWording}`);
|
throw new Error(`sendGroupFileDownloadReq error: ${resp.download.clientWording}`);
|
||||||
}
|
}
|
||||||
return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=`
|
return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -338,4 +338,12 @@ export class NTQQWebApi {
|
|||||||
}
|
}
|
||||||
return (hash & 0x7FFFFFFF).toString();
|
return (hash & 0x7FFFFFFF).toString();
|
||||||
}
|
}
|
||||||
|
public getBknFromSKey(sKey: string) {
|
||||||
|
let hash = 5381;
|
||||||
|
for (let i = 0; i < sKey.length; i++) {
|
||||||
|
const code = sKey.charCodeAt(i);
|
||||||
|
hash = hash + (hash << 5) + code;
|
||||||
|
}
|
||||||
|
return (hash & 0x7FFFFFFF).toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/core/external/appid.json
vendored
8
src/core/external/appid.json
vendored
@@ -50,5 +50,13 @@
|
|||||||
"9.9.16-28788": {
|
"9.9.16-28788": {
|
||||||
"appid": 537249739,
|
"appid": 537249739,
|
||||||
"qua": "V1_WIN_NQ_9.9.16_28788_GW_B"
|
"qua": "V1_WIN_NQ_9.9.16_28788_GW_B"
|
||||||
|
},
|
||||||
|
"9.9.16-28971":{
|
||||||
|
"appid": 537249775,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.16_28971_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.13-28971": {
|
||||||
|
"appid": 537249848,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.13_28971_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
8
src/core/external/offset.json
vendored
8
src/core/external/offset.json
vendored
@@ -18,5 +18,13 @@
|
|||||||
"3.2.13-28788-x64": {
|
"3.2.13-28788-x64": {
|
||||||
"send": "A0CEC20",
|
"send": "A0CEC20",
|
||||||
"recv": "A0D2520"
|
"recv": "A0D2520"
|
||||||
|
},
|
||||||
|
"3.2.13-28788-arm64": {
|
||||||
|
"send": "6E91018",
|
||||||
|
"recv": "6E94850"
|
||||||
|
},
|
||||||
|
"9.9.16-28971-x64": {
|
||||||
|
"send": "38079F0",
|
||||||
|
"recv": "380BE24"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -22,7 +22,7 @@ export class PacketClient {
|
|||||||
private websocket: WebSocket | undefined;
|
private websocket: WebSocket | undefined;
|
||||||
private isConnected: boolean = false;
|
private isConnected: boolean = false;
|
||||||
private reconnectAttempts: number = 0;
|
private reconnectAttempts: number = 0;
|
||||||
private readonly maxReconnectAttempts: number = 5;//现在暂时不可配置
|
private readonly maxReconnectAttempts: number = 60;//现在暂时不可配置
|
||||||
private readonly cb = new LRUCache<string, (json: RecvPacketData) => Promise<void>>(500); // trace_id-type callback
|
private readonly cb = new LRUCache<string, (json: RecvPacketData) => Promise<void>>(500); // trace_id-type callback
|
||||||
private readonly clientUrl: string = '';
|
private readonly clientUrl: string = '';
|
||||||
readonly napCatCore: NapCatCore;
|
readonly napCatCore: NapCatCore;
|
||||||
@@ -47,7 +47,7 @@ export class PacketClient {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(): Promise<void> {
|
connect(cb: any): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
//this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`);
|
//this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`);
|
||||||
this.websocket = new WebSocket(this.clientUrl);
|
this.websocket = new WebSocket(this.clientUrl);
|
||||||
@@ -57,6 +57,7 @@ export class PacketClient {
|
|||||||
this.isConnected = true;
|
this.isConnected = true;
|
||||||
this.reconnectAttempts = 0;
|
this.reconnectAttempts = 0;
|
||||||
this.logger.log.bind(this.logger)(`[Core] [Packet Server] Connected to ${this.clientUrl}`);
|
this.logger.log.bind(this.logger)(`[Core] [Packet Server] Connected to ${this.clientUrl}`);
|
||||||
|
cb();
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,17 +75,17 @@ export class PacketClient {
|
|||||||
this.websocket.onclose = () => {
|
this.websocket.onclose = () => {
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
//this.logger.logWarn.bind(this.logger)(`[Core] [Packet Server] Disconnected from ${this.clientUrl}`);
|
//this.logger.logWarn.bind(this.logger)(`[Core] [Packet Server] Disconnected from ${this.clientUrl}`);
|
||||||
this.attemptReconnect();
|
this.attemptReconnect(cb);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private attemptReconnect(): void {
|
private attemptReconnect(cb: any): void {
|
||||||
try {
|
try {
|
||||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||||
this.reconnectAttempts++;
|
this.reconnectAttempts++;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.connect().catch((error) => {
|
this.connect(cb).catch((error) => {
|
||||||
this.logger.logError.bind(this.logger)(`[Core] [Packet Server] Reconnecting attempt failed,${error.message}`);
|
this.logger.logError.bind(this.logger)(`[Core] [Packet Server] Reconnecting attempt failed,${error.message}`);
|
||||||
});
|
});
|
||||||
}, 5000 * this.reconnectAttempts);
|
}, 5000 * this.reconnectAttempts);
|
||||||
|
@@ -42,7 +42,7 @@ export class PacketHighwaySession {
|
|||||||
sigSession: null,
|
sigSession: null,
|
||||||
sessionKey: null,
|
sessionKey: null,
|
||||||
serverAddr: [],
|
serverAddr: [],
|
||||||
}
|
};
|
||||||
this.packer = packer;
|
this.packer = packer;
|
||||||
this.packetHighwayClient = new PacketHighwayClient(this.sig, this.logger);
|
this.packetHighwayClient = new PacketHighwayClient(this.sig, this.logger);
|
||||||
}
|
}
|
||||||
@@ -69,8 +69,8 @@ export class PacketHighwaySession {
|
|||||||
const rsp = new NapProtoMsg(HttpConn0x6ff_501Response).decode(
|
const rsp = new NapProtoMsg(HttpConn0x6ff_501Response).decode(
|
||||||
Buffer.from(req.hex_data, 'hex')
|
Buffer.from(req.hex_data, 'hex')
|
||||||
);
|
);
|
||||||
this.sig.sigSession = rsp.httpConn.sigSession
|
this.sig.sigSession = rsp.httpConn.sigSession;
|
||||||
this.sig.sessionKey = rsp.httpConn.sessionKey
|
this.sig.sessionKey = rsp.httpConn.sessionKey;
|
||||||
for (const info of rsp.httpConn.serverInfos) {
|
for (const info of rsp.httpConn.serverInfos) {
|
||||||
if (info.serviceType !== 1) continue;
|
if (info.serviceType !== 1) continue;
|
||||||
for (const addr of info.serverAddrs) {
|
for (const addr of info.serverAddrs) {
|
||||||
@@ -78,7 +78,7 @@ export class PacketHighwaySession {
|
|||||||
this.sig.serverAddr.push({
|
this.sig.serverAddr.push({
|
||||||
ip: int32ip2str(addr.ip),
|
ip: int32ip2str(addr.ip),
|
||||||
port: addr.port
|
port: addr.port
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ export class PacketHighwaySession {
|
|||||||
hash: {
|
hash: {
|
||||||
fileSha1: [sha1]
|
fileSha1: [sha1]
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
await this.packetHighwayClient.upload(
|
await this.packetHighwayClient.upload(
|
||||||
1004,
|
1004,
|
||||||
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
||||||
@@ -157,7 +157,7 @@ export class PacketHighwaySession {
|
|||||||
hash: {
|
hash: {
|
||||||
fileSha1: [sha1]
|
fileSha1: [sha1]
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
await this.packetHighwayClient.upload(
|
await this.packetHighwayClient.upload(
|
||||||
1003,
|
1003,
|
||||||
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
|
||||||
|
@@ -53,7 +53,7 @@ abstract class HighwayUploader {
|
|||||||
uint32LoginSigType: 8,
|
uint32LoginSigType: 8,
|
||||||
appId: 1600001604,
|
appId: 1600001604,
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract upload(): Promise<void>;
|
abstract upload(): Promise<void>;
|
||||||
@@ -90,7 +90,7 @@ export class HighwayTcpUploader extends HighwayUploader {
|
|||||||
const upload = new Promise<void>((resolve, _) => {
|
const upload = new Promise<void>((resolve, _) => {
|
||||||
const socket = net.connect(this.trans.port, this.trans.server, () => {
|
const socket = net.connect(this.trans.port, this.trans.server, () => {
|
||||||
this.trans.data.pipe(highwayTransForm).pipe(socket, { end: false });
|
this.trans.data.pipe(highwayTransForm).pipe(socket, { end: false });
|
||||||
})
|
});
|
||||||
const handleRspHeader = (header: Buffer) => {
|
const handleRspHeader = (header: Buffer) => {
|
||||||
const rsp = new NapProtoMsg(RespDataHighwayHead).decode(header);
|
const rsp = new NapProtoMsg(RespDataHighwayHead).decode(header);
|
||||||
if (rsp.errorCode !== 0) {
|
if (rsp.errorCode !== 0) {
|
||||||
@@ -111,25 +111,25 @@ export class HighwayTcpUploader extends HighwayUploader {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError(`[Highway] tcpUpload parse response error: ${e}`);
|
this.logger.logError(`[Highway] tcpUpload parse response error: ${e}`);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
socket.on('close', () => {
|
socket.on('close', () => {
|
||||||
this.logger.logDebug('[Highway] tcpUpload socket closed.');
|
this.logger.logDebug('[Highway] tcpUpload socket closed.');
|
||||||
resolve();
|
resolve();
|
||||||
})
|
});
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
this.logger.logError('[Highway] tcpUpload socket.on error:', err);
|
this.logger.logError('[Highway] tcpUpload socket.on error:', err);
|
||||||
})
|
});
|
||||||
this.trans.data.on('error', (err) => {
|
this.trans.data.on('error', (err) => {
|
||||||
this.logger.logError('[Highway] tcpUpload readable error:', err);
|
this.logger.logError('[Highway] tcpUpload readable error:', err);
|
||||||
socket.end();
|
socket.end();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
const timeout = new Promise<void>((_, reject) => {
|
const timeout = new Promise<void>((_, reject) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(new Error(`[Highway] tcpUpload timeout after ${this.trans.timeout}s`))
|
reject(new Error(`[Highway] tcpUpload timeout after ${this.trans.timeout}s`));
|
||||||
}, (this.trans.timeout ?? Infinity) * 1000
|
}, (this.trans.timeout ?? Infinity) * 1000
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
await Promise.race([upload, timeout]);
|
await Promise.race([upload, timeout]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ export class HighwayHttpUploader extends HighwayUploader {
|
|||||||
async upload(): Promise<void> {
|
async upload(): Promise<void> {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
for await (const chunk of this.trans.data) {
|
for await (const chunk of this.trans.data) {
|
||||||
let block = chunk as Buffer;
|
const block = chunk as Buffer;
|
||||||
try {
|
try {
|
||||||
await this.uploadBlock(block, offset);
|
await this.uploadBlock(block, offset);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -153,7 +153,7 @@ export class HighwayHttpUploader extends HighwayUploader {
|
|||||||
private async uploadBlock(block: Buffer, offset: number): Promise<void> {
|
private async uploadBlock(block: Buffer, offset: number): Promise<void> {
|
||||||
const chunkMD5 = crypto.createHash('md5').update(block).digest();
|
const chunkMD5 = crypto.createHash('md5').update(block).digest();
|
||||||
const payload = this.buildPicUpHead(offset, block.length, chunkMD5);
|
const payload = this.buildPicUpHead(offset, block.length, chunkMD5);
|
||||||
const frame = Frame.pack(Buffer.from(payload), block)
|
const frame = Frame.pack(Buffer.from(payload), block);
|
||||||
const resp = await this.httpPostHighwayContent(frame, `http://${this.trans.server}:${this.trans.port}/cgi-bin/httpconn?htcmd=0x6FF0087&uin=${this.trans.uin}`);
|
const resp = await this.httpPostHighwayContent(frame, `http://${this.trans.server}:${this.trans.port}/cgi-bin/httpconn?htcmd=0x6FF0087&uin=${this.trans.uin}`);
|
||||||
const [head, body] = Frame.unpack(resp);
|
const [head, body] = Frame.unpack(resp);
|
||||||
const headData = new NapProtoMsg(RespDataHighwayHead).decode(head);
|
const headData = new NapProtoMsg(RespDataHighwayHead).decode(head);
|
||||||
|
@@ -5,7 +5,7 @@ import {NTHighwayIPv4} from "@/core/packet/proto/highway/highway";
|
|||||||
export const int32ip2str = (ip: number) => {
|
export const int32ip2str = (ip: number) => {
|
||||||
ip = ip & 0xffffffff;
|
ip = ip & 0xffffffff;
|
||||||
return [ip & 0xff, (ip & 0xff00) >> 8, (ip & 0xff0000) >> 16, ((ip & 0xff000000) >> 24) & 0xff].join('.');
|
return [ip & 0xff, (ip & 0xff00) >> 8, (ip & 0xff0000) >> 16, ((ip & 0xff000000) >> 24) & 0xff].join('.');
|
||||||
}
|
};
|
||||||
|
|
||||||
export const oidbIpv4s2HighwayIpv4s = (ipv4s: NapProtoEncodeStructType<typeof IPv4>[]): NapProtoEncodeStructType<typeof NTHighwayIPv4>[] =>{
|
export const oidbIpv4s2HighwayIpv4s = (ipv4s: NapProtoEncodeStructType<typeof IPv4>[]): NapProtoEncodeStructType<typeof NTHighwayIPv4>[] =>{
|
||||||
return ipv4s.map((ip) => {
|
return ipv4s.map((ip) => {
|
||||||
@@ -15,6 +15,6 @@ export const oidbIpv4s2HighwayIpv4s = (ipv4s: NapProtoEncodeStructType<typeof IP
|
|||||||
ip: int32ip2str(ip.outIP!),
|
ip: int32ip2str(ip.outIP!),
|
||||||
},
|
},
|
||||||
port: ip.outPort!
|
port: ip.outPort!
|
||||||
} as NapProtoEncodeStructType<typeof NTHighwayIPv4>
|
} as NapProtoEncodeStructType<typeof NTHighwayIPv4>;
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
@@ -82,50 +82,50 @@ export class PacketMsgConverter {
|
|||||||
);
|
);
|
||||||
if (key) {
|
if (key) {
|
||||||
const elementData = (element as any)[key]; // TODO:
|
const elementData = (element as any)[key]; // TODO:
|
||||||
if (elementData) return this.rawToPacketMsgConverters[key](element as any)
|
if (elementData) return this.rawToPacketMsgConverters[key](element as any);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}).filter((e) => e !== null)
|
}).filter((e) => e !== null)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private rawToPacketMsgConverters: RawToPacketMsgConverters = {
|
private rawToPacketMsgConverters: RawToPacketMsgConverters = {
|
||||||
textElement: (element: SendTextElement) => {
|
textElement: (element: SendTextElement) => {
|
||||||
if (element.textElement.atType) {
|
if (element.textElement.atType) {
|
||||||
return new PacketMsgAtElement(element)
|
return new PacketMsgAtElement(element);
|
||||||
}
|
}
|
||||||
return new PacketMsgTextElement(element)
|
return new PacketMsgTextElement(element);
|
||||||
},
|
},
|
||||||
picElement: (element: SendPicElement) => {
|
picElement: (element: SendPicElement) => {
|
||||||
return new PacketMsgPicElement(element)
|
return new PacketMsgPicElement(element);
|
||||||
},
|
},
|
||||||
replyElement: (element: SendReplyElement) => {
|
replyElement: (element: SendReplyElement) => {
|
||||||
return new PacketMsgReplyElement(element)
|
return new PacketMsgReplyElement(element);
|
||||||
},
|
},
|
||||||
faceElement: (element: SendFaceElement) => {
|
faceElement: (element: SendFaceElement) => {
|
||||||
return new PacketMsgFaceElement(element)
|
return new PacketMsgFaceElement(element);
|
||||||
},
|
},
|
||||||
marketFaceElement: (element: SendMarketFaceElement) => {
|
marketFaceElement: (element: SendMarketFaceElement) => {
|
||||||
return new PacketMsgMarkFaceElement(element)
|
return new PacketMsgMarkFaceElement(element);
|
||||||
},
|
},
|
||||||
videoElement: (element: SendVideoElement) => {
|
videoElement: (element: SendVideoElement) => {
|
||||||
return new PacketMsgVideoElement(element)
|
return new PacketMsgVideoElement(element);
|
||||||
},
|
},
|
||||||
fileElement: (element: SendFileElement) => {
|
fileElement: (element: SendFileElement) => {
|
||||||
return new PacketMsgFileElement(element)
|
return new PacketMsgFileElement(element);
|
||||||
},
|
},
|
||||||
pttElement: (element: SendPttElement) => {
|
pttElement: (element: SendPttElement) => {
|
||||||
return new PacketMsgPttElement(element)
|
return new PacketMsgPttElement(element);
|
||||||
},
|
},
|
||||||
arkElement: (element: SendArkElement) => {
|
arkElement: (element: SendArkElement) => {
|
||||||
return new PacketMsgLightAppElement(element)
|
return new PacketMsgLightAppElement(element);
|
||||||
},
|
},
|
||||||
markdownElement: (element: SendMarkdownElement) => {
|
markdownElement: (element: SendMarkdownElement) => {
|
||||||
return new PacketMsgMarkDownElement(element)
|
return new PacketMsgMarkDownElement(element);
|
||||||
},
|
},
|
||||||
// TODO: check this logic, move it in arkElement?
|
// TODO: check this logic, move it in arkElement?
|
||||||
structLongMsgElement: (element: SendStructLongMsgElement) => {
|
structLongMsgElement: (element: SendStructLongMsgElement) => {
|
||||||
return new PacketMultiMsgElement(element)
|
return new PacketMultiMsgElement(element);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import assert from "node:assert";
|
import assert from "node:assert";
|
||||||
import * as zlib from "node:zlib";
|
import * as zlib from "node:zlib";
|
||||||
import * as crypto from "node:crypto";
|
|
||||||
import { NapProtoEncodeStructType, NapProtoMsg } from "@/core/packet/proto/NapProto";
|
import { NapProtoEncodeStructType, NapProtoMsg } from "@/core/packet/proto/NapProto";
|
||||||
import {
|
import {
|
||||||
CustomFace,
|
CustomFace,
|
||||||
@@ -28,10 +27,9 @@ import {
|
|||||||
} from "@/core";
|
} from "@/core";
|
||||||
import { MsgInfo } from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
|
import { MsgInfo } from "@/core/packet/proto/oidb/common/Ntv2.RichMediaReq";
|
||||||
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/msg/message";
|
import { PacketMsg, PacketSendMsgElement } from "@/core/packet/msg/message";
|
||||||
|
import { ForwardMsgBuilder } from "@/common/forward-msg-builder";
|
||||||
|
|
||||||
// raw <-> packet
|
// raw <-> packet
|
||||||
// TODO: check ob11 -> raw impl!
|
|
||||||
// TODO: parse to raw element
|
|
||||||
// TODO: SendStructLongMsgElement
|
// TODO: SendStructLongMsgElement
|
||||||
export abstract class IPacketMsgElement<T extends PacketSendMsgElement> {
|
export abstract class IPacketMsgElement<T extends PacketSendMsgElement> {
|
||||||
protected constructor(rawElement: T) {
|
protected constructor(rawElement: T) {
|
||||||
@@ -103,7 +101,7 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
|
|||||||
|
|
||||||
export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
||||||
path: string;
|
path: string;
|
||||||
name: string
|
name: string;
|
||||||
size: number;
|
size: number;
|
||||||
md5: string;
|
md5: string;
|
||||||
width: number;
|
width: number;
|
||||||
@@ -133,7 +131,7 @@ export class PacketMsgPicElement extends IPacketMsgElement<SendPicElement> {
|
|||||||
pbElem: new NapProtoMsg(MsgInfo).encode(this.msgInfo),
|
pbElem: new NapProtoMsg(MsgInfo).encode(this.msgInfo),
|
||||||
businessType: 10,
|
businessType: 10,
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
@@ -187,7 +185,7 @@ export class PacketMsgReplyElement extends IPacketMsgElement<SendReplyElement> {
|
|||||||
uid: String(this.targetUid),
|
uid: String(this.targetUid),
|
||||||
}),
|
}),
|
||||||
} : undefined,
|
} : undefined,
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
@@ -221,7 +219,7 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
|
|||||||
}),
|
}),
|
||||||
businessType: 1
|
businessType: 1
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
} else if (this.faceId < 260) {
|
} else if (this.faceId < 260) {
|
||||||
return [{
|
return [{
|
||||||
face: {
|
face: {
|
||||||
@@ -239,7 +237,7 @@ export class PacketMsgFaceElement extends IPacketMsgElement<SendFaceElement> {
|
|||||||
}),
|
}),
|
||||||
businessType: 1
|
businessType: 1
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,11 +276,11 @@ export class PacketMsgMarkFaceElement extends IPacketMsgElement<SendMarketFaceEl
|
|||||||
field8: 1
|
field8: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
return this.emojiName;
|
return `[${this.emojiName}]`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,11 +318,11 @@ export class PacketMsgLightAppElement extends IPacketMsgElement<SendArkElement>
|
|||||||
zlib.deflateSync(Buffer.from(this.payload, 'utf-8'))
|
zlib.deflateSync(Buffer.from(this.payload, 'utf-8'))
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
return "[小程序]";
|
return "[卡片消息]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,11 +343,11 @@ export class PacketMsgMarkDownElement extends IPacketMsgElement<SendMarkdownElem
|
|||||||
}),
|
}),
|
||||||
businessType: 1
|
businessType: 1
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
return this.content;
|
return `[Markdown消息 ${this.content}]`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,58 +361,15 @@ export class PacketMultiMsgElement extends IPacketMsgElement<SendStructLongMsgEl
|
|||||||
this.message = message ?? [];
|
this.message = message ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
get isGroupMsg(): boolean {
|
|
||||||
return this.message.some(msg => msg.groupId !== undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
get JSON() {
|
|
||||||
const id = crypto.randomUUID();
|
|
||||||
return {
|
|
||||||
app: "com.tencent.multimsg",
|
|
||||||
config: {
|
|
||||||
autosize: 1,
|
|
||||||
forward: 1,
|
|
||||||
round: 1,
|
|
||||||
type: "normal",
|
|
||||||
width: 300
|
|
||||||
},
|
|
||||||
desc: "[聊天记录]",
|
|
||||||
extra: {
|
|
||||||
filename: id,
|
|
||||||
tsum: this.message.length,
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
detail: {
|
|
||||||
news: this.message.length === 0 ? [{
|
|
||||||
text: "[Nya~ This message is send from NapCat.Packet!]",
|
|
||||||
}] : this.message.map(packetMsg => ({
|
|
||||||
text: `${packetMsg.senderName}: ${packetMsg.msg.map(msg => msg.toPreview()).join('')}`,
|
|
||||||
})),
|
|
||||||
resid: this.resid,
|
|
||||||
source: this.isGroupMsg ? "群聊的聊天记录" :
|
|
||||||
this.message.length
|
|
||||||
? Array.from(new Set(this.message.map(msg => msg.senderName)))
|
|
||||||
.join('和') + '的聊天记录'
|
|
||||||
: '聊天记录',
|
|
||||||
summary: `查看${this.message.length}条转发消息`,
|
|
||||||
uniseq: id,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prompt: "[聊天记录]",
|
|
||||||
ver: "0.0.0.5",
|
|
||||||
view: "contact",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
|
||||||
return [{
|
return [{
|
||||||
lightAppElem: {
|
lightAppElem: {
|
||||||
data: Buffer.concat([
|
data: Buffer.concat([
|
||||||
Buffer.from([0x01]),
|
Buffer.from([0x01]),
|
||||||
zlib.deflateSync(Buffer.from(JSON.stringify(this.JSON), 'utf-8'))
|
zlib.deflateSync(Buffer.from(JSON.stringify(ForwardMsgBuilder.fromPacketMsg(this.resid, this.message)), 'utf-8'))
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}]
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
toPreview(): string {
|
toPreview(): string {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as zlib from "node:zlib";
|
import * as zlib from "node:zlib";
|
||||||
import * as crypto from "node:crypto";
|
import * as crypto from "node:crypto";
|
||||||
import {calculateSha1} from "@/core/packet/utils/crypto/hash"
|
import { calculateSha1 } from "@/core/packet/utils/crypto/hash";
|
||||||
import { NapProtoMsg } from "@/core/packet/proto/NapProto";
|
import { NapProtoMsg } from "@/core/packet/proto/NapProto";
|
||||||
import { OidbSvcTrpcTcpBase } from "@/core/packet/proto/oidb/OidbBase";
|
import { OidbSvcTrpcTcpBase } from "@/core/packet/proto/oidb/OidbBase";
|
||||||
import { OidbSvcTrpcTcp0X9067_202 } from "@/core/packet/proto/oidb/Oidb.0x9067_202";
|
import { OidbSvcTrpcTcp0X9067_202 } from "@/core/packet/proto/oidb/Oidb.0x9067_202";
|
||||||
@@ -18,6 +18,7 @@ import {OidbSvcTrpcTcp0x6D6} from "@/core/packet/proto/oidb/Oidb.0x6D6";
|
|||||||
import { OidbSvcTrpcTcp0XE37_1200 } from "@/core/packet/proto/oidb/Oidb.0xE37_1200";
|
import { OidbSvcTrpcTcp0XE37_1200 } from "@/core/packet/proto/oidb/Oidb.0xE37_1200";
|
||||||
import { PacketMsgConverter } from "@/core/packet/msg/converter";
|
import { PacketMsgConverter } from "@/core/packet/msg/converter";
|
||||||
import { PacketClient } from "@/core/packet/client";
|
import { PacketClient } from "@/core/packet/client";
|
||||||
|
import { OidbSvcTrpcTcp0XEB7 } from "./proto/oidb/Oidb.0xEB7";
|
||||||
|
|
||||||
export type PacketHexStr = string & { readonly hexNya: unique symbol };
|
export type PacketHexStr = string & { readonly hexNya: unique symbol };
|
||||||
|
|
||||||
@@ -47,11 +48,11 @@ export class PacketPacker {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
packPokePacket(group: number, peer: number): PacketHexStr {
|
packPokePacket(peer: number, group?: number): PacketHexStr {
|
||||||
const oidb_0xed3 = new NapProtoMsg(OidbSvcTrpcTcp0XED3_1).encode({
|
const oidb_0xed3 = new NapProtoMsg(OidbSvcTrpcTcp0XED3_1).encode({
|
||||||
uin: peer,
|
uin: peer,
|
||||||
groupUin: group,
|
groupUin: group,
|
||||||
friendUin: group,
|
friendUin: group ?? peer,
|
||||||
ext: 0
|
ext: 0
|
||||||
});
|
});
|
||||||
return this.toHexStr(this.packOidbPacket(0xed3, 1, oidb_0xed3));
|
return this.toHexStr(this.packOidbPacket(0xed3, 1, oidb_0xed3));
|
||||||
@@ -217,7 +218,7 @@ export class PacketPacker {
|
|||||||
noNeedCompatMsg: false,
|
noNeedCompatMsg: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
return this.toHexStr(this.packOidbPacket(0x11c4, 100, req, true, false));
|
return this.toHexStr(this.packOidbPacket(0x11c4, 100, req, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +286,7 @@ export class PacketPacker {
|
|||||||
noNeedCompatMsg: false,
|
noNeedCompatMsg: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
return this.toHexStr(this.packOidbPacket(0x11c5, 100, req, true, false));
|
return this.toHexStr(this.packOidbPacket(0x11c5, 100, req, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +300,7 @@ export class PacketPacker {
|
|||||||
fileId: fileUUID
|
fileId: fileUUID
|
||||||
}
|
}
|
||||||
}), true, false)
|
}), true, false)
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
packC2CFileDownloadReq(selfUid: string, fileUUID: string, fileHash: string): PacketHexStr {
|
packC2CFileDownloadReq(selfUid: string, fileUUID: string, fileHash: string): PacketHexStr {
|
||||||
@@ -319,6 +320,19 @@ export class PacketPacker {
|
|||||||
field200: 1,
|
field200: 1,
|
||||||
field99999: Buffer.from([0xc0, 0x85, 0x2c, 0x01])
|
field99999: Buffer.from([0xc0, 0x85, 0x2c, 0x01])
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
|
}
|
||||||
|
packGroupSignReq(uin: string, groupCode: string): PacketHexStr {
|
||||||
|
return this.toHexStr(
|
||||||
|
this.packOidbPacket(0XEB7, 1, new NapProtoMsg(OidbSvcTrpcTcp0XEB7).encode(
|
||||||
|
{
|
||||||
|
body: {
|
||||||
|
uin: uin,
|
||||||
|
groupUin: groupCode,
|
||||||
|
version: "9.0.90"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
), false, false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ export const DataHighwayHead = {
|
|||||||
dataFlag: ProtoField(7, ScalarType.UINT32),
|
dataFlag: ProtoField(7, ScalarType.UINT32),
|
||||||
commandId: ProtoField(8, ScalarType.UINT32),
|
commandId: ProtoField(8, ScalarType.UINT32),
|
||||||
buildVer: ProtoField(9, ScalarType.BYTES, true),
|
buildVer: ProtoField(9, ScalarType.BYTES, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const FileUploadExt = {
|
export const FileUploadExt = {
|
||||||
unknown1: ProtoField(1, ScalarType.INT32),
|
unknown1: ProtoField(1, ScalarType.INT32),
|
||||||
@@ -20,7 +20,7 @@ export const FileUploadExt = {
|
|||||||
unknown3: ProtoField(3, ScalarType.INT32),
|
unknown3: ProtoField(3, ScalarType.INT32),
|
||||||
entry: ProtoField(100, () => FileUploadEntry),
|
entry: ProtoField(100, () => FileUploadEntry),
|
||||||
unknown200: ProtoField(200, ScalarType.INT32),
|
unknown200: ProtoField(200, ScalarType.INT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const FileUploadEntry = {
|
export const FileUploadEntry = {
|
||||||
busiBuff: ProtoField(100, () => ExcitingBusiInfo),
|
busiBuff: ProtoField(100, () => ExcitingBusiInfo),
|
||||||
@@ -28,14 +28,14 @@ export const FileUploadEntry = {
|
|||||||
clientInfo: ProtoField(300, () => ExcitingClientInfo),
|
clientInfo: ProtoField(300, () => ExcitingClientInfo),
|
||||||
fileNameInfo: ProtoField(400, () => ExcitingFileNameInfo),
|
fileNameInfo: ProtoField(400, () => ExcitingFileNameInfo),
|
||||||
host: ProtoField(500, () => ExcitingHostConfig),
|
host: ProtoField(500, () => ExcitingHostConfig),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingBusiInfo = {
|
export const ExcitingBusiInfo = {
|
||||||
busId: ProtoField(1, ScalarType.INT32),
|
busId: ProtoField(1, ScalarType.INT32),
|
||||||
senderUin: ProtoField(100, ScalarType.UINT64),
|
senderUin: ProtoField(100, ScalarType.UINT64),
|
||||||
receiverUin: ProtoField(200, ScalarType.UINT64),
|
receiverUin: ProtoField(200, ScalarType.UINT64),
|
||||||
groupCode: ProtoField(400, ScalarType.UINT64),
|
groupCode: ProtoField(400, ScalarType.UINT64),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingFileEntry = {
|
export const ExcitingFileEntry = {
|
||||||
fileSize: ProtoField(100, ScalarType.UINT64),
|
fileSize: ProtoField(100, ScalarType.UINT64),
|
||||||
@@ -44,7 +44,7 @@ export const ExcitingFileEntry = {
|
|||||||
md5S2: ProtoField(400, ScalarType.BYTES),
|
md5S2: ProtoField(400, ScalarType.BYTES),
|
||||||
fileId: ProtoField(600, ScalarType.STRING),
|
fileId: ProtoField(600, ScalarType.STRING),
|
||||||
uploadKey: ProtoField(700, ScalarType.BYTES),
|
uploadKey: ProtoField(700, ScalarType.BYTES),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingClientInfo = {
|
export const ExcitingClientInfo = {
|
||||||
clientType: ProtoField(100, ScalarType.INT32),
|
clientType: ProtoField(100, ScalarType.INT32),
|
||||||
@@ -52,31 +52,31 @@ export const ExcitingClientInfo = {
|
|||||||
terminalType: ProtoField(300, ScalarType.INT32),
|
terminalType: ProtoField(300, ScalarType.INT32),
|
||||||
clientVer: ProtoField(400, ScalarType.STRING),
|
clientVer: ProtoField(400, ScalarType.STRING),
|
||||||
unknown: ProtoField(600, ScalarType.INT32),
|
unknown: ProtoField(600, ScalarType.INT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingFileNameInfo = {
|
export const ExcitingFileNameInfo = {
|
||||||
fileName: ProtoField(100, ScalarType.STRING),
|
fileName: ProtoField(100, ScalarType.STRING),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingHostConfig = {
|
export const ExcitingHostConfig = {
|
||||||
hosts: ProtoField(200, () => ExcitingHostInfo, false, true),
|
hosts: ProtoField(200, () => ExcitingHostInfo, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingHostInfo = {
|
export const ExcitingHostInfo = {
|
||||||
url: ProtoField(1, () => ExcitingUrlInfo),
|
url: ProtoField(1, () => ExcitingUrlInfo),
|
||||||
port: ProtoField(2, ScalarType.UINT32),
|
port: ProtoField(2, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExcitingUrlInfo = {
|
export const ExcitingUrlInfo = {
|
||||||
unknown: ProtoField(1, ScalarType.INT32),
|
unknown: ProtoField(1, ScalarType.INT32),
|
||||||
host: ProtoField(2, ScalarType.STRING),
|
host: ProtoField(2, ScalarType.STRING),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LoginSigHead = {
|
export const LoginSigHead = {
|
||||||
uint32LoginSigType: ProtoField(1, ScalarType.UINT32),
|
uint32LoginSigType: ProtoField(1, ScalarType.UINT32),
|
||||||
bytesLoginSig: ProtoField(2, ScalarType.BYTES),
|
bytesLoginSig: ProtoField(2, ScalarType.BYTES),
|
||||||
appId: ProtoField(3, ScalarType.UINT32),
|
appId: ProtoField(3, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const NTV2RichMediaHighwayExt = {
|
export const NTV2RichMediaHighwayExt = {
|
||||||
fileUuid: ProtoField(1, ScalarType.STRING),
|
fileUuid: ProtoField(1, ScalarType.STRING),
|
||||||
@@ -85,25 +85,25 @@ export const NTV2RichMediaHighwayExt = {
|
|||||||
msgInfoBody: ProtoField(6, () => MsgInfoBody, false, true),
|
msgInfoBody: ProtoField(6, () => MsgInfoBody, false, true),
|
||||||
blockSize: ProtoField(10, ScalarType.UINT32),
|
blockSize: ProtoField(10, ScalarType.UINT32),
|
||||||
hash: ProtoField(11, () => NTHighwayHash),
|
hash: ProtoField(11, () => NTHighwayHash),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const NTHighwayHash = {
|
export const NTHighwayHash = {
|
||||||
fileSha1: ProtoField(1, ScalarType.BYTES, false, true),
|
fileSha1: ProtoField(1, ScalarType.BYTES, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const NTHighwayNetwork = {
|
export const NTHighwayNetwork = {
|
||||||
ipv4s: ProtoField(1, () => NTHighwayIPv4, false, true),
|
ipv4s: ProtoField(1, () => NTHighwayIPv4, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const NTHighwayIPv4 = {
|
export const NTHighwayIPv4 = {
|
||||||
domain: ProtoField(1, () => NTHighwayDomain),
|
domain: ProtoField(1, () => NTHighwayDomain),
|
||||||
port: ProtoField(2, ScalarType.UINT32),
|
port: ProtoField(2, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const NTHighwayDomain = {
|
export const NTHighwayDomain = {
|
||||||
isEnable: ProtoField(1, ScalarType.BOOL),
|
isEnable: ProtoField(1, ScalarType.BOOL),
|
||||||
ip: ProtoField(2, ScalarType.STRING),
|
ip: ProtoField(2, ScalarType.STRING),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ReqDataHighwayHead = {
|
export const ReqDataHighwayHead = {
|
||||||
msgBaseHead: ProtoField(1, () => DataHighwayHead, true),
|
msgBaseHead: ProtoField(1, () => DataHighwayHead, true),
|
||||||
@@ -111,7 +111,7 @@ export const ReqDataHighwayHead = {
|
|||||||
bytesReqExtendInfo: ProtoField(3, ScalarType.BYTES, true),
|
bytesReqExtendInfo: ProtoField(3, ScalarType.BYTES, true),
|
||||||
timestamp: ProtoField(4, ScalarType.UINT64),
|
timestamp: ProtoField(4, ScalarType.UINT64),
|
||||||
msgLoginSigHead: ProtoField(5, () => LoginSigHead, true),
|
msgLoginSigHead: ProtoField(5, () => LoginSigHead, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const RespDataHighwayHead = {
|
export const RespDataHighwayHead = {
|
||||||
msgBaseHead: ProtoField(1, () => DataHighwayHead, true),
|
msgBaseHead: ProtoField(1, () => DataHighwayHead, true),
|
||||||
@@ -124,7 +124,7 @@ export const RespDataHighwayHead = {
|
|||||||
timestamp: ProtoField(8, ScalarType.UINT64),
|
timestamp: ProtoField(8, ScalarType.UINT64),
|
||||||
range: ProtoField(9, ScalarType.UINT64),
|
range: ProtoField(9, ScalarType.UINT64),
|
||||||
isReset: ProtoField(10, ScalarType.UINT32),
|
isReset: ProtoField(10, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const SegHead = {
|
export const SegHead = {
|
||||||
serviceId: ProtoField(1, ScalarType.UINT32, true),
|
serviceId: ProtoField(1, ScalarType.UINT32, true),
|
||||||
@@ -140,7 +140,7 @@ export const SegHead = {
|
|||||||
queryTimes: ProtoField(11, ScalarType.UINT32),
|
queryTimes: ProtoField(11, ScalarType.UINT32),
|
||||||
updateCacheIp: ProtoField(12, ScalarType.UINT32),
|
updateCacheIp: ProtoField(12, ScalarType.UINT32),
|
||||||
cachePort: ProtoField(13, ScalarType.UINT32, true),
|
cachePort: ProtoField(13, ScalarType.UINT32, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const GroupAvatarExtra = {
|
export const GroupAvatarExtra = {
|
||||||
type: ProtoField(1, ScalarType.UINT32),
|
type: ProtoField(1, ScalarType.UINT32),
|
||||||
@@ -148,8 +148,8 @@ export const GroupAvatarExtra = {
|
|||||||
field3: ProtoField(3, () => GroupAvatarExtraField3),
|
field3: ProtoField(3, () => GroupAvatarExtraField3),
|
||||||
field5: ProtoField(5, ScalarType.UINT32),
|
field5: ProtoField(5, ScalarType.UINT32),
|
||||||
field6: ProtoField(6, ScalarType.UINT32),
|
field6: ProtoField(6, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const GroupAvatarExtraField3 = {
|
export const GroupAvatarExtraField3 = {
|
||||||
field1: ProtoField(1, ScalarType.UINT32),
|
field1: ProtoField(1, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
@@ -118,7 +118,7 @@ export const MarketFace = {
|
|||||||
|
|
||||||
export const MarketFacePbRes = {
|
export const MarketFacePbRes = {
|
||||||
field8: ProtoField(8, ScalarType.INT32)
|
field8: ProtoField(8, ScalarType.INT32)
|
||||||
}
|
};
|
||||||
|
|
||||||
export const CustomFace = {
|
export const CustomFace = {
|
||||||
guid: ProtoField(1, ScalarType.BYTES),
|
guid: ProtoField(1, ScalarType.BYTES),
|
||||||
@@ -315,7 +315,7 @@ export const SrcMsgPbRes = {
|
|||||||
senderUid: ProtoField(6, ScalarType.STRING, true),
|
senderUid: ProtoField(6, ScalarType.STRING, true),
|
||||||
receiverUid: ProtoField(7, ScalarType.STRING, true),
|
receiverUid: ProtoField(7, ScalarType.STRING, true),
|
||||||
friendSeq: ProtoField(8, ScalarType.UINT32, true),
|
friendSeq: ProtoField(8, ScalarType.UINT32, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LightAppElem = {
|
export const LightAppElem = {
|
||||||
data: ProtoField(1, ScalarType.BYTES),
|
data: ProtoField(1, ScalarType.BYTES),
|
||||||
@@ -358,4 +358,4 @@ export const QSmallFaceExtra = {
|
|||||||
|
|
||||||
export const MarkdownData = {
|
export const MarkdownData = {
|
||||||
content: ProtoField(1, ScalarType.STRING)
|
content: ProtoField(1, ScalarType.STRING)
|
||||||
}
|
};
|
||||||
|
@@ -14,6 +14,7 @@ export const OidbSvcTrpcTcp0X9067_202Key = {
|
|||||||
//Rsp
|
//Rsp
|
||||||
export const OidbSvcTrpcTcp0X9067_202_RkeyList = {
|
export const OidbSvcTrpcTcp0X9067_202_RkeyList = {
|
||||||
rkey: ProtoField(1, ScalarType.STRING),
|
rkey: ProtoField(1, ScalarType.STRING),
|
||||||
|
ttl: ProtoField(2, ScalarType.UINT64),
|
||||||
time: ProtoField(4, ScalarType.UINT32),
|
time: ProtoField(4, ScalarType.UINT32),
|
||||||
type: ProtoField(5, ScalarType.UINT32),
|
type: ProtoField(5, ScalarType.UINT32),
|
||||||
|
|
||||||
|
12
src/core/packet/proto/oidb/Oidb.0xEB7.ts
Normal file
12
src/core/packet/proto/oidb/Oidb.0xEB7.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { ScalarType } from "@protobuf-ts/runtime";
|
||||||
|
import { ProtoField } from "../NapProto";
|
||||||
|
|
||||||
|
export const OidbSvcTrpcTcp0XEB7_Body = {
|
||||||
|
uin: ProtoField(1, ScalarType.STRING),
|
||||||
|
groupUin: ProtoField(2, ScalarType.STRING),
|
||||||
|
version: ProtoField(3, ScalarType.STRING),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OidbSvcTrpcTcp0XEB7 = {
|
||||||
|
body: ProtoField(2, () => OidbSvcTrpcTcp0XEB7_Body),
|
||||||
|
}
|
@@ -160,7 +160,7 @@ export const PicUrlExtInfo = {
|
|||||||
|
|
||||||
export const VideoExtInfo = {
|
export const VideoExtInfo = {
|
||||||
VideoCodecFormat: ProtoField(1, ScalarType.UINT32),
|
VideoCodecFormat: ProtoField(1, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ExtBizInfo = {
|
export const ExtBizInfo = {
|
||||||
Pic: ProtoField(1, () => PicExtBizInfo),
|
Pic: ProtoField(1, () => PicExtBizInfo),
|
||||||
|
@@ -13,20 +13,20 @@ export const NTV2RichMediaResp = {
|
|||||||
uploadKeyRenewal: ProtoField(8, () => UploadKeyRenewalResp),
|
uploadKeyRenewal: ProtoField(8, () => UploadKeyRenewalResp),
|
||||||
downloadSafe: ProtoField(9, () => DownloadSafeResp),
|
downloadSafe: ProtoField(9, () => DownloadSafeResp),
|
||||||
extension: ProtoField(99, ScalarType.BYTES, true),
|
extension: ProtoField(99, ScalarType.BYTES, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const MultiMediaRespHead = {
|
export const MultiMediaRespHead = {
|
||||||
common: ProtoField(1, () => CommonHead),
|
common: ProtoField(1, () => CommonHead),
|
||||||
retCode: ProtoField(2, ScalarType.UINT32),
|
retCode: ProtoField(2, ScalarType.UINT32),
|
||||||
message: ProtoField(3, ScalarType.STRING),
|
message: ProtoField(3, ScalarType.STRING),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const DownloadResp = {
|
export const DownloadResp = {
|
||||||
rKeyParam: ProtoField(1, ScalarType.STRING),
|
rKeyParam: ProtoField(1, ScalarType.STRING),
|
||||||
rKeyTtlSecond: ProtoField(2, ScalarType.UINT32),
|
rKeyTtlSecond: ProtoField(2, ScalarType.UINT32),
|
||||||
info: ProtoField(3, () => DownloadInfo),
|
info: ProtoField(3, () => DownloadInfo),
|
||||||
rKeyCreateTime: ProtoField(4, ScalarType.UINT32),
|
rKeyCreateTime: ProtoField(4, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const DownloadInfo = {
|
export const DownloadInfo = {
|
||||||
domain: ProtoField(1, ScalarType.STRING),
|
domain: ProtoField(1, ScalarType.STRING),
|
||||||
@@ -36,7 +36,7 @@ export const DownloadInfo = {
|
|||||||
ipv6s: ProtoField(5, () => IPv6, false, true),
|
ipv6s: ProtoField(5, () => IPv6, false, true),
|
||||||
picUrlExtInfo: ProtoField(6, () => PicUrlExtInfo),
|
picUrlExtInfo: ProtoField(6, () => PicUrlExtInfo),
|
||||||
videoExtInfo: ProtoField(7, () => VideoExtInfo),
|
videoExtInfo: ProtoField(7, () => VideoExtInfo),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const IPv4 = {
|
export const IPv4 = {
|
||||||
outIP: ProtoField(1, ScalarType.UINT32),
|
outIP: ProtoField(1, ScalarType.UINT32),
|
||||||
@@ -44,7 +44,7 @@ export const IPv4 = {
|
|||||||
inIP: ProtoField(3, ScalarType.UINT32),
|
inIP: ProtoField(3, ScalarType.UINT32),
|
||||||
inPort: ProtoField(4, ScalarType.UINT32),
|
inPort: ProtoField(4, ScalarType.UINT32),
|
||||||
ipType: ProtoField(5, ScalarType.UINT32),
|
ipType: ProtoField(5, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const IPv6 = {
|
export const IPv6 = {
|
||||||
outIP: ProtoField(1, ScalarType.BYTES),
|
outIP: ProtoField(1, ScalarType.BYTES),
|
||||||
@@ -52,7 +52,7 @@ export const IPv6 = {
|
|||||||
inIP: ProtoField(3, ScalarType.BYTES),
|
inIP: ProtoField(3, ScalarType.BYTES),
|
||||||
inPort: ProtoField(4, ScalarType.UINT32),
|
inPort: ProtoField(4, ScalarType.UINT32),
|
||||||
ipType: ProtoField(5, ScalarType.UINT32),
|
ipType: ProtoField(5, ScalarType.UINT32),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const UploadResp = {
|
export const UploadResp = {
|
||||||
uKey: ProtoField(1, ScalarType.STRING, true),
|
uKey: ProtoField(1, ScalarType.STRING, true),
|
||||||
@@ -64,13 +64,13 @@ export const UploadResp = {
|
|||||||
ext: ProtoField(7, () => RichMediaStorageTransInfo, false, true),
|
ext: ProtoField(7, () => RichMediaStorageTransInfo, false, true),
|
||||||
compatQMsg: ProtoField(8, ScalarType.BYTES),
|
compatQMsg: ProtoField(8, ScalarType.BYTES),
|
||||||
subFileInfos: ProtoField(10, () => SubFileInfo, false, true),
|
subFileInfos: ProtoField(10, () => SubFileInfo, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const RichMediaStorageTransInfo = {
|
export const RichMediaStorageTransInfo = {
|
||||||
subType: ProtoField(1, ScalarType.UINT32),
|
subType: ProtoField(1, ScalarType.UINT32),
|
||||||
extType: ProtoField(2, ScalarType.UINT32),
|
extType: ProtoField(2, ScalarType.UINT32),
|
||||||
extValue: ProtoField(3, ScalarType.BYTES),
|
extValue: ProtoField(3, ScalarType.BYTES),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const SubFileInfo = {
|
export const SubFileInfo = {
|
||||||
subType: ProtoField(1, ScalarType.UINT32),
|
subType: ProtoField(1, ScalarType.UINT32),
|
||||||
@@ -78,32 +78,32 @@ export const SubFileInfo = {
|
|||||||
uKeyTtlSecond: ProtoField(3, ScalarType.UINT32),
|
uKeyTtlSecond: ProtoField(3, ScalarType.UINT32),
|
||||||
ipv4s: ProtoField(4, () => IPv4, false, true),
|
ipv4s: ProtoField(4, () => IPv4, false, true),
|
||||||
ipv6s: ProtoField(5, () => IPv6, false, true),
|
ipv6s: ProtoField(5, () => IPv6, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const DownloadSafeResp = {
|
export const DownloadSafeResp = {
|
||||||
}
|
};
|
||||||
|
|
||||||
export const UploadKeyRenewalResp = {
|
export const UploadKeyRenewalResp = {
|
||||||
ukey: ProtoField(1, ScalarType.STRING),
|
ukey: ProtoField(1, ScalarType.STRING),
|
||||||
ukeyTtlSec: ProtoField(2, ScalarType.UINT64),
|
ukeyTtlSec: ProtoField(2, ScalarType.UINT64),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const MsgInfoAuthResp = {
|
export const MsgInfoAuthResp = {
|
||||||
authCode: ProtoField(1, ScalarType.UINT32),
|
authCode: ProtoField(1, ScalarType.UINT32),
|
||||||
msg: ProtoField(2, ScalarType.BYTES),
|
msg: ProtoField(2, ScalarType.BYTES),
|
||||||
resultTime: ProtoField(3, ScalarType.UINT64),
|
resultTime: ProtoField(3, ScalarType.UINT64),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const UploadCompletedResp = {
|
export const UploadCompletedResp = {
|
||||||
msgSeq: ProtoField(1, ScalarType.UINT64),
|
msgSeq: ProtoField(1, ScalarType.UINT64),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const DeleteResp = {
|
export const DeleteResp = {
|
||||||
}
|
};
|
||||||
|
|
||||||
export const DownloadRKeyResp = {
|
export const DownloadRKeyResp = {
|
||||||
rKeys: ProtoField(1, () => RKeyInfo, false, true),
|
rKeys: ProtoField(1, () => RKeyInfo, false, true),
|
||||||
}
|
};
|
||||||
|
|
||||||
export const RKeyInfo = {
|
export const RKeyInfo = {
|
||||||
rkey: ProtoField(1, ScalarType.STRING),
|
rkey: ProtoField(1, ScalarType.STRING),
|
||||||
@@ -111,4 +111,4 @@ export const RKeyInfo = {
|
|||||||
storeId: ProtoField(3, ScalarType.UINT32),
|
storeId: ProtoField(3, ScalarType.UINT32),
|
||||||
rkeyCreateTime: ProtoField(4, ScalarType.UINT32, true),
|
rkeyCreateTime: ProtoField(4, ScalarType.UINT32, true),
|
||||||
type: ProtoField(5, ScalarType.UINT32, true),
|
type: ProtoField(5, ScalarType.UINT32, true),
|
||||||
}
|
};
|
||||||
|
@@ -76,7 +76,7 @@ export function decrypt(encrypted: Buffer, key: Buffer) {
|
|||||||
encrypted.writeInt32BE(r1, i);
|
encrypted.writeInt32BE(r1, i);
|
||||||
encrypted.writeInt32BE(r2, i + 4);
|
encrypted.writeInt32BE(r2, i + 4);
|
||||||
}
|
}
|
||||||
if (Buffer.compare(encrypted.subarray(encrypted.length - 7), BUF7) !== 0) throw ERROR_ENCRYPTED_ILLEGAL
|
if (Buffer.compare(encrypted.subarray(encrypted.length - 7), BUF7) !== 0) throw ERROR_ENCRYPTED_ILLEGAL;
|
||||||
// if (Buffer.compare(encrypted.slice(encrypted.length - 7), BUF7) !== 0) throw ERROR_ENCRYPTED_ILLEGAL;
|
// if (Buffer.compare(encrypted.slice(encrypted.length - 7), BUF7) !== 0) throw ERROR_ENCRYPTED_ILLEGAL;
|
||||||
return encrypted.subarray((encrypted[0] & 0x07) + 3, encrypted.length - 7);
|
return encrypted.subarray((encrypted[0] & 0x07) + 3, encrypted.length - 7);
|
||||||
// return encrypted.slice((encrypted[0] & 0x07) + 3, encrypted.length - 7);
|
// return encrypted.slice((encrypted[0] & 0x07) + 3, encrypted.length - 7);
|
||||||
|
@@ -239,7 +239,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<void>;
|
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<void>;
|
||||||
|
|
||||||
getGroupRecommendContactArkJson(groupCode: string): unknown;
|
getGroupRecommendContactArkJson(groupCode: string): Promise<GeneralCallResult & { arkJson: string }>;
|
||||||
|
|
||||||
getJoinGroupLink(param: {
|
getJoinGroupLink(param: {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { GroupNotifyMsgStatus } from '@/core';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
|
|
||||||
@@ -11,18 +12,22 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
|
|||||||
actionName = ActionName.GetGroupIgnoreAddRequest;
|
actionName = ActionName.GetGroupIgnoreAddRequest;
|
||||||
|
|
||||||
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
|
||||||
// const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
|
const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10);
|
||||||
// log(data);
|
const retData: any = {
|
||||||
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
|
join_requests: await Promise.all(
|
||||||
// const returnData: OB11GroupRequestNotify[] = [];
|
ignoredNotifies
|
||||||
// for (const notify of notifies) {
|
.filter(notify => notify.type === 7)
|
||||||
// const uin = || (await NTQQUserApi.getUserDetailInfo(notify.user1.uid))?.uin;
|
.map(async SSNotify => ({
|
||||||
// returnData.push({
|
request_id: SSNotify.seq,
|
||||||
// group_id: parseInt(notify.group.groupCode),
|
requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid),
|
||||||
// user_id: parseInt(uin),
|
requester_nick: SSNotify.user1?.nickName,
|
||||||
// flag: notify.seq
|
group_id: SSNotify.group?.groupCode,
|
||||||
// });
|
group_name: SSNotify.group?.groupName,
|
||||||
// }
|
checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
|
||||||
return null;
|
actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
|
||||||
|
}))),
|
||||||
|
};
|
||||||
|
|
||||||
|
return retData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
src/onebot/action/extends/SetGroupSign.ts
Normal file
22
src/onebot/action/extends/SetGroupSign.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
group_id: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['group_id'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class SetGroupSign extends BaseAction<Payload, any> {
|
||||||
|
actionName = ActionName.SetGroupSign;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
return await this.core.apis.PacketApi.sendGroupSignPacket(payload.group_id);
|
||||||
|
}
|
||||||
|
}
|
@@ -5,9 +5,9 @@ import { ActionName } from '../types';
|
|||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
|
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
|
||||||
|
|
||||||
export interface GetFilePayload {
|
// interface GetFilePayload {
|
||||||
file: string; // 文件名或者fileUuid
|
// file: string; // 文件名或者fileUuid
|
||||||
}
|
// }
|
||||||
|
|
||||||
export interface GetFileResponse {
|
export interface GetFileResponse {
|
||||||
file?: string; // path
|
file?: string; // path
|
||||||
@@ -16,19 +16,25 @@ export interface GetFileResponse {
|
|||||||
file_name?: string;
|
file_name?: string;
|
||||||
base64?: string;
|
base64?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetFileBase_PayloadSchema = {
|
const GetFileBase_PayloadSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
file: { type: 'string' },
|
file: { type: 'string' },
|
||||||
|
file_id: { type: 'string' }
|
||||||
},
|
},
|
||||||
required: ['file'],
|
oneOf: [
|
||||||
|
{ required: ['file'] },
|
||||||
|
{ required: ['file_id'] }
|
||||||
|
]
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
export type GetFilePayload = FromSchema<typeof GetFileBase_PayloadSchema>;
|
||||||
|
|
||||||
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
||||||
payloadSchema: any = GetFileBase_PayloadSchema;
|
payloadSchema = GetFileBase_PayloadSchema;
|
||||||
|
|
||||||
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
|
payload.file ||= payload.file_id || '';
|
||||||
//接收消息标记模式
|
//接收消息标记模式
|
||||||
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
|
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
|
||||||
if (contextMsgFile) {
|
if (contextMsgFile) {
|
||||||
@@ -115,27 +121,6 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetFile_PayloadSchema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
file_id: { type: 'string' },
|
|
||||||
file: { type: 'string' },
|
|
||||||
},
|
|
||||||
required: ['file_id'],
|
|
||||||
} as const satisfies JSONSchema;
|
|
||||||
|
|
||||||
type GetFile_Payload_Internal = FromSchema<typeof GetFile_PayloadSchema>;
|
|
||||||
|
|
||||||
interface GetFile_Payload extends GetFile_Payload_Internal {
|
|
||||||
file: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class GetFile extends GetFileBase {
|
export default class GetFile extends GetFileBase {
|
||||||
actionName = ActionName.GetFile;
|
actionName = ActionName.GetFile;
|
||||||
payloadSchema = GetFile_PayloadSchema;
|
|
||||||
|
|
||||||
async _handle(payload: GetFile_Payload): Promise<GetFileResponse> {
|
|
||||||
payload.file = payload.file_id;
|
|
||||||
return super._handle(payload);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,7 @@ export class GetGroupFileUrl extends GetPacketStatusDepends<Payload, GetGroupFil
|
|||||||
if (contextMsgFile?.fileUUID) {
|
if (contextMsgFile?.fileUUID) {
|
||||||
return {
|
return {
|
||||||
url: await this.core.apis.PacketApi.sendGroupFileDownloadReq(+payload.group_id, contextMsgFile.fileUUID)
|
url: await this.core.apis.PacketApi.sendGroupFileDownloadReq(+payload.group_id, contextMsgFile.fileUUID)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
throw new Error('real fileUUID not found!');
|
throw new Error('real fileUUID not found!');
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,6 @@ export class GroupPoke extends GetPacketStatusDepends<Payload, any> {
|
|||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
await this.core.apis.PacketApi.sendPokePacket(+payload.group_id, +payload.user_id);
|
await this.core.apis.PacketApi.sendPokePacket(+payload.user_id, +payload.group_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -91,6 +91,9 @@ import { GetGroupShutList } from './group/GetGroupShutList';
|
|||||||
import { GetGroupMemberList } from './group/GetGroupMemberList';
|
import { GetGroupMemberList } from './group/GetGroupMemberList';
|
||||||
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
|
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
|
||||||
import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus";
|
import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus";
|
||||||
|
import { FriendPoke } from "@/onebot/action/user/FriendPoke";
|
||||||
|
import { GetCredentials } from './system/GetCredentials';
|
||||||
|
import { SetGroupSign } from './extends/SetGroupSign';
|
||||||
|
|
||||||
|
|
||||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||||
@@ -113,6 +116,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new SetQQAvatar(obContext, core),
|
new SetQQAvatar(obContext, core),
|
||||||
new TranslateEnWordToZn(obContext, core),
|
new TranslateEnWordToZn(obContext, core),
|
||||||
new GetGroupRootFiles(obContext, core),
|
new GetGroupRootFiles(obContext, core),
|
||||||
|
new SetGroupSign(obContext, core),
|
||||||
// onebot11
|
// onebot11
|
||||||
new SendLike(obContext, core),
|
new SendLike(obContext, core),
|
||||||
new GetMsg(obContext, core),
|
new GetMsg(obContext, core),
|
||||||
@@ -179,6 +183,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new SetModelShow(obContext, core),
|
new SetModelShow(obContext, core),
|
||||||
new SetInputStatus(obContext, core),
|
new SetInputStatus(obContext, core),
|
||||||
new GetCSRF(obContext, core),
|
new GetCSRF(obContext, core),
|
||||||
|
new GetCredentials(obContext, core),
|
||||||
new DelGroupNotice(obContext, core),
|
new DelGroupNotice(obContext, core),
|
||||||
new DeleteGroupFile(obContext, core),
|
new DeleteGroupFile(obContext, core),
|
||||||
new CreateGroupFileFolder(obContext, core),
|
new CreateGroupFileFolder(obContext, core),
|
||||||
@@ -189,6 +194,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
|
|||||||
new FetchUserProfileLike(obContext, core),
|
new FetchUserProfileLike(obContext, core),
|
||||||
new GetPacketStatus(obContext, core),
|
new GetPacketStatus(obContext, core),
|
||||||
new GroupPoke(obContext, core),
|
new GroupPoke(obContext, core),
|
||||||
|
new FriendPoke(obContext, core),
|
||||||
new GetUserStatus(obContext, core),
|
new GetUserStatus(obContext, core),
|
||||||
new GetRkey(obContext, core),
|
new GetRkey(obContext, core),
|
||||||
new SetSpecialTittle(obContext, core),
|
new SetSpecialTittle(obContext, core),
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { ChatType, Peer } from '@/core/entities';
|
import { ChatType, Peer } from '@/core/entities';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@@ -49,23 +49,14 @@ export class MarkGroupMsgAsRead extends MarkMsgAsRead {
|
|||||||
actionName = ActionName.MarkGroupMsgAsRead;
|
actionName = ActionName.MarkGroupMsgAsRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class GoCQHTTPMarkMsgAsRead extends MarkMsgAsRead {
|
||||||
interface Payload {
|
|
||||||
message_id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GoCQHTTPMarkMsgAsRead extends BaseAction<Payload, null> {
|
|
||||||
actionName = ActionName.GoCQHTTP_MarkMsgAsRead;
|
actionName = ActionName.GoCQHTTP_MarkMsgAsRead;
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MarkAllMsgAsRead extends BaseAction<Payload, null> {
|
export class MarkAllMsgAsRead extends BaseAction<any, null> {
|
||||||
actionName = ActionName._MarkAllMsgAsRead;
|
actionName = ActionName._MarkAllMsgAsRead;
|
||||||
|
|
||||||
async _handle(payload: Payload): Promise<null> {
|
async _handle(): Promise<null> {
|
||||||
await this.core.apis.MsgApi.markAllMsgAsRead();
|
await this.core.apis.MsgApi.markAllMsgAsRead();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@ import {ChatType, ElementType, NapCatCore, Peer, RawMessage, SendArkElement, Sen
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { rawMsgWithSendMsg } from "@/core/packet/msg/converter";
|
import { rawMsgWithSendMsg } from "@/core/packet/msg/converter";
|
||||||
import { PacketMsg } from "@/core/packet/msg/message";
|
import { PacketMsg } from "@/core/packet/msg/message";
|
||||||
import {PacketMultiMsgElement} from "@/core/packet/msg/element";
|
import { ForwardMsgBuilder } from "@/common/forward-msg-builder";
|
||||||
|
|
||||||
export interface ReturnDataType {
|
export interface ReturnDataType {
|
||||||
message_id: number;
|
message_id: number;
|
||||||
@@ -115,7 +115,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||||
const packetMode = this.core.apis.PacketApi.available
|
const packetMode = this.core.apis.PacketApi.available;
|
||||||
const returnMsgAndResId = packetMode
|
const returnMsgAndResId = packetMode
|
||||||
? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[])
|
? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[])
|
||||||
: await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
|
: await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
|
||||||
@@ -126,6 +126,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
chatType: peer.chatType,
|
chatType: peer.chatType,
|
||||||
}, (returnMsgAndResId.message)!.msgId);
|
}, (returnMsgAndResId.message)!.msgId);
|
||||||
return { message_id: msgShortId!, res_id: returnMsgAndResId.res_id };
|
return { message_id: msgShortId!, res_id: returnMsgAndResId.res_id };
|
||||||
|
} else if (returnMsgAndResId.res_id && !returnMsgAndResId.message) {
|
||||||
|
throw Error(`发送转发消息(res_id:${returnMsgAndResId.res_id} 失败`);
|
||||||
}
|
}
|
||||||
throw Error('发送转发消息失败');
|
throw Error('发送转发消息失败');
|
||||||
} else {
|
} else {
|
||||||
@@ -143,6 +145,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
return { message_id: returnMsg!.id! };
|
return { message_id: returnMsg!.id! };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: recursively handle forwarded nodes
|
||||||
private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{
|
private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{
|
||||||
message: RawMessage | null,
|
message: RawMessage | null,
|
||||||
res_id?: string
|
res_id?: string
|
||||||
@@ -159,7 +162,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
groupId: msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : undefined,
|
groupId: msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : undefined,
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
msg: sendElements,
|
msg: sendElements,
|
||||||
}
|
};
|
||||||
logger.logDebug(`handleForwardedNodesPacket 开始转换 ${JSON.stringify(packetMsgElements)}`);
|
logger.logDebug(`handleForwardedNodesPacket 开始转换 ${JSON.stringify(packetMsgElements)}`);
|
||||||
const transformedMsg = this.core.apis.PacketApi.packetSession?.packer.packetConverter.rawMsgWithSendMsgToPacketMsg(packetMsgElements);
|
const transformedMsg = this.core.apis.PacketApi.packetSession?.packer.packetConverter.rawMsgWithSendMsgToPacketMsg(packetMsgElements);
|
||||||
logger.logDebug(`handleForwardedNodesPacket 转换为 ${JSON.stringify(transformedMsg)}`);
|
logger.logDebug(`handleForwardedNodesPacket 转换为 ${JSON.stringify(transformedMsg)}`);
|
||||||
@@ -169,22 +172,20 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const resid = await this.core.apis.PacketApi.sendUploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);
|
const resid = await this.core.apis.PacketApi.sendUploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);
|
||||||
const forwardJson = new PacketMultiMsgElement({
|
const forwardJson = ForwardMsgBuilder.fromPacketMsg(resid, packetMsg);
|
||||||
elementType: ElementType.STRUCTLONGMSG,
|
|
||||||
elementId: "",
|
|
||||||
structLongMsgElement: {
|
|
||||||
xmlContent: "",
|
|
||||||
resId: resid
|
|
||||||
}
|
|
||||||
}, packetMsg).JSON;
|
|
||||||
const finallySendElements = {
|
const finallySendElements = {
|
||||||
elementType: ElementType.ARK,
|
elementType: ElementType.ARK,
|
||||||
elementId: "",
|
elementId: "",
|
||||||
arkElement: {
|
arkElement: {
|
||||||
bytesData: JSON.stringify(forwardJson),
|
bytesData: JSON.stringify(forwardJson),
|
||||||
},
|
},
|
||||||
} as SendArkElement
|
} as SendArkElement;
|
||||||
const returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined)
|
let returnMsg: RawMessage | undefined;
|
||||||
|
try {
|
||||||
|
returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined);
|
||||||
|
} catch (e) {
|
||||||
|
logger.logWarn("发送伪造合并转发消息失败!", e);
|
||||||
|
}
|
||||||
return { message: returnMsg ?? null, res_id: resid };
|
return { message: returnMsg ?? null, res_id: resid };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,16 +10,16 @@ export abstract class GetPacketStatusDepends<PT, RT> extends BaseAction<PT, RT>
|
|||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
message: "packetServer不可用,请参照文档 https://napneko.github.io/config/advanced 检查packetServer状态或进行配置!",
|
message: "packetServer不可用,请参照文档 https://napneko.github.io/config/advanced 检查packetServer状态或进行配置!",
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
valid: true,
|
valid: true,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetPacketStatus extends GetPacketStatusDepends<any, null> {
|
export class GetPacketStatus extends GetPacketStatusDepends<any, null> {
|
||||||
async _handle(payload: any) {
|
async _handle(payload: any) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,12 @@ export class GetCSRF extends BaseAction<any, any> {
|
|||||||
actionName = ActionName.GetCSRF;
|
actionName = ActionName.GetCSRF;
|
||||||
|
|
||||||
async _handle(payload: any) {
|
async _handle(payload: any) {
|
||||||
|
const sKey = await this.core.apis.UserApi.getSKey();
|
||||||
|
if (!sKey) {
|
||||||
|
throw new Error('SKey is undefined');
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
token: '',
|
token: +this.core.apis.WebApi.getBknFromSKey(sKey),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
src/onebot/action/system/GetCredentials.ts
Normal file
31
src/onebot/action/system/GetCredentials.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
interface Response {
|
||||||
|
cookies: string,
|
||||||
|
token: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
domain: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['domain'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class GetCredentials extends BaseAction<Payload, Response> {
|
||||||
|
actionName = ActionName.GetCredentials;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
const cookiesObject = await this.core.apis.UserApi.getCookies(payload.domain);
|
||||||
|
//把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起
|
||||||
|
const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||||
|
const bkn = cookiesObject?.skey ? this.core.apis.WebApi.getBknFromCookie(cookiesObject) : '';
|
||||||
|
return { cookies: cookies, token: +bkn };
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
export type BaseCheckResult = ValidCheckResult | InvalidCheckResult
|
export type BaseCheckResult = ValidCheckResult | InvalidCheckResult;
|
||||||
|
|
||||||
export interface ValidCheckResult {
|
export interface ValidCheckResult {
|
||||||
valid: true;
|
valid: true;
|
||||||
@@ -14,117 +14,127 @@ export interface InvalidCheckResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum ActionName {
|
export enum ActionName {
|
||||||
// 以下为扩展napcat扩展
|
|
||||||
Unknown = 'unknown',
|
|
||||||
GroupPoke = 'group_poke',
|
|
||||||
SharePeer = 'ArkSharePeer',
|
|
||||||
ShareGroupEx = 'ArkShareGroup',
|
|
||||||
RebootNormal = 'reboot_normal',//无快速登录重新启动
|
|
||||||
GetRobotUinRange = 'get_robot_uin_range',
|
|
||||||
SetOnlineStatus = 'set_online_status',
|
|
||||||
GetFriendsWithCategory = 'get_friends_with_category',
|
|
||||||
GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
|
|
||||||
SetQQAvatar = 'set_qq_avatar',
|
|
||||||
GetConfig = 'get_config',
|
|
||||||
SetConfig = 'set_config',
|
|
||||||
Debug = 'debug',
|
|
||||||
GetFile = 'get_file',
|
|
||||||
ForwardFriendSingleMsg = 'forward_friend_single_msg',
|
|
||||||
ForwardGroupSingleMsg = 'forward_group_single_msg',
|
|
||||||
TranslateEnWordToZn = 'translate_en2zh',
|
|
||||||
GetGroupFileCount = 'get_group_file_count',
|
|
||||||
GetGroupFileList = 'get_group_file_list',
|
|
||||||
SetGroupFileFolder = 'set_group_file_folder',
|
|
||||||
DelGroupFile = 'del_group_file',
|
|
||||||
DelGroupFileFolder = 'del_group_file_folder',
|
|
||||||
// onebot 11
|
// onebot 11
|
||||||
Reboot = 'set_restart',
|
SendPrivateMsg = 'send_private_msg',
|
||||||
|
SendGroupMsg = 'send_group_msg',
|
||||||
|
SendMsg = 'send_msg',
|
||||||
|
DeleteMsg = 'delete_msg',
|
||||||
|
GetMsg = 'get_msg',
|
||||||
|
GoCQHTTP_GetForwardMsg = 'get_forward_msg',
|
||||||
SendLike = 'send_like',
|
SendLike = 'send_like',
|
||||||
|
SetGroupKick = 'set_group_kick',
|
||||||
|
SetGroupBan = 'set_group_ban',
|
||||||
|
// SetGroupAnoymousBan = 'set_group_anonymous_ban',
|
||||||
|
SetGroupWholeBan = 'set_group_whole_ban',
|
||||||
|
SetGroupAdmin = 'set_group_admin',
|
||||||
|
// SetGroupAnoymous = 'set_group_anonymous',
|
||||||
|
SetGroupCard = 'set_group_card',
|
||||||
|
SetGroupName = 'set_group_name',
|
||||||
|
SetGroupLeave = 'set_group_leave',
|
||||||
|
SetSpecialTittle = 'set_group_special_title',
|
||||||
|
SetFriendAddRequest = 'set_friend_add_request',
|
||||||
|
SetGroupAddRequest = 'set_group_add_request',
|
||||||
GetLoginInfo = 'get_login_info',
|
GetLoginInfo = 'get_login_info',
|
||||||
|
GoCQHTTP_GetStrangerInfo = 'get_stranger_info',
|
||||||
GetFriendList = 'get_friend_list',
|
GetFriendList = 'get_friend_list',
|
||||||
GetGroupInfo = 'get_group_info',
|
GetGroupInfo = 'get_group_info',
|
||||||
GetGroupList = 'get_group_list',
|
GetGroupList = 'get_group_list',
|
||||||
GetGroupMemberInfo = 'get_group_member_info',
|
GetGroupMemberInfo = 'get_group_member_info',
|
||||||
GetGroupMemberList = 'get_group_member_list',
|
GetGroupMemberList = 'get_group_member_list',
|
||||||
GetMsg = 'get_msg',
|
|
||||||
SendMsg = 'send_msg',
|
|
||||||
SendGroupMsg = 'send_group_msg',
|
|
||||||
SendPrivateMsg = 'send_private_msg',
|
|
||||||
DeleteMsg = 'delete_msg',
|
|
||||||
SetMsgEmojiLike = 'set_msg_emoji_like',
|
|
||||||
SetGroupAddRequest = 'set_group_add_request',
|
|
||||||
SetFriendAddRequest = 'set_friend_add_request',
|
|
||||||
SetGroupLeave = 'set_group_leave',
|
|
||||||
GetVersionInfo = 'get_version_info',
|
|
||||||
GetStatus = 'get_status',
|
|
||||||
CanSendRecord = 'can_send_record',
|
|
||||||
CanSendImage = 'can_send_image',
|
|
||||||
SetGroupKick = 'set_group_kick',
|
|
||||||
SetGroupBan = 'set_group_ban',
|
|
||||||
SetGroupWholeBan = 'set_group_whole_ban',
|
|
||||||
SetGroupAdmin = 'set_group_admin',
|
|
||||||
SetGroupCard = 'set_group_card',
|
|
||||||
SetGroupName = 'set_group_name',
|
|
||||||
GetImage = 'get_image',
|
|
||||||
GetRecord = 'get_record',
|
|
||||||
CleanCache = 'clean_cache',
|
|
||||||
GetCookies = 'get_cookies',
|
|
||||||
// 以下为go-cqhttp api
|
|
||||||
GoCQHTTP_HandleQuickAction = '.handle_quick_operation',
|
|
||||||
GetGroupHonorInfo = 'get_group_honor_info',
|
GetGroupHonorInfo = 'get_group_honor_info',
|
||||||
GoCQHTTP_GetEssenceMsg = 'get_essence_msg_list',
|
GetCookies = 'get_cookies',
|
||||||
GoCQHTTP_SendGroupNotice = '_send_group_notice',
|
GetCSRF = 'get_csrf_token',
|
||||||
GoCQHTTP_GetGroupNotice = '_get_group_notice',
|
GetCredentials = 'get_credentials',
|
||||||
GoCQHTTP_SendForwardMsg = 'send_forward_msg',
|
GetRecord = 'get_record',
|
||||||
|
GetImage = 'get_image',
|
||||||
|
CanSendImage = 'can_send_image',
|
||||||
|
CanSendRecord = 'can_send_record',
|
||||||
|
GetStatus = 'get_status',
|
||||||
|
GetVersionInfo = 'get_version_info',
|
||||||
|
// Reboot = 'set_restart',
|
||||||
|
// CleanCache = 'clean_cache',
|
||||||
|
|
||||||
|
// go-cqhttp
|
||||||
|
SetQQProfile = 'set_qq_profile',
|
||||||
|
// QidianGetAccountInfo = 'qidian_get_account_info',
|
||||||
|
// GetModelShow = '_get_model_show',
|
||||||
|
// SetModelShow = '_set_model_show',
|
||||||
|
GetOnlineClient = 'get_online_clients',
|
||||||
|
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
|
||||||
|
// DeleteFriend = 'delete_friend',
|
||||||
|
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
|
||||||
|
GoCQHTTP_MarkMsgAsRead = 'mark_msg_as_read',
|
||||||
GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg',
|
GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg',
|
||||||
GoCQHTTP_SendPrivateForwardMsg = 'send_private_forward_msg',
|
GoCQHTTP_SendPrivateForwardMsg = 'send_private_forward_msg',
|
||||||
GoCQHTTP_GetStrangerInfo = 'get_stranger_info',
|
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
|
||||||
GoCQHTTP_MarkMsgAsRead = 'mark_msg_as_read',
|
OCRImage = 'ocr_image',
|
||||||
GetGuildList = 'get_guild_list',
|
IOCRImage = '.ocr_image',
|
||||||
MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
|
GetGroupSystemMsg = 'get_group_system_msg',
|
||||||
MarkGroupMsgAsRead = 'mark_group_msg_as_read',
|
GoCQHTTP_GetEssenceMsg = 'get_essence_msg_list',
|
||||||
|
// GetGroupAtAllRemain = 'get_group_at_all_remain',
|
||||||
|
SetGroupPortrait = 'set_group_portrait',
|
||||||
|
SetEssenceMsg = 'set_essence_msg',
|
||||||
|
DelEssenceMsg = 'delete_essence_msg',
|
||||||
|
GoCQHTTP_SendGroupNotice = '_send_group_notice',
|
||||||
|
GoCQHTTP_GetGroupNotice = '_get_group_notice',
|
||||||
GoCQHTTP_UploadGroupFile = 'upload_group_file',
|
GoCQHTTP_UploadGroupFile = 'upload_group_file',
|
||||||
GOCQHTTP_DeleteGroupFile = 'delete_group_file',
|
GOCQHTTP_DeleteGroupFile = 'delete_group_file',
|
||||||
GOCQHTTP_GetGroupFileUrl = 'get_group_file_url',
|
|
||||||
GoCQHTTP_CreateGroupFileFolder = 'create_group_file_folder',
|
GoCQHTTP_CreateGroupFileFolder = 'create_group_file_folder',
|
||||||
GoCQHTTP_DeleteGroupFileFolder = 'delete_group_file_folder',
|
GoCQHTTP_DeleteGroupFileFolder = 'delete_group_folder',
|
||||||
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
|
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
|
||||||
GoCQHTTP_GetGroupRootFiles = 'get_group_root_files',
|
GoCQHTTP_GetGroupRootFiles = 'get_group_root_files',
|
||||||
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
|
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
|
||||||
|
GOCQHTTP_GetGroupFileUrl = 'get_group_file_url',
|
||||||
|
GOCQHTTP_UploadPrivateFile = 'upload_private_file',
|
||||||
|
// GOCQHTTP_ReloadEventFilter = 'reload_event_filter',
|
||||||
GoCQHTTP_DownloadFile = 'download_file',
|
GoCQHTTP_DownloadFile = 'download_file',
|
||||||
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
|
// GoCQHTTP_CheckUrlSafely = 'check_url_safely',
|
||||||
GoCQHTTP_GetForwardMsg = 'get_forward_msg',
|
// GoCQHTTP_GetWordSlices = '.get_word_slices',
|
||||||
|
GoCQHTTP_HandleQuickAction = '.handle_quick_operation',
|
||||||
|
|
||||||
|
// 以下为扩展napcat扩展
|
||||||
|
Unknown = 'unknown',
|
||||||
|
SharePeer = 'ArkSharePeer',
|
||||||
|
ShareGroupEx = 'ArkShareGroup',
|
||||||
|
// RebootNormal = 'reboot_normal', //无快速登录重新启动
|
||||||
|
GetRobotUinRange = 'get_robot_uin_range',
|
||||||
|
SetOnlineStatus = 'set_online_status',
|
||||||
|
GetFriendsWithCategory = 'get_friends_with_category',
|
||||||
|
SetQQAvatar = 'set_qq_avatar',
|
||||||
|
GetFile = 'get_file',
|
||||||
|
ForwardFriendSingleMsg = 'forward_friend_single_msg',
|
||||||
|
ForwardGroupSingleMsg = 'forward_group_single_msg',
|
||||||
|
TranslateEnWordToZn = 'translate_en2zh',
|
||||||
|
SetMsgEmojiLike = 'set_msg_emoji_like',
|
||||||
|
GoCQHTTP_SendForwardMsg = 'send_forward_msg',
|
||||||
|
MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
|
||||||
|
MarkGroupMsgAsRead = 'mark_group_msg_as_read',
|
||||||
GetFriendMsgHistory = 'get_friend_msg_history',
|
GetFriendMsgHistory = 'get_friend_msg_history',
|
||||||
GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
|
|
||||||
GetOnlineClient = 'get_online_clients',
|
|
||||||
OCRImage = 'ocr_image',
|
|
||||||
IOCRImage = '.ocr_image',
|
|
||||||
SetQQProfile = 'set_qq_profile',
|
|
||||||
CreateCollection = 'create_collection',
|
CreateCollection = 'create_collection',
|
||||||
GetCollectionList = 'get_collection_list',
|
GetCollectionList = 'get_collection_list',
|
||||||
SetLongNick = 'set_self_longnick',
|
SetLongNick = 'set_self_longnick',
|
||||||
SetEssenceMsg = 'set_essence_msg',
|
|
||||||
DelEssenceMsg = 'delete_essence_msg',
|
|
||||||
GetRecentContact = 'get_recent_contact',
|
GetRecentContact = 'get_recent_contact',
|
||||||
_MarkAllMsgAsRead = '_mark_all_as_read',
|
_MarkAllMsgAsRead = '_mark_all_as_read',
|
||||||
GetProfileLike = 'get_profile_like',
|
GetProfileLike = 'get_profile_like',
|
||||||
SetGroupPortrait = 'set_group_portrait',
|
|
||||||
FetchCustomFace = 'fetch_custom_face',
|
FetchCustomFace = 'fetch_custom_face',
|
||||||
GOCQHTTP_UploadPrivateFile = 'upload_private_file',
|
|
||||||
TestApi01 = 'test_api_01',
|
|
||||||
FetchEmojiLike = 'fetch_emoji_like',
|
FetchEmojiLike = 'fetch_emoji_like',
|
||||||
GetGuildProfile = 'get_guild_service_profile',
|
|
||||||
SetModelShow = '_set_model_show',
|
|
||||||
SetInputStatus = 'set_input_status',
|
SetInputStatus = 'set_input_status',
|
||||||
GetCSRF = 'get_csrf_token',
|
GetGroupInfoEx = 'get_group_info_ex',
|
||||||
|
GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
|
||||||
DelGroupNotice = '_del_group_notice',
|
DelGroupNotice = '_del_group_notice',
|
||||||
GetGroupInfoEx = "get_group_info_ex",
|
FetchUserProfileLike = 'fetch_user_profile_like',
|
||||||
GetGroupSystemMsg = 'get_group_system_msg',
|
FriendPoke = 'friend_poke',
|
||||||
FetchUserProfileLike = "fetch_user_profile_like",
|
GroupPoke = 'group_poke',
|
||||||
GetPacketStatus = 'nc_get_packet_status',
|
GetPacketStatus = 'nc_get_packet_status',
|
||||||
GetUserStatus = "nc_get_user_status",
|
GetUserStatus = 'nc_get_user_status',
|
||||||
GetRkey = "nc_get_rkey",
|
GetRkey = 'nc_get_rkey',
|
||||||
SetSpecialTittle = "set_group_special_title",
|
GetGroupShutList = 'get_group_shut_list',
|
||||||
|
|
||||||
|
GetGuildList = 'get_guild_list',
|
||||||
|
GetGuildProfile = 'get_guild_service_profile',
|
||||||
|
|
||||||
|
GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
|
||||||
|
|
||||||
|
SetGroupSign = "set_group_sign",
|
||||||
// UploadForwardMsg = "upload_forward_msg",
|
// UploadForwardMsg = "upload_forward_msg",
|
||||||
GetGroupShutList = "get_group_shut_list",
|
|
||||||
}
|
}
|
||||||
|
22
src/onebot/action/user/FriendPoke.ts
Normal file
22
src/onebot/action/user/FriendPoke.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
user_id: { type: ['number', 'string'] },
|
||||||
|
},
|
||||||
|
required: ['user_id'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class FriendPoke extends GetPacketStatusDepends<Payload, any> {
|
||||||
|
actionName = ActionName.FriendPoke;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
await this.core.apis.PacketApi.sendPokePacket(+payload.user_id);
|
||||||
|
}
|
||||||
|
}
|
@@ -35,6 +35,7 @@ import fs from 'node:fs';
|
|||||||
import fsPromise from 'node:fs/promises';
|
import fsPromise from 'node:fs/promises';
|
||||||
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
import { OB11FriendAddNoticeEvent } from '@/onebot/event/notice/OB11FriendAddNoticeEvent';
|
||||||
import { decodeSysMessage } from '@/core/packet/proto/old/ProfileLike';
|
import { decodeSysMessage } from '@/core/packet/proto/old/ProfileLike';
|
||||||
|
import { ForwardMsgBuilder } from "@/common/forward-msg-builder";
|
||||||
|
|
||||||
type RawToOb11Converters = {
|
type RawToOb11Converters = {
|
||||||
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
|
||||||
@@ -600,7 +601,13 @@ export class OneBotMsgApi {
|
|||||||
|
|
||||||
[OB11MessageDataType.node]: async () => undefined,
|
[OB11MessageDataType.node]: async () => undefined,
|
||||||
|
|
||||||
[OB11MessageDataType.forward]: async () => undefined,
|
[OB11MessageDataType.forward]: async ({ data }, context) => {
|
||||||
|
const jsonData = ForwardMsgBuilder.fromResId(data.id);
|
||||||
|
return this.ob11ToRawConverters.json({
|
||||||
|
data: { data: JSON.stringify(jsonData) },
|
||||||
|
type: OB11MessageDataType.json
|
||||||
|
}, context);
|
||||||
|
},
|
||||||
|
|
||||||
[OB11MessageDataType.xml]: async () => undefined,
|
[OB11MessageDataType.xml]: async () => undefined,
|
||||||
|
|
||||||
@@ -617,12 +624,20 @@ export class OneBotMsgApi {
|
|||||||
|
|
||||||
[OB11MessageDataType.miniapp]: async () => undefined,
|
[OB11MessageDataType.miniapp]: async () => undefined,
|
||||||
|
|
||||||
[OB11MessageDataType.contact]: async ({ data }, context) => {
|
[OB11MessageDataType.contact]: async ({ data: { type = "qq", id } }, context) => {
|
||||||
const arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(data.id.toString(), '');
|
if(type === "qq"){
|
||||||
|
const arkJson = await this.core.apis.UserApi.getBuddyRecommendContactArkJson(id.toString(), '');
|
||||||
return this.ob11ToRawConverters.json({
|
return this.ob11ToRawConverters.json({
|
||||||
data: { data: arkJson.arkMsg },
|
data: { data: arkJson.arkMsg },
|
||||||
type: OB11MessageDataType.json
|
type: OB11MessageDataType.json
|
||||||
}, context);
|
}, context);
|
||||||
|
}else if(type === "group"){
|
||||||
|
const arkJson = await this.core.apis.GroupApi.getGroupRecommendContactArkJson(id.toString());
|
||||||
|
return this.ob11ToRawConverters.json({
|
||||||
|
data: { data: arkJson.arkJson },
|
||||||
|
type: OB11MessageDataType.json
|
||||||
|
}, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -304,10 +304,10 @@ export class NapCatOneBot11Adapter {
|
|||||||
},
|
},
|
||||||
m.msgId,
|
m.msgId,
|
||||||
);
|
);
|
||||||
if (m.sourceType == MsgSourceType.K_DOWN_SOURCETYPE_AIOINNER) {
|
// if (m.sourceType == MsgSourceType.K_DOWN_SOURCETYPE_AIOINNER) {
|
||||||
await this.emitMsg(m)
|
await this.emitMsg(m)
|
||||||
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -576,8 +576,6 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.networkManager.emitEvent(ob11Msg);
|
this.networkManager.emitEvent(ob11Msg);
|
||||||
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
|
||||||
|
|
||||||
console.log('message', message);
|
|
||||||
|
|
||||||
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
||||||
if (groupEvent) {
|
if (groupEvent) {
|
||||||
// log("post group event", groupEvent);
|
// log("post group event", groupEvent);
|
||||||
|
@@ -85,6 +85,7 @@ export interface OB11MessageText {
|
|||||||
export interface OB11MessageContext {
|
export interface OB11MessageContext {
|
||||||
type: OB11MessageDataType.contact,
|
type: OB11MessageDataType.contact,
|
||||||
data: {
|
data: {
|
||||||
|
type:"qq"|"group",
|
||||||
id: string,
|
id: string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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('V3.0.3', 'napcat-update-button', 'secondary'),
|
SettingButton('V3.1.5', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -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("V3.0.3", "napcat-update-button", "secondary")
|
SettingButton("V3.1.5", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user