- Added support for multiple captcha providers including Google reCAPTCHA (v2 and v3), hCaptcha, and Cloudflare Turnstile. - Introduced new fields in the verification configuration for selecting captcha providers and enabling alt-account detection. - Implemented logic to handle verification attempts and flag potential alt accounts based on IP and invite code analysis. - Updated environment configuration to include necessary keys for captcha providers. - Enhanced the user interface to allow selection of captcha providers in the verification setup. - Improved backend handling of verification records to store additional data related to captcha provider usage.
56 lines
2.2 KiB
TypeScript
56 lines
2.2 KiB
TypeScript
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'),
|
|
BOT_TOKEN: z.string().min(1),
|
|
BOT_CLIENT_ID: z.string().min(1),
|
|
BOT_GUILD_ID: z.preprocess(emptyToUndefined, z.string().min(1).optional()),
|
|
DATABASE_URL: z.string().url(),
|
|
REDIS_URL: z.string().url(),
|
|
LOG_LEVEL: z.string().default('info'),
|
|
DEFAULT_LOCALE: z.enum(['de', 'en']).default('de'),
|
|
BACKUP_RETENTION_DAYS: z.coerce.number().int().positive().default(14),
|
|
BACKUP_CRON: z.string().default('0 3 * * *'),
|
|
BACKUP_DIR: z.string().default('/backups'),
|
|
METRICS_TOKEN: z.preprocess(emptyToUndefined, z.string().min(1).optional()),
|
|
SENTRY_DSN: z.preprocess(emptyToUndefined, z.string().url().optional()),
|
|
HEALTH_PORT: z.coerce.number().int().positive().default(8080),
|
|
PUBLIC_BASE_URL: z.string().url().default('http://localhost:8080'),
|
|
TWITCH_CLIENT_ID: z.preprocess(emptyToUndefined, z.string().min(1).optional()),
|
|
TWITCH_CLIENT_SECRET: z.preprocess(emptyToUndefined, z.string().min(1).optional()),
|
|
OWNER_USER_IDS: z.preprocess(
|
|
emptyToUndefined,
|
|
z
|
|
.string()
|
|
.optional()
|
|
.transform((value) =>
|
|
value
|
|
? value
|
|
.split(',')
|
|
.map((id) => id.trim())
|
|
.filter((id) => id.length > 0)
|
|
: []
|
|
)
|
|
),
|
|
WEBUI_URL: z.preprocess(emptyToUndefined, z.string().url().optional()),
|
|
SUPPORT_SERVER_URL: z.preprocess(emptyToUndefined, z.string().url().optional()),
|
|
/// Salt for hashing client IPs in verification alt-detection (shared with WebUI).
|
|
CAPTCHA_IP_HASH_SALT: z.preprocess(emptyToUndefined, z.string().min(16).optional())
|
|
});
|
|
|
|
export const env = EnvSchema.parse(process.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();
|
|
}
|