diff --git a/src/utils/image-metadata.ts b/src/utils/image-metadata.ts index 2d5e861f..75b2f6ba 100644 --- a/src/utils/image-metadata.ts +++ b/src/utils/image-metadata.ts @@ -6,7 +6,7 @@ import { Stickynotes } from '@soapbox/stickynotes'; const console = new Stickynotes('ditto:uploaders'); -function toByteArray(f: File): Promise { +export function toByteArray(f: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.addEventListener('loadend', (m) => { diff --git a/src/utils/upload.ts b/src/utils/upload.ts index 81c88c86..cadac9bc 100644 --- a/src/utils/upload.ts +++ b/src/utils/upload.ts @@ -3,6 +3,9 @@ import { HTTPException } from '@hono/hono/http-exception'; import { AppContext } from '@/app.ts'; import { Conf } from '@/config.ts'; import { DittoUpload, dittoUploads } from '@/DittoUploads.ts'; +import { getOptionalNip94Metadata, toByteArray } from '@/utils/image-metadata.ts'; +import type { Nip94MetadataOptional } from '@/interfaces/Nip94Metadata.ts'; +import { encodeHex } from '@std/encoding/hex'; interface FileMeta { pubkey: string; @@ -30,12 +33,31 @@ export async function uploadFile( } const tags = await uploader.upload(file, { signal }); + const tagMap = tags.reduce((map, value) => map.set(value[0], value.slice(1)), new Map()); + const url = tags[0][1]; if (description) { tags.push(['alt', description]); } + let metadata: Nip94MetadataOptional | undefined; + if (!tagMap.has('dim')) { + // blurhash needs us to call sharp() anyway to decode the image data. + // all getOptionalNip94Metadata does is call these in sequence, plus + // one extra sha256 which is whatever (and actually does come in handy later.) + metadata ??= await getOptionalNip94Metadata(file); + tags.push(['dim', metadata.dim!]); + if (!tagMap.has('blurhash')) { + tags.push(['blurhash', metadata.blurhash!]); + } + } + if (!tagMap.has('x') || !tagMap.has('ox')) { + const hash = metadata?.x || await crypto.subtle.digest('SHA-256', await toByteArray(file)).then(encodeHex); + tags.push(['x', hash!]); + tags.push(['ox', hash!]); + } + const upload = { id: crypto.randomUUID(), url,