import type { AccountDetail, AccountListResponse, BotDetail, BotListResponse, ChannelDetail, EmojiListResponse, ChannelListResponse, CommandResult, GroupMessageDetail, GroupMessageListResponse, MessageDetail, MessageListResponse, OfficialStarGiftListResponse, StarGiftCollectiblePreview, StarGiftListResponse } from "./types"; export class APIError extends Error { status: number; constructor(status: number, message: string) { super(message); this.status = status; } } async function request(url: string, init: RequestInit = {}): Promise { const isForm = typeof FormData !== "undefined" && init.body instanceof FormData; const response = await fetch(url, { credentials: "same-origin", headers: isForm ? init.headers : { "Content-Type": "application/json", ...(init.headers ?? {}) }, ...init }); const text = await response.text(); const data = text ? JSON.parse(text) : null; if (!response.ok) { const message = data?.error || data?.Error || data?.message || response.statusText; throw new APIError(response.status, message); } return data as T; } export function errorMessage(error: unknown): string { if (error instanceof Error) { return error.message; } return String(error); } export const api = { session: () => request<{ actor: string }>("/api/session"), login: (secret: string) => request<{ actor: string }>("/api/login", { method: "POST", body: JSON.stringify({ secret }) }), logout: () => request<{ ok: boolean }>("/api/logout", { method: "POST", body: "{}" }), accounts: (params: URLSearchParams) => request(`/api/accounts?${params.toString()}`), account: (id: number) => request(`/api/accounts/${id}`), channels: (params: URLSearchParams) => request(`/api/channels?${params.toString()}`), channel: (id: number) => request(`/api/channels/${id}`), bots: (params: URLSearchParams) => request(`/api/bots?${params.toString()}`), bot: (id: number) => request(`/api/bots/${id}`), emoji: (params: URLSearchParams) => request(`/api/emoji?${params.toString()}`), emojiAnimation: (documentID: string) => request>(`/api/emoji/${encodeURIComponent(documentID)}/animation`), messages: (params: URLSearchParams) => request(`/api/messages?${params.toString()}`), message: (ownerUserID: number, msgID: number) => { const params = new URLSearchParams({ owner_user_id: String(ownerUserID), msg_id: String(msgID) }); return request(`/api/messages/detail?${params.toString()}`); }, groupMessages: (params: URLSearchParams) => request(`/api/messages/groups?${params.toString()}`), groupMessage: (channelID: number, msgID: number) => { const params = new URLSearchParams({ channel_id: String(channelID), msg_id: String(msgID) }); return request(`/api/messages/groups/detail?${params.toString()}`); }, gifts: () => request("/api/gifts"), officialGifts: () => request("/api/official-gifts"), officialGiftAnimation: (id: string) => request>(`/api/official-gifts/${encodeURIComponent(id)}/animation`), giftAnimation: (id: string) => request>(`/api/gifts/${encodeURIComponent(id)}/animation`), giftCollectibles: (id: string) => request(`/api/gifts/${encodeURIComponent(id)}/collectibles`), giftCollectibleAnimation: (giftID: string, kind: "model" | "pattern", attributeID: string) => request>(`/api/gifts/${encodeURIComponent(giftID)}/collectibles/${kind}/${encodeURIComponent(attributeID)}/animation`), importGift: (form: FormData) => request("/api/actions/import-gift", { method: "POST", body: form }), importOfficialGift: (payload: Record) => request("/api/actions/import-official-gift", { method: "POST", body: JSON.stringify(payload) }), publishGiftCollectibles: (giftID: string, form: FormData) => request(`/api/actions/publish-gift-collectibles?gift_id=${encodeURIComponent(giftID)}`, { method: "POST", body: form }), action: (path: string, payload: Record) => request(path, { method: "POST", body: JSON.stringify(payload) }) };