Compare commits

...

31 Commits

Author SHA1 Message Date
手瓜一十雪
fb09af0e64 release: v3.1.8 2024-10-26 21:25:03 +08:00
手瓜一十雪
0d99d30b2d feat: version hint 2024-10-26 21:24:24 +08:00
手瓜一十雪
0000ec8b5b fix: fetchFavEmojiList 2024-10-26 21:15:11 +08:00
手瓜一十雪
0085bd8a1f fix: q-gate 2024-10-26 20:46:38 +08:00
手瓜一十雪
617139dfa4 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-10-26 20:36:59 +08:00
手瓜一十雪
4eb4a612d0 fix: type 2024-10-26 20:25:34 +08:00
pk5ls20
cda5e784f6 fix: payload basic check in GetPacketStatusDepends 2024-10-26 19:51:43 +08:00
手瓜一十雪
d93a280ab3 fix: 进一步getNextMemberList 2024-10-26 18:40:21 +08:00
手瓜一十雪
f7e2b3a4a7 feat: new function 2024-10-26 18:10:08 +08:00
手瓜一十雪
39d9c8fa74 release: v3.1.7 2024-10-26 16:26:30 +08:00
手瓜一十雪
8823895a03 Merge pull request #466 from cnxysoft/upmain
perf: 群成员拉取
2024-10-26 16:18:17 +08:00
手瓜一十雪
b44a9e696c Merge branch 'main' into pr/466 2024-10-26 15:47:13 +08:00
手瓜一十雪
cf28a3dc17 fix: ai solve 2024-10-26 10:49:18 +08:00
手瓜一十雪
7416e6caf6 feat: GoCQHTTPDeleteFriend 2024-10-26 10:36:41 +08:00
手瓜一十雪
90f6896f3c feat: GoCQ兼容性提高 2024-10-26 10:22:04 +08:00
Alen
eebcd0700d Merge branch 'main' into upmain 2024-10-26 07:22:25 +08:00
Alen
133eee0c66 perf: 群成员拉取
getgroupmemberlist启用no_cache
2024-10-26 07:20:40 +08:00
pk5ls20
640fb75f74 feat: support for customizing the timestamp of fake forwardMsg 2024-10-26 04:06:42 +08:00
Alen
51dcc1add6 Merge branch 'main' into upmain 2024-10-25 23:58:18 +08:00
Alen
730c928f91 Merge pull request #465 from cnxysoft/upmain
refactor: 群成员列表获取
2024-10-25 23:49:27 +08:00
Alen
c3b7e111b9 style: 2024-10-25 22:26:18 +08:00
pk5ls20
1874e48925 Merge pull request #464 from clansty/feat/nested-forward
feat: 嵌套合并转发消息
2024-10-25 22:13:32 +08:00
pk5ls20
e7a082c91c feat: better recursive parsing with depth limits 2024-10-25 22:10:24 +08:00
Alen
5d4f45407e fix: 群成员拉取 2024-10-25 21:50:19 +08:00
Clansty
17c37ec32f feat: 嵌套合并转发消息 2024-10-25 19:37:04 +08:00
手瓜一十雪
b5f8140c79 feat: v3 Logo 2024-10-25 19:31:44 +08:00
手瓜一十雪
63f746c237 style: lint 2024-10-25 18:09:41 +08:00
手瓜一十雪
dac6709f27 feat: 6.9.56-28418-mac 2024-10-25 17:57:28 +08:00
Alen
2f08b72d69 fix: 群成员拉取 2024-10-24 23:00:38 +08:00
Alen
0081000ef0 Merge branch 'main' into upmain 2024-10-23 01:08:56 +08:00
Alen
ad4d6a1070 refactor: 群成员获取 2024-10-23 01:07:52 +08:00
41 changed files with 443 additions and 196 deletions

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 335 KiB

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "3.1.6",
"version": "3.1.8",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",

View File

@@ -55,10 +55,10 @@ export class ForwardMsgBuilder {
const isGroupMsg = msg.some(m => m.isGroupMsg);
if (!source) {
source = isGroupMsg ? "群聊的聊天记录" :
msg.length
? Array.from(new Set(msg.map(m => m.senderName)))
.join('和') + '的聊天记录'
: '聊天记录';
msg.length
? Array.from(new Set(msg.map(m => m.senderName)))
.join('和') + '的聊天记录'
: '聊天记录';
}
if (!news) {
news = msg.length === 0 ? [{

View File

@@ -1 +1 @@
export const napCatVersion = '3.1.6';
export const napCatVersion = '3.1.8';

View File

@@ -378,8 +378,8 @@ export class NTQQFileApi {
};
try {
if (this.core.apis.PacketApi.available) {
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;
const rkey_expired_private = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000;
const 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();
}

View File

@@ -34,7 +34,13 @@ export class NTQQFriendApi {
data.forEach((value) => retMap.set(value.uin!, value.uid!));
return retMap;
}
async delBuudy(uid: string, tempBlock = false, tempBothDel = false) {
return this.context.session.getBuddyService().delBuddy({
friendUid: uid,
tempBlock: tempBlock,
tempBothDel: tempBothDel
});
}
async getBuddyV2ExWithCate(refresh = false) {
const categoryMap: Map<string, any> = new Map();
const buddyService = this.context.session.getBuddyService();

View File

@@ -316,18 +316,42 @@ export class NTQQGroupApi {
return undefined;
}
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', 1, 2000, (params) => params.sceneId === sceneId)
.catch();
const result = await this.context.session.getGroupService().getNextMemberList(sceneId!, undefined, num);
async tryGetGroupMembersV2(modeListener = false, groupQQ: string, num = 30, timeout = 100): Promise<{
infos: Map<string, GroupMember>;
finish: boolean;
hasNext: boolean | undefined;
}>{
const sceneId = this.context.session.getGroupService().createMemberListScene(groupQQ, 'groupMemberList_MainWindow_1');
const once = this.core.eventWrapper.registerListen('NodeIKernelGroupListener/onMemberListChange', 0, timeout, (params) => params.sceneId === sceneId)
.catch(() => {});
const result = await this.context.session.getGroupService().getNextMemberList(sceneId, undefined, num);
if (result.errCode !== 0) {
throw new Error('获取群成员列表出错,' + result.errMsg);
}
if (result.result.infos.size === 0) {
return (await once)[0].infos;
let resMode2;
if (modeListener) {
const ret = (await once)?.[0];
if (ret) {
resMode2 = ret;
}
}
return result.result.infos;
this.context.session.getGroupService().destroyMemberListScene(sceneId);
return {
infos: resMode2?.infos || result.result.infos,
finish: result.result.finish,
hasNext: resMode2?.hasNext,
};
}
async getGroupMembersV2(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
let res = await this.tryGetGroupMembersV2(true, groupQQ);
if (res.hasNext || !res.finish || res.infos.size === 0) {
res = await this.tryGetGroupMembersV2(false, groupQQ, num);
}
if ((res.infos.size === 0 || res.infos.size === 30) && res.finish) {
res = await this.tryGetGroupMembersV2(true, groupQQ, num);
}
return res.infos;
}
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
@@ -425,7 +449,7 @@ export class NTQQGroupApi {
}
async getGroupRemainAtTimes(GroupCode: string) {
this.context.session.getGroupService().getGroupRemainAtTimes(GroupCode);
return this.context.session.getGroupService().getGroupRemainAtTimes(GroupCode);
}
async getMemberExtInfo(groupCode: string, uin: string) {

View File

@@ -3,7 +3,7 @@ import { ChatType, InstanceContext, NapCatCore } from '..';
import offset from '@/core/external/offset.json';
import { PacketClient, RecvPacketData } from '@/core/packet/client';
import { PacketSession } from "@/core/packet/session";
import {OidbPacket, PacketHexStr} from "@/core/packet/packer";
import { OidbPacket, PacketHexStr } from "@/core/packet/packer";
import { NapProtoMsg } from '@/core/packet/proto/NapProto';
import { OidbSvcTrpcTcp0X9067_202_Rsp_Body } from '@/core/packet/proto/oidb/Oidb.0x9067_202';
import { OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp } from '@/core/packet/proto/oidb/OidbBase';
@@ -62,7 +62,10 @@ export class NTQQPacketApi {
this.qqVersion = qqversion;
const offsetTable: OffsetType = offset;
const table = offsetTable[qqversion + '-' + os.arch()];
if (!table) return false;
if (!table) {
this.logger.logError('PacketServer Offset table not found for QQVersion: ', qqversion + '-' + os.arch());
return false;
}
const url = 'ws://' + this.serverUrl + '/ws';
this.packetSession = new PacketSession(this.core.context.logger, new PacketClient(url, this.core));
const cb = () => {
@@ -103,7 +106,7 @@ export class NTQQPacketApi {
let status = 0;
try {
const packet = this.packetSession?.packer.packStatusPacket(uin);
const ret = await this.sendOidbPacket( packet!, true);
const ret = await this.sendOidbPacket(packet!, true);
const data = Buffer.from(ret.hex_data, 'hex');
const ext = new NapProtoMsg(OidbSvcTrpcTcp0XFE1_2RSP).decode(new NapProtoMsg(OidbSvcTrpcTcpBase).decode(data).body).data.status.value;
// ext & 0xff00 + ext >> 16 & 0xff
@@ -146,7 +149,7 @@ export class NTQQPacketApi {
peerUid: groupUin ? String(groupUin) : this.core.selfInfo.uid
}, e));
}
if (e instanceof PacketMsgFileElement){
if (e instanceof PacketMsgFileElement) {
reqList.push(this.packetSession?.highwaySession.uploadFile({
chatType: groupUin ? ChatType.KCHATTYPEGROUP : ChatType.KCHATTYPEC2C,
peerUid: groupUin ? String(groupUin) : this.core.selfInfo.uid

View File

@@ -34,5 +34,9 @@
"3.2.12-28971-arm64": {
"send": "6E91318",
"recv": "6E94B50"
},
"6.9.56-28418-arm64": {
"send": "4471360",
"recv": "4473BCC"
}
}

View File

@@ -71,7 +71,8 @@ export class NodeIKernelGroupListener {
sceneId: string,
ids: string[],
infos: Map<string, GroupMember>, // uid -> GroupMember
finish: boolean,
hasPrev: boolean,
hasNext: boolean,
hasRobot: boolean
}) {
}

View File

@@ -167,7 +167,7 @@ export class PacketHighwaySession {
});
await this.packetHighwayClient.upload(
1004,
fs.createReadStream(img.path, {highWaterMark: BlockSize}),
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
img.size,
md5,
extend
@@ -207,7 +207,7 @@ export class PacketHighwaySession {
});
await this.packetHighwayClient.upload(
1003,
fs.createReadStream(img.path, {highWaterMark: BlockSize}),
fs.createReadStream(img.path, { highWaterMark: BlockSize }),
img.size,
md5,
extend
@@ -244,10 +244,10 @@ export class PacketHighwaySession {
hash: {
fileSha1: await calculateSha1StreamBytes(video.filePath!)
}
})
});
await this.packetHighwayClient.upload(
1005,
fs.createReadStream(video.filePath!, {highWaterMark: BlockSize}),
fs.createReadStream(video.filePath!, { highWaterMark: BlockSize }),
+video.fileSize!,
md5,
extend
@@ -275,7 +275,7 @@ export class PacketHighwaySession {
});
await this.packetHighwayClient.upload(
1006,
fs.createReadStream(video.thumbPath!, {highWaterMark: BlockSize}),
fs.createReadStream(video.thumbPath!, { highWaterMark: BlockSize }),
+video.thumbSize!,
md5,
extend
@@ -312,10 +312,10 @@ export class PacketHighwaySession {
hash: {
fileSha1: await calculateSha1StreamBytes(video.filePath!)
}
})
});
await this.packetHighwayClient.upload(
1001,
fs.createReadStream(video.filePath!, {highWaterMark: BlockSize}),
fs.createReadStream(video.filePath!, { highWaterMark: BlockSize }),
+video.fileSize!,
md5,
extend
@@ -343,7 +343,7 @@ export class PacketHighwaySession {
});
await this.packetHighwayClient.upload(
1002,
fs.createReadStream(video.thumbPath!, {highWaterMark: BlockSize}),
fs.createReadStream(video.thumbPath!, { highWaterMark: BlockSize }),
+video.thumbSize!,
md5,
extend
@@ -379,10 +379,10 @@ export class PacketHighwaySession {
hash: {
fileSha1: [sha1]
}
})
});
await this.packetHighwayClient.upload(
1008,
fs.createReadStream(ptt.filePath, {highWaterMark: BlockSize}),
fs.createReadStream(ptt.filePath, { highWaterMark: BlockSize }),
ptt.fileSize,
md5,
extend
@@ -418,10 +418,10 @@ export class PacketHighwaySession {
hash: {
fileSha1: [sha1]
}
})
});
await this.packetHighwayClient.upload(
1007,
fs.createReadStream(ptt.filePath, {highWaterMark: BlockSize}),
fs.createReadStream(ptt.filePath, { highWaterMark: BlockSize }),
ptt.fileSize,
md5,
extend
@@ -484,10 +484,10 @@ export class PacketHighwaySession {
}
},
unknown200: 0,
})
});
await this.packetHighwayClient.upload(
71,
fs.createReadStream(file.filePath, {highWaterMark: BlockSize}),
fs.createReadStream(file.filePath, { highWaterMark: BlockSize }),
file.fileSize,
file.fileMd5,
ext
@@ -549,10 +549,10 @@ export class PacketHighwaySession {
},
unknown200: 1,
unknown3: 0
})
});
await this.packetHighwayClient.upload(
95,
fs.createReadStream(file.filePath, {highWaterMark: BlockSize}),
fs.createReadStream(file.filePath, { highWaterMark: BlockSize }),
file.fileSize,
file.fileMd5,
ext

View File

@@ -30,7 +30,7 @@ abstract class HighwayUploader {
reject(new Error(`[Highway] timeout after ${this.trans.timeout}s`));
}, (this.trans.timeout ?? Infinity) * 1000
);
})
});
}
buildPicUpHead(offset: number, bodyLength: number, bodyMd5: Uint8Array): Uint8Array {
@@ -100,7 +100,7 @@ export class HighwayTcpUploader extends HighwayUploader {
const upload = new Promise<void>((resolve, reject) => {
const highwayTransForm = new HighwayTcpUploaderTransform(this);
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 rsp = new NapProtoMsg(RespDataHighwayHead).decode(header);
@@ -159,7 +159,7 @@ export class HighwayHttpUploader extends HighwayUploader {
try {
await this.uploadBlock(block, offset);
} catch (err) {
throw new Error(`[Highway] httpUpload Error uploading block at offset ${offset}: ${err}`)
throw new Error(`[Highway] httpUpload Error uploading block at offset ${offset}: ${err}`);
}
offset += block.length;
}

View File

@@ -15,9 +15,9 @@ export class PacketMsgBuilder {
protected static failBackText = new PacketMsgTextElement(
{
textElement: {content: "[该消息类型暂不支持查看]"}!
textElement: { content: "[该消息类型暂不支持查看]" }!
} as SendTextElement
)
);
buildFakeMsg(selfUid: string, element: PacketMsg[]): NapProtoEncodeStructType<typeof PushMsgBody>[] {
return element.map((node): NapProtoEncodeStructType<typeof PushMsgBody> => {
@@ -50,7 +50,7 @@ export class PacketMsgBuilder {
divSeq: node.groupId ? undefined : 4,
msgId: crypto.randomBytes(4).readUInt32LE(0),
sequence: crypto.randomBytes(4).readUInt32LE(0),
timeStamp: Math.floor(Date.now() / 1000),
timeStamp: +node.time.toString().substring(0, 10),
field7: BigInt(1),
field8: 0,
field9: 0,

View File

@@ -89,11 +89,11 @@ export class PacketMsgAtElement extends PacketMsgTextElement {
text: {
str: this.text,
pbReserve: new NapProtoMsg(MentionExtra).encode({
type: this.atAll ? 1 : 2,
uin: 0,
field5: 0,
uid: this.targetUid,
}
type: this.atAll ? 1 : 2,
uin: 0,
field5: 0,
uid: this.targetUid,
}
)
}
}];
@@ -308,7 +308,7 @@ export class PacketMsgVideoElement extends IPacketMsgElement<SendVideoElement> {
this.filePath = element.videoElement.filePath;
this.thumbSize = element.videoElement.thumbSize;
this.thumbPath = element.videoElement.thumbPath?.get(0);
this.fileMd5 = element.videoElement.videoMd5
this.fileMd5 = element.videoElement.videoMd5;
this.thumbMd5 = element.videoElement.thumbMd5;
this.thumbWidth = element.videoElement.thumbWidth;
this.thumbHeight = element.videoElement.thumbHeight;
@@ -355,7 +355,7 @@ export class PacketMsgPttElement extends IPacketMsgElement<SendPttElement> {
}
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
return []
return [];
// if (!this.msgInfo) return [];
// return [{
// commonElem: {
@@ -382,7 +382,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
isGroupFile?: boolean;
_private_send_uid?: string;
_private_recv_uid?: string;
_e37_800_rsp?: NapProtoEncodeStructType<typeof OidbSvcTrpcTcp0XE37_800Response>
_e37_800_rsp?: NapProtoEncodeStructType<typeof OidbSvcTrpcTcp0XE37_800Response>;
constructor(element: SendFileElement) {
super(element);
@@ -423,7 +423,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
destUid: this._private_recv_uid,
}
}
})
});
}
buildElement(): NapProtoEncodeStructType<typeof Elem>[] {
@@ -443,7 +443,7 @@ export class PacketMsgFileElement extends IPacketMsgElement<SendFileElement> {
fileMd5: this.fileMd5,
}
}
})
});
lb.writeUInt16BE(transElemVal.length);
return [{
transElem: {

View File

@@ -61,7 +61,7 @@ export class PacketPacker {
return {
cmd: `OidbSvcTrpcTcp.0x${cmd.toString(16).toUpperCase()}_${subCmd}`,
data: this.packetPacket(data)
}
};
}
packPokePacket(peer: number, group?: number): OidbPacket {
@@ -114,7 +114,7 @@ export class PacketPacker {
packStatusPacket(uin: number): OidbPacket {
const oidb_0xfe1_2 = new NapProtoMsg(OidbSvcTrpcTcp0XFE1_2).encode({
uin: uin,
key: [{key: 27372}]
key: [{ key: 27372 }]
});
return this.packOidbPacket(0xfe1, 2, oidb_0xfe1_2);
}
@@ -240,68 +240,68 @@ export class PacketPacker {
async packUploadC2CImgReq(peerUin: string, img: PacketMsgPicElement): Promise<OidbPacket> {
const req = new NapProtoMsg(NTV2RichMediaReq).encode({
reqHead: {
common: {
requestId: 1,
command: 100
reqHead: {
common: {
requestId: 1,
command: 100
},
scene: {
requestType: 2,
businessType: 1,
sceneType: 1,
c2C: {
accountType: 2,
targetUid: peerUin
},
scene: {
requestType: 2,
businessType: 1,
sceneType: 1,
c2C: {
accountType: 2,
targetUid: peerUin
},
client: {
agentType: 2,
}
},
upload: {
uploadInfo: [
{
fileInfo: {
fileSize: +img.size,
fileHash: img.md5,
fileSha1: img.sha1!,
fileName: img.name,
type: {
type: 1,
picFormat: img.picType, //TODO: extend NapCat imgType /cc @MliKiowa
videoFormat: 0,
voiceFormat: 0,
},
width: img.width,
height: img.height,
time: 0,
original: 1
},
subFileType: 0,
}
],
tryFastUploadCompleted: true,
srvSendMsg: false,
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
compatQMsgSceneType: 1,
extBizInfo: {
pic: {
bytesPbReserveTroop: Buffer.from("0800180020004200500062009201009a0100a2010c080012001800200028003a00", 'hex'),
textSummary: "Nya~", // TODO:
},
client: {
agentType: 2,
video: {
bytesPbReserve: Buffer.alloc(0),
},
ptt: {
bytesPbReserve: Buffer.alloc(0),
bytesReserve: Buffer.alloc(0),
bytesGeneralFlags: Buffer.alloc(0),
}
},
upload: {
uploadInfo: [
{
fileInfo: {
fileSize: +img.size,
fileHash: img.md5,
fileSha1: img.sha1!,
fileName: img.name,
type: {
type: 1,
picFormat: img.picType, //TODO: extend NapCat imgType /cc @MliKiowa
videoFormat: 0,
voiceFormat: 0,
},
width: img.width,
height: img.height,
time: 0,
original: 1
},
subFileType: 0,
}
],
tryFastUploadCompleted: true,
srvSendMsg: false,
clientRandomId: crypto.randomBytes(8).readBigUInt64BE() & BigInt('0x7FFFFFFFFFFFFFFF'),
compatQMsgSceneType: 1,
extBizInfo: {
pic: {
bytesPbReserveTroop: Buffer.from("0800180020004200500062009201009a0100a2010c080012001800200028003a00", 'hex'),
textSummary: "Nya~", // TODO:
},
video: {
bytesPbReserve: Buffer.alloc(0),
},
ptt: {
bytesPbReserve: Buffer.alloc(0),
bytesReserve: Buffer.alloc(0),
bytesGeneralFlags: Buffer.alloc(0),
}
},
clientSeq: 0,
noNeedCompatMsg: false,
}
clientSeq: 0,
noNeedCompatMsg: false,
}
}
);
return this.packOidbPacket(0x11c5, 100, req, true, false);
}
@@ -538,7 +538,7 @@ export class PacketPacker {
clientSeq: 0,
noNeedCompatMsg: false
}
})
});
return this.packOidbPacket(0x126E, 100, req, true, false);
}
@@ -600,7 +600,7 @@ export class PacketPacker {
clientSeq: 0,
noNeedCompatMsg: false
}
})
});
return this.packOidbPacket(0x126D, 100, req, true, false);
}
@@ -642,7 +642,7 @@ export class PacketPacker {
businessId: 3,
clientType: 1,
flagSupportMediaPlatform: 1
})
});
return this.packOidbPacket(0xE37, 1700, body, false, false);
}
@@ -664,13 +664,13 @@ export class PacketPacker {
packGroupFileDownloadReq(groupUin: number, fileUUID: string): OidbPacket {
return this.packOidbPacket(0x6D6, 2, new NapProtoMsg(OidbSvcTrpcTcp0x6D6).encode({
download: {
groupUin: groupUin,
appId: 7,
busId: 102,
fileId: fileUUID
}
}), true, false
download: {
groupUin: groupUin,
appId: 7,
busId: 102,
fileId: fileUUID
}
}), true, false
);
}

View File

@@ -118,7 +118,7 @@ export const FileExtra = {
export const PrivateFileExtra = {
field2: ProtoField(2, () => PrivateFileExtraField2),
}
};
export const PrivateFileExtraField2 = {
field1: ProtoField(1, ScalarType.UINT32),
@@ -131,7 +131,7 @@ export const PrivateFileExtraField2 = {
fileHash: ProtoField(14, ScalarType.STRING),
selfUid: ProtoField(15, ScalarType.STRING),
destUid: ProtoField(16, ScalarType.STRING),
}
};
export const GroupFileExtra = {
field1: ProtoField(1, ScalarType.UINT32),

View File

@@ -1,6 +1,6 @@
import { ScalarType } from "@protobuf-ts/runtime";
import { ProtoField } from "../NapProto";
import {OidbSvcTrpcTcp0XE37_800_1200Metadata} from "@/core/packet/proto/oidb/Oidb.0xE37_1200";
import { OidbSvcTrpcTcp0XE37_800_1200Metadata } from "@/core/packet/proto/oidb/Oidb.0xE37_1200";
export const OidbSvcTrpcTcp0XE37_800 = {
subCommand: ProtoField(1, ScalarType.UINT32),
@@ -59,4 +59,4 @@ export const OidbSvcTrpcTcp0XE37_800Response = {
export const OidbSvcTrpcTcp0XE37_800ResponseBody = {
field10: ProtoField(10, ScalarType.UINT32, true),
field30: ProtoField(30, () => OidbSvcTrpcTcp0XE37_800_1200Metadata, true),
}
};

View File

@@ -8,7 +8,7 @@ export const OidbSvcTrpcTcp0XE37_1700 = {
businessId: ProtoField(101, ScalarType.INT32, true),
clientType: ProtoField(102, ScalarType.INT32, true),
flagSupportMediaPlatform: ProtoField(200, ScalarType.INT32, true),
}
};
export const ApplyUploadReqV3 = {
senderUid: ProtoField(10, ScalarType.STRING, true),
@@ -20,4 +20,4 @@ export const ApplyUploadReqV3 = {
localPath: ProtoField(70, ScalarType.STRING, true),
md5CheckSum: ProtoField(110, ScalarType.BYTES, true),
sha3CheckSum: ProtoField(120, ScalarType.BYTES, true),
}
};

View File

@@ -9,4 +9,4 @@ export const OidbSvcTrpcTcp0XEB7_Body = {
export const OidbSvcTrpcTcp0XEB7 = {
body: ProtoField(2, () => OidbSvcTrpcTcp0XEB7_Body),
}
};

View File

@@ -2,7 +2,7 @@
import * as crypto from 'crypto';
import * as stream from 'stream';
import * as fs from 'fs';
import {CalculateStreamBytesTransform} from "@/core/packet/utils/crypto/sha1StreamBytesTransform";
import { CalculateStreamBytesTransform } from "@/core/packet/utils/crypto/sha1StreamBytesTransform";
function sha1Stream(readable: stream.Readable) {
return new Promise((resolve, reject) => {

View File

@@ -73,7 +73,7 @@ export class Sha1Stream {
this._count[1] = (this._count[1] + (dataLen >>> 29)) >>> 0;
let partLen = (this.Sha1BlockSize - index) >>> 0;
const partLen = (this.Sha1BlockSize - index) >>> 0;
let i = 0;
if (dataLen >= partLen) {
@@ -100,11 +100,11 @@ export class Sha1Stream {
public final(): Buffer {
const digest = Buffer.allocUnsafe(this.Sha1DigestSize);
const bits = Buffer.allocUnsafe(8)
const bits = Buffer.allocUnsafe(8);
bits.writeUInt32BE(this._count[1], 0);
bits.writeUInt32BE(this._count[0], 4);
let index = ((this._count[0] >>> 3) & 0x3F) >>> 0;
const index = ((this._count[0] >>> 3) & 0x3F) >>> 0;
const padLen = ((index < 56) ? (56 - index) : (120 - index)) >>> 0;
this.update(this._padding, padLen);
this.update(bits);

View File

@@ -1,5 +1,5 @@
import * as stream from "node:stream";
import {Sha1Stream} from "@/core/packet/utils/crypto/sha1Stream";
import { Sha1Stream } from "@/core/packet/utils/crypto/sha1Stream";
export class CalculateStreamBytesTransform extends stream.Transform {
private readonly blockSize = 1024 * 1024;

View File

@@ -66,7 +66,11 @@ export interface NodeIKernelBuddyService {
accept: boolean;
}): Promise<void>;
delBuddy(uid: number): void;
delBuddy(param: {
friendUid: string;
tempBlock: boolean;
tempBothDel: boolean;
}): Promise<unknown>;
delBatchBuddy(uids: number[]): void;

View File

@@ -12,6 +12,13 @@ import {
import { GeneralCallResult } from '@/core/services/common';
export interface NodeIKernelGroupService {
// --->
// 待启用 For Next Version 3.2.0
// isTroopMember ? 0 : 111
getGroupMemberMaxNum(groupCode: string, serviceType: number): Promise<unknown>;
getAllGroupPrivilegeFlag(troopUinList: string[], serviceType: number): Promise<unknown>;
// <---
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>;
@@ -114,8 +121,8 @@ export interface NodeIKernelGroupService {
destroyMemberListScene(SceneId: string): void;
getNextMemberList(sceneId: string, a: undefined, num: number): Promise<{
errCode: number,
getNextMemberList(sceneId: string, groupMemberInfoListId: { index: number, uid: string } | undefined, num: number): Promise<{
errCode: number,
errMsg: string,
result: { ids: string[], infos: Map<string, GroupMember>, finish: boolean, hasRobot: boolean }
}>;
@@ -225,7 +232,15 @@ export interface NodeIKernelGroupService {
getGroupStatisticInfo(groupCode: string): unknown;
getGroupRemainAtTimes(groupCode: string): number;
getGroupRemainAtTimes(groupCode: string): Promise<GeneralCallResult & {
atInfo: {
canAtAll: boolean
RemainAtAllCountForUin: number
RemainAtAllCountForGroup: number
atTimesMsg: string
canNotAtAllMsg: ''
}
}>;
getJoinGroupNoVerifyFlag(groupCode: string): unknown;

View File

@@ -327,8 +327,7 @@ export interface NodeIKernelMsgService {
setPttPlayedState(...args: unknown[]): unknown;
//uk1 uk2 true
fetchFavEmojiList(str: string, num: number, uk1: boolean, uk2: boolean): Promise<GeneralCallResult & {
fetchFavEmojiList(str: string, num: number, backward: boolean, forceRefresh: boolean): Promise<GeneralCallResult & {
emojiInfoList: Array<{
uin: string,
emoId: number,

View File

@@ -86,7 +86,7 @@ export interface NodeQQNTWrapperUtil {
calcThumbSize(arg0: number, arg1: number, arg2: unknown): unknown;
fullWordToHalfWord(arg0: string): unknown;
fullWordToHalfWord(word: string): unknown;
getNTUserDataInfoConfig(): unknown;

View File

@@ -0,0 +1,30 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['number', 'string'] }
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPGetGroupAtAllRemain extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetGroupAtAllRemain;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
let ret = await this.core.apis.GroupApi.getGroupRemainAtTimes(payload.group_id.toString());
if (!ret.atInfo || ret.result !== 0) {
throw new Error('atInfo not found');
}
let data = {
can_at_all: ret.atInfo.canAtAll,
remain_at_all_count_for_group: ret.atInfo.RemainAtAllCountForGroup,
remain_at_all_count_for_uin: ret.atInfo.RemainAtAllCountForUin
};
return data;
}
}

View File

@@ -0,0 +1,21 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {
url: { type: 'string' },
},
required: ['url'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPCheckUrlSafely extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CheckUrlSafely;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return { level: 1 };
}
}

View File

@@ -0,0 +1,38 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {
friend_id: { type: ['string', 'number'] },
temp_block: { type: 'boolean' },
temp_both_del: { type: 'boolean' },
},
required: ['friend_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPDeleteFriend extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteFriend;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
let uid = await this.core.apis.UserApi.getUidByUinV2(payload.friend_id.toString());
if (!uid) {
return {
valid: false,
message: '好友不存在',
};
}
let isBuddy = await this.core.apis.FriendApi.isBuddy(uid);
if (!isBuddy) {
return {
valid: false,
message: '不是好友',
};
}
return await this.core.apis.FriendApi.delBuudy(uid, payload.temp_block, payload.temp_both_del);
}
}

View File

@@ -0,0 +1,28 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {
model: { type: 'string' },
}
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPGetModelShow extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetModelShow;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
if (!payload.model) {
payload.model = 'napcat';
}
return [{
variants: {
model_show: "napcat",
need_pay: false
}
}];
}
}

View File

@@ -0,0 +1,19 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
//兼容性代码
export class GoCQHTTPSetModelShow extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_SetModelShow;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return null;
}
}

View File

@@ -1,10 +0,0 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
export default class SetModelShow extends BaseAction<null, null> {
actionName = ActionName.SetModelShow;
async _handle(payload: null): Promise<null> {
return null;
}
}

View File

@@ -21,7 +21,14 @@ export class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
async _handle(payload: Payload) {
const groupIdStr = payload.group_id.toString();
const groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(groupIdStr);
const noCache = payload.no_cache ? this.stringToBoolean(payload.no_cache) : false;
const memberCache = this.core.apis.GroupApi.groupMemberCache;
let groupMembers;
if (noCache) {
groupMembers = await this.core.apis.GroupApi.getGroupMembersV2(groupIdStr);
} else {
groupMembers = memberCache.get(groupIdStr) ?? await this.core.apis.GroupApi.getGroupMembersV2(groupIdStr);
}
const memberPromises = Array.from(groupMembers.values()).map(item =>
OB11Entities.groupMember(groupIdStr, item)
@@ -30,4 +37,7 @@ export class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
const MemberMap = new Map(_groupMembers.map(member => [member.user_id, member]));
return Array.from(MemberMap.values());
}
}
stringToBoolean(str: string | boolean): boolean {
return typeof str === 'boolean' ? str : str.toLowerCase() === "true";
}
}

View File

@@ -71,7 +71,6 @@ import { FetchUserProfileLike } from './extends/FetchUserProfileLike';
import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '@/onebot';
import GetGuildProfile from './guild/GetGuildProfile';
import SetModelShow from './go-cqhttp/SetModelShow';
import { SetInputStatus } from './extends/SetInputStatus';
import { GetCSRF } from './system/GetCSRF';
import { DelGroupNotice } from './group/DelGroupNotice';
@@ -94,6 +93,11 @@ import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus";
import { FriendPoke } from "@/onebot/action/user/FriendPoke";
import { GetCredentials } from './system/GetCredentials';
import { SetGroupSign } from './extends/SetGroupSign';
import { GoCQHTTPGetGroupAtAllRemain } from './go-cqhttp/GetGroupAtAllRemain';
import { GoCQHTTPCheckUrlSafely } from './go-cqhttp/GoCQHTTPCheckUrlSafely';
import { GoCQHTTPGetModelShow } from './go-cqhttp/GoCQHTTPGetModelShow';
import { GoCQHTTPSetModelShow } from './go-cqhttp/GoCQHTTPSetModelShow';
import { GoCQHTTPDeleteFriend } from './go-cqhttp/GoCQHTTPDeleteFriend';
export type ActionMap = Map<string, BaseAction<any, any>>;
@@ -151,6 +155,8 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new GetRobotUinRange(obContext, core),
new GetFriendWithCategory(obContext, core),
//以下为go-cqhttp api
new GoCQHTTPDeleteFriend(obContext, core),
new GoCQHTTPCheckUrlSafely(obContext, core),
new GetOnlineClient(obContext, core),
new OCRImage(obContext, core),
new IOCRImage(obContext, core),
@@ -158,6 +164,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SendGroupNotice(obContext, core),
new GetGroupNotice(obContext, core),
new GetGroupEssence(obContext, core),
new GoCQHTTPGetGroupAtAllRemain(obContext, core),
new GoCQHTTPSendForwardMsg(obContext, core),
new GoCQHTTPSendGroupForwardMsg(obContext, core),
new GoCQHTTPSendPrivateForwardMsg(obContext, core),
@@ -180,7 +187,9 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new FetchCustomFace(obContext, core),
new GoCQHTTPUploadPrivateFile(obContext, core),
new GetGuildProfile(obContext, core),
new SetModelShow(obContext, core),
new GoCQHTTPGetModelShow(obContext, core),
new GoCQHTTPSetModelShow(obContext, core),
new GoCQHTTPCheckUrlSafely(obContext, core),
new SetInputStatus(obContext, core),
new GetCSRF(obContext, core),
new GetCredentials(obContext, core),

View File

@@ -116,9 +116,17 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
const packetMode = this.core.apis.PacketApi.available;
const returnMsgAndResId = packetMode
? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[], payload.source, payload.news, payload.summary, payload.prompt)
: await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
let returnMsgAndResId: { message: RawMessage | null, res_id?: string } | null;
try {
returnMsgAndResId = packetMode
? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[], payload.source, payload.news, payload.summary, payload.prompt)
: await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
} catch (e) {
throw Error(packetMode ? `发送伪造合并转发消息失败: ${e}` : `发送合并转发消息失败: ${e}`);
}
if (!returnMsgAndResId) {
throw Error('发送合并转发消息失败returnMsgAndResId 为空!');
}
if (returnMsgAndResId.message) {
const msgShortId = MessageUnique.createUniqueMsgId({
guildId: '',
@@ -129,7 +137,6 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} else if (returnMsgAndResId.res_id && !returnMsgAndResId.message) {
throw Error(`发送转发消息res_id${returnMsgAndResId.res_id} 失败`);
}
throw Error('发送转发消息失败');
} else {
// if (getSpecialMsgNum(payload, OB11MessageDataType.music)) {
// const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic;
@@ -145,22 +152,42 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
return { message_id: returnMsg!.id! };
}
// TODO: recursively handle forwarded nodes
private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: { text: string }[], summary?: string, prompt?: string): Promise<{
message: RawMessage | null,
private async uploadForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: {
text: string
}[], summary?: string, prompt?: string, parentMeta?: {
user_id: string,
nickname: string,
}, dp: number = 0): Promise<{
finallySendElements: SendArkElement,
res_id?: string
}> {
} | null> {
const logger = this.core.context.logger;
const packetMsg: PacketMsg[] = [];
for (const node of messageNodes) {
if (dp >= 3) {
logger.logWarn('转发消息深度超过3层将停止解析');
break;
}
if ((node.data.id && typeof node.data.content !== "string") || !node.data.id) {
const OB11Data = normalize(node.data.content);
const { sendElements } = await this.obContext.apis.MsgApi.createSendElements(OB11Data, msgPeer);
const OB11Data = normalize(node.type === OB11MessageDataType.node ? node.data.content : node);
let sendElements: SendMessageElement[];
if (getSpecialMsgNum({message: OB11Data}, OB11MessageDataType.node)) {
const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, OB11Data as OB11MessageNode[], node.data.source, node.data.news, node.data.summary, node.data.prompt, {
user_id: node.data.user_id?.toString() ?? parentMeta?.user_id ?? this.core.selfInfo.uin,
nickname: node.data.nickname ?? parentMeta?.nickname ?? "QQ用户",
}, dp + 1);
sendElements = uploadReturnData?.finallySendElements ? [uploadReturnData.finallySendElements] : [];
} else {
const sendElementsCreateReturn = await this.obContext.apis.MsgApi.createSendElements(OB11Data, msgPeer);
sendElements = sendElementsCreateReturn.sendElements;
}
const packetMsgElements: rawMsgWithSendMsg = {
senderUin: Number(node.data.user_id) ?? +this.core.selfInfo.uin,
senderName: node.data.nickname,
senderUin: Number(node.data.user_id ?? parentMeta?.user_id) || +this.core.selfInfo.uin,
senderName: node.data.nickname ?? parentMeta?.nickname ?? "QQ用户",
groupId: msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : undefined,
time: Date.now(),
time: Number(node.data.time) || Date.now(),
msg: sendElements,
};
logger.logDebug(`handleForwardedNodesPacket 开始转换 ${JSON.stringify(packetMsgElements)}`);
@@ -171,22 +198,37 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
logger.logDebug(`handleForwardedNodesPacket 跳过元素 ${JSON.stringify(node)}`);
}
}
if (packetMsg.length === 0) {
logger.logWarn('handleForwardedNodesPacket 元素为空!');
return null;
}
const resid = await this.core.apis.PacketApi.sendUploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);
const forwardJson = ForwardMsgBuilder.fromPacketMsg(resid, packetMsg, source, news, summary, prompt);
const finallySendElements = {
elementType: ElementType.ARK,
elementId: "",
arkElement: {
bytesData: JSON.stringify(forwardJson),
},
} as SendArkElement;
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 {
finallySendElements: {
elementType: ElementType.ARK,
elementId: "",
arkElement: {
bytesData: JSON.stringify(forwardJson),
},
} as SendArkElement,
res_id: resid,
};
}
private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[], source?: string, news?: {
text: string
}[], summary?: string, prompt?: string): Promise<{
message: RawMessage | null,
res_id?: string
}> {
let returnMsg: RawMessage | undefined, res_id: string | undefined;
const uploadReturnData = await this.uploadForwardedNodesPacket(msgPeer, messageNodes, source, news, summary, prompt);
res_id = uploadReturnData?.res_id;
const finallySendElements = uploadReturnData?.finallySendElements;
if (!finallySendElements) throw Error('转发消息失败,生成节点为空');
returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined);
return {message: returnMsg ?? null, res_id};
}
private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{

View File

@@ -5,16 +5,14 @@ import { ActionName, BaseCheckResult } from '../types';
export abstract class GetPacketStatusDepends<PT, RT> extends BaseAction<PT, RT> {
actionName = ActionName.GetPacketStatus;
protected async check(): Promise<BaseCheckResult>{
protected async check(payload: PT): Promise<BaseCheckResult>{
if (!this.core.apis.PacketApi.available) {
return {
valid: false,
message: "packetServer不可用请参照文档 https://napneko.github.io/config/advanced 检查packetServer状态或进行配置",
};
}
return {
valid: true,
};
return await super.check(payload);
}
}

View File

@@ -57,11 +57,11 @@ export enum ActionName {
// go-cqhttp
SetQQProfile = 'set_qq_profile',
// QidianGetAccountInfo = 'qidian_get_account_info',
// GetModelShow = '_get_model_show',
// SetModelShow = '_set_model_show',
GoCQHTTP_GetModelShow = '_get_model_show',
GoCQHTTP_SetModelShow = '_set_model_show',
GetOnlineClient = 'get_online_clients',
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
// DeleteFriend = 'delete_friend',
GoCQHTTP_DeleteFriend = 'delete_friend',
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
GoCQHTTP_MarkMsgAsRead = 'mark_msg_as_read',
GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg',
@@ -71,7 +71,7 @@ export enum ActionName {
IOCRImage = '.ocr_image',
GetGroupSystemMsg = 'get_group_system_msg',
GoCQHTTP_GetEssenceMsg = 'get_essence_msg_list',
// GetGroupAtAllRemain = 'get_group_at_all_remain',
GoCQHTTP_GetGroupAtAllRemain = 'get_group_at_all_remain',
SetGroupPortrait = 'set_group_portrait',
SetEssenceMsg = 'set_essence_msg',
DelEssenceMsg = 'delete_essence_msg',
@@ -88,8 +88,8 @@ export enum ActionName {
GOCQHTTP_UploadPrivateFile = 'upload_private_file',
// GOCQHTTP_ReloadEventFilter = 'reload_event_filter',
GoCQHTTP_DownloadFile = 'download_file',
// GoCQHTTP_CheckUrlSafely = 'check_url_safely',
// GoCQHTTP_GetWordSlices = '.get_word_slices',
GoCQHTTP_CheckUrlSafely = 'check_url_safely',
GoCQHTTP_GetWordSlices = '.get_word_slices',
GoCQHTTP_HandleQuickAction = '.handle_quick_operation',
// 以下为扩展napcat扩展

View File

@@ -152,6 +152,11 @@ export interface OB11MessageNode {
user_id?: number | string // number
nickname: string
content: OB11MessageMixType
source?: string,
news?: { text: string }[],
summary?: string,
prompt?: string
time?: string
};
}
@@ -225,6 +230,7 @@ export interface OB11PostSendMsg {
news?: { text: string }[],
summary?: string,
prompt?: string
time?: string
}
export interface OB11PostContext {
message_type?: 'private' | 'group'

View File

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

View File

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