import type { OptionDefinition } from "command-line-args"; import type { KeywordLike } from "./keywords.js"; import { readFile } from "node:fs/promises"; import cmdline from "command-line-args"; import yaml from "js-yaml"; export interface Configuration { bindHost: string; port: number; wordsCounter: boolean; keywordsFile: string; watchFile: boolean; includePeers?: number[]; excludePeers?: number[]; keywords?: KeywordLike[]; } const optionDefinitions: OptionDefinition[] = [ { name: "bind-host", alias: "b", type: String, defaultValue: "0.0.0.0" }, { name: "port", alias: "p", type: Number, defaultValue: 9669 }, { name: "words-counter", type: Boolean, defaultValue: false }, { name: "keywords-file", alias: "k", type: String }, { name: "watch-file", alias: "w", type: Boolean, defaultValue: false }, { name: "include-peers", alias: "i", type: String, multiple: true }, { name: "exclude-peers", alias: "x", type: String, multiple: true }, ]; const cli = cmdline(optionDefinitions); const config: Configuration = { bindHost: cli["bind-host"], port: cli.port, wordsCounter: cli["words-counter"], keywordsFile: cli["keywords-file"], watchFile: cli["watch-file"], keywords: cli["keywords-file"] ? await readKeywords(cli["keywords-file"]) : undefined, }; if (cli["include-peers"] && cli["exclude-peers"]) { throw new Error("Conflicting configuration: --include-peers and --exclude-peers can't be both specified at the same time."); } if (cli["include-peers"]) { config.includePeers = []; for (const o of cli["include-peers"] as string[]) { config.includePeers.push(...o.split(",").map(i => parseInt(i)).filter(i => !isNaN(i))); } } if (cli["exclude-peers"]) { config.excludePeers = []; for (const o of cli["exclude-peers"] as string[]) { config.excludePeers.push(...o.split(",").map(i => parseInt(i)).filter(i => !isNaN(i))); } } export async function readKeywords(filePath: string): Promise { const doc = yaml.load(await readFile(filePath, "utf8")) as { keywords?: any[] }; if (doc.keywords && doc.keywords.constructor.name === "Array") { const keywords: KeywordLike[] = []; for (const item of doc.keywords) { if (typeof item === "string") { keywords.push(item); } else if (typeof item === "object" && item.name && item.pattern) { keywords.push({ name: item.name, pattern: new RegExp(item.pattern, "gi"), }); } } return keywords; } else { throw new Error("Keywords file format error: no 'keywords' property, or not an array."); } } export { config };