diff --git a/app/[leaflet_id]/publish/publishBskyPost.ts b/app/[leaflet_id]/publish/publishBskyPost.ts index 7fa16dd6..9fc2efb9 100644 --- a/app/[leaflet_id]/publish/publishBskyPost.ts +++ b/app/[leaflet_id]/publish/publishBskyPost.ts @@ -12,6 +12,10 @@ import { AtpBaseClient, PubLeafletDocument } from "lexicons/api"; import { createOauthClient } from "src/atproto-oauth"; import { supabaseServerClient } from "supabase/serverClient"; import { Json } from "supabase/database.types"; +import { + getMicroLinkOgImage, + getWebpageImage, +} from "src/utils/getMicroLinkOgImage"; export async function publishPostToBsky(args: { text: string; @@ -31,14 +35,11 @@ export async function publishPostToBsky(args: { credentialSession.fetchHandler.bind(credentialSession), ); let newPostUrl = args.url; - let preview_image = await fetch( - `https://pro.microlink.io/?url=${newPostUrl}&screenshot=true&viewport.width=1400&viewport.height=733&meta=false&embed=screenshot.url&force=true`, - { - headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - }, - ); + let preview_image = await getWebpageImage(newPostUrl, { + width: 1400, + height: 733, + noCache: true, + }); let binary = await preview_image.blob(); let resized_preview_image = await sharp(await binary.arrayBuffer()) diff --git a/app/api/link_previews/route.ts b/app/api/link_previews/route.ts index 090674d9..9b7ad6b2 100644 --- a/app/api/link_previews/route.ts +++ b/app/api/link_previews/route.ts @@ -5,6 +5,10 @@ import { NextRequest } from "next/server"; import * as z from "zod"; import { createClient } from "@supabase/supabase-js"; import { Database } from "supabase/database.types"; +import { + getMicroLinkOgImage, + getWebpageImage, +} from "src/utils/getMicroLinkOgImage"; let supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, process.env.SUPABASE_SERVICE_ROLE_KEY as string, @@ -27,17 +31,7 @@ export type LinkPreviewMetadataResult = ReturnType; export type LinkPreviewImageResult = ReturnType; async function get_link_image_preview(url: string) { - let image = await fetch( - `https://pro.microlink.io/?url=${url}&screenshot&viewport.width=1400&viewport.height=1213&embed=screenshot.url&meta=false&force=true`, - { - headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - next: { - revalidate: 600, - }, - }, - ); + let image = await getWebpageImage(url, { width: 1400, height: 1213 }); let key = await hash(url); if (image.status === 200) { await supabase.storage diff --git a/src/utils/getMicroLinkOgImage.ts b/src/utils/getMicroLinkOgImage.ts index 4ccf6ece..fac40494 100644 --- a/src/utils/getMicroLinkOgImage.ts +++ b/src/utils/getMicroLinkOgImage.ts @@ -2,21 +2,58 @@ import { headers } from "next/headers"; export async function getMicroLinkOgImage( path: string, - options?: { width?: number; height?: number; deviceScaleFactor?: number }, + options?: { + width?: number; + height?: number; + deviceScaleFactor?: number; + noCache?: boolean; + }, ) { const headersList = await headers(); const hostname = headersList.get("x-forwarded-host"); let protocol = headersList.get("x-forwarded-proto"); let full_path = `${protocol}://${hostname}${path}`; + return getWebpageImage(full_path, options); +} + +export async function getWebpageImage( + url: string, + options?: { + width?: number; + height?: number; + deviceScaleFactor?: number; + noCache?: boolean; + }, +) { let response = await fetch( - `https://pro.microlink.io/?url=${encodeURIComponent(full_path)}&screenshot=true&viewport.width=${options?.width || 1400}&viewport.height=${options?.height || 733}&viewport.deviceScaleFactor=${options?.deviceScaleFactor || 1}&meta=false&embed=screenshot.url&force=true`, + `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT}/browser-rendering/screenshot`, { + method: "POST", headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - next: { - revalidate: 600, + "Content-type": "application/json", + Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`, }, + body: JSON.stringify({ + url, + addStyleTag: [ + { + content: `* {overflow: hidden !important; }`, + }, + ], + gotoOptions: { + waitUntil: "load", + }, + viewport: { + width: options?.width || 1400, + height: options?.height || 733, + deviceScaleFactor: options?.deviceScaleFactor, + }, + }), + next: !options?.noCache + ? undefined + : { + revalidate: 600, + }, }, ); const clonedResponse = response.clone();