mic-bot/cfg/config.ts
2024-10-24 16:39:42 +02:00

126 lines
3.9 KiB
TypeScript

import type * as pg from "npm:pg";
import { strToBool } from "../utils/convert.ts";
import { BadConfigErr } from "../utils/errors.ts";
import { readJsonFileSync } from "../utils/io.ts";
import * as path from "jsr:@std/path";
export const POSTGRES_PASSWORD = "POSTGRES_PASSWORD"
export const MIC_APPLY_MIGRATIONS = "MIC_APPLY_MIGRATIONS"
export const DEFAULT_CONFIG_FILE_PATH = import.meta.dirname ? path.join(import.meta.dirname, '../config.json') : '/app/config.json'
export const MIC_DROP_DB = "MIC_DROP_DB"
export const BOT_TOKEN = "BOT_TOKEN"
export const MIC_CONFIG_PATH = "MIC_CONFIG_PATH"
export enum BotMode{ setup, normal }
export type BotConfig = {
mode: BotMode,
bot_token: string,
chat_id: number,
admin_ids: number[],
}
export interface EnvConfig {
db_password?: string,
bot_token?: string,
mic_config_path?: string,
mic_apply_migrations: boolean,
mic_drop_db: boolean,
}
export interface FileConfig {
db_user?: string,
db_name?: string,
db_port?: number,
db_host?: string,
db_tls?: boolean,
db_password_file?: string,
bot_token?: string,
}
export interface Config {
db_user?: string,
db_name?: string,
db_port?: number,
db_host?: string,
db_tls?: boolean,
db_password: string,
bot_token: string,
config_path: string,
apply_migrations: boolean,
drop_db: boolean,
}
export interface MigrationConfig {
dropDb: boolean
applyMigrations: boolean
migrationsPath: string
}
export interface CompiledConfig {
pgPoolCfg: pg.PoolConfig
botCfg: BotConfig
migrationCfg?: MigrationConfig
}
export const getEnvConfig = (): EnvConfig => {
const apply_migrations =
strToBool(Deno.env.get(MIC_APPLY_MIGRATIONS) || "n") || false
if (apply_migrations) Deno.env.set(MIC_APPLY_MIGRATIONS, "n")
const drop_db = strToBool(Deno.env.get(MIC_DROP_DB) || "n") || false
if (drop_db) Deno.env.set(MIC_DROP_DB, "n")
return {
db_password: Deno.env.get(POSTGRES_PASSWORD),
bot_token: Deno.env.get(BOT_TOKEN),
mic_config_path: Deno.env.get(MIC_CONFIG_PATH),
mic_apply_migrations: apply_migrations,
mic_drop_db: drop_db,
}
}
export const getConfig = (): Config => {
const envCfg = getEnvConfig()
const config_path = envCfg.mic_config_path || DEFAULT_CONFIG_FILE_PATH
const fileCfg = readJsonFileSync<FileConfig>(config_path)
let db_password: string;
if (fileCfg.db_password_file) {
const decoder = new TextDecoder("utf-8")
const data = Deno.readFileSync(fileCfg.db_password_file)
db_password = decoder.decode(data).toString()
if (db_password[db_password.length - 1] === '\n') {
db_password = db_password.slice(0, -1)
}
} else if (envCfg.db_password) {
db_password = envCfg.db_password
} else throw new BadConfigErr(
"Expected db_password_file to be set in the config "+
"or the POSTGRES_PASSWORD environment variable, "+
"but bot both are undefined. "+
"Check the Config section in README.md"
)
const bot_token: string | undefined = envCfg.bot_token || fileCfg.bot_token
if (!bot_token) throw new BadConfigErr(
"Expected bot_token to be set in the config "+
"or at the BOT_TOKEN environment variable, "+
"but bot token is undefined. "+
"Check the Config section in README.md"
)
return {
db_host: fileCfg.db_host,
db_user: fileCfg.db_user,
db_name: fileCfg.db_name,
db_port: fileCfg.db_port,
db_tls: fileCfg.db_tls,
db_password,
config_path,
apply_migrations: envCfg.mic_apply_migrations,
drop_db: envCfg.mic_drop_db,
bot_token,
}
}