From 9a9bc319634df14b230ee446d0d6dc48d2051584 Mon Sep 17 00:00:00 2001 From: arne Date: Thu, 5 Jan 2023 11:09:32 +0100 Subject: [PATCH] Better error handling, wait for media to be processed --- main.ts | 91 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/main.ts b/main.ts index c689d6c..af9ed77 100644 --- a/main.ts +++ b/main.ts @@ -1,6 +1,26 @@ const MASTODON_INSTANCE_URL = Deno.env.get("MASTODON_INSTANCE_URL"); // e.g. https://botsin.space const MASTODON_ACCESS_TOKEN = Deno.env.get("MASTODON_ACCESS_TOKEN"); // you can get this at $INSTANCE_URL/settings/applications +if (MASTODON_INSTANCE_URL == null || MASTODON_INSTANCE_URL === '' || MASTODON_ACCESS_TOKEN == null || MASTODON_ACCESS_TOKEN === '') { + console.error('Please set MASTODON_INSTANE_URL and MASTODON_ACCESS_TOKEN!') + Deno.exit(1) +} + +// some helpers to work with the mastodon api + +const handleResponse = async (res: Response) => { + if (res.ok) return { response: res, data: await res.json() } + throw new Error(await res.text()) +} + +const api = (path: string, params: { body?: FormData | string, method?: string }) => fetch(`${MASTODON_INSTANCE_URL.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`, { + method: "POST", + headers: { + Authorization: `Bearer ${MASTODON_ACCESS_TOKEN}`, + }, + ...params, +}).then(handleResponse) + // first we need to find out which files we can post, and which ones we already // have posted @@ -32,6 +52,8 @@ const fileToPost = availableFiles[Math.floor(Math.random() * availableFiles.length)]; const bytes = await Deno.readFile(`./posts/${fileToPost}`); +console.log(`Will post file ${fileToPost}`) + // we need two requests // 1. upload media // 2. create status with media id @@ -40,45 +62,34 @@ const bytes = await Deno.readFile(`./posts/${fileToPost}`); const mediaData = new FormData(); mediaData.append("file", new Blob([bytes])); -type MediaResponse = { - "id": string; - "type": string; - "url": string; - "preview_url": string; - "remote_url": null; - "text_url": string; - "meta": { - "focus": { - "x": number; - "y": number; - }; - "original": { - "width": number; - "height": number; - "size": string; - "aspect": number; - }; - "small": { - "width": number; - "height": number; - "size": string; - "aspect": number; - }; - }; - "description": string; - "blurhash": string; -}; - console.log("Sending post request to", `${MASTODON_INSTANCE_URL}/api/v2/media`); -const mediaRequest = await fetch(`${MASTODON_INSTANCE_URL}/api/v2/media`, { - method: "POST", - headers: { - Authorization: `Bearer ${MASTODON_ACCESS_TOKEN}`, - }, - body: mediaData, -}).then((res) => res.json()) as unknown as MediaResponse; +const { data: mediaRequest } = await api('/api/v2/media', { body: mediaData }) as unknown as { data: { id: string } }; console.log("mediaRequest", mediaRequest); +// now we have to wait until the media file is processed +const sleep = (milliseconds: number) => new Promise((resolve, reject) => { + setTimeout(resolve, milliseconds) +}) + +const startTime = Date.now() +while (true) { + if ((Date.now() - startTime) / 1000 >= 60) { + console.error('Timeout waiting for media to be processed.') + Deno.exit(1) + } + + const { response } = await api(`/api/v1/media/${mediaRequest.id}`, { + method: 'GET' + }) + if (response.status === 200) { + console.log('Media finished processing!') + break + } else { + console.log('Media still processing…') + await sleep(5000) + } +} + // see https://docs.joinmastodon.org/methods/statuses/#create const statusData = new FormData(); statusData.append("media_ids[]", mediaRequest.id); @@ -87,13 +98,7 @@ console.log( "Sending post request to", `${MASTODON_INSTANCE_URL}/api/v1/statuses`, ); -const statusRequest = await fetch(`${MASTODON_INSTANCE_URL}/api/v1/statuses`, { - method: "POST", - headers: { - Authorization: `Bearer ${MASTODON_ACCESS_TOKEN}`, - }, - body: statusData, -}).then((res) => res.json()); +const { data: statusRequest } = await api('/api/v1/statuses', { body: statusData }); console.log("statusRequest", statusRequest); console.log("Linking posted file so we can skip it in the future…");