import { createAuthenticatedFetch } from 'kody:runtime' import { DISCORD_API_BASE_URL, DISCORD_USER_AGENT, missingOauthIntegrationError, throwDiscordApiError, } from './errors.ts' import { integrationName, type InputRecord } from './validation.ts' const fetchers = new Map() async function oauthFetch(integration: string): Promise { const cached = fetchers.get(integration) if (cached) return cached try { const authed = await createAuthenticatedFetch(integration) fetchers.set(integration, authed) return authed } catch (error) { throw missingOauthIntegrationError(integration, error) } } export async function discordOauthRequest( path: string, input: InputRecord, init: { method?: string; query?: Record } = {}, ): Promise { const integration = integrationName(input) const url = new URL(DISCORD_API_BASE_URL + path) for (const [key, value] of Object.entries(init.query ?? {})) { if (value === undefined) continue url.searchParams.set(key, String(value)) } const authedFetch = await oauthFetch(integration) const response = await authedFetch(url.toString(), { method: init.method ?? 'GET', headers: { accept: 'application/json', 'User-Agent': DISCORD_USER_AGENT, }, }) const text = await response.text() let json: unknown = null if (text) { try { json = JSON.parse(text) } catch { json = text } } if (!response.ok) { throwDiscordApiError({ status: response.status, path: url.pathname + url.search, lane: 'oauth', details: json ?? text, integration, }) } return json }