ogcard: ensure we use jpeg images for satori compat (#10023)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
// @NOTE satori does not currently support webp, see vercel/satori#273
|
||||||
function detectMime(buf: Buffer): string {
|
function detectMime(buf: Buffer): string {
|
||||||
if (buf[0] === 0xff && buf[1] === 0xd8) return 'image/jpeg'
|
if (buf[0] === 0xff && buf[1] === 0xd8) return 'image/jpeg'
|
||||||
if (buf[0] === 0x89 && buf[1] === 0x50) return 'image/png'
|
if (buf[0] === 0x89 && buf[1] === 0x50) return 'image/png'
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import assert from 'node:assert'
|
import assert from 'node:assert'
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {AppBskyGraphDefs, AtUri} from '@atproto/api'
|
import {type AppBskyGraphDefs, AtUri} from '@atproto/api'
|
||||||
import resvg from '@resvg/resvg-js'
|
import resvg from '@resvg/resvg-js'
|
||||||
import {Express} from 'express'
|
import {type Express} from 'express'
|
||||||
import satori from 'satori'
|
import satori from 'satori'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
STARTERPACK_HEIGHT,
|
STARTERPACK_HEIGHT,
|
||||||
STARTERPACK_WIDTH,
|
STARTERPACK_WIDTH,
|
||||||
} from '../components/StarterPack.js'
|
} from '../components/StarterPack.js'
|
||||||
import {AppContext} from '../context.js'
|
import {type AppContext} from '../context.js'
|
||||||
import {httpLogger} from '../logger.js'
|
import {httpLogger} from '../logger.js'
|
||||||
import {loadEmojiAsSvg} from '../util.js'
|
import {loadEmojiAsSvg} from '../util.js'
|
||||||
import {handler, originVerifyMiddleware} from './util.js'
|
import {handler, originVerifyMiddleware} from './util.js'
|
||||||
@@ -83,12 +83,18 @@ export default function (ctx: AppContext, app: Express) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getImage(url: string) {
|
async function getImage(url: string) {
|
||||||
const response = await fetch(url)
|
const response = await fetch(ensureJpeg(url))
|
||||||
const arrayBuf = await response.arrayBuffer() // must drain body even if it will be discarded
|
const arrayBuf = await response.arrayBuffer() // must drain body even if it will be discarded
|
||||||
if (response.status !== 200) return null
|
if (response.status !== 200) return null
|
||||||
return Buffer.from(arrayBuf)
|
return Buffer.from(arrayBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CDN URLs end with @jpeg, @webp, or no extension (which may default to webp).
|
||||||
|
// We want to ensure the image URLs we use are for jpegs, required for compat with satori.
|
||||||
|
function ensureJpeg(url: string) {
|
||||||
|
return url.replace(/(@[a-z]{3,5})?$/, '@jpeg')
|
||||||
|
}
|
||||||
|
|
||||||
const hideAvatarLabels = new Set([
|
const hideAvatarLabels = new Set([
|
||||||
'!hide',
|
'!hide',
|
||||||
'!warn',
|
'!warn',
|
||||||
|
|||||||
Reference in New Issue
Block a user