mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-04 22:51:13 +00:00
Refactor imports and add generic protocol config API
Replaced all '@/napcat-satori/...' imports with relative paths for consistency and compatibility. Added generic protocol config get/set handlers and routes in the web UI backend to support extensible protocol configuration management. Improved error handling and default value logic for Satori protocol configuration.
This commit is contained in:
parent
506358e01a
commit
26d38bebe7
@ -1,5 +1,5 @@
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
|
||||
export abstract class SatoriAction<PayloadType, ReturnType> {
|
||||
abstract actionName: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriChannel, SatoriChannelType } from '@/napcat-satori/types';
|
||||
import { SatoriChannel, SatoriChannelType } from '../../types';
|
||||
|
||||
interface ChannelGetPayload {
|
||||
channel_id: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriChannel, SatoriChannelType, SatoriPageResult } from '@/napcat-satori/types';
|
||||
import { SatoriChannel, SatoriChannelType, SatoriPageResult } from '../../types';
|
||||
|
||||
interface ChannelListPayload {
|
||||
guild_id: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriGuild } from '@/napcat-satori/types';
|
||||
import { SatoriGuild } from '../../types';
|
||||
|
||||
interface GuildGetPayload {
|
||||
guild_id: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriGuild, SatoriPageResult } from '@/napcat-satori/types';
|
||||
import { SatoriGuild, SatoriPageResult } from '../../types';
|
||||
|
||||
interface GuildListPayload {
|
||||
next?: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriGuildMember } from '@/napcat-satori/types';
|
||||
import { SatoriGuildMember } from '../../types';
|
||||
|
||||
interface GuildMemberGetPayload {
|
||||
guild_id: string;
|
||||
@ -25,7 +25,7 @@ export class GuildMemberGetAction extends SatoriAction<GuildMemberGetPayload, Sa
|
||||
avatar: `https://q1.qlogo.cn/g?b=qq&nk=${memberInfo.uin}&s=640`,
|
||||
},
|
||||
nick: memberInfo.cardName || memberInfo.nick,
|
||||
joined_at: memberInfo.joinTime ? memberInfo.joinTime * 1000 : undefined,
|
||||
joined_at: memberInfo.joinTime ? Number(memberInfo.joinTime) * 1000 : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriGuildMember, SatoriPageResult } from '@/napcat-satori/types';
|
||||
import { SatoriGuildMember, SatoriPageResult } from '../../types';
|
||||
import { GroupMember } from 'napcat-core';
|
||||
|
||||
interface GuildMemberListPayload {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriAction } from './SatoriAction';
|
||||
|
||||
// 导入所有 Action
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriMessage, SatoriChannelType } from '@/napcat-satori/types';
|
||||
import { SatoriMessage, SatoriChannelType } from '../../types';
|
||||
import { ChatType, SendMessageElement } from 'napcat-core';
|
||||
|
||||
interface MessageCreatePayload {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriMessage, SatoriChannelType } from '@/napcat-satori/types';
|
||||
import { SatoriMessage, SatoriChannelType } from '../../types';
|
||||
import { ChatType } from 'napcat-core';
|
||||
|
||||
interface MessageGetPayload {
|
||||
@ -13,7 +13,13 @@ export class MessageGetAction extends SatoriAction<MessageGetPayload, SatoriMess
|
||||
async handle (payload: MessageGetPayload): Promise<SatoriMessage> {
|
||||
const { channel_id, message_id } = payload;
|
||||
|
||||
const [type, id] = channel_id.split(':');
|
||||
const parts = channel_id.split(':');
|
||||
const type = parts[0];
|
||||
const id = parts[1];
|
||||
|
||||
if (!type || !id) {
|
||||
throw new Error(`无效的频道ID: ${channel_id}`);
|
||||
}
|
||||
|
||||
let chatType: ChatType;
|
||||
let peerUid: string;
|
||||
@ -36,6 +42,10 @@ export class MessageGetAction extends SatoriAction<MessageGetPayload, SatoriMess
|
||||
}
|
||||
|
||||
const msg = msgs.msgList[0];
|
||||
if (!msg) {
|
||||
throw new Error('消息不存在');
|
||||
}
|
||||
|
||||
const content = await this.satoriAdapter.apis.MsgApi.parseElements(msg.elements);
|
||||
|
||||
const message: SatoriMessage = {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriUser, SatoriPageResult } from '@/napcat-satori/types';
|
||||
import { SatoriUser, SatoriPageResult } from '../../types';
|
||||
|
||||
interface FriendListPayload {
|
||||
next?: string;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SatoriAction } from '../SatoriAction';
|
||||
import { SatoriUser } from '@/napcat-satori/types';
|
||||
import { SatoriUser } from '../../types';
|
||||
|
||||
interface UserGetPayload {
|
||||
user_id: string;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { NapCatCore, RawMessage, ChatType } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import {
|
||||
SatoriEvent,
|
||||
SatoriChannelType,
|
||||
SatoriLoginStatus,
|
||||
} from '@/napcat-satori/types';
|
||||
} from '../types';
|
||||
|
||||
export class SatoriEventApi {
|
||||
private satoriAdapter: NapCatSatoriAdapter;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriMsgApi } from './msg';
|
||||
import { SatoriEventApi } from './event';
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NapCatCore, MessageElement, ElementType, NTMsgAtType } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
|
||||
export class SatoriMsgApi {
|
||||
private core: NapCatCore;
|
||||
|
||||
@ -12,10 +12,10 @@ import {
|
||||
GroupNotifyMsgStatus,
|
||||
GroupNotifyMsgType,
|
||||
} from 'napcat-core';
|
||||
import { SatoriConfigLoader, SatoriConfig, SatoriConfigSchema, SatoriNetworkAdapterConfig } from '@/napcat-satori/config';
|
||||
import { SatoriConfigLoader, SatoriConfig, SatoriConfigSchema, SatoriNetworkAdapterConfig } from './config';
|
||||
import { NapCatPathWrapper } from 'napcat-common/src/path';
|
||||
import { createSatoriApis, SatoriApiList } from '@/napcat-satori/api';
|
||||
import { createSatoriActionMap, SatoriActionMap } from '@/napcat-satori/action';
|
||||
import { createSatoriApis, SatoriApiList } from './api';
|
||||
import { createSatoriActionMap, SatoriActionMap } from './action';
|
||||
import {
|
||||
SatoriNetworkManager,
|
||||
SatoriWebSocketServerAdapter,
|
||||
@ -23,10 +23,11 @@ import {
|
||||
SatoriWebHookClientAdapter,
|
||||
SatoriNetworkReloadType,
|
||||
ISatoriNetworkAdapter,
|
||||
} from '@/napcat-satori/network';
|
||||
import { SatoriLoginStatus } from '@/napcat-satori/types';
|
||||
} from './network';
|
||||
import { SatoriLoginStatus } from './types';
|
||||
import { MessageUnique } from 'napcat-common/src/message-unique';
|
||||
import { proxiedListenerOf } from '@/napcat-core/helper/proxy-handler';
|
||||
import { WebUiDataRuntime } from 'napcat-webui-backend/src/helper/Data';
|
||||
|
||||
export class NapCatSatoriAdapter {
|
||||
readonly core: NapCatCore;
|
||||
@ -101,6 +102,13 @@ export class NapCatSatoriAdapter {
|
||||
// 发送登录成功事件
|
||||
const loginEvent = this.apis.EventApi.createLoginUpdatedEvent(SatoriLoginStatus.ONLINE);
|
||||
await this.networkManager.emitEvent(loginEvent);
|
||||
|
||||
// 注册 Satori 配置热重载回调
|
||||
WebUiDataRuntime.setOnSatoriConfigChanged(async (newConfig) => {
|
||||
const prev = this.configLoader.configData;
|
||||
this.configLoader.save(newConfig);
|
||||
await this.reloadNetwork(prev, newConfig);
|
||||
});
|
||||
}
|
||||
|
||||
async reloadNetwork (prev: SatoriConfig, now: SatoriConfig): Promise<void> {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { SatoriNetworkAdapterConfig } from '@/napcat-satori/config/config';
|
||||
import { SatoriNetworkAdapterConfig } from '../config/config';
|
||||
import { LogWrapper } from 'napcat-core/helper/log';
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { SatoriActionMap } from '@/napcat-satori/action';
|
||||
import { SatoriEvent } from '@/napcat-satori/types';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriActionMap } from '../action';
|
||||
import { SatoriEvent } from '../types';
|
||||
|
||||
export enum SatoriNetworkReloadType {
|
||||
Normal = 0,
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import express, { Express, Request, Response, NextFunction } from 'express';
|
||||
import { createServer, Server } from 'http';
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { SatoriActionMap } from '@/napcat-satori/action';
|
||||
import { SatoriHttpServerConfig } from '@/napcat-satori/config/config';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriActionMap } from '../action';
|
||||
import { SatoriHttpServerConfig } from '../config/config';
|
||||
import {
|
||||
ISatoriNetworkAdapter,
|
||||
SatoriEmitEventContent,
|
||||
SatoriNetworkReloadType,
|
||||
} from './adapter';
|
||||
import { SatoriApiResponse, SatoriLoginStatus } from '@/napcat-satori/types';
|
||||
import { SatoriApiResponse, SatoriLoginStatus } from '../types';
|
||||
|
||||
export class SatoriHttpServerAdapter extends ISatoriNetworkAdapter<SatoriHttpServerConfig> {
|
||||
private app: Express | null = null;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ISatoriNetworkAdapter, SatoriEmitEventContent, SatoriNetworkReloadType } from './adapter';
|
||||
import { SatoriNetworkAdapterConfig } from '@/napcat-satori/config/config';
|
||||
import { ISatoriNetworkAdapter, SatoriEmitEventContent } from './adapter';
|
||||
import { SatoriNetworkAdapterConfig } from '../config/config';
|
||||
|
||||
export class SatoriNetworkManager {
|
||||
adapters: Map<string, ISatoriNetworkAdapter<SatoriNetworkAdapterConfig>> = new Map();
|
||||
@ -23,7 +23,7 @@ export class SatoriNetworkManager {
|
||||
|
||||
async openAllAdapters (): Promise<void> {
|
||||
const openPromises = Array.from(this.adapters.values()).map((adapter) =>
|
||||
adapter.open().catch((e) => {
|
||||
Promise.resolve(adapter.open()).catch((e) => {
|
||||
adapter.logger.logError(`[Satori] 适配器 ${adapter.name} 启动失败: ${e}`);
|
||||
})
|
||||
);
|
||||
@ -32,7 +32,7 @@ export class SatoriNetworkManager {
|
||||
|
||||
async closeAllAdapters (): Promise<void> {
|
||||
const closePromises = Array.from(this.adapters.values()).map((adapter) =>
|
||||
adapter.close().catch((e) => {
|
||||
Promise.resolve(adapter.close()).catch((e) => {
|
||||
adapter.logger.logError(`[Satori] 适配器 ${adapter.name} 关闭失败: ${e}`);
|
||||
})
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { SatoriActionMap } from '@/napcat-satori/action';
|
||||
import { SatoriWebHookClientConfig } from '@/napcat-satori/config/config';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriActionMap } from '../action';
|
||||
import { SatoriWebHookClientConfig } from '../config/config';
|
||||
import {
|
||||
ISatoriNetworkAdapter,
|
||||
SatoriEmitEventContent,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { WebSocketServer, WebSocket } from 'ws';
|
||||
import { createServer, Server, IncomingMessage } from 'http';
|
||||
import { NapCatCore } from 'napcat-core';
|
||||
import { NapCatSatoriAdapter } from '@/napcat-satori/index';
|
||||
import { SatoriActionMap } from '@/napcat-satori/action';
|
||||
import { SatoriWebSocketServerConfig } from '@/napcat-satori/config/config';
|
||||
import { NapCatSatoriAdapter } from '../index';
|
||||
import { SatoriActionMap } from '../action';
|
||||
import { SatoriWebSocketServerConfig } from '../config/config';
|
||||
import {
|
||||
ISatoriNetworkAdapter,
|
||||
SatoriEmitEventContent,
|
||||
@ -15,7 +15,7 @@ import {
|
||||
SatoriIdentifyBody,
|
||||
SatoriReadyBody,
|
||||
SatoriLoginStatus,
|
||||
} from '@/napcat-satori/types';
|
||||
} from '../types';
|
||||
|
||||
interface ClientInfo {
|
||||
ws: WebSocket;
|
||||
|
||||
@ -104,6 +104,78 @@ export const SatoriSetConfigHandler: RequestHandler = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取指定协议配置
|
||||
export const GetProtocolConfigHandler: RequestHandler = (req, res) => {
|
||||
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||
if (!isLogin) {
|
||||
return sendError(res, 'Not Login');
|
||||
}
|
||||
|
||||
const { name } = req.params;
|
||||
const uin = WebUiDataRuntime.getQQLoginUin();
|
||||
// 映射 protocol name 到文件名
|
||||
const protocolId = name === 'onebot11' ? 'onebot11' : name;
|
||||
|
||||
const configFilePath = resolve(webUiPathWrapper.configPath, `./${protocolId}_${uin}.json`);
|
||||
|
||||
try {
|
||||
let configData: any = {};
|
||||
// Satori 特殊处理默认值, 其他协议也可以在这里添加默认值
|
||||
if (name === 'satori') {
|
||||
configData = {
|
||||
network: {
|
||||
websocketServers: [],
|
||||
httpServers: [],
|
||||
webhookClients: [],
|
||||
},
|
||||
platform: 'qq',
|
||||
selfId: uin,
|
||||
};
|
||||
}
|
||||
|
||||
if (existsSync(configFilePath)) {
|
||||
const content = readFileSync(configFilePath, 'utf-8');
|
||||
configData = json5.parse(content);
|
||||
}
|
||||
return sendSuccess(res, configData);
|
||||
} catch (e) {
|
||||
return sendError(res, 'Config Get Error: ' + e);
|
||||
}
|
||||
};
|
||||
|
||||
// 设置指定协议配置
|
||||
export const SetProtocolConfigHandler: RequestHandler = async (req, res) => {
|
||||
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||
if (!isLogin) {
|
||||
return sendError(res, 'Not Login');
|
||||
}
|
||||
|
||||
const { name } = req.params;
|
||||
if (isEmpty(req.body.config)) {
|
||||
return sendError(res, 'config is empty');
|
||||
}
|
||||
|
||||
try {
|
||||
const config = json5.parse(req.body.config);
|
||||
if (name === 'satori') {
|
||||
await WebUiDataRuntime.setSatoriConfig(config);
|
||||
} else {
|
||||
// 对于未特殊处理的协议,走通用的写文件逻辑
|
||||
const uin = WebUiDataRuntime.getQQLoginUin();
|
||||
// TODO: 这里目前 napcat-core 及其 helper 可能没有通用的 setConfig,
|
||||
// 但 WebUiDataRuntime.setSatoriConfig 本质也是写文件。
|
||||
// 暂时只支持 Satori 的通用调用 via this handler,
|
||||
// OneBot11 还是走原来的 /api/config
|
||||
if (name !== 'satori') {
|
||||
return sendError(res, 'Protocol not supported for generic set yet');
|
||||
}
|
||||
}
|
||||
return sendSuccess(res, null);
|
||||
} catch (e) {
|
||||
return sendError(res, 'Error: ' + e);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取所有协议配置
|
||||
export const GetAllProtocolConfigsHandler: RequestHandler = (_req, res) => {
|
||||
const isLogin = WebUiDataRuntime.getQQLoginStatus();
|
||||
|
||||
@ -5,6 +5,8 @@ import {
|
||||
SatoriGetConfigHandler,
|
||||
SatoriSetConfigHandler,
|
||||
GetAllProtocolConfigsHandler,
|
||||
GetProtocolConfigHandler,
|
||||
SetProtocolConfigHandler,
|
||||
} from '@/napcat-webui-backend/src/api/ProtocolConfig';
|
||||
|
||||
const router = Router();
|
||||
@ -18,8 +20,12 @@ router.get('/status', GetProtocolStatusHandler);
|
||||
// 获取所有协议配置
|
||||
router.get('/all', GetAllProtocolConfigsHandler);
|
||||
|
||||
// Satori 配置
|
||||
// Satori 配置 (Reserved for backward compatibility or specific usage)
|
||||
router.get('/satori', SatoriGetConfigHandler);
|
||||
router.post('/satori', SatoriSetConfigHandler);
|
||||
|
||||
// 通用协议配置路由
|
||||
router.get('/:name/config', GetProtocolConfigHandler);
|
||||
router.post('/:name/config', SetProtocolConfigHandler);
|
||||
|
||||
export { router as ProtocolConfigRouter };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user