add more metadata to IPFSUploader

This commit is contained in:
Siddharth Singh 2024-10-27 07:35:29 +05:30
parent 9b473406cf
commit 0058437170
No known key found for this signature in database
3 changed files with 67 additions and 2 deletions

View file

@ -41,6 +41,7 @@
"@gfx/canvas-wasm": "jsr:@gfx/canvas-wasm@^0.4.2",
"@hono/hono": "jsr:@hono/hono@^4.4.6",
"@isaacs/ttlcache": "npm:@isaacs/ttlcache@^1.4.1",
"@jcayzac/image-information": "npm:@jcayzac/image-information@1.1.1",
"@lambdalisue/async": "jsr:@lambdalisue/async@^2.1.1",
"@negrel/webpush": "jsr:@negrel/webpush@^0.3.0",
"@noble/secp256k1": "npm:@noble/secp256k1@^2.0.0",
@ -59,6 +60,7 @@
"@std/json": "jsr:@std/json@^0.223.0",
"@std/media-types": "jsr:@std/media-types@^0.224.1",
"@std/streams": "jsr:@std/streams@^0.223.0",
"blurhash": "npm:blurhash@2.0.5",
"comlink": "npm:comlink@^4.4.1",
"comlink-async-generator": "npm:comlink-async-generator@^0.0.1",
"commander": "npm:commander@12.1.0",

28
deno.lock generated
View file

@ -80,12 +80,14 @@
"jsr:@std/streams@0.223": "0.223.0",
"npm:@electric-sql/pglite@~0.2.8": "0.2.8",
"npm:@isaacs/ttlcache@^1.4.1": "1.4.1",
"npm:@jcayzac/image-information@1.1.1": "1.1.1",
"npm:@noble/hashes@^1.4.0": "1.4.0",
"npm:@noble/secp256k1@2": "2.1.0",
"npm:@scure/base@^1.1.6": "1.1.6",
"npm:@scure/bip32@^1.4.0": "1.4.0",
"npm:@scure/bip39@^1.3.0": "1.3.0",
"npm:@types/node@*": "18.16.19",
"npm:blurhash@2.0.5": "2.0.5",
"npm:comlink-async-generator@*": "0.0.1",
"npm:comlink-async-generator@^0.0.1": "0.0.1",
"npm:comlink@^4.4.1": "4.4.1",
@ -658,6 +660,12 @@
"@isaacs/ttlcache@1.4.1": {
"integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="
},
"@jcayzac/image-information@1.1.1": {
"integrity": "sha512-WXM5RTu3tTuAPXPx4ytbywjqTxnjBUWM1sY+7A9UPqPwQbM9V3jkY/rzo1OJ6VYSpogFdK4cyc+o9FZFZLW+nw==",
"dependencies": [
"image-size"
]
},
"@noble/ciphers@0.5.3": {
"integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w=="
},
@ -769,6 +777,9 @@
"bintrees@1.0.2": {
"integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="
},
"blurhash@2.0.5": {
"integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w=="
},
"braces@3.0.2": {
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dependencies": [
@ -987,6 +998,15 @@
"safer-buffer"
]
},
"image-size@1.1.1": {
"integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==",
"dependencies": [
"queue"
]
},
"inherits@2.0.4": {
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-fullwidth-code-point@4.0.0": {
"integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="
},
@ -1260,6 +1280,12 @@
"punycode@2.3.1": {
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
},
"queue@6.0.2": {
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
"dependencies": [
"inherits"
]
},
"restore-cursor@4.0.0": {
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
"dependencies": [
@ -2104,12 +2130,14 @@
"jsr:@std/streams@0.223",
"npm:@electric-sql/pglite@~0.2.8",
"npm:@isaacs/ttlcache@^1.4.1",
"npm:@jcayzac/image-information@1.1.1",
"npm:@noble/secp256k1@2",
"npm:@scure/base@^1.1.6",
"npm:comlink-async-generator@^0.0.1",
"npm:comlink@^4.4.1",
"npm:commander@12.1.0",
"npm:entities@^4.5.0",
"npm:fast-blurhash@1.1.4",
"npm:fast-stable-stringify@1",
"npm:formdata-helper@0.3",
"npm:hono-rate-limiter@0.3",

View file

@ -1,5 +1,11 @@
import { NUploader } from '@nostrify/nostrify';
import { z } from 'zod';
import { probe } from '@jcayzac/image-information';
import { Stickynotes } from '@soapbox/stickynotes';
import { encode } from 'blurhash';
import { encodeHex } from '@std/encoding/hex';
const console = new Stickynotes('ditto:ipfs:uploader');
export interface IPFSUploaderOpts {
baseUrl: string;
@ -7,6 +13,19 @@ export interface IPFSUploaderOpts {
fetch?: typeof fetch;
}
function toByteArray(f: File): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener('loadend', (m) => {
if (m?.target?.result instanceof ArrayBuffer) {
resolve(new Uint8Array(m.target.result));
} else reject('Error loading file: readAsArrayBufferFailed');
});
reader.addEventListener('error', (e) => reject(e));
reader.readAsArrayBuffer(f);
});
}
/**
* IPFS uploader. It expects an IPFS node up and running.
* It will try to connect to `http://localhost:5001` by default,
@ -36,13 +55,29 @@ export class IPFSUploader implements NUploader {
});
const { Hash: cid } = IPFSUploader.schema().parse(await response.json());
return [
const tags: [['url', string], ...string[][]] = [
['url', new URL(`/ipfs/${cid}`, this.baseUrl).toString()],
['m', file.type],
['cid', cid],
['size', file.size.toString()],
];
try {
const buffer = await toByteArray(file);
const hash = await crypto.subtle.digest('SHA-256', buffer).then(encodeHex);
tags.push(['x', hash], ['ox', hash]);
const metadata = probe(buffer);
if (metadata) {
// sane default from https://github.com/woltapp/blurhash readme
const blurhash = encode(new Uint8ClampedArray(buffer), metadata.width, metadata.height, 4, 4);
tags.push(['blurhash', blurhash]);
tags.push(['dim', `${metadata.width}x${metadata.height}`]);
}
} catch (e) {
console.error(`Error parsing ipfs metadata: ${e}`);
}
return tags;
}
async delete(cid: string, opts?: { signal?: AbortSignal }): Promise<void> {