Merge branch 'nostrify-22' into 'main'
Upgrade Nostrify to v0.22.0 See merge request soapbox-pub/ditto!283
This commit is contained in:
commit
281f0f9625
|
@ -22,7 +22,7 @@
|
|||
"@isaacs/ttlcache": "npm:@isaacs/ttlcache@^1.4.1",
|
||||
"@lambdalisue/async": "jsr:@lambdalisue/async@^2.1.1",
|
||||
"@noble/secp256k1": "npm:@noble/secp256k1@^2.0.0",
|
||||
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.21.1",
|
||||
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.22.0",
|
||||
"@sentry/deno": "https://deno.land/x/sentry@7.112.2/index.mjs",
|
||||
"@soapbox/kysely-deno-sqlite": "jsr:@soapbox/kysely-deno-sqlite@^2.1.0",
|
||||
"@soapbox/stickynotes": "jsr:@soapbox/stickynotes@^0.4.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { NostrEvent, NostrSigner, NStore } from '@nostrify/nostrify';
|
||||
import { NostrEvent, NostrSigner, NStore, NUploader } from '@nostrify/nostrify';
|
||||
import Debug from '@soapbox/stickynotes/debug';
|
||||
import { type Context, Env as HonoEnv, type Handler, Hono, Input as HonoInput, type MiddlewareHandler } from 'hono';
|
||||
import { cors, logger, serveStatic } from 'hono/middleware';
|
||||
|
@ -81,7 +81,6 @@ import { hostMetaController } from '@/controllers/well-known/host-meta.ts';
|
|||
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
|
||||
import { nostrController } from '@/controllers/well-known/nostr.ts';
|
||||
import { webfingerController } from '@/controllers/well-known/webfinger.ts';
|
||||
import { DittoUploader } from '@/interfaces/DittoUploader.ts';
|
||||
import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts';
|
||||
import { cacheMiddleware } from '@/middleware/cacheMiddleware.ts';
|
||||
import { cspMiddleware } from '@/middleware/cspMiddleware.ts';
|
||||
|
@ -97,7 +96,7 @@ interface AppEnv extends HonoEnv {
|
|||
/** Signer to get the logged-in user's pubkey, relays, and to sign events, or `undefined` if the user isn't logged in. */
|
||||
signer?: NostrSigner;
|
||||
/** Uploader for the user to upload files. */
|
||||
uploader?: DittoUploader;
|
||||
uploader?: NUploader;
|
||||
/** NIP-98 signed event proving the pubkey is owned by the user. */
|
||||
proof?: NostrEvent;
|
||||
/** Store */
|
||||
|
|
|
@ -140,6 +140,10 @@ class Conf {
|
|||
static get nostrbuildEndpoint(): string {
|
||||
return Deno.env.get('NOSTRBUILD_ENDPOINT') || 'https://nostr.build/api/v2/upload/files';
|
||||
}
|
||||
/** Default Blossom servers to use when the `blossom` uploader is set. */
|
||||
static get blossomServers(): string[] {
|
||||
return Deno.env.get('BLOSSOM_SERVERS')?.split(',') || ['https://blossom.primal.net/'];
|
||||
}
|
||||
/** Module to upload files with. */
|
||||
static get uploader() {
|
||||
return Deno.env.get('DITTO_UPLOADER');
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export interface DittoUploader {
|
||||
upload(file: File, opts?: { signal?: AbortSignal }): Promise<[['url', string], ...string[][]]>;
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
import { BlossomUploader, NostrBuildUploader } from '@nostrify/nostrify/uploaders';
|
||||
|
||||
import { AppMiddleware } from '@/app.ts';
|
||||
import { Conf } from '@/config.ts';
|
||||
import { DenoUploader } from '@/uploaders/DenoUploader.ts';
|
||||
import { IPFSUploader } from '@/uploaders/IPFSUploader.ts';
|
||||
import { NostrBuildUploader } from '@/uploaders/NostrBuildUploader.ts';
|
||||
import { S3Uploader } from '@/uploaders/S3Uploader.ts';
|
||||
import { fetchWorker } from '@/workers/fetch.ts';
|
||||
|
||||
/** Set an uploader for the user. */
|
||||
export const uploaderMiddleware: AppMiddleware = async (c, next) => {
|
||||
const signer = c.get('signer');
|
||||
|
||||
switch (Conf.uploader) {
|
||||
case 's3':
|
||||
c.set('uploader', new S3Uploader(Conf.s3));
|
||||
|
@ -19,7 +22,12 @@ export const uploaderMiddleware: AppMiddleware = async (c, next) => {
|
|||
c.set('uploader', new DenoUploader({ baseUrl: Conf.mediaDomain, dir: Conf.uploadsDir }));
|
||||
break;
|
||||
case 'nostrbuild':
|
||||
c.set('uploader', new NostrBuildUploader({ endpoint: Conf.nostrbuildEndpoint, fetch: fetchWorker }));
|
||||
c.set('uploader', new NostrBuildUploader({ endpoint: Conf.nostrbuildEndpoint, signer, fetch: fetchWorker }));
|
||||
break;
|
||||
case 'blossom':
|
||||
if (signer) {
|
||||
c.set('uploader', new BlossomUploader({ servers: Conf.blossomServers, signer, fetch: fetchWorker }));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import { join } from 'node:path';
|
||||
|
||||
import { NUploader } from '@nostrify/nostrify';
|
||||
import { crypto } from '@std/crypto';
|
||||
import { encodeHex } from '@std/encoding/hex';
|
||||
import { extensionsByType } from '@std/media-types';
|
||||
|
||||
import { DittoUploader } from '@/interfaces/DittoUploader.ts';
|
||||
|
||||
export interface DenoUploaderOpts {
|
||||
baseUrl: string;
|
||||
dir: string;
|
||||
}
|
||||
|
||||
/** Local Deno filesystem uploader. */
|
||||
export class DenoUploader implements DittoUploader {
|
||||
export class DenoUploader implements NUploader {
|
||||
baseUrl: string;
|
||||
dir: string;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { NUploader } from '@nostrify/nostrify';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { DittoUploader } from '@/interfaces/DittoUploader.ts';
|
||||
|
||||
export interface IPFSUploaderOpts {
|
||||
baseUrl: string;
|
||||
apiUrl?: string;
|
||||
|
@ -13,7 +12,7 @@ export interface IPFSUploaderOpts {
|
|||
* It will try to connect to `http://localhost:5001` by default,
|
||||
* and upload the file using the REST API.
|
||||
*/
|
||||
export class IPFSUploader implements DittoUploader {
|
||||
export class IPFSUploader implements NUploader {
|
||||
private baseUrl: string;
|
||||
private apiUrl: string;
|
||||
private fetch: typeof fetch;
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
import { DittoUploader } from '@/interfaces/DittoUploader.ts';
|
||||
|
||||
export interface NostrBuildUploaderOpts {
|
||||
endpoint?: string;
|
||||
fetch?: typeof fetch;
|
||||
}
|
||||
|
||||
/** Upload files to nostr.build or another compatible server. */
|
||||
export class NostrBuildUploader implements DittoUploader {
|
||||
private endpoint: string;
|
||||
private fetch: typeof fetch;
|
||||
|
||||
constructor(opts: NostrBuildUploaderOpts) {
|
||||
this.endpoint = opts.endpoint ?? 'https://nostr.build/api/v2/upload/files';
|
||||
this.fetch = opts.fetch ?? globalThis.fetch;
|
||||
}
|
||||
|
||||
async upload(file: File, opts?: { signal?: AbortSignal }): Promise<[['url', string], ...string[][]]> {
|
||||
const formData = new FormData();
|
||||
formData.append('fileToUpload', file);
|
||||
|
||||
const response = await this.fetch(this.endpoint, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
signal: opts?.signal,
|
||||
});
|
||||
|
||||
const json = await response.json();
|
||||
const [data] = NostrBuildUploader.schema().parse(json).data;
|
||||
|
||||
const tags: [['url', string], ...string[][]] = [
|
||||
['url', data.url],
|
||||
['m', data.mime],
|
||||
['x', data.sha256],
|
||||
['ox', data.original_sha256],
|
||||
['size', data.size.toString()],
|
||||
];
|
||||
|
||||
if (data.dimensions) {
|
||||
tags.push(['dim', `${data.dimensions.width}x${data.dimensions.height}`]);
|
||||
}
|
||||
|
||||
if (data.blurhash) {
|
||||
tags.push(['blurhash', data.blurhash]);
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
/** nostr.build API response schema. */
|
||||
private static schema() {
|
||||
return z.object({
|
||||
data: z.object({
|
||||
url: z.string().url(),
|
||||
blurhash: z.string().optional().catch(undefined),
|
||||
sha256: z.string(),
|
||||
original_sha256: z.string(),
|
||||
mime: z.string(),
|
||||
size: z.number(),
|
||||
dimensions: z.object({
|
||||
width: z.number(),
|
||||
height: z.number(),
|
||||
}).optional().catch(undefined),
|
||||
}).array().min(1),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import { join } from 'node:path';
|
||||
|
||||
import { S3Client } from '@bradenmacdonald/s3-lite-client';
|
||||
import { NUploader } from '@nostrify/nostrify';
|
||||
import { crypto } from '@std/crypto';
|
||||
import { encodeHex } from '@std/encoding/hex';
|
||||
import { extensionsByType } from '@std/media-types';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
import { DittoUploader } from '@/interfaces/DittoUploader.ts';
|
||||
|
||||
export interface S3UploaderOpts {
|
||||
endPoint: string;
|
||||
|
@ -21,7 +21,7 @@ export interface S3UploaderOpts {
|
|||
}
|
||||
|
||||
/** S3-compatible uploader for AWS, Wasabi, DigitalOcean Spaces, and more. */
|
||||
export class S3Uploader implements DittoUploader {
|
||||
export class S3Uploader implements NUploader {
|
||||
private client: S3Client;
|
||||
|
||||
constructor(opts: S3UploaderOpts) {
|
||||
|
|
Loading…
Reference in New Issue