import { z } from 'zod' import semver from 'semver' import pkg from '../../package.json' import { Config } from '../interface/Config' import { Account } from '../interface/Account' const NumberOrString = z.union([z.number(), z.string()]) const LogFilterSchema = z.object({ enabled: z.boolean(), mode: z.enum(['whitelist', 'blacklist']), levels: z.array(z.enum(['debug', 'info', 'warn', 'error'])).optional(), keywords: z.array(z.string()).optional(), regexPatterns: z.array(z.string()).optional() }) const DelaySchema = z.object({ min: NumberOrString, max: NumberOrString }) const QueryEngineSchema = z.enum(['google', 'wikipedia', 'reddit', 'local']) // Webhook const WebhookSchema = z.object({ discord: z .object({ enabled: z.boolean(), url: z.string() }) .optional(), ntfy: z .object({ enabled: z.boolean().optional(), url: z.string(), topic: z.string().optional(), token: z.string().optional(), title: z.string().optional(), tags: z.array(z.string()).optional(), priority: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4), z.literal(5)]).optional() }) .optional(), webhookLogFilter: LogFilterSchema }) // Config export const ConfigSchema = z.object({ baseURL: z.string(), sessionPath: z.string(), headless: z.boolean(), runOnZeroPoints: z.boolean(), clusters: z.number().int().nonnegative(), errorDiagnostics: z.boolean(), workers: z.object({ doDailySet: z.boolean(), doSpecialPromotions: z.boolean(), doMorePromotions: z.boolean(), doPunchCards: z.boolean(), doAppPromotions: z.boolean(), doDesktopSearch: z.boolean(), doMobileSearch: z.boolean(), doDailyCheckIn: z.boolean(), doReadToEarn: z.boolean() }), searchOnBingLocalQueries: z.boolean(), globalTimeout: NumberOrString, searchSettings: z.object({ scrollRandomResults: z.boolean(), clickRandomResults: z.boolean(), parallelSearching: z.boolean(), queryEngines: z.array(QueryEngineSchema), searchResultVisitTime: NumberOrString, searchDelay: DelaySchema, readDelay: DelaySchema }), debugLogs: z.boolean(), proxy: z.object({ queryEngine: z.boolean() }), consoleLogFilter: LogFilterSchema, webhook: WebhookSchema }) // Account export const AccountSchema = z.object({ email: z.string(), password: z.string(), totpSecret: z.string().optional(), recoveryEmail: z.string(), geoLocale: z.string(), langCode: z.string(), proxy: z.object({ proxyAxios: z.boolean(), url: z.string(), port: z.number(), password: z.string(), username: z.string() }), saveFingerprint: z.object({ mobile: z.boolean(), desktop: z.boolean() }) }) export function validateConfig(data: unknown): Config { return ConfigSchema.parse(data) as Config } export function validateAccounts(data: unknown): Account[] { return z.array(AccountSchema).parse(data) } export function checkNodeVersion(): void { try { const requiredVersion = pkg.engines?.node if (!requiredVersion) { console.warn('No Node.js version requirement found in package.json "engines" field.') return } if (!semver.satisfies(process.version, requiredVersion)) { console.error(`Current Node.js version ${process.version} does not satisfy requirement: ${requiredVersion}`) process.exit(1) } } catch (error) { console.error('Failed to validate Node.js version:', error) process.exit(1) } }