Alt support (nip98)

This commit is contained in:
Kieran 2024-09-08 16:33:22 +01:00
parent 7fa2633a1e
commit d41d561fdc
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
4 changed files with 36 additions and 18 deletions

View File

@ -0,0 +1,2 @@
alter table uploads
add column alt varchar(512);

View File

@ -13,6 +13,7 @@ pub struct FileUpload {
pub width: Option<u32>, pub width: Option<u32>,
pub height: Option<u32>, pub height: Option<u32>,
pub blur_hash: Option<String>, pub blur_hash: Option<String>,
pub alt: Option<String>,
#[sqlx(skip)] #[sqlx(skip)]
#[cfg(feature = "labels")] #[cfg(feature = "labels")]
@ -88,14 +89,15 @@ impl Database {
pub async fn add_file(&self, file: &FileUpload, user_id: u64) -> Result<(), Error> { pub async fn add_file(&self, file: &FileUpload, user_id: u64) -> Result<(), Error> {
let mut tx = self.pool.begin().await?; let mut tx = self.pool.begin().await?;
let q = sqlx::query("insert ignore into \ let q = sqlx::query("insert ignore into \
uploads(id,name,size,mime_type,blur_hash,width,height) values(?,?,?,?,?,?,?)") uploads(id,name,size,mime_type,blur_hash,width,height,alt) values(?,?,?,?,?,?,?,?)")
.bind(&file.id) .bind(&file.id)
.bind(&file.name) .bind(&file.name)
.bind(file.size) .bind(file.size)
.bind(&file.mime_type) .bind(&file.mime_type)
.bind(&file.blur_hash) .bind(&file.blur_hash)
.bind(file.width) .bind(file.width)
.bind(file.height); .bind(file.height)
.bind(&file.alt);
tx.execute(q).await?; tx.execute(q).await?;
let q2 = sqlx::query("insert ignore into user_uploads(file,user_id) values(?,?)") let q2 = sqlx::query("insert ignore into user_uploads(file,user_id) values(?,?)")

View File

@ -154,6 +154,7 @@ impl FileStore {
#[cfg(feature = "labels")] #[cfg(feature = "labels")]
labels, labels,
created: Utc::now(), created: Utc::now(),
..Default::default()
}, },
}); });
} }

View File

@ -5,12 +5,12 @@ use std::time::Duration;
use log::error; use log::error;
use nostr::Timestamp; use nostr::Timestamp;
use rocket::{FromForm, Responder, Route, routes, State};
use rocket::data::ToByteUnit; use rocket::data::ToByteUnit;
use rocket::form::Form; use rocket::form::Form;
use rocket::fs::TempFile; use rocket::fs::TempFile;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use rocket::serde::Serialize; use rocket::serde::Serialize;
use rocket::{routes, FromForm, Responder, Route, State};
use crate::auth::nip98::Nip98Auth; use crate::auth::nip98::Nip98Auth;
use crate::db::{Database, FileUpload}; use crate::db::{Database, FileUpload};
@ -227,15 +227,11 @@ async fn upload(
Ok(f) => f, Ok(f) => f,
Err(e) => return Nip96Response::error(&format!("Could not open file: {}", e)), Err(e) => return Nip96Response::error(&format!("Could not open file: {}", e)),
}; };
let mime_type = form.media_type let mime_type = form.media_type.unwrap_or("application/octet-stream");
.unwrap_or("application/octet-stream");
if form.expiration.is_some() { if form.expiration.is_some() {
return Nip96Response::error("Expiration not supported"); return Nip96Response::error("Expiration not supported");
} }
if form.alt.is_some() {
return Nip96Response::error("\"alt\" is not supported");
}
// account for upload speeds as slow as 1MB/s (8 Mbps) // account for upload speeds as slow as 1MB/s (8 Mbps)
let mbs = form.size / 1.megabytes().as_u64() as usize; let mbs = form.size / 1.megabytes().as_u64() as usize;
@ -259,16 +255,25 @@ async fn upload(
Some(c) => c.to_string(), Some(c) => c.to_string(),
None => "".to_string(), None => "".to_string(),
}; };
blob.upload.alt = match &form.alt {
Some(s) => Some(s.to_string()),
None => None,
};
let pubkey_vec = auth.event.pubkey.to_bytes().to_vec(); let pubkey_vec = auth.event.pubkey.to_bytes().to_vec();
if let Some(wh) = webhook.as_ref() { if let Some(wh) = webhook.as_ref() {
match wh.store_file(&pubkey_vec, blob.clone()) { match wh.store_file(&pubkey_vec, blob.clone()) {
Ok(store) => if !store { Ok(store) => {
let _ = fs::remove_file(blob.path); if !store {
return Nip96Response::error("Upload rejected"); let _ = fs::remove_file(blob.path);
return Nip96Response::error("Upload rejected");
}
} }
Err(e) => { Err(e) => {
let _ = fs::remove_file(blob.path); let _ = fs::remove_file(blob.path);
return Nip96Response::error(&format!("Internal error, failed to call webhook: {}", e)); return Nip96Response::error(&format!(
"Internal error, failed to call webhook: {}",
e
));
} }
} }
} }
@ -290,7 +295,10 @@ async fn upload(
return Nip96Response::error(&format!("Could not save file (db): {}", e)); return Nip96Response::error(&format!("Could not save file (db): {}", e));
} }
Nip96Response::UploadResult(Json(Nip96UploadResult::from_upload(settings, &blob.upload))) Nip96Response::UploadResult(Json(Nip96UploadResult::from_upload(
settings,
&blob.upload,
)))
} }
Err(e) => { Err(e) => {
error!("{}", e.to_string()); error!("{}", e.to_string());
@ -312,7 +320,6 @@ async fn delete(
} }
} }
#[rocket::get("/n96?<page>&<count>")] #[rocket::get("/n96?<page>&<count>")]
async fn list_files( async fn list_files(
auth: Nip98Auth, auth: Nip98Auth,
@ -323,17 +330,23 @@ async fn list_files(
) -> Nip96Response { ) -> Nip96Response {
let pubkey_vec = auth.event.pubkey.to_bytes().to_vec(); let pubkey_vec = auth.event.pubkey.to_bytes().to_vec();
let server_count = count.min(5_000).max(1); let server_count = count.min(5_000).max(1);
match db.list_files(&pubkey_vec, page * server_count, server_count).await { match db
.list_files(&pubkey_vec, page * server_count, server_count)
.await
{
Ok((files, total)) => Nip96Response::FileList(Json(Nip96FileListResults { Ok((files, total)) => Nip96Response::FileList(Json(Nip96FileListResults {
count: server_count, count: server_count,
page, page,
total: total as u32, total: total as u32,
files: files files: files
.iter() .iter()
.map(|f| Nip96UploadResult::from_upload(settings, f).nip94_event.unwrap()) .map(|f| {
Nip96UploadResult::from_upload(settings, f)
.nip94_event
.unwrap()
})
.collect(), .collect(),
} })),
)),
Err(e) => Nip96Response::error(&format!("Could not list files: {}", e)), Err(e) => Nip96Response::error(&format!("Could not list files: {}", e)),
} }
} }