Compare commits

...

31 Commits

Author SHA1 Message Date
手瓜一十雪
672ae8decf fix: Once处理空格目录 中文目录 2024-12-02 22:08:08 +08:00
手瓜一十雪
2abc7e541d fix: 空格目录启动问题 2024-12-02 21:23:13 +08:00
手瓜一十雪
45b1f369ac style: 异步实现 2024-12-02 11:44:37 +08:00
手瓜一十雪
3b5d2c8f6f style: 简化写法 2024-12-02 11:16:12 +08:00
Mlikiowa
5376e16c9f release: v4.2.10 2024-12-01 11:12:10 +00:00
bietiaop
af052242fa feat:带等级的实时日志 2024-12-01 15:19:23 +08:00
手瓜一十雪
85e0b71545 chore: daily -> weekly 2024-12-01 13:26:56 +08:00
手瓜一十雪
1206d1fcf6 chore: bug report 2024-12-01 13:25:36 +08:00
手瓜一十雪
f7534dc438 fix: 自动迁移 2024-12-01 13:20:20 +08:00
手瓜一十雪
97f317254e fix: MiniApp type check 2024-12-01 13:11:56 +08:00
手瓜一十雪
9eaf51e15f fix: nullable 2024-12-01 13:04:00 +08:00
手瓜一十雪
7221f4ac02 fix: type-check 2024-12-01 12:50:13 +08:00
手瓜一十雪
1bb6dce239 refactor: type-check (#586)
* refactor: type-check

* fix: default

* refactor: type-check
2024-12-01 12:41:51 +08:00
bietiaop
d13db5e8eb feat: 实时日志 (#584)
* feat: 历史日志

* feat: 实时日志

* fix: EventEmitter实现事件监听
2024-12-01 09:31:47 +08:00
Mlikiowa
040b5535f3 release: v4.2.9 2024-11-30 06:12:44 +00:00
手瓜一十雪
b44e1618fb fix: quick error 2024-11-30 14:12:23 +08:00
手瓜一十雪
1e13483bc3 fix: type 2024-11-30 13:32:21 +08:00
手瓜一十雪
f9519d3923 style: lint 2024-11-30 13:29:10 +08:00
手瓜一十雪
86cdfbb79b feat: 取消上报 pic_type 2024-11-30 12:11:33 +08:00
手瓜一十雪
a70585e854 feat: 处理失败的情况 2024-11-30 12:08:58 +08:00
Mlikiowa
040d0a8635 release: v4.2.8 2024-11-30 01:39:59 +00:00
手瓜一十雪
efa512ab21 fix: #580 2024-11-30 09:34:03 +08:00
bietiaop
9b04aed8b3 feat: 历史日志 2024-11-30 09:30:13 +08:00
手瓜一十雪
7087eafe37 feat: Universal Package (#578)
* feat: 统一包支持

* feat: Universal
2024-11-29 15:11:35 +08:00
Mlikiowa
c81c4af653 release: v4.2.7 2024-11-29 04:48:36 +00:00
手瓜一十雪
c05cc9dd02 feat: 迁移29927 2024-11-29 12:48:03 +08:00
手瓜一十雪
1a0da00f2d refactor: webui log 移除公网输出 2024-11-29 12:41:52 +08:00
手瓜一十雪
31b0c1d3d7 refactor: react webui 2024-11-29 12:22:25 +08:00
手瓜一十雪
53c1d40bcf refactor: logger bind (#577) 2024-11-28 20:55:28 +08:00
手瓜一十雪
97cacb4383 refactor: framework的操作性 2024-11-28 20:00:24 +08:00
Mlikiowa
e03905abaf release: v4.2.6 2024-11-28 07:28:33 +00:00
126 changed files with 1352 additions and 1593 deletions

2
.env.universal Normal file
View File

@@ -0,0 +1,2 @@
VITE_BUILD_TYPE = Production
VITE_BUILD_PLATFORM = Universal

View File

@@ -10,13 +10,12 @@ body:
在提交新的 Bug 反馈前,请确保您: 在提交新的 Bug 反馈前,请确保您:
* 已经搜索了现有的 issues并且没有找到可以解决您问题的方法 * 已经搜索了现有的 issues并且没有找到可以解决您问题的方法
* 不与现有的某一 issue 重复 * 不与现有的某一 issue 重复
* 不涉及[已经停止维护的特性](https://github.com/NapNeko/NapCatQQ?tab=readme-ov-file#挥别昨日),例如 CQ 码
- type: input - type: input
id: system-version id: system-version
attributes: attributes:
label: 系统版本 label: 系统版本
description: 运行 QQNT 的系统版本 description: 运行 QQNT 的系统版本
placeholder: Windows 10 Pro Workstation 22H2 placeholder: Windows 11 24H2
validations: validations:
required: true required: true
- type: input - type: input
@@ -24,7 +23,7 @@ body:
attributes: attributes:
label: QQNT 版本 label: QQNT 版本
description: 可在 QQNT 的「关于」的设置页中找到 description: 可在 QQNT 的「关于」的设置页中找到
placeholder: 9.9.7-21804 placeholder: 9.9.16-29927
validations: validations:
required: true required: true
- type: input - type: input
@@ -40,21 +39,21 @@ body:
attributes: attributes:
label: OneBot 客户端 label: OneBot 客户端
description: 连接至 NapCat 的客户端版本信息 description: 连接至 NapCat 的客户端版本信息
placeholder: Overflow 2.16.0-2cf7991-SNAPSHOT placeholder: Karin 1.0.0
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: what-happened id: what-happened
attributes: attributes:
label: 发生了什么? label: 发生了什么?
description: 填写你认为的 NapCat 的不正常行为 description: 填写你认为的 NapCat 的常行为
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: how-reproduce id: how-reproduce
attributes: attributes:
label: 如何复现 label: 如何复现
description: 填写应当如何操作才能触发这个不正常行为 description: 填写应当如何操作才能触发这个常行为
placeholder: | placeholder: |
1. xxx 1. xxx
2. xxx 2. xxx

View File

@@ -1,11 +1,6 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2 version: 2
updates: updates:
- package-ecosystem: "npm" # See documentation for possible values - package-ecosystem: "npm"
directory: "/" # Location of package manifests directory: "/"
schedule: schedule:
interval: "daily" interval: "weekly"

Binary file not shown.

Binary file not shown.

View File

@@ -1,9 +1,9 @@
{ {
"name": "qq-chat", "name": "qq-chat",
"version": "9.9.16-29456", "version": "9.9.16-29927",
"verHash": "dd395162", "verHash": "3e273e30",
"linuxVersion": "3.2.13-29456", "linuxVersion": "3.2.13-29927",
"linuxVerHash": "e379390a", "linuxVerHash": "833d113c",
"type": "module", "type": "module",
"private": true, "private": true,
"description": "QQ", "description": "QQ",
@@ -18,7 +18,7 @@
"qd": "externals/devtools/cli/index.js" "qd": "externals/devtools/cli/index.js"
}, },
"main": "./loadNapCat.js", "main": "./loadNapCat.js",
"buildVersion": "29456", "buildVersion": "29927",
"isPureShell": true, "isPureShell": true,
"isByteCodeShell": true, "isByteCodeShell": true,
"platform": "win32", "platform": "win32",

View File

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

View File

@@ -2,11 +2,13 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "4.2.5", "version": "4.2.10",
"scripts": { "scripts": {
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
"build:framework": "npm run build:webui && vite build --mode framework || exit 1", "build:framework": "npm run build:webui && vite build --mode framework || exit 1",
"build:shell": "npm run build:webui && vite build --mode shell || exit 1", "build:shell": "npm run build:webui && vite build --mode shell || exit 1",
"build:webui": "cd napcat.webui && vite build", "build:webui": "cd napcat.webui && vite build",
"dev:universal": "vite build --mode universal",
"dev:framework": "vite build --mode framework", "dev:framework": "vite build --mode framework",
"dev:shell": "vite build --mode shell", "dev:shell": "vite build --mode shell",
"dev:webui": "cd napcat.webui && npm run webui:dev", "dev:webui": "cd napcat.webui && npm run webui:dev",
@@ -41,13 +43,13 @@
"file-type": "^19.0.0", "file-type": "^19.0.0",
"globals": "^15.12.0", "globals": "^15.12.0",
"image-size": "^1.1.1", "image-size": "^1.1.1",
"json-schema-to-ts": "^3.1.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"typescript-eslint": "^8.13.0", "typescript-eslint": "^8.13.0",
"vite": "^6.0.1", "vite": "^6.0.1",
"vite-plugin-cp": "^4.0.8", "vite-plugin-cp": "^4.0.8",
"vite-tsconfig-paths": "^5.1.0", "vite-tsconfig-paths": "^5.1.0",
"winston": "^3.17.0" "winston": "^3.17.0",
"@sinclair/typebox": "^0.34.9"
}, },
"dependencies": { "dependencies": {
"express": "^5.0.0", "express": "^5.0.0",

View File

@@ -96,7 +96,7 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
}; };
} }
} catch (error: any) { } catch (error: any) {
logger.logError.bind(logger)('convert silk failed', error.stack); logger.logError('convert silk failed', error.stack);
return {}; return {};
} }
} }

View File

@@ -33,27 +33,27 @@ export abstract class ConfigBase<T> {
} }
read(copy_default: boolean = true): T { read(copy_default: boolean = true): T {
const logger = this.core.context.logger;
const configPath = this.getConfigPath(this.core.selfInfo.uin); const configPath = this.getConfigPath(this.core.selfInfo.uin);
if (!fs.existsSync(configPath) && copy_default) { if (!fs.existsSync(configPath) && copy_default) {
try { try {
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8')); fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
logger.log(`[Core] [Config] 配置文件创建成功!\n`); this.core.context.logger.log(`[Core] [Config] 配置文件创建成功!\n`);
} catch (e: any) { } catch (e: any) {
logger.logError.bind(logger)(`[Core] [Config] 创建配置文件时发生错误:`, e.message); this.core.context.logger.logError(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
} }
} else if (!fs.existsSync(configPath) && !copy_default) { } else if (!fs.existsSync(configPath) && !copy_default) {
fs.writeFileSync(configPath, '{}'); fs.writeFileSync(configPath, '{}');
} }
try { try {
this.configData = JSON.parse(fs.readFileSync(configPath, 'utf-8')); this.configData = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
logger.logDebug(`[Core] [Config] 配置文件${configPath}加载`, this.configData); this.core.context.logger.logDebug(`[Core] [Config] 配置文件${configPath}加载`, this.configData);
return this.configData; return this.configData;
} catch (e: any) { } catch (e: any) {
if (e instanceof SyntaxError) { if (e instanceof SyntaxError) {
logger.logError.bind(logger)(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message); this.core.context.logger.logError(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
} else { } else {
logger.logError.bind(logger)(`[Core] [Config] 读取配置文件时发生错误:`, e.message); this.core.context.logger.logError(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
} }
return {} as T; return {} as T;
} }
@@ -61,14 +61,13 @@ export abstract class ConfigBase<T> {
save(newConfigData: T = this.configData) { save(newConfigData: T = this.configData) {
const logger = this.core.context.logger;
const selfInfo = this.core.selfInfo; const selfInfo = this.core.selfInfo;
this.configData = newConfigData; this.configData = newConfigData;
const configPath = this.getConfigPath(selfInfo.uin); const configPath = this.getConfigPath(selfInfo.uin);
try { try {
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2)); fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
} catch (e: any) { } catch (e: any) {
logger.logError.bind(logger)(`保存配置文件 ${configPath} 时发生错误:`, e.message); this.core.context.logger.logError(`保存配置文件 ${configPath} 时发生错误:`, e.message);
} }
} }
} }

View File

@@ -200,17 +200,7 @@ export async function checkUriType(Uri: string) {
} }
// 默认file:// // 默认file://
if (uri.startsWith('file:')) { if (uri.startsWith('file:')) {
// 兼容file:/// const filePath: string = decodeURIComponent(uri.startsWith('file:///') && process.platform === 'win32' ? uri.slice(8) : uri.slice(7));
// file:///C:/1.jpg
if (uri.startsWith('file:///') && process.platform === 'win32') {
const filePath: string = uri.slice(8);
return { Uri: filePath, Type: FileUriType.Local };
}
// 处理默认规范
// file://C:\1.jpg
// file:///test/1.jpg
const filePath: string = uri.slice(7);
return { Uri: filePath, Type: FileUriType.Local }; return { Uri: filePath, Type: FileUriType.Local };
} }
if (uri.startsWith('data:')) { if (uri.startsWith('data:')) {

View File

@@ -1,9 +1,9 @@
import winston, { format, transports } from 'winston'; import winston, { format, transports } from 'winston';
import { truncateString } from '@/common/helper'; import { truncateString } from '@/common/helper';
import path from 'node:path'; import path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs/promises';
import { NTMsgAtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core'; import { NTMsgAtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core';
import EventEmitter from 'node:events';
export enum LogLevel { export enum LogLevel {
DEBUG = 'debug', DEBUG = 'debug',
INFO = 'info', INFO = 'info',
@@ -24,6 +24,36 @@ function getFormattedTimestamp() {
return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}.${milliseconds}`; return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}.${milliseconds}`;
} }
const logEmitter = new EventEmitter();
export type LogListener = (msg: string) => void;
class Subscription {
public static MAX_HISTORY = 100;
public static history: string[] = [];
subscribe(listener: LogListener) {
for (const history of Subscription.history) {
try {
listener(history);
} catch (_) {
// ignore
}
}
logEmitter.on('log', listener);
}
unsubscribe(listener: LogListener) {
logEmitter.off('log', listener);
}
notify(msg: string) {
logEmitter.emit('log', msg);
if (Subscription.history.length >= Subscription.MAX_HISTORY) {
Subscription.history.shift();
}
Subscription.history.push(msg);
}
}
export const logSubscription = new Subscription();
export class LogWrapper { export class LogWrapper {
fileLogEnabled = true; fileLogEnabled = true;
consoleLogEnabled = true; consoleLogEnabled = true;
@@ -47,7 +77,7 @@ export class LogWrapper {
filename: logPath, filename: logPath,
level: 'debug', level: 'debug',
maxsize: 5 * 1024 * 1024, // 5MB maxsize: 5 * 1024 * 1024, // 5MB
maxFiles: 5 maxFiles: 5,
}), }),
new transports.Console({ new transports.Console({
format: format.combine( format: format.combine(
@@ -56,9 +86,9 @@ export class LogWrapper {
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : ''; const userInfo = meta.userInfo ? `${meta.userInfo} | ` : '';
return `${timestamp} [${level}] ${userInfo}${message}`; return `${timestamp} [${level}] ${userInfo}${message}`;
}) })
) ),
}) }),
] ],
}); });
this.setLogSelfInfo({ nick: '', uid: '' }); this.setLogSelfInfo({ nick: '', uid: '' });
@@ -67,26 +97,20 @@ export class LogWrapper {
cleanOldLogs(logDir: string) { cleanOldLogs(logDir: string) {
const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000; const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
fs.readdir(logDir, (err, files) => { fs.readdir(logDir).then((files) => {
if (err) { files.forEach((file) => {
this.logger.error('Failed to read log directory', err);
return;
}
files.forEach(file => {
const filePath = path.join(logDir, file); const filePath = path.join(logDir, file);
this.deleteOldLogFile(filePath, oneWeekAgo); this.deleteOldLogFile(filePath, oneWeekAgo);
}); });
}).catch((err) => {
this.logger.error('Failed to read log directory', err);
}); });
} }
private deleteOldLogFile(filePath: string, oneWeekAgo: number) { private deleteOldLogFile(filePath: string, oneWeekAgo: number) {
fs.stat(filePath, (err, stats) => { fs.stat(filePath).then((stats) => {
if (err) {
this.logger.error('Failed to get file stats', err);
return;
}
if (stats.mtime.getTime() < oneWeekAgo) { if (stats.mtime.getTime() < oneWeekAgo) {
fs.unlink(filePath, err => { fs.unlink(filePath).catch((err) => {
if (err) { if (err) {
if (err.code === 'ENOENT') { if (err.code === 'ENOENT') {
this.logger.warn(`File already deleted: ${filePath}`); this.logger.warn(`File already deleted: ${filePath}`);
@@ -98,6 +122,8 @@ export class LogWrapper {
} }
}); });
} }
}).catch((err) => {
this.logger.error('Failed to get file stats', err);
}); });
} }
@@ -111,7 +137,7 @@ export class LogWrapper {
}); });
} }
setLogSelfInfo(selfInfo: { nick: string, uid: string }) { setLogSelfInfo(selfInfo: { nick: string; uid: string }) {
const userInfo = `${selfInfo.nick}`; const userInfo = `${selfInfo.nick}`;
this.logger.defaultMeta = { userInfo }; this.logger.defaultMeta = { userInfo };
} }
@@ -135,14 +161,16 @@ export class LogWrapper {
} }
formatMsg(msg: any[]) { formatMsg(msg: any[]) {
return msg.map(msgItem => { return msg
if (msgItem instanceof Error) { .map((msgItem) => {
return msgItem.stack; if (msgItem instanceof Error) {
} else if (typeof msgItem === 'object') { return msgItem.stack;
return JSON.stringify(truncateString(JSON.parse(JSON.stringify(msgItem, null, 2)))); } else if (typeof msgItem === 'object') {
} return JSON.stringify(truncateString(JSON.parse(JSON.stringify(msgItem, null, 2))));
return msgItem; }
}).join(' '); return msgItem;
})
.join(' ');
} }
_log(level: LogLevel, ...args: any[]) { _log(level: LogLevel, ...args: any[]) {
@@ -155,6 +183,7 @@ export class LogWrapper {
// eslint-disable-next-line no-control-regex // eslint-disable-next-line no-control-regex
this.logger.log(level, message.replace(/\x1B[@-_][0-?]*[ -/]*[@-~]/g, '')); this.logger.log(level, message.replace(/\x1B[@-_][0-?]*[ -/]*[@-~]/g, ''));
} }
logSubscription.notify(JSON.stringify({ level, message }));
} }
log(...args: any[]) { log(...args: any[]) {
@@ -282,13 +311,9 @@ function textElementToText(textElement: any): string {
} }
function replyElementToText(replyElement: any, msg: RawMessage, recursiveLevel: number): string { function replyElementToText(replyElement: any, msg: RawMessage, recursiveLevel: number): string {
const recordMsgOrNull = msg.records.find( const recordMsgOrNull = msg.records.find((record) => replyElement.sourceMsgIdInRecords === record.msgId);
record => replyElement.sourceMsgIdInRecords === record.msgId, return `[回复消息 ${recordMsgOrNull && recordMsgOrNull.peerUin != '284840486' && recordMsgOrNull.peerUin != '1094950020'
); ? rawMessageToText(recordMsgOrNull, recursiveLevel + 1)
return `[回复消息 ${recordMsgOrNull && : `未找到消息记录 (MsgId = ${replyElement.sourceMsgIdInRecords})`
recordMsgOrNull.peerUin != '284840486' && recordMsgOrNull.peerUin != '1094950020' }]`;
? }
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
`未找到消息记录 (MsgId = ${replyElement.sourceMsgIdInRecords})`
}]`;
}

View File

@@ -1,6 +1,5 @@
import https from 'node:https'; import https from 'node:https';
import http from 'node:http'; import http from 'node:http';
import { readFileSync } from 'node:fs';
export class RequestUtil { export class RequestUtil {
// 适用于获取服务器下发cookies时获取仅GET // 适用于获取服务器下发cookies时获取仅GET
@@ -69,7 +68,7 @@ export class RequestUtil {
// 'Content-Length': Buffer.byteLength(postData), // 'Content-Length': Buffer.byteLength(postData),
// }, // },
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const req = protocol.request(options, (res: any) => { const req = protocol.request(options, (res: http.IncomingMessage) => {
let responseBody = ''; let responseBody = '';
res.on('data', (chunk: string | Buffer) => { res.on('data', (chunk: string | Buffer) => {
responseBody += chunk.toString(); responseBody += chunk.toString();
@@ -112,24 +111,4 @@ export class RequestUtil {
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}) { static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}) {
return this.HttpGetJson<string>(url, method, data, headers, false, false); return this.HttpGetJson<string>(url, method, data, headers, false, false);
} }
static async createFormData(boundary: string, filePath: string): Promise<Buffer> {
let type = 'image/png';
if (filePath.endsWith('.jpg')) {
type = 'image/jpeg';
}
const formDataParts = [
`------${boundary}\r\n`,
`Content-Disposition: form-data; name="share_image"; filename="${filePath}"\r\n`,
'Content-Type: ' + type + '\r\n\r\n',
];
const fileContent = readFileSync(filePath);
const footer = `\r\n------${boundary}--`;
return Buffer.concat([
Buffer.from(formDataParts.join(''), 'utf8'),
fileContent,
Buffer.from(footer, 'utf8'),
]);
}
} }

View File

@@ -1 +1 @@
export const napCatVersion = '4.2.5'; export const napCatVersion = '4.2.10';

View File

@@ -142,7 +142,6 @@ export class NTQQFileApi {
} }
async createValidSendVideoElement(context: SendMessageContext, filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> { async createValidSendVideoElement(context: SendMessageContext, filePath: string, fileName: string = '', diyThumbPath: string = ''): Promise<SendVideoElement> {
const logger = this.core.context.logger;
let videoInfo = { let videoInfo = {
width: 1920, width: 1920,
height: 1080, height: 1080,
@@ -152,9 +151,9 @@ export class NTQQFileApi {
filePath, filePath,
}; };
try { try {
videoInfo = await getVideoInfo(filePath, logger); videoInfo = await getVideoInfo(filePath, this.context.logger);
} catch (e) { } catch (e) {
logger.logError.bind(logger)('获取视频信息失败,将使用默认值', e); this.context.logger.logError('获取视频信息失败,将使用默认值', e);
} }
let fileExt = 'mp4'; let fileExt = 'mp4';
@@ -162,7 +161,7 @@ export class NTQQFileApi {
const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext; const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
if (tempExt) fileExt = tempExt; if (tempExt) fileExt = tempExt;
} catch (e) { } catch (e) {
this.context.logger.logError.bind(logger)('获取文件类型失败', e); this.context.logger.logError('获取文件类型失败', e);
} }
const newFilePath = filePath + '.' + fileExt; const newFilePath = filePath + '.' + fileExt;
fs.copyFileSync(filePath, newFilePath); fs.copyFileSync(filePath, newFilePath);
@@ -183,7 +182,7 @@ export class NTQQFileApi {
ffmpeg(filePath) ffmpeg(filePath)
.on('error', (err) => { .on('error', (err) => {
try { try {
logger.logDebug('获取视频封面失败,使用默认封面', err); this.context.logger.logDebug('获取视频封面失败,使用默认封面', err);
if (diyThumbPath) { if (diyThumbPath) {
fsPromises.copyFile(diyThumbPath, thumbPath).then(() => { fsPromises.copyFile(diyThumbPath, thumbPath).then(() => {
resolve(thumbPath); resolve(thumbPath);
@@ -193,7 +192,7 @@ export class NTQQFileApi {
resolve(thumbPath); resolve(thumbPath);
} }
} catch (error) { } catch (error) {
logger.logError.bind(logger)('获取视频封面失败,使用默认封面失败', error); this.context.logger.logError('获取视频封面失败,使用默认封面失败', error);
} }
}) })
.screenshots({ .screenshots({
@@ -230,6 +229,7 @@ export class NTQQFileApi {
} }
async createValidSendPttElement(pttPath: string): Promise<SendPttElement> { async createValidSendPttElement(pttPath: string): Promise<SendPttElement> {
const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger); const { converted, path: silkPath, duration } = await encodeSilk(pttPath, this.core.NapCatTempPath, this.core.context.logger);
if (!silkPath) { if (!silkPath) {
throw new Error('语音转换失败, 请检查语音文件是否正常'); throw new Error('语音转换失败, 请检查语音文件是否正常');
@@ -239,8 +239,7 @@ export class NTQQFileApi {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
if (converted) { if (converted) {
fsPromises.unlink(silkPath).then().catch( fsPromises.unlink(silkPath).then().catch((e) => this.context.logger.logError('删除临时文件失败', e)
(e) => this.context.logger.logError.bind(this.context.logger)('删除临时文件失败', e)
); );
} }
return { return {
@@ -454,7 +453,7 @@ export class NTQQFileApi {
} }
} }
} catch (error: any) { } catch (error: any) {
this.context.logger.logError.bind(this.context.logger)('获取rkey失败', error.message); this.context.logger.logError('获取rkey失败', error.message);
} }
if (!rkeyData.online_rkey) { if (!rkeyData.online_rkey) {
@@ -464,7 +463,7 @@ export class NTQQFileApi {
rkeyData.private_rkey = tempRkeyData.private_rkey; rkeyData.private_rkey = tempRkeyData.private_rkey;
rkeyData.online_rkey = tempRkeyData.expired_time > Date.now() / 1000; rkeyData.online_rkey = tempRkeyData.expired_time > Date.now() / 1000;
} catch (e) { } catch (e) {
this.context.logger.logError.bind(this.context.logger)('获取rkey失败 Fallback Old Mode', e); this.context.logger.logError('获取rkey失败 Fallback Old Mode', e);
} }
} }

View File

@@ -27,7 +27,7 @@ export class NTQQGroupApi {
this.core = core; this.core = core;
} }
async initApi() { async initApi() {
this.initCache().then().catch(this.context.logger.logError.bind(this.context.logger)); this.initCache().then().catch(e => this.context.logger.logError(e));
} }
async initCache() { async initCache() {
this.groups = await this.getGroups(); this.groups = await this.getGroups();

View File

@@ -31,7 +31,7 @@ export class NTQQPacketApi {
await this.InitSendPacket(this.context.basicInfoWrapper.getFullQQVesion()) await this.InitSendPacket(this.context.basicInfoWrapper.getFullQQVesion())
.then() .then()
.catch((err) => { .catch((err) => {
this.logger.logError.bind(this.core.context.logger); this.logger.logError(err);
this.errStack.push(err); this.errStack.push(err);
}); });
} }

View File

@@ -27,7 +27,6 @@ export class RkeyManager {
await this.refreshRkey(); await this.refreshRkey();
} catch (e) { } catch (e) {
throw new Error(`获取rkey失败: ${e}`);//外抛 throw new Error(`获取rkey失败: ${e}`);//外抛
//this.logger.logError.bind(this.logger)('获取rkey失败', e);
} }
} }
return this.rkeyData; return this.rkeyData;
@@ -50,7 +49,7 @@ export class RkeyManager {
expired_time: temp.expired_time expired_time: temp.expired_time
}; };
} catch (e) { } catch (e) {
this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e); this.logger.logError(`[Rkey] Get Rkey ${url} Error `, e);
//是否为最后一个url //是否为最后一个url
if (url === this.serverUrl[this.serverUrl.length - 1]) { if (url === this.serverUrl[this.serverUrl.length - 1]) {
throw new Error(`获取rkey失败: ${e}`);//外抛 throw new Error(`获取rkey失败: ${e}`);//外抛

View File

@@ -127,7 +127,7 @@ export class NapCatCore {
await api.initApi(); await api.initApi();
} }
} }
this.initNapCatCoreListeners().then().catch(this.context.logger.logError.bind(this.context.logger)); this.initNapCatCoreListeners().then().catch((e) => this.context.logger.logError(e));
this.context.logger.setFileLogEnabled( this.context.logger.setFileLogEnabled(
this.configLoader.configData.fileLog, this.configLoader.configData.fileLog,
@@ -154,7 +154,7 @@ export class NapCatCore {
const msgListener = new NodeIKernelMsgListener(); const msgListener = new NodeIKernelMsgListener();
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => { msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
// 下线通知 // 下线通知
this.context.logger.logError.bind(this.context.logger)('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc); this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
this.selfInfo.online = false; this.selfInfo.online = false;
}; };
msgListener.onRecvMsg = (msgs) => { msgListener.onRecvMsg = (msgs) => {

View File

@@ -163,7 +163,7 @@ export interface NodeIKernelGroupService {
getGroupPortrait(): void; getGroupPortrait(): void;
modifyGroupName(groupCode: string, groupName: string, arg: false): void; modifyGroupName(groupCode: string, groupName: string, isNormalMember: boolean): Promise<GeneralCallResult>;
modifyGroupRemark(groupCode: string, remark: string): void; modifyGroupRemark(groupCode: string, remark: string): void;

View File

@@ -1,6 +1,16 @@
//LiteLoader需要提供部分IPC接口以便于其他插件调用 //LiteLoader需要提供部分IPC接口以便于其他插件调用
const { ipcMain } = require('electron'); const { ipcMain } = require('electron');
const napcat = require('./napcat.cjs'); const napcat = require('./napcat.cjs');
const { shell } = require('electron');
ipcMain.handle('napcat_get_webtoken', async (event, arg) => { ipcMain.handle('napcat_get_webtoken', async (event, arg) => {
return napcat.NCgetWebUiUrl(); return napcat.NCgetWebUiUrl();
}); });
ipcMain.on('open_external_url', (event, url) => {
shell.openExternal(url);
});
ipcMain.handle('napcat_get_reactweb', async (event, arg) => {
let url = new URL(await napcat.NCgetWebUiUrl());
let port = url.port;
let token = url.searchParams.get('token');
return `https://napcat.152710.xyz/web_login?back=http://127.0.0.1:${port}&token=${token}`;
});

View File

@@ -58,7 +58,7 @@ export async function NCoreInitFramework(
await loaderObject.core.initCore(); await loaderObject.core.initCore();
//启动WebUi //启动WebUi
InitWebUi(logger, pathWrapper).then().catch(logger.logError.bind(logger)); InitWebUi(logger, pathWrapper).then().catch(e => logger.logError(e));
//初始化LLNC的Onebot实现 //初始化LLNC的Onebot实现
await new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper).InitOneBot(); await new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper).InitOneBot();
} }

View File

@@ -1,10 +1,14 @@
const { contextBridge } = require('electron'); const { contextBridge, ipcRenderer } = require('electron');
const { ipcRenderer } = require('electron');
const napcat = { const napcat = {
getWebUiUrl: async () => { getWebUiUrl: async () => {
return ipcRenderer.invoke('napcat_get_webtoken'); return ipcRenderer.invoke('napcat_get_webtoken');
}, },
openExternalUrl: async (url) => {
ipcRenderer.send('open_external_url', url);
},
getWebUiUrlReact: async () => {
return ipcRenderer.invoke('napcat_get_reactweb');
}
}; };
// 在window对象下导出只读对象 // 在window对象下导出只读对象
contextBridge.exposeInMainWorld('napcat', napcat); contextBridge.exposeInMainWorld('napcat', napcat);

View File

@@ -1,27 +1,20 @@
export const onSettingWindowCreated = async (view) => { export const onSettingWindowCreated = async (view) => {
// view.style.width = "100%";
// view.style.height = "100%";
// //添加iframe
// const iframe = document.createElement("iframe");
// iframe.src = await window.napcat.getWebUiUrl();
// iframe.width = "100%";
// iframe.height = "100%";
// iframe.style.border = "none";
// //去掉iframe滚动条
// //iframe.scrolling = "no";
// //有滚动条何尝不是一种美
// view.appendChild(iframe);
let webui = await window.napcat.getWebUiUrl(); let webui = await window.napcat.getWebUiUrl();
let webuiReact = await window.napcat.getWebUiUrlReact();
view.innerHTML = ` view.innerHTML = `
<setting-section data-title=""> <setting-section data-title="">
<setting-panel> <setting-panel>
<setting-list data-direction="column"> <setting-list data-direction="column">
<setting-item> <setting-item>
<setting-button data-type="primary" class="nc_openwebui">打开配置页面</setting-button> <setting-button data-type="primary" class="nc_openwebui">在QQ内打开配置页面(VUE)</setting-button>
<setting-button data-type="primary" class="nc_openwebui_ex">在默认浏览器打开配置页面(VUE)</setting-button>
</setting-item>
<setting-item>
<setting-button data-type="primary" class="nc_openwebui_ex_react">在默认浏览器打开配置页面(React)</setting-button>
</setting-item> </setting-item>
<setting-item> <setting-item>
<div> <div>
<setting-text>WebUi远程地址可以点击下方复制哦~</setting-text>
<setting-text class="nc_webui">WebUi</setting-text> <setting-text class="nc_webui">WebUi</setting-text>
</div> </div>
</setting-item> </setting-item>
@@ -29,8 +22,27 @@ export const onSettingWindowCreated = async (view) => {
</setting-panel> </setting-panel>
</setting-section> </setting-section>
`; `;
view.querySelector('.nc_openwebui').addEventListener('click', () => { view.querySelector('.nc_openwebui').addEventListener('click', () => {
window.open(webui, '_blank'); window.open(webui, '_blank');
}); });
view.querySelector('.nc_openwebui_ex').addEventListener('click', () => {
window.napcat.openExternalUrl(webui);
});
view.querySelector('.nc_openwebui_ex_react').addEventListener('click', () => {
window.napcat.openExternalUrl(webuiReact);
});
view.querySelector('.nc_webui').innerText = webui; view.querySelector('.nc_webui').innerText = webui;
};
// 添加点击复制功能
view.querySelector('.nc_webui').addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(webui);
alert('WebUi URL 已复制到剪贴板');
} catch (err) {
console.error('复制到剪贴板失败: ', err);
}
});
};

View File

@@ -42,7 +42,7 @@ export abstract class OneBotAction<PayloadType, ReturnDataType> {
protected async check(payload: PayloadType): Promise<BaseCheckResult> { protected async check(payload: PayloadType): Promise<BaseCheckResult> {
if (this.payloadSchema) { if (this.payloadSchema) {
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.payloadSchema); this.validate = new Ajv({ allowUnionTypes: true, useDefaults: true }).compile(this.payloadSchema);
} }
if (this.validate && !this.validate(payload)) { if (this.validate && !this.validate(payload)) {
const errors = this.validate.errors as ErrorObject[]; const errors = this.validate.errors as ErrorObject[];

View File

@@ -1,17 +1,13 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Type, Static } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', rawData: Type.String(),
properties: { brief: Type.String(),
rawData: { type: 'string' }, });
brief: { type: 'string' },
},
required: ['brief', 'rawData'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class CreateCollection extends OneBotAction<Payload, any> { export class CreateCollection extends OneBotAction<Payload, any> {
actionName = ActionName.CreateCollection; actionName = ActionName.CreateCollection;
@@ -25,4 +21,4 @@ export class CreateCollection extends OneBotAction<Payload, any> {
payload.brief, payload.rawData, payload.brief, payload.rawData,
); );
} }
} }

View File

@@ -1,23 +1,19 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Type, Static } from '@sinclair/typebox';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', count: Type.Union([Type.Number(), Type.String()], { default: 48 }),
properties: { });
count: { type: ['number', 'string'] },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class FetchCustomFace extends OneBotAction<Payload, string[]> { export class FetchCustomFace extends OneBotAction<Payload, string[]> {
actionName = ActionName.FetchCustomFace; actionName = ActionName.FetchCustomFace;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa const ret = await this.core.apis.MsgApi.fetchFavEmojiList(+payload.count);
const ret = await this.core.apis.MsgApi.fetchFavEmojiList(+(payload.count ?? 48));
return ret.emojiInfoList.map(e => e.url); return ret.emojiInfoList.map(e => e.url);
} }
} }

View File

@@ -1,32 +1,27 @@
//getMsgEmojiLikesList import { Type, Static } from '@sinclair/typebox';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { emojiId: Type.Union([Type.Number(), Type.String()]),
user_id: { type: 'string' }, emojiType: Type.Union([Type.Number(), Type.String()]),
group_id: { type: 'string' }, count: Type.Union([Type.Number(), Type.String()], { default: 20 }),
emojiId: { type: 'string' }, });
emojiType: { type: 'string' },
message_id: { type: ['string', 'number'] },
count: { type: ['string', 'number'] },
},
required: ['emojiId', 'emojiType', 'message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class FetchEmojiLike extends OneBotAction<Payload, any> { export class FetchEmojiLike extends OneBotAction<Payload, any> {
actionName = ActionName.FetchEmojiLike; actionName = ActionName.FetchEmojiLike;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msgIdPeer) throw new Error('消息不存在'); if (!msgIdPeer) throw new Error('消息不存在');
const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0]; const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
return await this.core.apis.MsgApi.getMsgEmojiLikesList(msgIdPeer.Peer, msg.msgSeq, payload.emojiId, payload.emojiType, +(payload.count ?? 20)); return await this.core.apis.MsgApi.getMsgEmojiLikesList(
msgIdPeer.Peer, msg.msgSeq, payload.emojiId.toString(), payload.emojiType.toString(), +payload.count
);
} }
} }

View File

@@ -1,11 +1,17 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
export class FetchUserProfileLike extends OneBotAction<{ qq: number }, any> { const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
});
type Payload = Static<typeof SchemaData>;
export class FetchUserProfileLike extends OneBotAction<Payload, any> {
actionName = ActionName.FetchUserProfileLike; actionName = ActionName.FetchUserProfileLike;
async _handle(payload: { qq: number }) { async _handle(payload: Payload) {
if (!payload.qq) throw new Error('qq is required'); return await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
return await this.core.apis.UserApi.getUidByUinV2(payload.qq.toString());
} }
} }

View File

@@ -1,18 +1,14 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
import { Type, Static } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { chat_type: Type.Union([Type.Union([Type.Number(), Type.String()])], { default: 1 }),
group_id: { type: ['number', 'string'] }, });
chat_type: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
interface GetAiCharactersResponse { interface GetAiCharactersResponse {
type: string; type: string;
@@ -28,7 +24,7 @@ export class GetAiCharacters extends GetPacketStatusDepends<Payload, GetAiCharac
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const rawList = await this.core.apis.PacketApi.pkt.operation.FetchAiVoiceList(+payload.group_id, +(payload.chat_type ?? 1) as AIVoiceChatType); const rawList = await this.core.apis.PacketApi.pkt.operation.FetchAiVoiceList(+payload.group_id, +payload.chat_type as AIVoiceChatType);
return rawList?.map((item) => ({ return rawList?.map((item) => ({
type: item.category, type: item.category,
characters: item.voices.map((voice) => ({ characters: item.voices.map((voice) => ({

View File

@@ -1,23 +1,19 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Type, Static } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', category: Type.Union([Type.Number(), Type.String()]),
properties: { count: Type.Union([Type.Union([Type.Number(), Type.String()])], { default: 1 }),
category: { type: ['number', 'string'] }, });
count: { type: ['number', 'string'] },
},
required: ['category', 'count'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetCollectionList extends OneBotAction<Payload, any> { export class GetCollectionList extends OneBotAction<Payload, any> {
actionName = ActionName.GetCollectionList; actionName = ActionName.GetCollectionList;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
return await this.core.apis.CollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1)); return await this.core.apis.CollectionApi.getAllCollection(+payload.category, +payload.count);
} }
} }

View File

@@ -1,16 +1,11 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
});
const SchemaData = { type Payload = Static<typeof SchemaData>;
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupInfoEx extends OneBotAction<Payload, any> { export class GetGroupInfoEx extends OneBotAction<Payload, any> {
actionName = ActionName.GetGroupInfoEx; actionName = ActionName.GetGroupInfoEx;

View File

@@ -1,47 +1,37 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { MiniAppInfo, MiniAppInfoHelper } from "@/core/packet/utils/helper/miniAppHelper"; import { MiniAppInfo, MiniAppInfoHelper } from "@/core/packet/utils/helper/miniAppHelper";
import { MiniAppData, MiniAppRawData, MiniAppReqCustomParams, MiniAppReqParams } from "@/core/packet/entities/miniApp"; import { MiniAppData, MiniAppRawData, MiniAppReqCustomParams, MiniAppReqParams } from "@/core/packet/entities/miniApp";
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Union([
type: 'object', Type.Object({
properties: { type: Type.Union([Type.Literal('bili'), Type.Literal('weibo')]),
type: { title: Type.String(),
type: 'string', desc: Type.String(),
enum: ['bili', 'weibo'] picUrl: Type.String(),
}, jumpUrl: Type.String(),
title: { type: 'string' }, rawArkData: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
desc: { type: 'string' }, }),
picUrl: { type: 'string' }, Type.Object({
jumpUrl: { type: 'string' }, title: Type.String(),
iconUrl: { type: 'string' }, desc: Type.String(),
sdkId: { type: 'string' }, picUrl: Type.String(),
appId: { type: 'string' }, jumpUrl: Type.String(),
scene: { type: ['number', 'string'] }, iconUrl: Type.String(),
templateType: { type: ['number', 'string'] }, appId: Type.String(),
businessType: { type: ['number', 'string'] }, scene: Type.Union([Type.Number(), Type.String()]),
verType: { type: ['number', 'string'] }, templateType: Type.Union([Type.Number(), Type.String()]),
shareType: { type: ['number', 'string'] }, businessType: Type.Union([Type.Number(), Type.String()]),
versionId: { type: 'string' }, verType: Type.Union([Type.Number(), Type.String()]),
withShareTicket: { type: ['number', 'string'] }, shareType: Type.Union([Type.Number(), Type.String()]),
rawArkData: { type: ['boolean', 'string'] } versionId: Type.String(),
}, sdkId: Type.String(),
oneOf: [ withShareTicket: Type.Union([Type.Number(), Type.String()]),
{ rawArkData: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
required: ['type', 'title', 'desc', 'picUrl', 'jumpUrl'] })
}, ]);
{ type Payload = Static<typeof SchemaData>;
required: [
'title', 'desc', 'picUrl', 'jumpUrl',
'iconUrl', 'appId', 'scene', 'templateType', 'businessType',
'verType', 'shareType', 'versionId', 'withShareTicket'
]
}
]
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetMiniAppArk extends GetPacketStatusDepends<Payload, { export class GetMiniAppArk extends GetPacketStatusDepends<Payload, {
data: MiniAppData | MiniAppRawData data: MiniAppData | MiniAppRawData
@@ -57,7 +47,7 @@ export class GetMiniAppArk extends GetPacketStatusDepends<Payload, {
picUrl: payload.picUrl, picUrl: payload.picUrl,
jumpUrl: payload.jumpUrl jumpUrl: payload.jumpUrl
} as MiniAppReqCustomParams; } as MiniAppReqCustomParams;
if (payload.type) { if ('type' in payload) {
reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template); reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template);
} else { } else {
const { appId, scene, iconUrl, templateType, businessType, verType, shareType, versionId, withShareTicket } = payload; const { appId, scene, iconUrl, templateType, businessType, verType, shareType, versionId, withShareTicket } = payload;

View File

@@ -1,34 +1,28 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Type, Static } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
properties: { start: Type.Union([Type.Number(), Type.String()], { default: 0 }),
user_id: { type: ['number', 'string'] }, count: Type.Union([Type.Number(), Type.String()], { default: 10 }),
start: { type: ['number', 'string'] }, type: Type.Union([Type.Number(), Type.String()], { default: 2 }),
count: { type: ['number', 'string'] }, });
type: { type: ['number', 'string'] },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetProfileLike extends OneBotAction<Payload, any> { export class GetProfileLike extends OneBotAction<Payload, any> {
actionName = ActionName.GetProfileLike; actionName = ActionName.GetProfileLike;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const start = payload.start ? Number(payload.start) : 0;
const count = payload.count ? Number(payload.count) : 10;
const type = payload.count ? Number(payload.count) : 2;
const user_uid = const user_uid =
this.core.selfInfo.uin === payload.user_id || !payload.user_id ? this.core.selfInfo.uin === payload.user_id || !payload.user_id ?
this.core.selfInfo.uid : this.core.selfInfo.uid :
await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString()); await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const ret = await this.core.apis.UserApi.getProfileLike(user_uid ?? this.core.selfInfo.uid, start, count, type); const ret = await this.core.apis.UserApi.getProfileLike(user_uid ?? this.core.selfInfo.uid, +payload.start, +payload.count, +payload.type);
const listdata = ret.info.userLikeInfos[0].voteInfo.userInfos; const listdata = ret.info.userLikeInfos[0].voteInfo.userInfos;
for (const item of listdata) { for (const item of listdata) {
item.uin = parseInt((await this.core.apis.UserApi.getUinByUidV2(item.uid)) || ''); item.uin = +((await this.core.apis.UserApi.getUinByUidV2(item.uid)) ?? '');
} }
return ret.info.userLikeInfos[0].voteInfo; return ret.info.userLikeInfos[0].voteInfo;
} }

View File

@@ -1,8 +1,7 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
export class GetRkey extends GetPacketStatusDepends<void, Array<any>> {
export class GetRkey extends GetPacketStatusDepends<null, Array<any>> {
actionName = ActionName.GetRkey; actionName = ActionName.GetRkey;
async _handle() { async _handle() {

View File

@@ -4,7 +4,7 @@ import { ActionName } from '@/onebot/action/router';
export class GetRobotUinRange extends OneBotAction<void, Array<any>> { export class GetRobotUinRange extends OneBotAction<void, Array<any>> {
actionName = ActionName.GetRobotUinRange; actionName = ActionName.GetRobotUinRange;
async _handle(payload: void) { async _handle() {
return await this.core.apis.UserApi.getRobotUinRange(); return await this.core.apis.UserApi.getRobotUinRange();
} }
} }

View File

@@ -1,16 +1,12 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
// no_cache get时传字符串 import { Static, Type } from '@sinclair/typebox';
const SchemaData = {
type: 'object',
properties: {
user_id: { type: ['number', 'string'] },
},
required: ['user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
});
type Payload = Static<typeof SchemaData>;
export class GetUserStatus extends GetPacketStatusDepends<Payload, { status: number; ext_status: number; } | undefined> { export class GetUserStatus extends GetPacketStatusDepends<Payload, { status: number; ext_status: number; } | undefined> {
actionName = ActionName.GetUserStatus; actionName = ActionName.GetUserStatus;

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { checkFileExist, uri2local } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import fs from 'fs'; import fs from 'fs';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', image: Type.String(),
properties: { });
image: { type: 'string' },
},
required: ['image'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class OCRImage extends OneBotAction<Payload, any> { export class OCRImage extends OneBotAction<Payload, any> {
actionName = ActionName.OCRImage; actionName = ActionName.OCRImage;
@@ -29,12 +25,12 @@ export class OCRImage extends OneBotAction<Payload, any> {
fs.unlink(path, () => { }); fs.unlink(path, () => { });
if (!ret) { if (!ret) {
throw new Error(`OCR ${payload.file}失败`); throw new Error(`OCR ${payload.image}失败`);
} }
return ret.result; return ret.result;
} }
fs.unlink(path, () => { }); fs.unlink(path, () => { });
throw new Error(`OCR ${payload.file}失败,文件可能不存在`); throw new Error(`OCR ${payload.image}失败,文件可能不存在`);
} }
} }

View File

@@ -1,16 +1,12 @@
import { GetPacketStatusDepends } from '@/onebot/action/packet/GetPacketStatus'; import { GetPacketStatusDepends } from '@/onebot/action/packet/GetPacketStatus';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetGroupSign extends GetPacketStatusDepends<Payload, any> { export class SetGroupSign extends GetPacketStatusDepends<Payload, any> {
actionName = ActionName.SetGroupSign; actionName = ActionName.SetGroupSign;

View File

@@ -1,18 +1,14 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { ChatType } from '@/core'; import { ChatType } from '@/core';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Union([Type.Number(), Type.String()]),
properties: { event_type: Type.Number(),
event_type: { type: 'number' }, });
user_id: { type: ['number', 'string'] },
},
required: ['event_type', 'user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetInputStatus extends OneBotAction<Payload, any> { export class SetInputStatus extends OneBotAction<Payload, any> {
actionName = ActionName.SetInputStatus; actionName = ActionName.SetInputStatus;

View File

@@ -1,16 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', longNick: Type.String(),
properties: { });
longNick: { type: 'string' },
},
required: ['longNick'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetLongNick extends OneBotAction<Payload, any> { export class SetLongNick extends OneBotAction<Payload, any> {
actionName = ActionName.SetLongNick; actionName = ActionName.SetLongNick;

View File

@@ -1,19 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
// 设置在线状态
const SchemaData = { const SchemaData = Type.Object({
type: 'object', status: Type.Union([Type.Number(), Type.String()]),
properties: { ext_status: Type.Union([Type.Number(), Type.String()]),
status: { type: ['number', 'string'] }, battery_status: Type.Union([Type.Number(), Type.String()]),
ext_status: { type: ['number', 'string'] }, });
battery_status: { type: ['number', 'string'] },
},
required: ['status', 'ext_status', 'battery_status'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetOnlineStatus extends OneBotAction<Payload, null> { export class SetOnlineStatus extends OneBotAction<Payload, null> {
actionName = ActionName.SetOnlineStatus; actionName = ActionName.SetOnlineStatus;
@@ -21,9 +16,9 @@ export class SetOnlineStatus extends OneBotAction<Payload, null> {
async _handle(payload: Payload) { async _handle(payload: Payload) {
const ret = await this.core.apis.UserApi.setSelfOnlineStatus( const ret = await this.core.apis.UserApi.setSelfOnlineStatus(
parseInt(payload.status.toString()), +payload.status,
parseInt(payload.ext_status.toString()), +payload.ext_status,
parseInt(payload.battery_status.toString()), +payload.battery_status,
); );
if (ret.result !== 0) { if (ret.result !== 0) {
throw new Error('设置在线状态失败'); throw new Error('设置在线状态失败');

View File

@@ -1,28 +1,18 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName, BaseCheckResult } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import * as fs from 'node:fs'; import fs from 'node:fs/promises';
import { checkFileExist, uri2local } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import { Static, Type } from '@sinclair/typebox';
interface Payload { const SchemaData = Type.Object({
file: string; file: Type.String(),
} });
type Payload = Static<typeof SchemaData>;
export default class SetAvatar extends OneBotAction<Payload, null> { export default class SetAvatar extends OneBotAction<Payload, null> {
actionName = ActionName.SetQQAvatar; actionName = ActionName.SetQQAvatar;
payloadSchema = SchemaData;
// 用不着复杂检测
protected async check(payload: Payload): Promise<BaseCheckResult> {
if (!payload.file || typeof payload.file != 'string') {
return {
valid: false,
message: 'file字段不能为空或者类型错误',
};
}
return {
valid: true,
};
}
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) { if (!success) {
@@ -31,9 +21,7 @@ export default class SetAvatar extends OneBotAction<Payload, null> {
if (path) { if (path) {
await checkFileExist(path, 5000);// 避免崩溃 await checkFileExist(path, 5000);// 避免崩溃
const ret = await this.core.apis.UserApi.setQQAvatar(path); const ret = await this.core.apis.UserApi.setQQAvatar(path);
fs.unlink(path, () => { fs.unlink(path).catch(() => { });
});
if (!ret) { if (!ret) {
throw new Error(`头像${payload.file}设置失败,api无返回`); throw new Error(`头像${payload.file}设置失败,api无返回`);
} }
@@ -44,8 +32,7 @@ export default class SetAvatar extends OneBotAction<Payload, null> {
throw new Error(`头像${payload.file}设置失败,未知的错误,${ret.result}:${ret.errMsg}`); throw new Error(`头像${payload.file}设置失败,未知的错误,${ret.result}:${ret.errMsg}`);
} }
} else { } else {
fs.unlink(path, () => { }); fs.unlink(path).catch(() => { });
throw new Error(`头像${payload.file}设置失败,无法获取头像,文件可能不存在`); throw new Error(`头像${payload.file}设置失败,无法获取头像,文件可能不存在`);
} }
return null; return null;

View File

@@ -1,17 +1,14 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
const SchemaData = { import { Static, Type } from '@sinclair/typebox';
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
user_id: { type: ['number', 'string'] },
special_title: { type: 'string' },
},
required: ['group_id', 'user_id', 'special_title'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
user_id: Type.Union([Type.Number(), Type.String()]),
special_title: Type.String(),
});
type Payload = Static<typeof SchemaData>;
export class SetSpecialTittle extends GetPacketStatusDepends<Payload, any> { export class SetSpecialTittle extends GetPacketStatusDepends<Payload, any> {
actionName = ActionName.SetSpecialTittle; actionName = ActionName.SetSpecialTittle;

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
properties: { group_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
user_id: { type: 'string' }, phoneNumber: Type.String({ default: '' }),
group_id: { type: 'string' }, });
phoneNumber: { type: 'string' },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
type Payload = Static<typeof SchemaData>;
export class SharePeer extends OneBotAction<Payload, any> { export class SharePeer extends OneBotAction<Payload, any> {
actionName = ActionName.SharePeer; actionName = ActionName.SharePeer;
@@ -20,28 +16,24 @@ export class SharePeer extends OneBotAction<Payload, any> {
async _handle(payload: Payload) { async _handle(payload: Payload) {
if (payload.group_id) { if (payload.group_id) {
return await this.core.apis.GroupApi.getGroupRecommendContactArkJson(payload.group_id); return await this.core.apis.GroupApi.getGroupRecommendContactArkJson(payload.group_id.toString());
} else if (payload.user_id) { } else if (payload.user_id) {
return await this.core.apis.UserApi.getBuddyRecommendContactArkJson(payload.user_id, payload.phoneNumber || ''); return await this.core.apis.UserApi.getBuddyRecommendContactArkJson(payload.user_id.toString(), payload.phoneNumber);
} }
} }
} }
const SchemaDataGroupEx = { const SchemaDataGroupEx = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: 'string' },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type PayloadGroupEx = FromSchema<typeof SchemaDataGroupEx>; type PayloadGroupEx = Static<typeof SchemaDataGroupEx>;
export class ShareGroupEx extends OneBotAction<PayloadGroupEx, any> { export class ShareGroupEx extends OneBotAction<PayloadGroupEx, any> {
actionName = ActionName.ShareGroupEx; actionName = ActionName.ShareGroupEx;
payloadSchema = SchemaDataGroupEx; payloadSchema = SchemaDataGroupEx;
async _handle(payload: PayloadGroupEx) { async _handle(payload: PayloadGroupEx) {
return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id); return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id.toString());
} }
} }

View File

@@ -1,19 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', words: Type.Array(Type.String()),
properties: { });
words: {
type: 'array',
items: { type: 'string' },
},
},
required: ['words'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class TranslateEnWordToZn extends OneBotAction<Payload, Array<any> | null> { export class TranslateEnWordToZn extends OneBotAction<Payload, Array<any> | null> {
actionName = ActionName.TranslateEnWordToZn; actionName = ActionName.TranslateEnWordToZn;

View File

@@ -2,12 +2,8 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { FileNapCatOneBotUUID } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types'; import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
import { Static, Type } from '@sinclair/typebox';
// interface GetFilePayload {
// file: string; // 文件名或者fileUuid
// }
export interface GetFileResponse { export interface GetFileResponse {
file?: string; // path file?: string; // path
@@ -16,19 +12,14 @@ export interface GetFileResponse {
file_name?: string; file_name?: string;
base64?: string; base64?: string;
} }
const GetFileBase_PayloadSchema = {
type: 'object',
properties: {
file: { type: 'string' },
file_id: { type: 'string' }
},
oneOf: [
{ required: ['file'] },
{ required: ['file_id'] }
]
} as const satisfies JSONSchema;
export type GetFilePayload = FromSchema<typeof GetFileBase_PayloadSchema>; const GetFileBase_PayloadSchema = Type.Object({
file: Type.Optional(Type.String()),
file_id: Type.Optional(Type.String())
});
export type GetFilePayload = Static<typeof GetFileBase_PayloadSchema>;
export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> { export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> {
payloadSchema = GetFileBase_PayloadSchema; payloadSchema = GetFileBase_PayloadSchema;
@@ -50,12 +41,12 @@ export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> {
let url = ''; let url = '';
if (mixElement?.picElement && rawMessage) { if (mixElement?.picElement && rawMessage) {
const tempData = const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement) as OB11MessageImage | undefined; await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement, { parseMultMsg: false }) as OB11MessageImage | undefined;
url = tempData?.data.url ?? ''; url = tempData?.data.url ?? '';
} }
if (mixElement?.videoElement && rawMessage) { if (mixElement?.videoElement && rawMessage) {
const tempData = const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement) as OB11MessageVideo | undefined; await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement, { parseMultMsg: false }) as OB11MessageVideo | undefined;
url = tempData?.data.url ?? ''; url = tempData?.data.url ?? '';
} }
const res: GetFileResponse = { const res: GetFileResponse = {

View File

@@ -1,18 +1,14 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { FileNapCatOneBotUUID } from "@/common/helper"; import { FileNapCatOneBotUUID } from "@/common/helper";
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { file_id: Type.String(),
group_id: { type: ['number', 'string'] }, });
file_id: { type: ['string'] },
},
required: ['group_id', 'file_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
interface GetGroupFileUrlResponse { interface GetGroupFileUrlResponse {
url?: string; url?: string;

View File

@@ -1,17 +1,13 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { folder_name: Type.String(),
group_id: { type: ['string', 'number'] }, });
folder_name: { type: 'string' },
},
required: ['group_id', 'folder_name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class CreateGroupFileFolder extends OneBotAction<Payload, any> { export class CreateGroupFileFolder extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder; actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;

View File

@@ -1,18 +1,15 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FileNapCatOneBotUUID } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { file_id: Type.String(),
group_id: { type: ['string', 'number'] }, });
file_id: { type: 'string' },
},
required: ['group_id', 'file_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class DeleteGroupFile extends OneBotAction<Payload, any> { export class DeleteGroupFile extends OneBotAction<Payload, any> {
actionName = ActionName.GOCQHTTP_DeleteGroupFile; actionName = ActionName.GOCQHTTP_DeleteGroupFile;

View File

@@ -1,18 +1,14 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { folder_id: Type.Optional(Type.String()),
group_id: { type: ['string', 'number'] }, folder: Type.Optional(Type.String()),
folder_id: { type: 'string' }, });
folder: { type: 'string' }
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class DeleteGroupFileFolder extends OneBotAction<Payload, any> { export class DeleteGroupFileFolder extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder; actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;

View File

@@ -4,29 +4,20 @@ import fs from 'fs';
import { join as joinPath } from 'node:path'; import { join as joinPath } from 'node:path';
import { calculateFileMD5, httpDownload } from '@/common/file'; import { calculateFileMD5, httpDownload } from '@/common/file';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
interface FileResponse { interface FileResponse {
file: string; file: string;
} }
const SchemaData = { const SchemaData = Type.Object({
type: 'object', url: Type.Optional(Type.String()),
properties: { base64: Type.Optional(Type.String()),
thread_count: { type: ['number', 'string'] }, name: Type.Optional(Type.String()),
url: { type: 'string' }, headers: Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())])),
base64: { type: 'string' }, });
name: { type: 'string' },
headers: {
type: ['string', 'array'],
items: {
type: 'string',
},
},
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class GoCQHTTPDownloadFile extends OneBotAction<Payload, FileResponse> { export default class GoCQHTTPDownloadFile extends OneBotAction<Payload, FileResponse> {
actionName = ActionName.GoCQHTTP_DownloadFile; actionName = ActionName.GoCQHTTP_DownloadFile;

View File

@@ -1,20 +1,15 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { OB11Message, OB11MessageData, OB11MessageDataType, OB11MessageForward, OB11MessageNodePlain as OB11MessageNode } from '@/onebot'; import { OB11Message, OB11MessageData, OB11MessageDataType, OB11MessageForward, OB11MessageNodePlain as OB11MessageNode } from '@/onebot';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
message_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
});
type Payload = Static<typeof SchemaData>;
const SchemaData = {
type: 'object',
properties: {
message_id: { type: 'string' },
id: { type: 'string' },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, any> { export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetForwardMsg; actionName = ActionName.GoCQHTTP_GetForwardMsg;
@@ -60,7 +55,7 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, any> {
throw new Error('message_id is required'); throw new Error('message_id is required');
} }
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId); const rootMsgId = MessageUnique.getShortIdByMsgId(msgId.toString());
const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId ?? +msgId); const rootMsg = MessageUnique.getMsgIdAndPeerByShortId(rootMsgId ?? +msgId);
if (!rootMsg) { if (!rootMsg) {
throw new Error('msg not found'); throw new Error('msg not found');

View File

@@ -2,26 +2,22 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import { OB11Message } from '@/onebot'; import { OB11Message } from '@/onebot';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { ChatType } from '@/core/types'; import { ChatType } from '@/core/types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { AdapterConfigWrap } from '@/onebot/config/config'; import { AdapterConfigWrap } from '@/onebot/config/config';
import { Static, Type } from '@sinclair/typebox';
interface Response { interface Response {
messages: OB11Message[]; messages: OB11Message[];
} }
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
message_seq: Type.Optional(Type.Union([Type.Number(), Type.String()])),
count: Type.Union([Type.Number(), Type.String()], { default: 20 }),
reverseOrder: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
});
const SchemaData = {
type: 'object',
properties: {
user_id: { type: ['number', 'string'] },
message_seq: { type: ['number', 'string'] },
count: { type: ['number', 'string'] },
reverseOrder: { type: ['boolean', 'string'] },
},
required: ['user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class GetFriendMsgHistory extends OneBotAction<Payload, Response> { export default class GetFriendMsgHistory extends OneBotAction<Payload, Response> {
actionName = ActionName.GetFriendMsgHistory; actionName = ActionName.GetFriendMsgHistory;
@@ -30,7 +26,7 @@ export default class GetFriendMsgHistory extends OneBotAction<Payload, Response>
async _handle(payload: Payload, adapter: string): Promise<Response> { async _handle(payload: Payload, adapter: string): Promise<Response> {
//处理参数 //处理参数
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const MsgCount = +(payload.count ?? 20);
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder; const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
if (!uid) throw new Error(`记录${payload.user_id}不存在`); if (!uid) throw new Error(`记录${payload.user_id}不存在`);
const friend = await this.core.apis.FriendApi.isBuddy(uid); const friend = await this.core.apis.FriendApi.isBuddy(uid);
@@ -38,7 +34,7 @@ export default class GetFriendMsgHistory extends OneBotAction<Payload, Response>
const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0'); const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0');
const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0'; const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0';
const msgList = hasMessageSeq ? const msgList = hasMessageSeq ?
(await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList; (await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, +payload.count)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, +payload.count)).msgList;
if (msgList.length === 0) throw new Error(`消息${payload.message_seq}不存在`); if (msgList.length === 0) throw new Error(`消息${payload.message_seq}不存在`);
//翻转消息 //翻转消息
if (isReverseOrder) msgList.reverse(); if (isReverseOrder) msgList.reverse();

View File

@@ -1,15 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()])
properties: { });
group_id: { type: ['number', 'string'] }
}, type Payload = Static<typeof SchemaData>;
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPGetGroupAtAllRemain extends OneBotAction<Payload, any> { export class GoCQHTTPGetGroupAtAllRemain extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetGroupAtAllRemain; actionName = ActionName.GoCQHTTP_GetGroupAtAllRemain;

View File

@@ -1,16 +1,12 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()])
properties: { });
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupFileSystemInfo extends OneBotAction<Payload, { export class GetGroupFileSystemInfo extends OneBotAction<Payload, {
file_count: number, file_count: number,

View File

@@ -1,20 +1,17 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { folder_id: Type.Optional(Type.String()),
group_id: { type: ['string', 'number'] }, folder: Type.Optional(Type.String()),
folder_id: { type: 'string' }, file_count: Type.Union([Type.Number(), Type.String()], { default: 50 }),
folder: { type: 'string' }, });
file_count: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupFilesByFolder extends OneBotAction<any, any> { export class GetGroupFilesByFolder extends OneBotAction<any, any> {
actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder; actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder;
@@ -23,7 +20,7 @@ export class GetGroupFilesByFolder extends OneBotAction<any, any> {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: +(payload.file_count ?? 50), fileCount: +payload.file_count,
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { WebHonorType } from '@/core/types'; import { WebHonorType } from '@/core/types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { type: Type.Optional(Type.Enum(WebHonorType))
group_id: { type: ['number', 'string'] }, });
type: { enum: [WebHonorType.ALL, WebHonorType.EMOTION, WebHonorType.LEGEND, WebHonorType.PERFORMER, WebHonorType.STRONG_NEWBIE, WebHonorType.TALKATIVE] },
}, type Payload = Static<typeof SchemaData>;
required: ['group_id'],
} as const satisfies JSONSchema;
// enum是不是有点抽象
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupHonorInfo extends OneBotAction<Payload, Array<any>> { export class GetGroupHonorInfo extends OneBotAction<Payload, Array<any>> {
actionName = ActionName.GetGroupHonorInfo; actionName = ActionName.GetGroupHonorInfo;

View File

@@ -2,26 +2,24 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import { OB11Message } from '@/onebot'; import { OB11Message } from '@/onebot';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { ChatType, Peer } from '@/core/types'; import { ChatType, Peer } from '@/core/types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { AdapterConfigWrap } from '@/onebot/config/config'; import { AdapterConfigWrap } from '@/onebot/config/config';
import { Static, Type } from '@sinclair/typebox';
interface Response { interface Response {
messages: OB11Message[]; messages: OB11Message[];
} }
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { message_seq: Type.Optional(Type.Union([Type.Number(), Type.String()])),
group_id: { type: ['number', 'string'] }, count: Type.Union([Type.Number(), Type.String()], { default: 20 }),
message_seq: { type: ['number', 'string'] }, reverseOrder: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
count: { type: ['number', 'string'] }, });
reverseOrder: { type: ['boolean', 'string'] },
},
required: ['group_id'], type Payload = Static<typeof SchemaData>;
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Response> { export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Response> {
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory; actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
@@ -30,13 +28,12 @@ export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Re
async _handle(payload: Payload, adapter: string): Promise<Response> { async _handle(payload: Payload, adapter: string): Promise<Response> {
//处理参数 //处理参数
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder; const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
const MsgCount = +(payload.count ?? 20);
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() }; const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0'); const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0');
//拉取消息 //拉取消息
const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0'; const startMsgId = hasMessageSeq ? (MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq!)?.MsgId ?? payload.message_seq!.toString()) : '0';
const msgList = hasMessageSeq ? const msgList = hasMessageSeq ?
(await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, MsgCount)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, MsgCount)).msgList; (await this.core.apis.MsgApi.getMsgHistory(peer, startMsgId, +payload.count)).msgList : (await this.core.apis.MsgApi.getAioFirstViewLatestMsgs(peer, +payload.count)).msgList;
if (msgList.length === 0) throw new Error(`消息${payload.message_seq}不存在`); if (msgList.length === 0) throw new Error(`消息${payload.message_seq}不存在`);
//翻转消息 //翻转消息
if (isReverseOrder) msgList.reverse(); if (isReverseOrder) msgList.reverse();

View File

@@ -1,19 +1,16 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OB11GroupFile, OB11GroupFileFolder } from '@/onebot'; import { OB11GroupFile, OB11GroupFileFolder } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { file_count: Type.Union([Type.Number(), Type.String()], { default: 50 }),
group_id: { type: ['string', 'number'] }, });
file_count: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupRootFiles extends OneBotAction<Payload, { export class GetGroupRootFiles extends OneBotAction<Payload, {
files: OB11GroupFile[], files: OB11GroupFile[],
@@ -24,7 +21,7 @@ export class GetGroupRootFiles extends OneBotAction<Payload, {
async _handle(payload: Payload) { async _handle(payload: Payload) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), { const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: +(payload.file_count ?? 50), fileCount: +payload.file_count,
startIndex: 0, startIndex: 0,
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,

View File

@@ -1,15 +1,7 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { JSONSchema } from 'json-schema-to-ts';
import { sleep } from '@/common/helper'; import { sleep } from '@/common/helper';
const SchemaData = {
type: 'object',
properties: {
no_cache: { type: 'boolean' },
},
} as const satisfies JSONSchema;
export class GetOnlineClient extends OneBotAction<void, Array<any>> { export class GetOnlineClient extends OneBotAction<void, Array<any>> {
actionName = ActionName.GetOnlineClient; actionName = ActionName.GetOnlineClient;

View File

@@ -2,18 +2,14 @@ import { OneBotAction } from '@/onebot/action/OneBotAction';
import { OB11User, OB11UserSex } from '@/onebot'; import { OB11User, OB11UserSex } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { calcQQLevel } from '@/common/helper'; import { calcQQLevel } from '@/common/helper';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
user_id: { type: ['number', 'string'] },
},
required: ['user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class GoCQHTTPGetStrangerInfo extends OneBotAction<Payload, OB11User> { export default class GoCQHTTPGetStrangerInfo extends OneBotAction<Payload, OB11User> {
actionName = ActionName.GoCQHTTP_GetStrangerInfo; actionName = ActionName.GoCQHTTP_GetStrangerInfo;

View File

@@ -1,15 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', url: Type.String(),
properties: { });
url: { type: 'string' },
}, type Payload = Static<typeof SchemaData>;
required: ['url'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPCheckUrlSafely extends OneBotAction<Payload, any> { export class GoCQHTTPCheckUrlSafely extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_CheckUrlSafely; actionName = ActionName.GoCQHTTP_CheckUrlSafely;

View File

@@ -1,22 +1,15 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', friend_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
properties: { user_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
friend_id: { type: ['string', 'number'] }, temp_block: Type.Optional(Type.Boolean()),
user_id: { type: ['string', 'number'] }, temp_both_del: Type.Optional(Type.Boolean()),
temp_block: { type: 'boolean' }, });
temp_both_del: { type: 'boolean' },
},
oneOf: [
{ required: ['friend_id'] },
{ required: ['user_id'] },
],
} as const satisfies JSONSchema; type Payload = Static<typeof SchemaData>;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPDeleteFriend extends OneBotAction<Payload, any> { export class GoCQHTTPDeleteFriend extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_DeleteFriend; actionName = ActionName.GoCQHTTP_DeleteFriend;

View File

@@ -1,14 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', model: Type.String(),
properties: { });
model: { type: 'string' },
} type Payload = Static<typeof SchemaData>;
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GoCQHTTPGetModelShow extends OneBotAction<Payload, any> { export class GoCQHTTPGetModelShow extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetModelShow; actionName = ActionName.GoCQHTTP_GetModelShow;

View File

@@ -1,19 +1,10 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
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 OneBotAction<Payload, any> { export class GoCQHTTPSetModelShow extends OneBotAction<void, any> {
actionName = ActionName.GoCQHTTP_SetModelShow; actionName = ActionName.GoCQHTTP_SetModelShow;
payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: void) {
return null; return null;
} }
} }

View File

@@ -13,7 +13,7 @@ export class GoCQHTTPHandleQuickAction extends OneBotAction<Payload, null> {
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
this.obContext.apis.QuickActionApi this.obContext.apis.QuickActionApi
.handleQuickOperation(payload.context, payload.operation) .handleQuickOperation(payload.context, payload.operation)
.catch(this.core.context.logger.logError.bind(this.core.context.logger)); .catch(e => this.core.context.logger.logError(e));
return null; return null;
} }
} }

View File

@@ -1,25 +1,21 @@
import { checkFileExist, uri2local } from '@/common/file'; import { checkFileExist, uri2local } from '@/common/file';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { unlink } from 'node:fs'; import { unlink } from 'node:fs/promises';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { content: Type.String(),
group_id: { type: ['number', 'string'] }, image: Type.Optional(Type.String()),
content: { type: 'string' }, pinned: Type.Union([Type.Number(), Type.String()], { default: 0 }),
image: { type: 'string' }, type: Type.Union([Type.Number(), Type.String()], { default: 1 }),
pinned: { type: ['number', 'string'] }, confirm_required: Type.Union([Type.Number(), Type.String()], { default: 1 }),
type: { type: ['number', 'string'] }, is_show_edit_card: Type.Union([Type.Number(), Type.String()], { default: 0 }),
confirm_required: { type: ['number', 'string'] }, tip_window_type: Type.Union([Type.Number(), Type.String()], { default: 0 })
is_show_edit_card: { type: ['number', 'string'] }, });
tip_window_type: { type: ['number', 'string'] },
},
required: ['group_id', 'content'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SendGroupNotice extends OneBotAction<Payload, null> { export class SendGroupNotice extends OneBotAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice; actionName = ActionName.GoCQHTTP_SendGroupNotice;
@@ -45,26 +41,18 @@ export class SendGroupNotice extends OneBotAction<Payload, null> {
throw new Error(`群公告${payload.image}设置失败,图片上传失败`); throw new Error(`群公告${payload.image}设置失败,图片上传失败`);
} }
unlink(path, () => { unlink(path).catch(() => { });
});
UploadImage = ImageUploadResult.picInfo; UploadImage = ImageUploadResult.picInfo;
} }
const noticeType = +(payload.type ?? 1);
const noticePinned = +(payload.pinned ?? 0);
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice( const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
payload.group_id.toString(), payload.group_id.toString(),
payload.content, payload.content,
noticePinned, +payload.pinned,
noticeType, +payload.type,
noticeShowEditCard, +payload.is_show_edit_card,
noticeTipWindowType, +payload.tip_window_type,
noticeConfirmRequired, +payload.confirm_required,
UploadImage?.id, UploadImage?.id,
UploadImage?.width, UploadImage?.width,
UploadImage?.height UploadImage?.height

View File

@@ -1,28 +1,18 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName, BaseCheckResult } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import * as fs from 'node:fs';
import { checkFileExistV2, uri2local } from '@/common/file'; import { checkFileExistV2, uri2local } from '@/common/file';
import { Static, Type } from '@sinclair/typebox';
import fs from 'node:fs/promises';
const SchemaData = Type.Object({
file: Type.String(),
group_id: Type.Union([Type.Number(), Type.String()])
});
interface Payload { type Payload = Static<typeof SchemaData>;
file: string,
group_id: number
}
export default class SetGroupPortrait extends OneBotAction<Payload, any> { export default class SetGroupPortrait extends OneBotAction<Payload, any> {
actionName = ActionName.SetGroupPortrait; actionName = ActionName.SetGroupPortrait;
payloadSchema = SchemaData;
// 用不着复杂检测
protected async check(payload: Payload): Promise<BaseCheckResult> {
if (!payload.file || typeof payload.file != 'string' || !payload.group_id || typeof payload.group_id != 'number') {
return {
valid: false,
message: 'file和group_id字段不能为空或者类型错误',
};
}
return {
valid: true,
};
}
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file)); const { path, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
@@ -32,7 +22,7 @@ export default class SetGroupPortrait extends OneBotAction<Payload, any> {
if (path) { if (path) {
await checkFileExistV2(path, 5000); // 文件不存在QQ会崩溃需要提前判断 await checkFileExistV2(path, 5000); // 文件不存在QQ会崩溃需要提前判断
const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path); const ret = await this.core.apis.GroupApi.setGroupAvatar(payload.group_id.toString(), path);
fs.unlink(path, () => { }); fs.unlink(path).catch(() => { });
if (!ret) { if (!ret) {
throw new Error(`头像${payload.file}设置失败,api无返回`); throw new Error(`头像${payload.file}设置失败,api无返回`);
} }
@@ -43,7 +33,7 @@ export default class SetGroupPortrait extends OneBotAction<Payload, any> {
} }
return ret; return ret;
} else { } else {
fs.unlink(path, () => { }); fs.unlink(path).catch(() => { });
throw new Error(`头像${payload.file}设置失败,无法获取头像,文件可能不存在`); throw new Error(`头像${payload.file}设置失败,无法获取头像,文件可能不存在`);
} }
} }

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', nickname: Type.String(),
properties: { personal_note: Type.Optional(Type.String()),
nickname: { type: 'string' }, sex: Type.Optional(Type.Union([Type.Number(), Type.String()])), // 传Sex值建议传0
personal_note: { type: 'string' }, });
sex: { type: ['number', 'string'] },//传Sex值建议传0
},
required: ['nickname'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetQQProfile extends OneBotAction<Payload, any> { export class SetQQProfile extends OneBotAction<Payload, any> {
actionName = ActionName.SetQQProfile; actionName = ActionName.SetQQProfile;

View File

@@ -3,22 +3,18 @@ import { ActionName } from '@/onebot/action/router';
import { ChatType, Peer } from '@/core/types'; import { ChatType, Peer } from '@/core/types';
import fs from 'fs'; import fs from 'fs';
import { uri2local } from '@/common/file'; import { uri2local } from '@/common/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { SendMessageContext } from '@/onebot/api';
import { MessageContext } from '@/onebot/api'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { file: Type.String(),
group_id: { type: ['number', 'string'] }, name: Type.String(),
file: { type: 'string' }, folder: Type.Optional(Type.String()),
name: { type: 'string' }, folder_id: Type.Optional(Type.String()),//临时扩展
folder: { type: 'string' }, });
folder_id: { type: 'string' },//临时扩展
},
required: ['group_id', 'file', 'name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class GoCQHTTPUploadGroupFile extends OneBotAction<Payload, null> { export default class GoCQHTTPUploadGroupFile extends OneBotAction<Payload, null> {
actionName = ActionName.GoCQHTTP_UploadGroupFile; actionName = ActionName.GoCQHTTP_UploadGroupFile;
@@ -37,7 +33,7 @@ export default class GoCQHTTPUploadGroupFile extends OneBotAction<Payload, null>
if (!downloadResult.success) { if (!downloadResult.success) {
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
const msgContext: MessageContext = { const msgContext: SendMessageContext = {
peer: peer, peer: peer,
deleteAfterSentFiles: [] deleteAfterSentFiles: []
}; };

View File

@@ -3,21 +3,17 @@ import { ActionName } from '@/onebot/action/router';
import { ChatType, Peer, SendFileElement } from '@/core/types'; import { ChatType, Peer, SendFileElement } from '@/core/types';
import fs from 'fs'; import fs from 'fs';
import { uri2local } from '@/common/file'; import { uri2local } from '@/common/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { SendMessageContext } from '@/onebot/api';
import { MessageContext } from '@/onebot/api';
import { ContextMode, createContext } from '@/onebot/action/msg/SendMsg'; import { ContextMode, createContext } from '@/onebot/action/msg/SendMsg';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Union([Type.Number(), Type.String()]),
properties: { file: Type.String(),
user_id: { type: ['number', 'string'] }, name: Type.String(),
file: { type: 'string' }, });
name: { type: 'string' },
},
required: ['user_id', 'file', 'name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, null> { export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, null> {
actionName = ActionName.GOCQHTTP_UploadPrivateFile; actionName = ActionName.GOCQHTTP_UploadPrivateFile;
@@ -45,7 +41,7 @@ export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, nul
throw new Error(downloadResult.errMsg); throw new Error(downloadResult.errMsg);
} }
const msgContext: MessageContext = { const msgContext: SendMessageContext = {
peer: await createContext(this.core, { peer: await createContext(this.core, {
user_id: payload.user_id.toString(), user_id: payload.user_id.toString(),
group_id: undefined, group_id: undefined,

View File

@@ -1,17 +1,13 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
message_id: { type: ['number', 'string'] },
},
required: ['message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class DelEssenceMsg extends OneBotAction<Payload, any> { export default class DelEssenceMsg extends OneBotAction<Payload, any> {
actionName = ActionName.DelEssenceMsg; actionName = ActionName.DelEssenceMsg;

View File

@@ -1,18 +1,13 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
notice_id: Type.String()
});
const SchemaData = { type Payload = Static<typeof SchemaData>;
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
notice_id: { type: 'string' },
},
required: ['group_id', 'notice_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DelGroupNotice extends OneBotAction<Payload, any> { export class DelGroupNotice extends OneBotAction<Payload, any> {
actionName = ActionName.DelGroupNotice; actionName = ActionName.DelGroupNotice;

View File

@@ -1,19 +1,15 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', character: Type.String(),
properties: { group_id: Type.Union([Type.Number(), Type.String()]),
character: { type: ['string'] }, text: Type.String(),
group_id: { type: ['number', 'string'] }, });
text: { type: 'string' },
},
required: ['character', 'group_id', 'text'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetAiRecord extends GetPacketStatusDepends<Payload, string> { export class GetAiRecord extends GetPacketStatusDepends<Payload, string> {
actionName = ActionName.GetAiRecord; actionName = ActionName.GetAiRecord;

View File

@@ -1,20 +1,16 @@
import { ChatType, Peer } from '@/core'; import { ChatType, Peer } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import crypto from 'crypto'; import crypto from 'crypto';
import { AdapterConfigWrap } from '@/onebot/config/config'; import { AdapterConfigWrap } from '@/onebot/config/config';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: ['number', 'string'] }
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupEssence extends OneBotAction<Payload, any> { export class GetGroupEssence extends OneBotAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetEssenceMsg; actionName = ActionName.GoCQHTTP_GetEssenceMsg;

View File

@@ -1,17 +1,6 @@
import { GroupNotifyMsgStatus } from '@/core'; import { GroupNotifyMsgStatus } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupIgnoredNotifies extends OneBotAction<void, any> { export class GetGroupIgnoredNotifies extends OneBotAction<void, any> {
actionName = ActionName.GetGroupIgnoredNotifies; actionName = ActionName.GetGroupIgnoredNotifies;

View File

@@ -2,17 +2,13 @@ import { OB11Group } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
class GetGroupInfo extends OneBotAction<Payload, OB11Group> { class GetGroupInfo extends OneBotAction<Payload, OB11Group> {
actionName = ActionName.GetGroupInfo; actionName = ActionName.GetGroupInfo;

View File

@@ -2,16 +2,13 @@ import { OB11Group } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
// no_cache get时传字符串
const SchemaData = {
type: 'object',
properties: {
no_cache: { type: ['boolean', 'string'] },
},
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; const SchemaData = Type.Object({
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
});
type Payload = Static<typeof SchemaData>;
class GetGroupList extends OneBotAction<Payload, OB11Group[]> { class GetGroupList extends OneBotAction<Payload, OB11Group[]> {
actionName = ActionName.GetGroupList; actionName = ActionName.GetGroupList;

View File

@@ -2,19 +2,15 @@ import { OB11GroupMember } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { user_id: Type.Union([Type.Number(), Type.String()]),
group_id: { type: ['number', 'string'] }, no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
user_id: { type: ['number', 'string'] }, });
no_cache: { type: ['boolean', 'string'] },
},
required: ['group_id', 'user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> { class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> {
actionName = ActionName.GetGroupMemberInfo; actionName = ActionName.GetGroupMemberInfo;

View File

@@ -2,18 +2,14 @@ import { OB11GroupMember } from '@/onebot';
import { OB11Construct } from '@/onebot/helper/data'; import { OB11Construct } from '@/onebot/helper/data';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
group_id: { type: ['number', 'string'] }, });
no_cache: { type: ['boolean', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupMemberList extends OneBotAction<Payload, OB11GroupMember[]> { export class GetGroupMemberList extends OneBotAction<Payload, OB11GroupMember[]> {
actionName = ActionName.GetGroupMemberList; actionName = ActionName.GetGroupMemberList;

View File

@@ -1,8 +1,7 @@
import { WebApiGroupNoticeFeed } from '@/core'; import { WebApiGroupNoticeFeed } from '@/core';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
interface GroupNotice { interface GroupNotice {
sender_id: number; sender_id: number;
publish_time: number; publish_time: number;
@@ -17,15 +16,11 @@ interface GroupNotice {
}; };
} }
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
type ApiGroupNotice = GroupNotice & WebApiGroupNoticeFeed; type ApiGroupNotice = GroupNotice & WebApiGroupNoticeFeed;

View File

@@ -1,16 +1,12 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
group_id: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class GetGroupShutList extends OneBotAction<Payload, any> { export class GetGroupShutList extends OneBotAction<Payload, any> {
actionName = ActionName.GetGroupShutList; actionName = ActionName.GetGroupShutList;

View File

@@ -1,17 +1,13 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
// no_cache get时传字符串 import { Static, Type } from '@sinclair/typebox';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
user_id: { type: ['number', 'string'] },
},
required: ['group_id', 'user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
user_id: Type.Union([Type.Number(), Type.String()]),
});
type Payload = Static<typeof SchemaData>;
export class GroupPoke extends GetPacketStatusDepends<Payload, any> { export class GroupPoke extends GetPacketStatusDepends<Payload, any> {
actionName = ActionName.GroupPoke; actionName = ActionName.GroupPoke;

View File

@@ -1,21 +1,18 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus"; import { GetPacketStatusDepends } from "@/onebot/action/packet/GetPacketStatus";
import { uri2local } from "@/common/file"; import { uri2local } from "@/common/file";
import { ChatType, Peer } from "@/core"; import { ChatType, Peer } from "@/core";
import { AIVoiceChatType } from "@/core/packet/entities/aiChat"; import { AIVoiceChatType } from "@/core/packet/entities/aiChat";
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', character: Type.String(),
properties: { group_id: Type.Union([Type.Number(), Type.String()]),
character: { type: ['string'] }, text: Type.String(),
group_id: { type: ['number', 'string'] }, });
text: { type: 'string' },
}, type Payload = Static<typeof SchemaData>;
required: ['character', 'group_id', 'text'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class SendGroupAiRecord extends GetPacketStatusDepends<Payload, { export class SendGroupAiRecord extends GetPacketStatusDepends<Payload, {
message_id: number message_id: number

View File

@@ -1,24 +1,20 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
message_id: { type: ['number', 'string'] },
},
required: ['message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetEssenceMsg extends OneBotAction<Payload, any> { export default class SetEssenceMsg extends OneBotAction<Payload, any> {
actionName = ActionName.SetEssenceMsg; actionName = ActionName.SetEssenceMsg;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> { async _handle(payload: Payload): Promise<any> {
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msg) { if (!msg) {
throw new Error('msg not found'); throw new Error('msg not found');
} }

View File

@@ -1,19 +1,15 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { NTGroupRequestOperateTypes } from '@/core/types'; import { NTGroupRequestOperateTypes } from '@/core/types';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', flag: Type.String(),
properties: { approve: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
flag: { type: 'string' }, reason: Type.Union([Type.String({ default: ' ' }), Type.Null()]),
approve: { type: ['string', 'boolean'] }, });
reason: { type: 'string', nullable: true },
},
required: ['flag'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetGroupAddRequest extends OneBotAction<Payload, null> { export default class SetGroupAddRequest extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupAddRequest; actionName = ActionName.SetGroupAddRequest;

View File

@@ -1,19 +1,15 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { NTGroupMemberRole } from '@/core/types'; import { NTGroupMemberRole } from '@/core/types';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { user_id: Type.Union([Type.Number(), Type.String()]),
group_id: { type: ['number', 'string'] }, enable: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
user_id: { type: ['number', 'string'] }, });
enable: { type: ['boolean', 'string'] },
},
required: ['group_id', 'user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetGroupAdmin extends OneBotAction<Payload, null> { export default class SetGroupAdmin extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupAdmin; actionName = ActionName.SetGroupAdmin;

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { user_id: Type.Union([Type.Number(), Type.String()]),
group_id: { type: ['number', 'string'] }, duration: Type.Union([Type.Number(), Type.String()], { default: 0 }),
user_id: { type: ['number', 'string'] }, });
duration: { type: ['number', 'string'] },
},
required: ['group_id', 'user_id', 'duration'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetGroupBan extends OneBotAction<Payload, null> { export default class SetGroupBan extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupBan; actionName = ActionName.SetGroupBan;
@@ -22,7 +18,7 @@ export default class SetGroupBan extends OneBotAction<Payload, null> {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString()); const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('uid error'); if (!uid) throw new Error('uid error');
await this.core.apis.GroupApi.banMember(payload.group_id.toString(), await this.core.apis.GroupApi.banMember(payload.group_id.toString(),
[{ uid: uid, timeStamp: parseInt(payload.duration.toString()) }]); [{ uid: uid, timeStamp: +payload.duration}]);
return null; return null;
} }
} }

View File

@@ -1,18 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { user_id: Type.Union([Type.Number(), Type.String()]),
group_id: { type: ['number', 'string'] }, card: Type.Optional(Type.String())
user_id: { type: ['number', 'string'] }, });
card: { type: 'string' },
},
required: ['group_id', 'user_id', 'card'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetGroupCard extends OneBotAction<Payload, null> { export default class SetGroupCard extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupCard; actionName = ActionName.SetGroupCard;

View File

@@ -1,19 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
user_id: Type.Union([Type.Number(), Type.String()]),
reject_add_request: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
});
const SchemaData = { type Payload = Static<typeof SchemaData>;
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
user_id: { type: ['number', 'string'] },
reject_add_request: { type: ['boolean', 'string'] },
},
required: ['group_id', 'user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupKick extends OneBotAction<Payload, null> { export default class SetGroupKick extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupKick; actionName = ActionName.SetGroupKick;

View File

@@ -1,17 +1,14 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { is_dismiss: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
group_id: { type: ['number', 'string'] }, });
is_dismiss: { type: ['boolean', 'string'] },
}, type Payload = Static<typeof SchemaData>;
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupLeave extends OneBotAction<Payload, any> { export default class SetGroupLeave extends OneBotAction<Payload, any> {
actionName = ActionName.SetGroupLeave; actionName = ActionName.SetGroupLeave;
payloadSchema = SchemaData; payloadSchema = SchemaData;

View File

@@ -1,23 +1,24 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { group_name: Type.String(),
group_id: { type: ['number', 'string'] }, });
group_name: { type: 'string' },
}, type Payload = Static<typeof SchemaData>;
required: ['group_id', 'group_name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupName extends OneBotAction<Payload, null> { export default class SetGroupName extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupName; actionName = ActionName.SetGroupName;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
await this.core.apis.GroupApi.setGroupName(payload.group_id.toString(), payload.group_name); const ret = await this.core.apis.GroupApi.setGroupName(payload.group_id.toString(), payload.group_name);
if (ret.result !== 0) {
throw new Error(`设置群名称失败 ErrCode: ${ret.result} ErrMsg: ${ret.errMsg}`);
}
return null; return null;
} }
} }

View File

@@ -1,17 +1,13 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', group_id: Type.Union([Type.Number(), Type.String()]),
properties: { enable: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
group_id: { type: ['number', 'string'] }, });
enable: { type: ['boolean', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export default class SetGroupWholeBan extends OneBotAction<Payload, null> { export default class SetGroupWholeBan extends OneBotAction<Payload, null> {
actionName = ActionName.SetGroupWholeBan; actionName = ActionName.SetGroupWholeBan;

View File

@@ -1,22 +1,13 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
message_id: {
oneOf: [
{ type: 'number' },
{ type: 'string' },
],
},
},
required: ['message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
class DeleteMsg extends OneBotAction<Payload, void> { class DeleteMsg extends OneBotAction<Payload, void> {
actionName = ActionName.DeleteMsg; actionName = ActionName.DeleteMsg;

View File

@@ -1,20 +1,16 @@
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ChatType, Peer } from '@/core/types'; import { ChatType, Peer } from '@/core/types';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { group_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
message_id: { type: ['number', 'string'] }, user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
group_id: { type: ['number', 'string'] }, });
user_id: { type: ['number', 'string'] },
},
required: ['message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
class ForwardSingleMsg extends OneBotAction<Payload, null> { class ForwardSingleMsg extends OneBotAction<Payload, null> {
protected async getTargetPeer(payload: Payload): Promise<Peer> { protected async getTargetPeer(payload: Payload): Promise<Peer> {
@@ -29,7 +25,7 @@ class ForwardSingleMsg extends OneBotAction<Payload, null> {
} }
async _handle(payload: Payload): Promise<null> { async _handle(payload: Payload): Promise<null> {
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msg) { if (!msg) {
throw new Error(`无法找到消息${payload.message_id}`); throw new Error(`无法找到消息${payload.message_id}`);
} }

View File

@@ -1,23 +1,18 @@
import { OB11Message } from '@/onebot'; import { OB11Message } from '@/onebot';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { RawMessage } from '@/core'; import { RawMessage } from '@/core';
import { AdapterConfigWrap } from '@/onebot/config/config'; import { AdapterConfigWrap } from '@/onebot/config/config';
import { Static, Type } from '@sinclair/typebox';
export type ReturnDataType = OB11Message export type ReturnDataType = OB11Message
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { });
message_id: { type: ['number', 'string'] },
},
required: ['message_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
class GetMsg extends OneBotAction<Payload, OB11Message> { class GetMsg extends OneBotAction<Payload, OB11Message> {
actionName = ActionName.GetMsg; actionName = ActionName.GetMsg;

View File

@@ -1,19 +1,16 @@
import { ChatType, Peer } from '@/core/types'; import { ChatType, Peer } from '@/core/types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', user_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
properties: { group_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
user_id: { type: ['number', 'string'] }, message_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
group_id: { type: ['number', 'string'] }, });
message_id: { type: ['number', 'string'] },
},
} as const satisfies JSONSchema;
type PlayloadType = FromSchema<typeof SchemaData>; type PlayloadType = Static<typeof SchemaData>;
class MarkMsgAsRead extends OneBotAction<PlayloadType, null> { class MarkMsgAsRead extends OneBotAction<PlayloadType, null> {
async getPeer(payload: PlayloadType): Promise<Peer> { async getPeer(payload: PlayloadType): Promise<Peer> {

View File

@@ -162,11 +162,10 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
finallySendElements: SendArkElement, finallySendElements: SendArkElement,
res_id?: string res_id?: string
} | null> { } | null> {
const logger = this.core.context.logger;
const packetMsg: PacketMsg[] = []; const packetMsg: PacketMsg[] = [];
for (const node of messageNodes) { for (const node of messageNodes) {
if (dp >= 3) { if (dp >= 3) {
logger.logWarn('转发消息深度超过3层将停止解析'); this.core.context.logger.logWarn('转发消息深度超过3层将停止解析');
break; break;
} }
if (!node.data.id) { if (!node.data.id) {
@@ -191,29 +190,29 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
time: Number(node.data.time) || Date.now(), time: Number(node.data.time) || Date.now(),
msg: sendElements, msg: sendElements,
}; };
logger.logDebug(`handleForwardedNodesPacket[SendRaw] 开始转换 ${stringifyWithBigInt(packetMsgElements)}`); this.core.context.logger.logDebug(`handleForwardedNodesPacket[SendRaw] 开始转换 ${stringifyWithBigInt(packetMsgElements)}`);
const transformedMsg = this.core.apis.PacketApi.pkt.msgConverter.rawMsgWithSendMsgToPacketMsg(packetMsgElements); const transformedMsg = this.core.apis.PacketApi.pkt.msgConverter.rawMsgWithSendMsgToPacketMsg(packetMsgElements);
logger.logDebug(`handleForwardedNodesPacket[SendRaw] 转换为 ${stringifyWithBigInt(transformedMsg)}`); this.core.context.logger.logDebug(`handleForwardedNodesPacket[SendRaw] 转换为 ${stringifyWithBigInt(transformedMsg)}`);
packetMsg.push(transformedMsg); packetMsg.push(transformedMsg);
} else if (node.data.id) { } else if (node.data.id) {
const id = node.data.id; const id = node.data.id;
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(+id) || MessageUnique.getPeerByMsgId(id); const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(+id) || MessageUnique.getPeerByMsgId(id);
if (!nodeMsg) { if (!nodeMsg) {
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', id); this.core.context.logger.logError('转发消息失败,未找到消息', id);
continue; continue;
} }
const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsg.Peer, [nodeMsg.MsgId])).msgList[0]; const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsg.Peer, [nodeMsg.MsgId])).msgList[0];
logger.logDebug(`handleForwardedNodesPacket[PureRaw] 开始转换 ${stringifyWithBigInt(msg)}`); this.core.context.logger.logDebug(`handleForwardedNodesPacket[PureRaw] 开始转换 ${stringifyWithBigInt(msg)}`);
await this.core.apis.FileApi.downloadRawMsgMedia([msg]); await this.core.apis.FileApi.downloadRawMsgMedia([msg]);
const transformedMsg = this.core.apis.PacketApi.pkt.msgConverter.rawMsgToPacketMsg(msg, msgPeer); const transformedMsg = this.core.apis.PacketApi.pkt.msgConverter.rawMsgToPacketMsg(msg, msgPeer);
logger.logDebug(`handleForwardedNodesPacket[PureRaw] 转换为 ${stringifyWithBigInt(transformedMsg)}`); this.core.context.logger.logDebug(`handleForwardedNodesPacket[PureRaw] 转换为 ${stringifyWithBigInt(transformedMsg)}`);
packetMsg.push(transformedMsg); packetMsg.push(transformedMsg);
} else { } else {
logger.logDebug(`handleForwardedNodesPacket 跳过元素 ${stringifyWithBigInt(node)}`); this.core.context.logger.logDebug(`handleForwardedNodesPacket 跳过元素 ${stringifyWithBigInt(node)}`);
} }
} }
if (packetMsg.length === 0) { if (packetMsg.length === 0) {
logger.logWarn('handleForwardedNodesPacket 元素为空!'); this.core.context.logger.logWarn('handleForwardedNodesPacket 元素为空!');
return null; return null;
} }
const resid = await this.core.apis.PacketApi.pkt.operation.UploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0); const resid = await this.core.apis.PacketApi.pkt.operation.UploadForwardMsg(packetMsg, msgPeer.chatType === ChatType.KCHATTYPEGROUP ? +msgPeer.peerUid : 0);
@@ -253,14 +252,13 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
peerUid: this.core.selfInfo.uid, peerUid: this.core.selfInfo.uid,
}; };
let nodeMsgIds: string[] = []; let nodeMsgIds: string[] = [];
const logger = this.core.context.logger;
for (const messageNode of messageNodes) { for (const messageNode of messageNodes) {
const nodeId = messageNode.data.id; const nodeId = messageNode.data.id;
if (nodeId) { if (nodeId) {
// 对Msgid和OB11ID混用情况兜底 // 对Msgid和OB11ID混用情况兜底
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId); const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
if (!nodeMsg) { if (!nodeMsg) {
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', nodeId); this.core.context.logger.logError('转发消息失败,未找到消息', nodeId);
continue; continue;
} }
nodeMsgIds.push(nodeMsg.MsgId); nodeMsgIds.push(nodeMsg.MsgId);
@@ -272,7 +270,7 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息 const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
if (isNodeMsg !== 0) { if (isNodeMsg !== 0) {
if (isNodeMsg !== OB11Data.length) { if (isNodeMsg !== OB11Data.length) {
logger.logError.bind(this.core.context.logger)('子消息中包含非node消息 跳过不合法部分'); this.core.context.logger.logError('子消息中包含非node消息 跳过不合法部分');
continue; continue;
} }
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node)); const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
@@ -309,7 +307,7 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
} }
}); });
} catch (e: any) { } catch (e: any) {
logger.logDebug('生成转发消息节点失败', e?.stack); this.core.context.logger.logDebug('生成转发消息节点失败', e?.stack);
} }
} }
} }
@@ -320,7 +318,7 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
for (const msgId of nodeMsgIds) { for (const msgId of nodeMsgIds) {
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId); const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
if (!nodeMsgPeer) { if (!nodeMsgPeer) {
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', msgId); this.core.context.logger.logError('转发消息失败,未找到消息', msgId);
continue; continue;
} }
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0]; const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
@@ -346,12 +344,12 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
} }
if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空'); if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
try { try {
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds); this.core.context.logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
return { return {
message: await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds) message: await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
}; };
} catch (e: any) { } catch (e: any) {
logger.logError.bind(this.core.context.logger)('forward failed', e?.stack); this.core.context.logger.logError('forward failed', e?.stack);
return { return {
message: null message: null
}; };
@@ -363,7 +361,6 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
chatType: ChatType.KCHATTYPEC2C, chatType: ChatType.KCHATTYPEC2C,
peerUid: this.core.selfInfo.uid, peerUid: this.core.selfInfo.uid,
}; };
const logger = this.core.context.logger;
//msg 为待克隆消息 //msg 为待克隆消息
const sendElements: SendMessageElement[] = []; const sendElements: SendMessageElement[] = [];
@@ -372,12 +369,12 @@ export class SendMsg extends OneBotAction<OB11PostSendMsg, ReturnDataType> {
} }
if (sendElements.length === 0) { if (sendElements.length === 0) {
logger.logDebug('需要clone的消息无法解析将会忽略掉', msg); this.core.context.logger.logDebug('需要clone的消息无法解析将会忽略掉', msg);
} }
try { try {
return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true); return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
} catch (e: any) { } catch (e: any) {
logger.logError.bind(this.core.context.logger)(e?.stack, '克隆转发消息失败,将忽略本条消息', msg); this.core.context.logger.logError(e?.stack, '克隆转发消息失败,将忽略本条消息', msg);
} }
} }
} }

View File

@@ -1,26 +1,22 @@
import { ActionName } from '@/onebot/action/router'; import { ActionName } from '@/onebot/action/router';
import { OneBotAction } from '@/onebot/action/OneBotAction'; import { OneBotAction } from '@/onebot/action/OneBotAction';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/message-unique'; import { MessageUnique } from '@/common/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = { const SchemaData = Type.Object({
type: 'object', message_id: Type.Union([Type.Number(), Type.String()]),
properties: { emoji_id: Type.Union([Type.Number(), Type.String()]),
message_id: { type: ['string', 'number'] }, set: Type.Optional(Type.Union([Type.Boolean(), Type.String()]))
emoji_id: { type: ['string', 'number'] }, });
set: { type: ['boolean', 'string'] }
},
required: ['message_id', 'emoji_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>; type Payload = Static<typeof SchemaData>;
export class SetMsgEmojiLike extends OneBotAction<Payload, any> { export class SetMsgEmojiLike extends OneBotAction<Payload, any> {
actionName = ActionName.SetMsgEmojiLike; actionName = ActionName.SetMsgEmojiLike;
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString())); const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msg) { if (!msg) {
throw new Error('msg not found'); throw new Error('msg not found');
} }

Some files were not shown because too many files have changed in this diff Show More