mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
add more metadata to IPFSUploader
This commit is contained in:
parent
6171a321e2
commit
b0a2422437
3 changed files with 67 additions and 2 deletions
|
|
@ -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
28
deno.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue