import type { MarketRecord } from "./types"; interface FetchResponseLike { json(): Promise; ok: boolean; } type FetchLike = ( input: string, init?: RequestInit ) => Promise; interface AuthorBaseClientOptions { baseUrl?: string; fetchImpl?: FetchLike; timeoutMs?: number; } export function createAuthorBaseClient(options: AuthorBaseClientOptions = {}) { const baseUrl = options.baseUrl ?? resolveBaseUrl(); const fetchImpl = options.fetchImpl ?? defaultFetch; const timeoutMs = options.timeoutMs ?? 8000; return { async loadAuthorBaseInfo(authorId: string): Promise { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeoutMs); try { const response = await fetchImpl( buildAuthorBaseInfoUrl(authorId, baseUrl), { credentials: "include", method: "GET", signal: controller.signal } ); if (!response.ok) { return buildFailedRecord(authorId, "request-failed"); } return mapAuthorBaseInfoResponse(authorId, await response.json()); } catch (error) { return buildFailedRecord( authorId, error instanceof Error && error.name === "AbortError" ? "timeout" : "request-failed" ); } finally { clearTimeout(timeoutId); } } }; } export function buildAuthorBaseInfoUrl( authorId: string, baseUrl: string ): string { const url = new URL("/gw/api/author/get_author_base_info", baseUrl); url.searchParams.set("o_author_id", authorId); url.searchParams.set("platform_source", "1"); url.searchParams.set("platform_channel", "1"); url.searchParams.set("recommend", "true"); url.searchParams.set("need_sec_uid", "true"); url.searchParams.set("need_linkage_info", "true"); return url.toString(); } export function mapAuthorBaseInfoResponse( authorId: string, payload: unknown ): MarketRecord { if (!isRecord(payload)) { return buildFailedRecord(authorId, "bad-response"); } const authorName = readString(payload.nick_name); if (!authorName) { return buildFailedRecord(authorId, "missing-rate"); } return { authorId, authorName, status: "success" }; } function buildFailedRecord( authorId: string, failureReason: MarketRecord["failureReason"] ): MarketRecord { return { authorId, authorName: "", failureReason, status: "failed" }; } function readString(value: unknown): string | null { return typeof value === "string" && value.trim() ? value.trim() : null; } function resolveBaseUrl(): string { if (typeof location !== "undefined" && location.origin) { return location.origin; } return "https://xingtu.cn"; } async function defaultFetch(input: string, init?: RequestInit) { return fetch(input, init); } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; }