mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
feat: add JSON config module with load/save/defaults
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
101d593c0e
commit
f152450931
3 files changed
+104
-1
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
data/
|
/data/
|
||||||
*.db
|
*.db
|
||||||
.env
|
.env
|
||||||
.superpowers/
|
.superpowers/
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { describe, it, expect, afterEach } from "vitest";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { mkdtempSync, rmSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { getDefaultConfig, loadConfig, saveConfig } from "./config.js";
|
||||||
|
|
||||||
|
describe("config", () => {
|
||||||
|
const dirs: string[] = [];
|
||||||
|
|
||||||
|
function makeTmpDir(): string {
|
||||||
|
const dir = mkdtempSync(join(tmpdir(), "tsmusicbot-test-"));
|
||||||
|
dirs.push(dir);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
for (const d of dirs) {
|
||||||
|
rmSync(d, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
dirs.length = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns default config when file does not exist", () => {
|
||||||
|
const config = loadConfig("/nonexistent/path/config.json");
|
||||||
|
expect(config).toEqual(getDefaultConfig());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("creates config file on save", () => {
|
||||||
|
const dir = makeTmpDir();
|
||||||
|
const path = join(dir, "sub", "config.json");
|
||||||
|
const config = getDefaultConfig();
|
||||||
|
saveConfig(path, config);
|
||||||
|
|
||||||
|
const loaded = loadConfig(path);
|
||||||
|
expect(loaded).toEqual(config);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("merges partial config with defaults", () => {
|
||||||
|
const dir = makeTmpDir();
|
||||||
|
const path = join(dir, "config.json");
|
||||||
|
|
||||||
|
// Save a partial config by writing only some fields
|
||||||
|
const partial = { webPort: 8080, locale: "en" };
|
||||||
|
const { writeFileSync } = require("node:fs");
|
||||||
|
writeFileSync(path, JSON.stringify(partial), "utf-8");
|
||||||
|
|
||||||
|
const loaded = loadConfig(path);
|
||||||
|
expect(loaded.webPort).toBe(8080);
|
||||||
|
expect(loaded.locale).toBe("en");
|
||||||
|
// defaults should fill in the rest
|
||||||
|
expect(loaded.theme).toBe("dark");
|
||||||
|
expect(loaded.commandPrefix).toBe("!");
|
||||||
|
expect(loaded.autoPauseOnEmpty).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
||||||
|
import { dirname } from "node:path";
|
||||||
|
|
||||||
|
export interface BotConfig {
|
||||||
|
webPort: number;
|
||||||
|
locale: string;
|
||||||
|
theme: string;
|
||||||
|
commandPrefix: string;
|
||||||
|
commandAliases: Record<string, string>;
|
||||||
|
neteaseApiPort: number;
|
||||||
|
qqMusicApiPort: number;
|
||||||
|
adminPassword: string;
|
||||||
|
adminGroups: number[];
|
||||||
|
autoReturnDelay: number;
|
||||||
|
autoPauseOnEmpty: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultConfig(): BotConfig {
|
||||||
|
return {
|
||||||
|
webPort: 3000,
|
||||||
|
locale: "zh",
|
||||||
|
theme: "dark",
|
||||||
|
commandPrefix: "!",
|
||||||
|
commandAliases: { p: "play", s: "skip", n: "next" },
|
||||||
|
neteaseApiPort: 3001,
|
||||||
|
qqMusicApiPort: 3002,
|
||||||
|
adminPassword: "",
|
||||||
|
adminGroups: [],
|
||||||
|
autoReturnDelay: 300,
|
||||||
|
autoPauseOnEmpty: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadConfig(path: string): BotConfig {
|
||||||
|
const defaults = getDefaultConfig();
|
||||||
|
try {
|
||||||
|
const raw = readFileSync(path, "utf-8");
|
||||||
|
const partial = JSON.parse(raw) as Partial<BotConfig>;
|
||||||
|
return { ...defaults, ...partial };
|
||||||
|
} catch {
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveConfig(path: string, config: BotConfig): void {
|
||||||
|
mkdirSync(dirname(path), { recursive: true });
|
||||||
|
writeFileSync(path, JSON.stringify(config, null, 2), "utf-8");
|
||||||
|
}
|
||||||
Reference in new issue
Block a user