mc-dashboard/lib/rcon.ts

66 lines
1.6 KiB
TypeScript
Raw Normal View History

import { Rcon } from "rcon-client";
import { MC_SERVER_IP, RCON_PORT, RCON_PASSWORD } from "./constants";
let pooled: Rcon | null = null;
let connecting: Promise<Rcon> | null = null;
let idleTimer: NodeJS.Timeout | null = null;
const IDLE_MS = 30_000;
async function open(): Promise<Rcon> {
const rcon = await Rcon.connect({
host: MC_SERVER_IP,
port: RCON_PORT,
password: RCON_PASSWORD,
timeout: 5000,
});
rcon.on("end", () => {
if (pooled === rcon) pooled = null;
});
rcon.on("error", () => {
if (pooled === rcon) pooled = null;
});
return rcon;
}
function scheduleIdleClose() {
if (idleTimer) clearTimeout(idleTimer);
idleTimer = setTimeout(() => {
const r = pooled;
pooled = null;
idleTimer = null;
r?.end().catch(() => {});
}, IDLE_MS);
}
async function getConnection(): Promise<Rcon> {
if (pooled) return pooled;
if (connecting) return connecting;
connecting = open()
.then((r) => {
pooled = r;
return r;
})
.finally(() => {
connecting = null;
});
return connecting;
}
export async function sendCommand(command: string): Promise<string> {
try {
const rcon = await getConnection();
const response = await rcon.send(command);
scheduleIdleClose();
return response;
} catch (e) {
// Drop the pooled connection on any error, retry once with fresh
const bad = pooled;
pooled = null;
bad?.end().catch(() => {});
const rcon = await getConnection();
const response = await rcon.send(command);
scheduleIdleClose();
return response;
}
}