import { waitForSlot } from "./rate-limiter"; const TIKHUB_BASE_URL = "https://api.tikhub.io"; // Runtime API Key (set via POST /api/settings) let runtimeApiKey: string | null = null; export function setRuntimeApiKey(key: string) { runtimeApiKey = key; } export function getApiKey(): string | null { return runtimeApiKey || process.env.TIKHUB_API_KEY || null; } export async function tikhubFetch( endpoint: string, params?: Record, method: "GET" | "POST" = "GET", body?: Record ): Promise { const apiKey = getApiKey(); if (!apiKey) { throw new TikHubError(401, "API Key 未配置,请在设置页面配置 TikHub API Key"); } await waitForSlot(); const url = new URL(endpoint, TIKHUB_BASE_URL); if (params) { Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v)); } const res = await fetch(url.toString(), { method, headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, ...(method === "POST" ? { body: JSON.stringify(body || {}) } : {}), }); if (!res.ok) { if (res.status === 401) { throw new TikHubError(401, "API Key 无效,请检查配置"); } if (res.status === 429) { throw new TikHubError(429, "请求过于频繁,请稍后重试"); } throw new TikHubError(res.status, `TikHub API 错误: ${res.status}`); } const json = await res.json(); // TikHub wraps all responses in { code, data, ... } envelope // Unwrap to return the inner data directly if (json?.code !== undefined && json?.data !== undefined) { return json.data as T; } return json as T; } export class TikHubError extends Error { constructor( public statusCode: number, message: string ) { super(message); this.name = "TikHubError"; } }