haixunMaster/lib/search/config.ts

73 lines
2.3 KiB
TypeScript

function envBool(key: string, fallback: boolean): boolean {
const raw = process.env[key]?.trim().toLowerCase();
if (!raw) return fallback;
return raw === "1" || raw === "true" || raw === "yes";
}
function envInt(key: string, fallback: number): number {
const raw = process.env[key]?.trim();
if (!raw) return fallback;
const n = Number.parseInt(raw, 10);
return Number.isFinite(n) && n > 0 ? n : fallback;
}
function parseDurationMs(value: string | undefined, fallbackMs: number): number {
if (!value?.trim()) return fallbackMs;
const m = value.trim().match(/^(\d+)(ms|s|m|h)$/i);
if (!m) return fallbackMs;
const n = Number.parseInt(m[1], 10);
const unit = m[2].toLowerCase();
if (unit === "ms") return n;
if (unit === "s") return n * 1000;
if (unit === "m") return n * 60_000;
return n * 3_600_000;
}
/** 已停用的搜尋環境變數(若存在會被忽略) */
export const LEGACY_SEARCH_ENV_KEYS = [
"SERPAPI_API_KEY",
"SERPER_API_KEY",
"GOOGLE_SEARCH_API_KEY",
"GOOGLE_CSE_API_KEY",
"GOOGLE_CSE_CX",
"GOOGLE_CSE_ID",
"BING_SEARCH_API_KEY",
"TAVILY_API_KEY",
"EXA_API_KEY",
"SEARXNG_BASE_URL",
"DUCKDUCKGO_ENABLED",
] as const;
export function detectLegacySearchEnvKeys(): string[] {
return LEGACY_SEARCH_ENV_KEYS.filter((k) => !!process.env[k]?.trim());
}
export function getSearchConfig() {
return {
threads: {
enabled: envBool("THREADS_API_ENABLED", true),
queryLimitPerDay: envInt("THREADS_QUERY_LIMIT_PER_DAY", 2200),
},
brave: {
enabled: envBool("BRAVE_SEARCH_ENABLED", true),
apiKey: process.env.BRAVE_SEARCH_API_KEY?.trim() ?? "",
baseUrl:
process.env.BRAVE_SEARCH_BASE_URL?.trim() ||
"https://api.search.brave.com/res/v1/web/search",
dailyLimit: envInt("BRAVE_DAILY_LIMIT", 30),
resultLimit: envInt("BRAVE_RESULT_LIMIT", 20),
cacheTtlMs: parseDurationMs(process.env.BRAVE_CACHE_TTL, 4 * 3_600_000),
scanMaxQueries: envInt("SCAN_BRAVE_MAX_QUERIES", 8),
},
crawler: {
enabled: envBool("CRAWLER_ENABLED", true),
cacheTtlMs: parseDurationMs(process.env.CRAWLER_CACHE_TTL, 3_600_000),
},
dedupe: {
notifyTtlMs: 24 * 3_600_000,
},
threadsCacheTtlMs: parseDurationMs(process.env.THREADS_SEARCH_CACHE_TTL, 15 * 60_000),
};
}
export type SearchConfig = ReturnType<typeof getSearchConfig>;