This commit is contained in:
2026-09-15 21:03:24 +07:00
parent ac70121bc9
commit 89396b8f07
2 changed files with 58 additions and 48 deletions
+32 -10
View File
@@ -4,30 +4,52 @@ use anyhow::{Error, anyhow};
use gpui::AsyncApp; use gpui::AsyncApp;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use gpui_tokio::Tokio; use gpui_tokio::Tokio;
#[cfg(not(target_arch = "wasm32"))]
use mime_guess::from_path; use mime_guess::from_path;
use nostr_blossom::prelude::*; use nostr_blossom::prelude::*;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub async fn upload(server: Url, path: PathBuf, cx: &AsyncApp) -> Result<Url, Error> { use crate::file::sha256_hex;
let content_type = from_path(&path).first_or_octet_stream().to_string();
let data = smol::fs::read(path).await?;
let keys = Keys::generate();
// Construct the blossom client /// Upload a blob to a blossom server and return its URL
let client = BlossomClient::new(server); #[cfg(not(target_arch = "wasm32"))]
pub(crate) async fn upload_blob(
server: &Url,
data: Vec<u8>,
content_type: &str,
sha256: &str,
cx: &AsyncApp,
) -> Result<Url, Error> {
let client = BlossomClient::new(server.clone());
let keys = Keys::generate();
let content_type = content_type.to_string();
let base = server.clone();
let hash = sha256.to_string();
Tokio::spawn(cx, async move { Tokio::spawn(cx, async move {
let blob = client match client
.upload_blob(data, Some(content_type), None, Some(&keys)) .upload_blob(data, Some(content_type), None, Some(&keys))
.await?; .await
{
Ok(blob.url) Ok(blob) => Ok(blob.url),
Err(e) if e.to_string().contains("201 Created") => Ok::<Url, Error>(base.join(&hash)?),
Err(e) => Err(anyhow!(e.to_string())),
}
}) })
.await .await
.map_err(|e| anyhow!("Upload error: {e}"))? .map_err(|e| anyhow!("Upload error: {e}"))?
} }
#[cfg(not(target_arch = "wasm32"))]
pub async fn upload(server: Url, path: PathBuf, cx: &AsyncApp) -> Result<Url, Error> {
let content_type = from_path(&path).first_or_octet_stream().to_string();
let data = smol::fs::read(&path).await?;
let sha256 = sha256_hex(&data);
upload_blob(&server, data, &content_type, &sha256, cx).await
}
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub async fn upload(_server: Url, _path: PathBuf, _cx: &AsyncApp) -> Result<Url, Error> { pub async fn upload(_server: Url, _path: PathBuf, _cx: &AsyncApp) -> Result<Url, Error> {
Err(anyhow!("File upload not supported on web")) Err(anyhow!("File upload not supported on web"))
+26 -38
View File
@@ -10,12 +10,8 @@ use futures::AsyncReadExt;
use gpui::http_client::AsyncBody; use gpui::http_client::AsyncBody;
use gpui::{AsyncApp, SharedString}; use gpui::{AsyncApp, SharedString};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use gpui_tokio::Tokio;
#[cfg(not(target_arch = "wasm32"))]
use mime_guess::from_path; use mime_guess::from_path;
use nostr::nips::nip94::Sha256Hash; use nostr::nips::nip94::Sha256Hash;
#[cfg(not(target_arch = "wasm32"))]
use nostr_blossom::prelude::*;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
@@ -182,49 +178,41 @@ pub async fn upload_encrypted(
let data = smol::fs::read(&path).await?; let data = smol::fs::read(&path).await?;
let encrypted = encrypt(&data)?; let encrypted = encrypt(&data)?;
let sha256 = Some(sha256_hex(&encrypted.data)); let sha256 = sha256_hex(&encrypted.data);
let original_sha256 = Some(sha256_hex(&data)); let original_sha256 = sha256_hex(&data);
let size = Some(encrypted.data.len() as u64); let size = encrypted.data.len() as u64;
let base_url = server.to_string(); let base_url = server.to_string();
let keys = Keys::generate();
let client = BlossomClient::new(server);
let url = Tokio::spawn(cx, async move { let url = crate::blossom::upload_blob(
let blob = client &server,
.upload_blob( encrypted.data,
encrypted.data, "application/octet-stream",
Some("application/octet-stream".to_string()), &sha256,
None, cx,
Some(&keys), )
)
.await
.map_err(|e| {
let message = e.to_string();
if !message.contains("415") {
return anyhow!(message);
}
anyhow!(
"{base_url} rejected the encrypted file. Encrypted attachments are uploaded as
opaque data, which this file server does not accept. Choose a different file
server in the settings."
)
})?;
Ok::<Url, Error>(blob.url)
})
.await .await
.map_err(|e| anyhow!("Upload error: {e}"))??; .map_err(|e| {
let message = e.to_string();
if !message.contains("415") {
return anyhow!(message);
}
anyhow!(
"{base_url} rejected the encrypted file. Encrypted attachments are uploaded as
opaque data, which this file server does not accept. Choose a different file
server in the settings."
)
})?;
Ok(FileAttachment { Ok(FileAttachment {
url, url,
mime, mime,
key: encrypted.key, key: encrypted.key,
nonce: encrypted.nonce, nonce: encrypted.nonce,
sha256, sha256: Some(sha256),
original_sha256, original_sha256: Some(original_sha256),
size, size: Some(size),
dim: None, dim: None,
name, name,
}) })