feat: DSL 磁力聚合 — 搜索/解析/预览/投递 + cilisousuo 源 + 中英双语 + Docker 部署

This commit is contained in:
ice-a
2026-10-16 18:53:45 +08:00
commit d6999104bf
64 changed files with 16524 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
import { ProxyAgent, fetch as undiciFetch, type RequestInit } from 'undici'
const agentCache = new Map<string, ProxyAgent>()
export function getProxyAgent(proxy?: string | null): ProxyAgent | undefined {
const uri = (proxy || '').trim()
if (!uri) return undefined
let agent = agentCache.get(uri)
if (!agent) {
agent = new ProxyAgent(uri)
agentCache.set(uri, agent)
}
return agent
}
export interface HttpOptions extends RequestInit {
/** 走 HTTP/HTTPS 代理,例如 http://127.0.0.1:7890 */
proxy?: string | null
timeoutMs?: number
}
/** 统一出口:带超时 + 可选代理的 fetch */
export async function httpFetch(url: string, options: HttpOptions = {}) {
const { proxy, timeoutMs = 12000, ...init } = options
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
try {
return await undiciFetch(url, {
...init,
dispatcher: getProxyAgent(proxy),
signal: controller.signal
})
} catch (err) {
if (controller.signal.aborted) throw new Error(`请求超时(${timeoutMs}ms):${url}`)
throw err
} finally {
clearTimeout(timer)
}
}
export async function httpText(url: string, options: HttpOptions = {}): Promise<string> {
const res = await httpFetch(url, options)
if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`)
return await res.text()
}
export async function httpJson<T = unknown>(url: string, options: HttpOptions = {}): Promise<T> {
const res = await httpFetch(url, options)
if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`)
return (await res.json()) as T
}
export const DEFAULT_UA =
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'