mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
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';
|
|
|
|
export interface S3UploaderOpts {
|
|
endPoint: string;
|
|
region: string;
|
|
accessKey?: string;
|
|
secretKey?: string;
|
|
bucket?: string;
|
|
pathStyle?: boolean;
|
|
port?: number;
|
|
sessionToken?: string;
|
|
useSSL?: boolean;
|
|
}
|
|
|
|
/** S3-compatible uploader for AWS, Wasabi, DigitalOcean Spaces, and more. */
|
|
export class S3Uploader implements NUploader {
|
|
private client: S3Client;
|
|
|
|
constructor(opts: S3UploaderOpts) {
|
|
this.client = new S3Client(opts);
|
|
}
|
|
|
|
async upload(file: File): Promise<[['url', string], ...string[][]]> {
|
|
const sha256 = encodeHex(await crypto.subtle.digest('SHA-256', file.stream()));
|
|
const ext = extensionsByType(file.type)?.[0] ?? 'bin';
|
|
const filename = `${sha256}.${ext}`;
|
|
|
|
await this.client.putObject(filename, file.stream(), {
|
|
metadata: {
|
|
'Content-Type': file.type,
|
|
'x-amz-acl': 'public-read',
|
|
},
|
|
});
|
|
|
|
const { pathStyle, bucket } = Conf.s3;
|
|
|
|
const path = (pathStyle && bucket) ? join(bucket, filename) : filename;
|
|
const url = new URL(path, Conf.mediaDomain).toString();
|
|
|
|
return [
|
|
['url', url],
|
|
['m', file.type],
|
|
['x', sha256],
|
|
['size', file.size.toString()],
|
|
];
|
|
}
|
|
|
|
async delete(objectName: string) {
|
|
await this.client.deleteObject(objectName);
|
|
}
|
|
}
|