81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
import type {bot_status} from "../../../types/bot/instance/bot_runtime";
|
|
import {BasePlugin, type PluginContext, type plugin} from "../../../types/bot/plugins/plugin";
|
|
|
|
const config_template = {
|
|
name: 'auto_reconnect' as const,
|
|
i18n: [{lang: 'zh-CN', name: '自动重连', description: 'Bot 连接断开后自动重连'}],
|
|
version: '1.0.0',
|
|
config: [
|
|
{
|
|
name: 'reconnect_delay' as const,
|
|
i18n: [{lang: 'zh-CN', name: '重连延时', description: '重连时的延时时间(单位:毫秒)'}],
|
|
required: false,
|
|
default: 1000,
|
|
type: 'number',
|
|
},
|
|
{
|
|
name: 'reconnect_max_attempts' as const,
|
|
i18n: [{lang: 'zh-CN', name: '最大重连次数', description: '最大重连次数,默认 10 次'}],
|
|
required: false,
|
|
default: 10,
|
|
type: 'number',
|
|
},
|
|
],
|
|
} satisfies plugin;
|
|
|
|
type auto_reconnect_status = {attempts: number};
|
|
type auto_reconnect_config = {
|
|
[K in typeof config_template['config'][number]['name']]: number;
|
|
};
|
|
|
|
export class init extends BasePlugin<auto_reconnect_config, auto_reconnect_status> {
|
|
readonly name = 'auto_reconnect';
|
|
readonly config_template = config_template;
|
|
private cleanup?: () => void;
|
|
|
|
constructor() {
|
|
super();
|
|
this.set_states({attempts: 0});
|
|
}
|
|
|
|
async init(context: PluginContext, config: auto_reconnect_config): Promise<void> {
|
|
const delay = Number.isInteger(config.reconnect_delay) && config.reconnect_delay >= 0
|
|
&& config.reconnect_delay <= 2_147_483_647 ? config.reconnect_delay : 1000;
|
|
const max_attempts = Number.isInteger(config.reconnect_max_attempts) && config.reconnect_max_attempts >= 0
|
|
&& config.reconnect_max_attempts < 100 ? config.reconnect_max_attempts : 10;
|
|
let uninjected = false;
|
|
|
|
const lost = () => {
|
|
if (uninjected || this.get_status()!.attempts >= max_attempts) return;
|
|
void context.schedule_reconnect(delay).catch(error => {
|
|
if (context.logger) context.log([context.logger.error(`安排自动重连失败: ${String(error)}`)]);
|
|
});
|
|
};
|
|
const attempt = () => { this.set_states({attempts: this.get_status()!.attempts + 1}); };
|
|
const reset = () => {
|
|
if (this.get_status()!.attempts !== 0) this.set_states({attempts: 0});
|
|
};
|
|
const updated = (value: bot_status) => {
|
|
if (value === 'online') reset();
|
|
};
|
|
this.cleanup = () => {
|
|
if (uninjected) return;
|
|
uninjected = true;
|
|
context.cancel_reconnect();
|
|
context.off('connection_lost', lost);
|
|
context.off('reconnect_attempt', attempt);
|
|
context.off('connection_requested', reset);
|
|
context.off('status_update', updated);
|
|
};
|
|
context.on('connection_lost', lost);
|
|
context.on('reconnect_attempt', attempt);
|
|
context.on('connection_requested', reset);
|
|
context.on('status_update', updated);
|
|
}
|
|
|
|
async dispose(): Promise<void> {
|
|
this.cleanup?.();
|
|
this.cleanup = undefined;
|
|
}
|
|
}
|