refactor: auto judge client

This commit is contained in:
pk5ls20 2024-11-05 14:24:54 +08:00
parent 017b8b7f15
commit ad6f21980c
No known key found for this signature in database
GPG Key ID: 6370ED7A169F493A
4 changed files with 35 additions and 49 deletions

View File

@ -30,10 +30,6 @@ export abstract class PacketClient {
this.config = core.configLoader.configData; this.config = core.configLoader.configData;
} }
get available(): boolean {
return this.isAvailable;
}
private randText(len: number): string { private randText(len: number): string {
let text = ''; let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
@ -43,13 +39,11 @@ export abstract class PacketClient {
return text; return text;
} }
static create(core: NapCatCore): PacketClient { get available(): boolean {
throw new Error("Must be implemented by subclasses"); return this.isAvailable;
} }
static compatibilityScore(logger: LogWrapper): number { abstract check(core: NapCatCore): boolean;
throw new Error("Must be implemented by subclasses");
}
abstract init(pid: number, recv: string, send: string): Promise<void>; abstract init(pid: number, recv: string, send: string): Promise<void>;

View File

@ -5,7 +5,6 @@ import { fileURLToPath } from "url";
import fs from "fs"; import fs from "fs";
import { PacketClient } from "@/core/packet/client/client"; import { PacketClient } from "@/core/packet/client/client";
import { constants } from "node:os"; import { constants } from "node:os";
import { LogWrapper } from "@/common/log";
import { LRUCache } from "@/common/lru-cache"; import { LRUCache } from "@/common/lru-cache";
//0 send 1recv //0 send 1recv
export interface NativePacketExportType { export interface NativePacketExportType {
@ -13,10 +12,10 @@ export interface NativePacketExportType {
SendPacket?: (cmd: string, data: string, trace_id: string) => void; SendPacket?: (cmd: string, data: string, trace_id: string) => void;
} }
export class NativePacketClient extends PacketClient { export class NativePacketClient extends PacketClient {
static supportedPlatforms = ['win32.x64']; private readonly supportedPlatforms = ['win32.x64'];
private MoeHooExport: { exports: NativePacketExportType } = { exports: {} }; private MoeHooExport: { exports: NativePacketExportType } = { exports: {} };
private sendEvent = new LRUCache<number, string>(500);//seq->trace_id private sendEvent = new LRUCache<number, string>(500);//seq->trace_id
protected constructor(core: NapCatCore) { constructor(core: NapCatCore) {
super(core); super(core);
} }
@ -24,22 +23,18 @@ export class NativePacketClient extends PacketClient {
return this.isAvailable; return this.isAvailable;
} }
static compatibilityScore(logger: LogWrapper): number { check(): boolean {
const platform = process.platform + '.' + process.arch; const platform = process.platform + '.' + process.arch;
if (!this.supportedPlatforms.includes(platform)) { if (!this.supportedPlatforms.includes(platform)) {
logger.logError(`[Core] [Packet:Native] 不支持的平台: ${platform}`); this.logger.logWarn(`[Core] [Packet:Native] 不支持的平台: ${platform}`);
return 0; return false;
} }
const moehoo_path = path.join(dirname(fileURLToPath(import.meta.url)), './moehoo/MoeHoo.' + platform + '.node'); const moehoo_path = path.join(dirname(fileURLToPath(import.meta.url)), './moehoo/MoeHoo.' + platform + '.node');
if (!fs.existsSync(moehoo_path)) { if (!fs.existsSync(moehoo_path)) {
logger.logError(`[Core] [Packet:Native] 缺失运行时文件: ${moehoo_path}`); this.logger.logWarn(`[Core] [Packet:Native] 缺失运行时文件: ${moehoo_path}`);
return 0; return false;
} }
return 10; return true;
}
static create(core: NapCatCore): NativePacketClient {
return new NativePacketClient(core);
} }
async init(pid: number, recv: string, send: string): Promise<void> { async init(pid: number, recv: string, send: string): Promise<void> {

View File

@ -1,32 +1,31 @@
import { Data, WebSocket } from "ws"; import { Data, WebSocket } from "ws";
import { NapCatCore } from "@/core"; import { NapCatCore } from "@/core";
import { PacketClient, RecvPacket } from "@/core/packet/client/client"; import { PacketClient, RecvPacket } from "@/core/packet/client/client";
import { LogWrapper } from "@/common/log";
export class wsPacketClient extends PacketClient { export class wsPacketClient extends PacketClient {
private websocket: WebSocket | undefined; private websocket: WebSocket | undefined;
private reconnectAttempts: number = 0; private reconnectAttempts: number = 0;
private readonly maxReconnectAttempts: number = 60; // 现在暂时不可配置 private readonly maxReconnectAttempts: number = 60; // 现在暂时不可配置
private readonly clientUrl: string = ''; private readonly clientUrl: string | null = null;
private clientUrlWrap: (url: string) => string = (url: string) => `ws://${url}/ws`; private clientUrlWrap: (url: string) => string = (url: string) => `ws://${url}/ws`;
protected constructor(core: NapCatCore) { constructor(core: NapCatCore) {
super(core); super(core);
this.clientUrl = this.clientUrlWrap(this.config.packetServer ?? '127.0.0.1:8086'); this.clientUrl = this.config.packetServer ? this.clientUrlWrap( this.config.packetServer) : null;
} }
static compatibilityScore(logger: LogWrapper): number { check(): boolean {
return 10; if (!this.clientUrl) {
} this.logger.logWarn(`[Core] [Packet:Server] 未配置服务器地址`);
return false;
static create(core: NapCatCore): wsPacketClient { }
return new wsPacketClient(core); return true;
} }
connect(cb: () => void): Promise<void> { connect(cb: () => void): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`); //this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`);
this.websocket = new WebSocket(this.clientUrl); this.websocket = new WebSocket(this.clientUrl!);
this.websocket.on('error', (err) => { }/*this.logger.logError.bind(this.logger)('[Core] [Packet Server] Error:', err.message)*/); this.websocket.on('error', (err) => { }/*this.logger.logError.bind(this.logger)('[Core] [Packet Server] Error:', err.message)*/);
this.websocket.onopen = () => { this.websocket.onopen = () => {

View File

@ -7,12 +7,12 @@ import { wsPacketClient } from "@/core/packet/client/wsClient";
import { NapCatCore } from "@/core"; import { NapCatCore } from "@/core";
type clientPriority = { type clientPriority = {
[key: number]: typeof PacketClient; [key: number]: (core: NapCatCore) => PacketClient;
} }
const clientPriority: clientPriority = { const clientPriority: clientPriority = {
10: NativePacketClient, 10: (core: NapCatCore) => new NativePacketClient(core),
1: wsPacketClient, 1: (core: NapCatCore) => new wsPacketClient(core),
}; };
export class PacketSession { export class PacketSession {
@ -29,21 +29,19 @@ export class PacketSession {
} }
private judgeClient(core: NapCatCore): PacketClient { private judgeClient(core: NapCatCore): PacketClient {
let selectedClient: typeof PacketClient | null = null; const sortedClients = Object.entries(clientPriority)
let maxScore = -1; .map(([priority, clientFactory]) => {
for (const key in clientPriority) { const client = clientFactory(core);
const priority = parseInt(key); const score = +priority * +client.check(core);
const ClientClass = clientPriority[priority]; return { client, score };
const score = priority * ClientClass.compatibilityScore(core.context.logger); })
if (score > maxScore) { .filter(({ score }) => score > 0)
maxScore = score; .sort((a, b) => b.score - a.score);
selectedClient = ClientClass; const selectedClient = sortedClients[0]?.client;
}
}
if (!selectedClient) { if (!selectedClient) {
throw new Error("[Core] [Packet] 无可用的后端NapCat.Packet将不会加载"); throw new Error("[Core] [Packet] 无可用的后端NapCat.Packet将不会加载");
} }
this.logger.log(`[Core] [Packet] 自动选择 ${selectedClient.name} 作为后端`); this.logger.log(`[Core] [Packet] 自动选择 ${selectedClient.constructor.name} 作为后端`);
return selectedClient.create(core); return selectedClient;
} }
} }