mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
feat: Implement complete transform & Build & Upload FakeForwardMsg
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
@@ -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),
|
||||
];
|
||||
|
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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",
|
||||
}
|
||||
|
Reference in New Issue
Block a user