mirror of
https://github.com/hzrd149/nsite-gateway.git
synced 2025-06-23 12:05:01 +00:00
143 lines
3.9 KiB
JavaScript
143 lines
3.9 KiB
JavaScript
![]() |
import { multiServerUpload, BlossomClient } from "blossom-client-sdk";
|
||
|
import { SimplePool } from "nostr-tools";
|
||
|
|
||
|
const logContainer = document.getElementById("log");
|
||
|
function log(...args) {
|
||
|
const el = document.createElement("div");
|
||
|
el.innerText = args.join(" ");
|
||
|
logContainer.appendChild(el);
|
||
|
}
|
||
|
|
||
|
const uploadButton = document.getElementById("upload-button");
|
||
|
|
||
|
/** @type {HTMLInputElement} */
|
||
|
const filesInput = document.getElementById("files");
|
||
|
|
||
|
/**
|
||
|
* @param {FileSystemFileEntry} fileEntry
|
||
|
* @returns {File}
|
||
|
*/
|
||
|
export function readFileSystemFile(fileEntry) {
|
||
|
return new Promise((res, rej) => {
|
||
|
fileEntry.file(
|
||
|
(file) => res(file),
|
||
|
(err) => rej(err),
|
||
|
);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {FileSystemDirectoryEntry} directory
|
||
|
* @returns {FileSystemEntry[]}
|
||
|
*/
|
||
|
export function readFileSystemDirectory(directory) {
|
||
|
return new Promise((res, rej) => {
|
||
|
directory.createReader().readEntries(
|
||
|
(entries) => res(entries),
|
||
|
(err) => rej(err),
|
||
|
);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* uploads a file system entry to blossom servers
|
||
|
* @param {FileSystemEntry} entry
|
||
|
* @returns {{file: File, path: string, sha256: string}[]}
|
||
|
*/
|
||
|
async function readFileSystemEntry(entry) {
|
||
|
const files = [];
|
||
|
if (entry instanceof FileSystemFileEntry && entry.isFile) {
|
||
|
try {
|
||
|
const file = await readFileSystemFile(entry);
|
||
|
const sha256 = await BlossomClient.getFileSha256(file);
|
||
|
const path = entry.fullPath;
|
||
|
|
||
|
files.push({ file, path, sha256 });
|
||
|
} catch (e) {
|
||
|
log("Failed to add" + entry.fullPath);
|
||
|
log(e.message);
|
||
|
}
|
||
|
} else if (entry instanceof FileSystemDirectoryEntry && entry.isDirectory) {
|
||
|
const entries = await readFileSystemDirectory(entry);
|
||
|
for (const e of entries) files.push(...(await readFileSystemEntry(e)));
|
||
|
}
|
||
|
|
||
|
return files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* uploads a file system entry to blossom servers
|
||
|
* @param {FileList} list
|
||
|
* @returns {{file: File, path: string, sha256: string}[]}
|
||
|
*/
|
||
|
async function readFileList(list) {
|
||
|
const files = [];
|
||
|
for (const file of list) {
|
||
|
const path = file.webkitRelativePath ? file.webkitRelativePath : file.name;
|
||
|
const sha256 = await BlossomClient.getFileSha256(file);
|
||
|
files.push({ file, path, sha256 });
|
||
|
}
|
||
|
return files;
|
||
|
}
|
||
|
|
||
|
const pool = new SimplePool();
|
||
|
|
||
|
/**
|
||
|
* uploads a file system entry to blossom servers
|
||
|
* @param {{file:File, path:string}} files
|
||
|
* @param {import("blossom-client-sdk").Signer} signer
|
||
|
* @param {*} auth
|
||
|
* @param {string[]} servers
|
||
|
* @param {string[]} relays
|
||
|
*/
|
||
|
async function uploadFiles(files, signer, auth, servers, relays) {
|
||
|
for (const { file, path, sha256 } of files) {
|
||
|
try {
|
||
|
const upload = multiServerUpload(servers, file, signer, auth);
|
||
|
|
||
|
let published = false;
|
||
|
for await (let { blob } of upload) {
|
||
|
if (!published) {
|
||
|
const signed = await signer({
|
||
|
kind: 34128,
|
||
|
content: "",
|
||
|
created_at: Math.round(Date.now() / 1000),
|
||
|
tags: [
|
||
|
["d", path],
|
||
|
["x", sha256],
|
||
|
],
|
||
|
});
|
||
|
await pool.publish(relays, signed);
|
||
|
|
||
|
log("Published", path, sha256, signed.id);
|
||
|
}
|
||
|
}
|
||
|
} catch (error) {
|
||
|
log(`Failed to upload ${path}`, error);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uploadButton.addEventListener("click", async () => {
|
||
|
if (!window.nostr) return alert("Missing NIP-07 signer");
|
||
|
|
||
|
const signer = (draft) => window.nostr.signEvent(draft);
|
||
|
const relays = document.getElementById("relays").value.split(/\n|,/);
|
||
|
const servers = document.getElementById("servers").value.split(/\n|,/);
|
||
|
|
||
|
try {
|
||
|
if (filesInput.files) {
|
||
|
const files = await readFileList(filesInput.files);
|
||
|
|
||
|
// strip leading dir
|
||
|
for (const file of files) file.path = file.path.replace(/^[^\/]+\//, "/");
|
||
|
|
||
|
log(`Found ${files.length} files`);
|
||
|
|
||
|
await uploadFiles(files, signer, undefined, servers, relays);
|
||
|
}
|
||
|
} catch (error) {
|
||
|
alert(`Failed to upload files: ${error.message}`);
|
||
|
}
|
||
|
});
|