import { config } from 'dotenv'; import { z } from 'zod'; config(); const emptyToUndefined = (value: unknown) => value === '' || value === undefined || value === null ? undefined : value; const EnvSchema = z.object({ NODE_ENV: z.enum(['development', 'test', 'production']).default('development'), DATABASE_URL: z.string().url(), REDIS_URL: z.string().url(), BOT_CLIENT_ID: z.string().min(1), BOT_CLIENT_SECRET: z.string().min(1), BOT_TOKEN: z.string().min(1), WEBUI_URL: z.string().url().default('http://localhost:3000'), SESSION_SECRET: z.string().min(32, 'SESSION_SECRET must be at least 32 characters long'), SENTRY_DSN: z.preprocess(emptyToUndefined, z.string().optional()), DEFAULT_LOCALE: z.enum(['de', 'en']).default('de'), OWNER_USER_IDS: z.preprocess( (value) => (typeof value === 'string' && value.trim() === '' ? undefined : value), z .string() .optional() .transform((value) => value ? value .split(',') .map((id) => id.trim()) .filter((id) => id.length > 0) : [] ) ), SUPPORT_SERVER_URL: z.preprocess(emptyToUndefined, z.string().url().optional()), LEGAL_OPERATOR_NAME: z.preprocess(emptyToUndefined, z.string().min(1).optional()), LEGAL_OPERATOR_ADDRESS: z.preprocess(emptyToUndefined, z.string().min(1).optional()), LEGAL_OPERATOR_EMAIL: z.preprocess(emptyToUndefined, z.string().email().optional()), LEGAL_OPERATOR_PHONE: z.preprocess(emptyToUndefined, z.string().min(1).optional()) }); export const env = EnvSchema.parse(process.env); export type Env = typeof env; export function buildBotInviteUrl(clientId = env.BOT_CLIENT_ID): string { const url = new URL('https://discord.com/api/oauth2/authorize'); url.searchParams.set('client_id', clientId); url.searchParams.set('permissions', '4786708802825463'); url.searchParams.set('scope', 'bot applications.commands'); return url.toString(); }