UNPKG

masto

Version:

Mastodon API client for JavaScript, TypeScript, Node.js, browsers

92 lines (91 loc) 3.05 kB
import { snakeCase } from "change-case"; import { isRecord, sleep } from "../../utils/index.js"; import { MastoHttpError, MastoTimeoutError } from "../errors/index.js"; function isHttpActionType(actionType) { return ["fetch", "create", "update", "remove", "list"].includes(actionType); } function toHttpActionType(action) { if (isHttpActionType(action)) { return action; } switch (action) { case "lookup": case "verify_credentials": { return "fetch"; } case "update_credentials": { return "update"; } default: { return "create"; } } } function inferEncoding(action, path) { if ((action === "create" && path === "/api/v1/accounts") || (action === "update" && path === "/api/v1/accounts/update_credentials") || (action === "create" && path === "/api/v1/email") || (action === "create" && path === "/api/v1/featured_tag") || (action === "create" && path === "/api/v1/media") || (action === "create" && path === "/api/v2/media")) { return "multipart-form"; } return "json"; } async function waitForMediaAttachment(id, timeout, http) { let media; const signal = AbortSignal.timeout(timeout); while (!media) { if (signal.aborted) { throw new MastoTimeoutError(`Media processing timed out of ${timeout}ms`); } try { await sleep(1000); const processing = await http.get(`/api/v1/media/${id}`); if (processing.url) { media = processing; } } catch (error) { if (error instanceof MastoHttpError && error.statusCode === 404) { continue; } throw error; } } return media; } export class HttpActionDispatcherHookMastodon { http; mediaTimeout; constructor(http, mediaTimeout = 1000 * 60) { this.http = http; this.mediaTimeout = mediaTimeout; } beforeDispatch(action) { const type = toHttpActionType(action.type); const path = isHttpActionType(action.type) ? action.path : action.path + "/" + snakeCase(action.type); const encoding = inferEncoding(type, path); const meta = { ...action.meta, encoding }; return { type, path, data: action.data, meta }; } dispatch(action) { if (action.type === "update" && action.path === "/api/v1/accounts/update_credentials") { return this.http.patch(action.path, action.data, action.meta); } return false; } afterDispatch(action, result) { if (action.type === "create" && action.path === "/api/v2/media") { const media = result; if (isRecord(action.data) && action.data?.skipPolling === true) { return media; } return waitForMediaAttachment(media.id, this.mediaTimeout, this.http); } return result; } }