Blossom fixes
This commit is contained in:
parent
f9cdc6d85e
commit
7fa2633a1e
@ -2,7 +2,7 @@ use std::fs;
|
|||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use nostr::prelude::hex;
|
use nostr::prelude::hex;
|
||||||
use nostr::TagKind;
|
use nostr::{Alphabet, SingleLetterTag, TagKind};
|
||||||
use rocket::data::ByteUnit;
|
use rocket::data::ByteUnit;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::response::Responder;
|
use rocket::response::Responder;
|
||||||
@ -54,12 +54,16 @@ impl BlossomResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_method(event: &nostr::Event, method: &str) -> bool {
|
fn check_method(event: &nostr::Event, method: &str) -> bool {
|
||||||
if let Some(t) = event.tags.iter().find_map(|t| if t.kind() == TagKind::Method {
|
if let Some(t) = event.tags.iter().find_map(|t| {
|
||||||
t.content()
|
if t.kind() == TagKind::Method
|
||||||
} else {
|
|| t.kind() == TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::T))
|
||||||
None
|
{
|
||||||
|
t.content()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}) {
|
}) {
|
||||||
return t == method;
|
return t.eq_ignore_ascii_case(method);
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -90,24 +94,24 @@ async fn upload(
|
|||||||
return BlossomResponse::error("Invalid request method tag");
|
return BlossomResponse::error("Invalid request method tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = auth
|
let name = auth.event.tags.iter().find_map(|t| {
|
||||||
.event
|
if t.kind() == TagKind::Name {
|
||||||
.tags
|
t.content()
|
||||||
.iter()
|
|
||||||
.find_map(|t| if t.kind() == TagKind::Name { t.content() } else { None });
|
|
||||||
let size = match auth.event.tags.iter().find_map(|t| {
|
|
||||||
let values = t.as_vec();
|
|
||||||
if values.len() == 2 && values[0] == "size" {
|
|
||||||
Some(values[1].parse::<usize>().unwrap())
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
});
|
||||||
Some(s) => s,
|
let size = auth.event.tags.iter().find_map(|t| {
|
||||||
None => return BlossomResponse::error("Invalid request, no size tag"),
|
if t.kind() == TagKind::Size {
|
||||||
};
|
t.content().and_then(|v| v.parse::<usize>().ok())
|
||||||
if size > settings.max_upload_bytes {
|
} else {
|
||||||
return BlossomResponse::error("File too large");
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(z) = size {
|
||||||
|
if z > settings.max_upload_bytes {
|
||||||
|
return BlossomResponse::error("File too large");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let mime_type = auth
|
let mime_type = auth
|
||||||
.content_type
|
.content_type
|
||||||
|
102
ui/index.html
102
ui/index.html
@ -66,37 +66,80 @@
|
|||||||
const file = input.files[0];
|
const file = input.files[0];
|
||||||
console.debug(file);
|
console.debug(file);
|
||||||
|
|
||||||
const fd = new FormData();
|
const r_nip96 = document.querySelector("#method-nip96").checked;
|
||||||
fd.append("size", file.size.toString());
|
const r_blossom = document.querySelector("#method-blossom").checked;
|
||||||
fd.append("caption", file.name);
|
if (r_nip96) {
|
||||||
fd.append("media_type", file.type);
|
await uploadFilesNip96(file)
|
||||||
fd.append("file", file);
|
} else if (r_blossom) {
|
||||||
fd.append("no_transform", document.querySelector("#no_transform").checked.toString())
|
await uploadBlossom(file);
|
||||||
|
}
|
||||||
const auth_event = await window.nostr.signEvent({
|
|
||||||
kind: 27235,
|
|
||||||
created_at: Math.floor(new Date().getTime() / 1000),
|
|
||||||
content: "",
|
|
||||||
tags: [
|
|
||||||
["u", `${window.location.protocol}//${window.location.host}/n96`],
|
|
||||||
["method", "POST"]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
const rsp = await fetch("/n96", {
|
|
||||||
body: fd,
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
accept: "application/json",
|
|
||||||
authorization: `Nostr ${btoa(JSON.stringify(auth_event))}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await dumpToLog(rsp);
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (ex instanceof Error) {
|
if (ex instanceof Error) {
|
||||||
alert(ex.message);
|
alert(ex.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||||
|
return [...new Uint8Array(buffer)]
|
||||||
|
.map(x => x.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadBlossom(file) {
|
||||||
|
const hash = await window.crypto.subtle.digest("SHA-256", await file.arrayBuffer());
|
||||||
|
|
||||||
|
const now = Math.floor(new Date().getTime() / 1000);
|
||||||
|
const auth_event = await window.nostr.signEvent({
|
||||||
|
kind: 24242,
|
||||||
|
created_at: now,
|
||||||
|
content: `Upload ${file.name}`,
|
||||||
|
tags: [
|
||||||
|
["t", "upload"],
|
||||||
|
["u", `${window.location.protocol}//${window.location.host}/upload`],
|
||||||
|
["x", buf2hex(hash)],
|
||||||
|
["method", "PUT"],
|
||||||
|
["expiration", (now + 10).toString()]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const rsp = await fetch("/upload", {
|
||||||
|
body: file,
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
accept: "application/json",
|
||||||
|
authorization: `Nostr ${btoa(JSON.stringify(auth_event))}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await dumpToLog(rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadFilesNip96(file) {
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append("size", file.size.toString());
|
||||||
|
fd.append("caption", file.name);
|
||||||
|
fd.append("media_type", file.type);
|
||||||
|
fd.append("file", file);
|
||||||
|
fd.append("no_transform", document.querySelector("#no_transform").checked.toString())
|
||||||
|
|
||||||
|
const auth_event = await window.nostr.signEvent({
|
||||||
|
kind: 27235,
|
||||||
|
created_at: Math.floor(new Date().getTime() / 1000),
|
||||||
|
content: "",
|
||||||
|
tags: [
|
||||||
|
["u", `${window.location.protocol}//${window.location.host}/n96`],
|
||||||
|
["method", "POST"]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const rsp = await fetch("/n96", {
|
||||||
|
body: fd,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
accept: "application/json",
|
||||||
|
authorization: `Nostr ${btoa(JSON.stringify(auth_event))}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await dumpToLog(rsp);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -105,7 +148,14 @@
|
|||||||
</h1>
|
</h1>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div>
|
<div>
|
||||||
Upload a file using NIP-96
|
<label>
|
||||||
|
NIP-96
|
||||||
|
<input type="radio" name="method" id="method-nip96"/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Blossom
|
||||||
|
<input type="radio" name="method" id="method-blossom"/>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div style="color: #ff8383;">
|
<div style="color: #ff8383;">
|
||||||
You must have a nostr extension for this to work
|
You must have a nostr extension for this to work
|
||||||
|
Loading…
x
Reference in New Issue
Block a user