feat: Implement complete transform & Build & Upload FakeForwardMsg

This commit is contained in:
pk5ls20
2024-10-19 22:13:31 +08:00
parent 9c17dc1b8f
commit c9e3bbcd9f
11 changed files with 290 additions and 146 deletions

View File

@@ -1,69 +0,0 @@
import BaseAction from '../BaseAction';
import {ActionName} from '../types';
import {FromSchema, JSONSchema} from 'json-schema-to-ts';
import {ChatType, SendTextElement} from "@/core";
import {PacketMsgPicElement, PacketMsgTextElement} from "@/core/packet/msg/element";
const SchemaData = {
type: 'object',
properties: {
group_id: {type: ['number', 'string']},
pic: {type: 'string'},
},
required: ['group_id', 'pic'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class UploadForwardMsg extends BaseAction<Payload, any> {
actionName = ActionName.UploadForwardMsg;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
if (!this.core.apis.PacketApi.available) {
throw new Error('PacketClient is not init');
}
// throw new Error('Not implemented');
const peer = {
chatType: ChatType.KCHATTYPEGROUP,
peerUid: "10001", // TODO: must be a valid group id
}
const img = await this.core.apis.FileApi.createValidSendPicElement(
{
deleteAfterSentFiles: [],
peer: peer
},
"", // TODO:
"www",
0,
)
const sendImg = new PacketMsgPicElement(img);
console.log(JSON.stringify(img));
await this.core.apis.PacketApi.packetSession?.highwaySession.uploadImage(
peer, sendImg
)
return await this.core.apis.PacketApi.sendUploadForwardMsg([
{
groupId: 10001,
senderId: 10001,
senderName: "qwq",
time: Math.floor(Date.now() / 1000),
msg: [new PacketMsgTextElement({
textElement: {
content: "Love from Napcat.Packet~"
}
} as SendTextElement)]
},
{
groupId: 10001,
senderId: 10001,
senderName: "qwq",
time: Math.floor(Date.now() / 1000),
msg: [new PacketMsgTextElement({
textElement: {
content: "Nya~"
}
} as SendTextElement), sendImg]
}], 10001); // TODO: must be a valid group id
}
}

View File

@@ -87,7 +87,6 @@ import { GroupPoke } from './group/GroupPoke';
import { GetUserStatus } from './extends/GetUserStatus';
import { GetRkey } from './extends/GetRkey';
import { SetSpecialTittle } from './extends/SetSpecialTittle';
import { UploadForwardMsg } from "@/onebot/action/extends/UploadForwardMsg";
import { GetGroupShutList } from './group/GetGroupShutList';
import { GetGroupMemberList } from './group/GetGroupMemberList';
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
@@ -193,7 +192,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new GetUserStatus(obContext, core),
new GetRkey(obContext, core),
new SetSpecialTittle(obContext, core),
new UploadForwardMsg(obContext, core),
// new UploadForwardMsg(obContext, core),
new GetGroupShutList(obContext, core),
new GetGroupFileUrl(obContext, core),
];

View File

@@ -6,14 +6,18 @@ import {
OB11PostContext,
OB11PostSendMsg,
} from '@/onebot/types';
import { ActionName, BaseCheckResult } from '@/onebot/action/types';
import { decodeCQCode } from '@/onebot/cqcode';
import { MessageUnique } from '@/common/message-unique';
import { ChatType, ElementType, NapCatCore, Peer, RawMessage, SendMessageElement } from '@/core';
import {ActionName, BaseCheckResult} from '@/onebot/action/types';
import {decodeCQCode} from '@/onebot/cqcode';
import {MessageUnique} from '@/common/message-unique';
import {ChatType, ElementType, NapCatCore, Peer, RawMessage, SendArkElement, SendMessageElement} from '@/core';
import BaseAction from '../BaseAction';
import {rawMsgWithSendMsg} from "@/core/packet/msg/converter";
import {PacketMsg} from "@/core/packet/msg/message";
import {PacketMultiMsgElement} from "@/core/packet/msg/element";
export interface ReturnDataType {
message_id: number;
res_id?: string;
}
export enum ContextMode {
@@ -26,7 +30,7 @@ export enum ContextMode {
export function normalize(message: OB11MessageMixType, autoEscape = false): OB11MessageData[] {
return typeof message === 'string' ? (
autoEscape ?
[{ type: OB11MessageDataType.text, data: { text: message } }] :
[{type: OB11MessageDataType.text, data: {text: message}}] :
decodeCQCode(message)
) : Array.isArray(message) ? message : [message];
}
@@ -96,10 +100,10 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素',
};
}
return { valid: true };
return {valid: true};
}
async _handle(payload: OB11PostSendMsg): Promise<{ message_id: number }> {
async _handle(payload: OB11PostSendMsg): Promise<ReturnDataType> {
this.contextMode = ContextMode.Normal;
if (payload.message_type === 'group') this.contextMode = ContextMode.Group;
if (payload.message_type === 'private') this.contextMode = ContextMode.Private;
@@ -111,17 +115,19 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
);
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
const returnMsg = await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
if (returnMsg) {
const packetMode = this.core.apis.PacketApi.available
const returnMsgAndResId = packetMode
? await this.handleForwardedNodesPacket(peer, messages as OB11MessageNode[])
: await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
if (returnMsgAndResId.message) {
const msgShortId = MessageUnique.createUniqueMsgId({
guildId: '',
peerUid: peer.peerUid,
chatType: peer.chatType,
}, returnMsg!.msgId);
return { message_id: msgShortId! };
} else {
throw Error('发送转发消息失败');
}, (returnMsgAndResId.message)!.msgId);
return {message_id: msgShortId!, res_id: returnMsgAndResId.res_id};
}
throw Error('发送转发消息失败');
} else {
// if (getSpecialMsgNum(payload, OB11MessageDataType.music)) {
// const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic;
@@ -131,13 +137,61 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
}
// log("send msg:", peer, sendElements)
const { sendElements, deleteAfterSentFiles } = await this.obContext.apis.MsgApi
const {sendElements, deleteAfterSentFiles} = await this.obContext.apis.MsgApi
.createSendElements(messages, peer);
const returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, sendElements, deleteAfterSentFiles);
return { message_id: returnMsg!.id! };
return {message_id: returnMsg!.id!};
}
private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<RawMessage | null> {
private async handleForwardedNodesPacket(msgPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{
message: RawMessage | null,
res_id?: string
}> {
const logger = this.core.context.logger;
const packetMsg: PacketMsg[] = [];
for (const node of messageNodes) {
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 packetMsgElements: rawMsgWithSendMsg = {
senderUin: node.data.user_id ?? +this.core.selfInfo.uin,
senderName: node.data.nickname,
groupId: msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : undefined,
time: Date.now(),
msg: sendElements,
}
logger.logDebug(`handleForwardedNodesPacket 开始转换 ${JSON.stringify(packetMsgElements)}`);
const transformedMsg = this.core.apis.PacketApi.packetSession?.packer.packetConverter.rawMsgWithSendMsgToPacketMsg(packetMsgElements);
logger.logDebug(`handleForwardedNodesPacket 转换为 ${JSON.stringify(transformedMsg)}`);
packetMsg.push(transformedMsg!);
} else {
logger.logDebug(`handleForwardedNodesPacket 跳过元素 ${JSON.stringify(node)}`);
}
}
const resid = await this.core.apis.PacketApi.sendUploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);
const forwardJson = new PacketMultiMsgElement({
elementType: ElementType.STRUCTLONGMSG,
elementId: "",
structLongMsgElement: {
xmlContent: "",
resId: resid
}
}, packetMsg).JSON;
const finallySendElements = {
elementType: ElementType.ARK,
elementId: "",
arkElement: {
bytesData: JSON.stringify(forwardJson),
},
} as SendArkElement
const returnMsg = await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(msgPeer, [finallySendElements], [], true).catch(_ => undefined)
return {message: returnMsg ?? null, res_id: resid};
}
private async handleForwardedNodes(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<{
message: RawMessage | null,
res_id?: string
}> {
const selfPeer = {
chatType: ChatType.KCHATTYPEC2C,
peerUid: this.core.selfInfo.uid,
@@ -147,7 +201,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
for (const messageNode of messageNodes) {
const nodeId = messageNode.data.id;
if (nodeId) {
//对Mgsid和OB11ID混用情况兜底
// 对Msgid和OB11ID混用情况兜底
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
if (!nodeMsg) {
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', nodeId);
@@ -167,15 +221,15 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
}
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
if (nodeMsg) {
nodeMsgIds.push(nodeMsg.msgId);
MessageUnique.createUniqueMsgId(selfPeer, nodeMsg.msgId);
nodeMsgIds.push(nodeMsg.message!.msgId);
MessageUnique.createUniqueMsgId(selfPeer, nodeMsg.message!.msgId);
}
//完成子卡片生成跳过后续
continue;
}
const { sendElements } = await this.obContext.apis.MsgApi
const {sendElements} = await this.obContext.apis.MsgApi
.createSendElements(OB11Data, destPeer);
//拆分消息
const MixElement = sendElements.filter(
@@ -214,7 +268,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
continue;
}
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
srcPeer = srcPeer ?? {chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid};
if (srcPeer.peerUid !== nodeMsg.peerUid) {
needSendSelf = true;
}
@@ -237,10 +291,14 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
try {
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
return {
message: await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
};
} catch (e) {
logger.logError.bind(this.core.context.logger)('forward failed', e);
return null;
return {
message: null
};
}
}

View File

@@ -125,6 +125,6 @@ export enum ActionName {
GetUserStatus = "nc_get_user_status",
GetRkey = "nc_get_rkey",
SetSpecialTittle = "set_group_special_title",
UploadForwardMsg = "upload_forward_msg",
// UploadForwardMsg = "upload_forward_msg",
GetGroupShutList = "get_goup_shut_list",
}