mirror of
https://github.com/YuzuZensai/TrollSSH.git
synced 2026-09-13 15:09:01 +00:00
✨ feat: expand config with playback, rendering, and connection limits
This commit is contained in:
+57
-16
@@ -3,43 +3,84 @@ import { loadConfig } from "./config";
|
||||
|
||||
describe("loadConfig", () => {
|
||||
test("returns defaults when env vars are unset", () => {
|
||||
const config = loadConfig({});
|
||||
expect(config).toEqual({
|
||||
expect(loadConfig({})).toEqual({
|
||||
host: "0.0.0.0",
|
||||
port: 22,
|
||||
maxLoop: 5,
|
||||
playbackMode: "loop",
|
||||
allowUserControl: true,
|
||||
switchDebounceMs: 120,
|
||||
loginDelay: 1500,
|
||||
maxConnections: 10,
|
||||
maxTotalConnections: 1000,
|
||||
maxAuthAttempts: 6,
|
||||
handshakeTimeout: 10000,
|
||||
maxDimension: 512,
|
||||
frameResolution: 360,
|
||||
brightnessThreshold: 40,
|
||||
charset: "detailed",
|
||||
invert: false,
|
||||
logCredentials: false,
|
||||
videoPath: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test("overrides defaults from env vars", () => {
|
||||
const config = loadConfig({
|
||||
HOST: "127.0.0.1",
|
||||
PORT: "2222",
|
||||
MAX_LOOP: "3",
|
||||
LOGIN_DELAY: "500",
|
||||
MAX_CONNECTIONS: "20",
|
||||
BRIGHTNESS_THRESHOLD: "60",
|
||||
LOG_CREDENTIALS: "true",
|
||||
});
|
||||
expect(config).toEqual({
|
||||
expect(
|
||||
loadConfig({
|
||||
HOST: "127.0.0.1",
|
||||
PORT: "2222",
|
||||
MAX_LOOP: "3",
|
||||
PLAYBACK_MODE: "random",
|
||||
ALLOW_USER_CONTROL: "false",
|
||||
SWITCH_DEBOUNCE_MS: "200",
|
||||
LOGIN_DELAY: "500",
|
||||
MAX_CONNECTIONS: "20",
|
||||
MAX_TOTAL_CONNECTIONS: "50",
|
||||
MAX_AUTH_ATTEMPTS: "3",
|
||||
HANDSHAKE_TIMEOUT: "5000",
|
||||
MAX_DIMENSION: "200",
|
||||
FRAME_RESOLUTION: "480",
|
||||
BRIGHTNESS_THRESHOLD: "60",
|
||||
CHARSET: "blocks",
|
||||
INVERT: "true",
|
||||
LOG_CREDENTIALS: "true",
|
||||
VIDEO_PATH: "/videos/clip.mkv",
|
||||
})
|
||||
).toEqual({
|
||||
host: "127.0.0.1",
|
||||
port: 2222,
|
||||
maxLoop: 3,
|
||||
playbackMode: "random",
|
||||
allowUserControl: false,
|
||||
switchDebounceMs: 200,
|
||||
loginDelay: 500,
|
||||
maxConnections: 20,
|
||||
maxTotalConnections: 50,
|
||||
maxAuthAttempts: 3,
|
||||
handshakeTimeout: 5000,
|
||||
maxDimension: 200,
|
||||
frameResolution: 480,
|
||||
brightnessThreshold: 60,
|
||||
charset: "blocks",
|
||||
invert: true,
|
||||
logCredentials: true,
|
||||
videoPath: "/videos/clip.mkv",
|
||||
});
|
||||
});
|
||||
|
||||
test("logCredentials is false for any value other than the string 'true'", () => {
|
||||
test("boolean env vars are true only for the exact string 'true'", () => {
|
||||
expect(loadConfig({ LOG_CREDENTIALS: "1" }).logCredentials).toBe(false);
|
||||
expect(loadConfig({ LOG_CREDENTIALS: "false" }).logCredentials).toBe(
|
||||
false
|
||||
);
|
||||
expect(loadConfig({ INVERT: "yes" }).invert).toBe(false);
|
||||
expect(loadConfig({ INVERT: "true" }).invert).toBe(true);
|
||||
});
|
||||
|
||||
test("falls back to defaults for non-numeric and out-of-range values", () => {
|
||||
expect(loadConfig({ PORT: "not-a-number" }).port).toBe(22);
|
||||
expect(loadConfig({ PORT: "99999" }).port).toBe(65535);
|
||||
expect(loadConfig({ MAX_DIMENSION: "0" }).maxDimension).toBe(1);
|
||||
expect(
|
||||
loadConfig({ BRIGHTNESS_THRESHOLD: "999" }).brightnessThreshold
|
||||
).toBe(100);
|
||||
});
|
||||
});
|
||||
|
||||
+62
-10
@@ -4,25 +4,77 @@ export interface Config {
|
||||
host: string;
|
||||
port: number;
|
||||
maxLoop: number;
|
||||
playbackMode: "loop" | "random";
|
||||
allowUserControl: boolean;
|
||||
switchDebounceMs: number;
|
||||
loginDelay: number;
|
||||
maxConnections: number;
|
||||
maxTotalConnections: number;
|
||||
maxAuthAttempts: number;
|
||||
handshakeTimeout: number;
|
||||
maxDimension: number;
|
||||
frameResolution: number;
|
||||
brightnessThreshold: number;
|
||||
charset: string;
|
||||
invert: boolean;
|
||||
logCredentials: boolean;
|
||||
videoPath?: string;
|
||||
}
|
||||
|
||||
function parseIntEnv(
|
||||
value: string | undefined,
|
||||
fallback: number,
|
||||
{ min, max }: { min?: number; max?: number } = {}
|
||||
): number {
|
||||
if (value === undefined || value.trim() === "") return fallback;
|
||||
const parsed = parseInt(value, 10);
|
||||
if (!Number.isFinite(parsed)) return fallback;
|
||||
let result = parsed;
|
||||
if (typeof min === "number") result = Math.max(min, result);
|
||||
if (typeof max === "number") result = Math.min(max, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseBoolEnv(value: string | undefined): boolean {
|
||||
return value === "true";
|
||||
}
|
||||
|
||||
export function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {
|
||||
const videoPath = env.VIDEO_PATH?.trim();
|
||||
|
||||
return {
|
||||
host: env.HOST ?? "0.0.0.0",
|
||||
port: env.PORT ? parseInt(env.PORT, 10) : 22,
|
||||
maxLoop: env.MAX_LOOP ? parseInt(env.MAX_LOOP, 10) : 5,
|
||||
loginDelay: env.LOGIN_DELAY ? parseInt(env.LOGIN_DELAY, 10) : 1500,
|
||||
maxConnections: env.MAX_CONNECTIONS
|
||||
? parseInt(env.MAX_CONNECTIONS, 10)
|
||||
: 10,
|
||||
brightnessThreshold: env.BRIGHTNESS_THRESHOLD
|
||||
? parseInt(env.BRIGHTNESS_THRESHOLD, 10)
|
||||
: 40,
|
||||
logCredentials: env.LOG_CREDENTIALS === "true",
|
||||
port: parseIntEnv(env.PORT, 22, { min: 1, max: 65535 }),
|
||||
maxLoop: parseIntEnv(env.MAX_LOOP, 5, { min: 1 }),
|
||||
playbackMode:
|
||||
env.PLAYBACK_MODE?.trim().toLowerCase() === "random"
|
||||
? "random"
|
||||
: "loop",
|
||||
allowUserControl: env.ALLOW_USER_CONTROL !== "false",
|
||||
switchDebounceMs: parseIntEnv(env.SWITCH_DEBOUNCE_MS, 120, { min: 0 }),
|
||||
loginDelay: parseIntEnv(env.LOGIN_DELAY, 1500, { min: 0 }),
|
||||
maxConnections: parseIntEnv(env.MAX_CONNECTIONS, 10, { min: 1 }),
|
||||
maxTotalConnections: parseIntEnv(env.MAX_TOTAL_CONNECTIONS, 1000, {
|
||||
min: 1,
|
||||
}),
|
||||
maxAuthAttempts: parseIntEnv(env.MAX_AUTH_ATTEMPTS, 6, { min: 1 }),
|
||||
handshakeTimeout: parseIntEnv(env.HANDSHAKE_TIMEOUT, 10000, { min: 0 }),
|
||||
maxDimension: parseIntEnv(env.MAX_DIMENSION, 512, {
|
||||
min: 1,
|
||||
max: 4096,
|
||||
}),
|
||||
frameResolution: parseIntEnv(env.FRAME_RESOLUTION, 360, {
|
||||
min: 16,
|
||||
max: 1080,
|
||||
}),
|
||||
brightnessThreshold: parseIntEnv(env.BRIGHTNESS_THRESHOLD, 40, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
}),
|
||||
charset: env.CHARSET?.trim() || "detailed",
|
||||
invert: parseBoolEnv(env.INVERT),
|
||||
logCredentials: parseBoolEnv(env.LOG_CREDENTIALS),
|
||||
videoPath: videoPath ? videoPath : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user