mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
refactor: completely remove genMessage.ts
This commit is contained in:
parent
f7a0fb22b4
commit
e4066fb8df
@ -1,11 +1,10 @@
|
||||
import BaseAction from '../BaseAction';
|
||||
import { ActionName } from '../types';
|
||||
import { ChatType, SendFileElement } from '@/core/entities';
|
||||
import { ChatType } from '@/core/entities';
|
||||
import fs from 'fs';
|
||||
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
||||
import { uri2local } from '@/common/utils/file';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { SendMsgElementConstructor } from '@/onebot/helper/genMessage';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
@ -34,7 +33,7 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
||||
if (!downloadResult.success) {
|
||||
throw new Error(downloadResult.errMsg);
|
||||
}
|
||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(this.CoreContext, downloadResult.path, payload.name, payload.folder_id);
|
||||
const sendFileEle = await this.CoreContext.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
|
||||
await sendMsg(this.CoreContext, {
|
||||
chatType: ChatType.KCHATTYPEGROUP,
|
||||
peerUid: payload.group_id.toString(),
|
||||
|
@ -5,7 +5,6 @@ import fs from 'fs';
|
||||
import { sendMsg } from '@/onebot/action/msg/SendMsg';
|
||||
import { uri2local } from '@/common/utils/file';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { SendMsgElementConstructor } from '@/onebot/helper/genMessage';
|
||||
|
||||
const SchemaData = {
|
||||
type: 'object',
|
||||
@ -47,7 +46,7 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
||||
if (!downloadResult.success) {
|
||||
throw new Error(downloadResult.errMsg);
|
||||
}
|
||||
const sendFileEle: SendFileElement = await SendMsgElementConstructor.file(this.CoreContext, downloadResult.path, payload.name);
|
||||
const sendFileEle: SendFileElement = await this.CoreContext.apis.FileApi.createValidSendFileElement(this.CoreContext, downloadResult.path, payload.name);
|
||||
await sendMsg(this.CoreContext, peer, [sendFileEle], [], true);
|
||||
return null;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
NapCatCore,
|
||||
Peer,
|
||||
RawMessage,
|
||||
SendMessageElement,
|
||||
SendMessageElement, SendTextElement,
|
||||
} from '@/core';
|
||||
import faceConfig from '@/core/external/face_config.json';
|
||||
import {
|
||||
@ -22,7 +22,7 @@ import {
|
||||
OB11MessageDataType,
|
||||
OB11MessageFileBase,
|
||||
} from '@/onebot';
|
||||
import { OB11Constructor, SendMsgElementConstructor } from '../helper';
|
||||
import { OB11Constructor } from '../helper';
|
||||
import { EventType } from '@/onebot/event/OB11BaseEvent';
|
||||
import { encodeCQCode } from '@/onebot/helper/cqcode';
|
||||
import { uri2local } from '@/common/utils/file';
|
||||
@ -402,18 +402,32 @@ export class OneBotMsgApi {
|
||||
}),
|
||||
|
||||
[OB11MessageDataType.at]: async ({ data: { qq: atQQ } }, context) => {
|
||||
function at(atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement {
|
||||
return {
|
||||
elementType: ElementType.TEXT,
|
||||
elementId: '',
|
||||
textElement: {
|
||||
content: `@${atName}`,
|
||||
atType,
|
||||
atUid,
|
||||
atTinyId: '',
|
||||
atNtUid,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!context.peer || context.peer.chatType == ChatType.KCHATTYPEC2C) return undefined;
|
||||
if (atQQ === 'all') return SendMsgElementConstructor.at(this.coreContext, atQQ, atQQ, AtType.atAll, '全体成员');
|
||||
if (atQQ === 'all') return at(atQQ, atQQ, AtType.atAll, '全体成员');
|
||||
const NTQQGroupApi = this.coreContext.apis.GroupApi;
|
||||
const NTQQUserApi = this.coreContext.apis.UserApi;
|
||||
const atMember = await NTQQGroupApi.getGroupMember(context.peer.peerUid, atQQ);
|
||||
if (atMember) {
|
||||
return SendMsgElementConstructor.at(this.coreContext, atQQ, atMember.uid, AtType.atUser, atMember.nick || atMember.cardName);
|
||||
return at(atQQ, atMember.uid, AtType.atUser, atMember.nick || atMember.cardName);
|
||||
}
|
||||
const uid = await NTQQUserApi.getUidByUinV2(`${atQQ}`);
|
||||
if (!uid) throw new Error('Get Uid Error');
|
||||
const info = await NTQQUserApi.getUserDetailInfo(uid);
|
||||
return SendMsgElementConstructor.at(this.coreContext, atQQ, uid, AtType.atUser, info.nick || '');
|
||||
return at(atQQ, uid, AtType.atUser, info.nick || '');
|
||||
},
|
||||
|
||||
[OB11MessageDataType.reply]: async ({ data: { id } }) => {
|
||||
@ -426,7 +440,16 @@ export class OneBotMsgApi {
|
||||
const replyMsg = (await NTQQMsgApi.getMsgsByMsgId(
|
||||
replyMsgM.Peer, [replyMsgM.MsgId!])).msgList[0];
|
||||
return replyMsg ?
|
||||
SendMsgElementConstructor.reply(this.coreContext, replyMsg.msgSeq, replyMsg.msgId, replyMsg.senderUin!, replyMsg.senderUin!) :
|
||||
{
|
||||
elementType: ElementType.REPLY,
|
||||
elementId: '',
|
||||
replyElement: {
|
||||
replayMsgSeq: replyMsg.msgSeq, // raw.msgSeq
|
||||
replayMsgId: replyMsg.msgId, // raw.msgId
|
||||
senderUin: replyMsg.senderUin!,
|
||||
senderUinStr: replyMsg.senderUin!,
|
||||
},
|
||||
} :
|
||||
undefined;
|
||||
},
|
||||
|
||||
|
@ -1,422 +0,0 @@
|
||||
import {
|
||||
AtType,
|
||||
ElementType,
|
||||
FaceIndex,
|
||||
FaceType,
|
||||
NapCatCore,
|
||||
PicType,
|
||||
SendArkElement,
|
||||
SendFaceElement,
|
||||
SendFileElement,
|
||||
SendMarkdownElement,
|
||||
SendMarketFaceElement,
|
||||
SendPicElement,
|
||||
SendPttElement,
|
||||
SendReplyElement,
|
||||
sendShareLocationElement,
|
||||
SendTextElement,
|
||||
SendVideoElement,
|
||||
viedo_type,
|
||||
} from '@/core';
|
||||
import * as fsnormal from 'node:fs';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import ffmpeg from 'fluent-ffmpeg';
|
||||
import { calculateFileMD5, isGIF } from '@/common/utils/file';
|
||||
import { defaultVideoThumbB64, getVideoInfo } from '@/common/utils/video';
|
||||
import { encodeSilk } from '@/common/utils/audio';
|
||||
import faceConfig from '@/core/external/face_config.json';
|
||||
import * as pathLib from 'node:path';
|
||||
|
||||
export class SendMsgElementConstructor {
|
||||
static location(CoreContext: NapCatCore): sendShareLocationElement {
|
||||
return {
|
||||
elementType: ElementType.SHARELOCATION,
|
||||
elementId: '',
|
||||
shareLocationElement: {
|
||||
text: '测试',
|
||||
ext: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static text(CoreContext: NapCatCore, content: string): SendTextElement {
|
||||
return {
|
||||
elementType: ElementType.TEXT,
|
||||
elementId: '',
|
||||
textElement: {
|
||||
content,
|
||||
atType: AtType.notAt,
|
||||
atUid: '',
|
||||
atTinyId: '',
|
||||
atNtUid: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static at(CoreContext: NapCatCore, atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement {
|
||||
return {
|
||||
elementType: ElementType.TEXT,
|
||||
elementId: '',
|
||||
textElement: {
|
||||
content: `@${atName}`,
|
||||
atType,
|
||||
atUid,
|
||||
atTinyId: '',
|
||||
atNtUid,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static reply(CoreContext: NapCatCore, msgSeq: string, msgId: string, senderUin: string, senderUinStr: string): SendReplyElement {
|
||||
return {
|
||||
elementType: ElementType.REPLY,
|
||||
elementId: '',
|
||||
replyElement: {
|
||||
replayMsgSeq: msgSeq, // raw.msgSeq
|
||||
replayMsgId: msgId, // raw.msgId
|
||||
senderUin: senderUin,
|
||||
senderUinStr: senderUinStr,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static async pic(coreContext: NapCatCore, picPath: string, summary: string = '', subType: 0 | 1 = 0): Promise<SendPicElement> {
|
||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
||||
const NTQQUserApi = coreContext.apis.UserApi;
|
||||
const NTQQFileApi = coreContext.apis.FileApi;
|
||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
||||
const logger = coreContext.context.logger;
|
||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(picPath, ElementType.PIC, subType);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
const imageSize = await NTQQFileApi.getImageSize(picPath);
|
||||
const picElement: any = {
|
||||
md5HexStr: md5,
|
||||
fileSize: fileSize.toString(),
|
||||
picWidth: imageSize?.width,
|
||||
picHeight: imageSize?.height,
|
||||
fileName: fileName,
|
||||
sourcePath: path,
|
||||
original: true,
|
||||
picType: isGIF(picPath) ? PicType.gif : PicType.jpg,
|
||||
picSubType: subType,
|
||||
fileUuid: '',
|
||||
fileSubId: '',
|
||||
thumbFileSize: 0,
|
||||
summary,
|
||||
};
|
||||
//logDebug('图片信息', picElement);
|
||||
return {
|
||||
elementType: ElementType.PIC,
|
||||
elementId: '',
|
||||
picElement,
|
||||
};
|
||||
}
|
||||
|
||||
static async file(coreContext: NapCatCore, filePath: string, fileName: string = '', folderId: string = ''): Promise<SendFileElement> {
|
||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
||||
const NTQQUserApi = coreContext.apis.UserApi;
|
||||
const NTQQFileApi = coreContext.apis.FileApi;
|
||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
||||
const logger = coreContext.context.logger;
|
||||
const { md5, fileName: _fileName, path, fileSize } = await NTQQFileApi.uploadFile(filePath, ElementType.FILE);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
const element: SendFileElement = {
|
||||
elementType: ElementType.FILE,
|
||||
elementId: '',
|
||||
fileElement: {
|
||||
fileName: fileName || _fileName,
|
||||
folderId: folderId,
|
||||
'filePath': path!,
|
||||
'fileSize': (fileSize).toString(),
|
||||
},
|
||||
};
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
static async video(coreContext: NapCatCore, filePath: string, fileName: string = '', diyThumbPath: string = '', videotype: viedo_type = viedo_type.VIDEO_FORMAT_MP4): Promise<SendVideoElement> {
|
||||
const NTQQFileApi = coreContext.apis.FileApi;
|
||||
const logger = coreContext.context.logger;
|
||||
const { fileName: _fileName, path, fileSize, md5 } = await NTQQFileApi.uploadFile(filePath, ElementType.VIDEO);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
let thumb = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`);
|
||||
thumb = pathLib.dirname(thumb);
|
||||
// log("thumb 目录", thumb)
|
||||
let videoInfo = {
|
||||
width: 1920, height: 1080,
|
||||
time: 15,
|
||||
format: 'mp4',
|
||||
size: fileSize,
|
||||
filePath,
|
||||
};
|
||||
try {
|
||||
videoInfo = await getVideoInfo(path, logger);
|
||||
//logDebug('视频信息', videoInfo);
|
||||
} catch (e) {
|
||||
logger.logError('获取视频信息失败', e);
|
||||
}
|
||||
const createThumb = new Promise<string | undefined>((resolve, reject) => {
|
||||
const thumbFileName = `${md5}_0.png`;
|
||||
const thumbPath = pathLib.join(thumb, thumbFileName);
|
||||
ffmpeg(filePath)
|
||||
.on('end', () => {
|
||||
})
|
||||
.on('error', (err) => {
|
||||
logger.logDebug('获取视频封面失败,使用默认封面', err);
|
||||
if (diyThumbPath) {
|
||||
fs.copyFile(diyThumbPath, thumbPath).then(() => {
|
||||
resolve(thumbPath);
|
||||
}).catch(reject);
|
||||
} else {
|
||||
fsnormal.writeFileSync(thumbPath, Buffer.from(defaultVideoThumbB64, 'base64'));
|
||||
resolve(thumbPath);
|
||||
}
|
||||
})
|
||||
.screenshots({
|
||||
timestamps: [0],
|
||||
filename: thumbFileName,
|
||||
folder: thumb,
|
||||
size: videoInfo.width + 'x' + videoInfo.height,
|
||||
}).on('end', () => {
|
||||
resolve(thumbPath);
|
||||
});
|
||||
});
|
||||
const thumbPath = new Map();
|
||||
const _thumbPath = await createThumb;
|
||||
const thumbSize = _thumbPath ? (await fs.stat(_thumbPath)).size : 0;
|
||||
// log("生成缩略图", _thumbPath)
|
||||
thumbPath.set(0, _thumbPath);
|
||||
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : "";
|
||||
const element: SendVideoElement = {
|
||||
elementType: ElementType.VIDEO,
|
||||
elementId: '',
|
||||
videoElement: {
|
||||
fileName: fileName || _fileName,
|
||||
filePath: path,
|
||||
videoMd5: md5,
|
||||
thumbMd5,
|
||||
fileTime: videoInfo.time,
|
||||
thumbPath: thumbPath,
|
||||
thumbSize,
|
||||
thumbWidth: videoInfo.width,
|
||||
thumbHeight: videoInfo.height,
|
||||
fileSize: '' + fileSize,
|
||||
//fileFormat: videotype
|
||||
// fileUuid: "",
|
||||
// transferStatus: 0,
|
||||
// progress: 0,
|
||||
// invalidState: 0,
|
||||
// fileSubId: "",
|
||||
// fileBizId: null,
|
||||
// originVideoMd5: "",
|
||||
// fileFormat: 2,
|
||||
// import_rich_media_context: null,
|
||||
// sourceVideoCodecFormat: 2
|
||||
},
|
||||
};
|
||||
// "fileElement": {
|
||||
// "fileMd5": "",
|
||||
// "fileName": "1.mp4",
|
||||
// "filePath": "C:\\Users\\nanae\\OneDrive\\Desktop\\1.mp4",
|
||||
// "fileSize": "1847007",
|
||||
// "picHeight": 1280,
|
||||
// "picWidth": 720,
|
||||
// "picThumbPath": {},
|
||||
// "file10MMd5": "",
|
||||
// "fileSha": "",
|
||||
// "fileSha3": "",
|
||||
// "fileUuid": "",
|
||||
// "fileSubId": "",
|
||||
// "thumbFileSize": 750
|
||||
// }
|
||||
return element;
|
||||
}
|
||||
|
||||
static async ptt(coreContext: NapCatCore, pttPath: string): Promise<SendPttElement> {
|
||||
const NTQQGroupApi = coreContext.apis.GroupApi;
|
||||
const NTQQUserApi = coreContext.apis.UserApi;
|
||||
const NTQQFileApi = coreContext.apis.FileApi;
|
||||
const NTQQMsgApi = coreContext.apis.MsgApi;
|
||||
const NTQQFriendApi = coreContext.apis.FriendApi;
|
||||
const logger = coreContext.context.logger;
|
||||
const {
|
||||
converted,
|
||||
path: silkPath,
|
||||
duration,
|
||||
} = await encodeSilk(pttPath, coreContext.NapCatTempPath, coreContext.context.logger);
|
||||
// log("生成语音", silkPath, duration);
|
||||
if (!silkPath) {
|
||||
throw '语音转换失败, 请检查语音文件是否正常';
|
||||
}
|
||||
const { md5, fileName, path, fileSize } = await NTQQFileApi.uploadFile(silkPath!, ElementType.PTT);
|
||||
if (fileSize === 0) {
|
||||
throw '文件异常,大小为0';
|
||||
}
|
||||
if (converted) {
|
||||
fs.unlink(silkPath).then();
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.PTT,
|
||||
elementId: '',
|
||||
pttElement: {
|
||||
fileName: fileName,
|
||||
filePath: path,
|
||||
md5HexStr: md5,
|
||||
fileSize: fileSize,
|
||||
// duration: Math.max(1, Math.round(fileSize / 1024 / 3)), // 一秒钟大概是3kb大小, 小于1秒的按1秒算
|
||||
duration: duration || 1,
|
||||
formatType: 1,
|
||||
voiceType: 1,
|
||||
voiceChangeType: 0,
|
||||
canConvert2Text: true,
|
||||
waveAmplitudes: [
|
||||
0, 18, 9, 23, 16, 17, 16, 15, 44, 17, 24, 20, 14, 15, 17,
|
||||
],
|
||||
fileSubId: '',
|
||||
playState: 1,
|
||||
autoConvertText: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// NodeIQQNTWrapperSession sendMsg [
|
||||
// "0",
|
||||
// {
|
||||
// "peerUid": "u_e_RIxgTs2NaJ68h0PwOPSg",
|
||||
// "chatType": 1,
|
||||
// "guildId": ""
|
||||
// },
|
||||
// [
|
||||
// {
|
||||
// "elementId": "0",
|
||||
// "elementType": 6,
|
||||
// "faceElement": {
|
||||
// "faceIndex": 0,
|
||||
// "faceType": 5,
|
||||
// "msgType": 0,
|
||||
// "pokeType": 1,
|
||||
// "pokeStrength": 0
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// {}
|
||||
// ]
|
||||
static face(CoreContext: NapCatCore, faceId: number): SendFaceElement {
|
||||
// 从face_config.json中获取表情名称
|
||||
const sysFaces = faceConfig.sysface;
|
||||
const emojiFaces = faceConfig.emoji;
|
||||
const face: any = sysFaces.find((face) => face.QSid === faceId.toString());
|
||||
faceId = parseInt(faceId.toString());
|
||||
// let faceType = parseInt(faceId.toString().substring(0, 1));
|
||||
let faceType = 1;
|
||||
if (faceId >= 222) {
|
||||
faceType = 2;
|
||||
}
|
||||
if (face.AniStickerType) {
|
||||
faceType = 3;
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
faceIndex: faceId,
|
||||
faceType,
|
||||
faceText: face.QDes,
|
||||
stickerId: face.AniStickerId,
|
||||
stickerType: face.AniStickerType,
|
||||
packId: face.AniStickerPackId,
|
||||
sourceType: 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static mface(CoreContext: NapCatCore, emojiPackageId: number, emojiId: string, key: string, faceName: string): SendMarketFaceElement {
|
||||
return {
|
||||
elementType: ElementType.MFACE,
|
||||
marketFaceElement: {
|
||||
emojiPackageId,
|
||||
emojiId,
|
||||
key,
|
||||
faceName: faceName || '[商城表情]',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static dice(CoreContext: NapCatCore, resultId: number | null): SendFaceElement {
|
||||
// 实际测试并不能控制结果
|
||||
|
||||
// 随机1到6
|
||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 6) + 1;
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
faceIndex: FaceIndex.dice,
|
||||
faceType: FaceType.dice,
|
||||
'faceText': '[骰子]',
|
||||
'packId': '1',
|
||||
'stickerId': '33',
|
||||
'sourceType': 1,
|
||||
'stickerType': 2,
|
||||
// resultId: resultId.toString(),
|
||||
'surpriseId': '',
|
||||
// "randomType": 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 猜拳(石头剪刀布)表情
|
||||
static rps(CoreContext: NapCatCore, resultId: number | null): SendFaceElement {
|
||||
// 实际测试并不能控制结果
|
||||
// if (isNull(resultId)) resultId = Math.floor(Math.random() * 3) + 1;
|
||||
return {
|
||||
elementType: ElementType.FACE,
|
||||
elementId: '',
|
||||
faceElement: {
|
||||
'faceIndex': FaceIndex.RPS,
|
||||
'faceText': '[包剪锤]',
|
||||
'faceType': 3,
|
||||
'packId': '1',
|
||||
'stickerId': '34',
|
||||
'sourceType': 1,
|
||||
'stickerType': 2,
|
||||
// 'resultId': resultId.toString(),
|
||||
'surpriseId': '',
|
||||
// "randomType": 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static ark(CoreContext: NapCatCore, data: any): SendArkElement {
|
||||
if (typeof data !== 'string') {
|
||||
data = JSON.stringify(data);
|
||||
}
|
||||
return {
|
||||
elementType: ElementType.ARK,
|
||||
elementId: '',
|
||||
arkElement: {
|
||||
bytesData: data,
|
||||
linkInfo: null,
|
||||
subElementType: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static markdown(CoreContext: NapCatCore, content: string): SendMarkdownElement {
|
||||
return {
|
||||
elementType: ElementType.MARKDOWN,
|
||||
elementId: '',
|
||||
markdownElement: {
|
||||
content,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
export * from './config';
|
||||
export * from './converter';
|
||||
export * from './quick';
|
||||
export * from './genMessage';
|
||||
export * from './event';
|
||||
|
Loading…
x
Reference in New Issue
Block a user