2
0
Fork 0
mirror of https://git.asonix.dog/asonix/pict-rs synced 2024-12-22 03:11:24 +00:00

Merge pull request 'Include blurhash in details json' (#75) from asonix/blurhash-in-details into main

Reviewed-on: https://git.asonix.dog/asonix/pict-rs/pulls/75
This commit is contained in:
asonix 2024-11-23 23:01:25 +00:00
commit deafc89e72
2 changed files with 85 additions and 29 deletions

View file

@ -25,6 +25,7 @@ enum ApiFormat {
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]
pub(crate) struct ApiDetails { pub(crate) struct ApiDetails {
blurhash: String,
width: u16, width: u16,
height: u16, height: u16,
frames: Option<u32>, frames: Option<u32>,
@ -49,7 +50,7 @@ pub(crate) struct DetailsInner {
} }
impl Details { impl Details {
pub(crate) fn into_api_details(self) -> ApiDetails { pub(crate) fn into_api_details(self, blurhash: String) -> ApiDetails {
let Details { let Details {
inner: inner:
DetailsInner { DetailsInner {
@ -63,6 +64,7 @@ impl Details {
} = self; } = self;
ApiDetails { ApiDetails {
blurhash,
width, width,
height, height,
frames, frames,

View file

@ -357,12 +357,20 @@ async fn handle_upload<S: Store + 'static>(
tracing::debug!("Uploaded {} as {:?}", image.filename, alias); tracing::debug!("Uploaded {} as {:?}", image.filename, alias);
let delete_token = image.result.delete_token(); let delete_token = image.result.delete_token();
let details = ensure_details(&state, alias).await?; let hash = state
.repo
.hash(alias)
.await?
.ok_or(UploadError::MissingAlias)?;
let details = ensure_details_hash(&state, hash.clone()).await?;
let blurhash = ensure_blurhash(&state, hash, Some(&details)).await?;
files.push(serde_json::json!({ files.push(serde_json::json!({
"file": alias.to_string(), "file": alias.to_string(),
"delete_token": delete_token.to_string(), "delete_token": delete_token.to_string(),
"details": details.into_api_details(), "details": details.into_api_details(blurhash.to_string()),
})); }));
} }
} }
@ -505,14 +513,20 @@ async fn claim_upload<S: Store + 'static>(
match upload_result { match upload_result {
UploadResult::Success { alias, token } => { UploadResult::Success { alias, token } => {
let details = ensure_details(&state, &alias).await?; let hash = state
.repo
.hash(&alias)
.await?
.ok_or(UploadError::MissingAlias)?;
let details = ensure_details_hash(&state, hash.clone()).await?;
let blurhash = ensure_blurhash(&state, hash, Some(&details)).await?;
Ok(HttpResponse::Ok().json(serde_json::json!({ Ok(HttpResponse::Ok().json(serde_json::json!({
"msg": "ok", "msg": "ok",
"files": [{ "files": [{
"file": alias.to_string(), "file": alias.to_string(),
"delete_token": token.to_string(), "delete_token": token.to_string(),
"details": details.into_api_details(), "details": details.into_api_details(blurhash.to_string()),
}] }]
}))) })))
} }
@ -612,12 +626,19 @@ async fn do_download_inline<S: Store + 'static>(
let (alias, delete_token, details) = ingest_inline(stream, state, upload_query).await?; let (alias, delete_token, details) = ingest_inline(stream, state, upload_query).await?;
let hash = state
.repo
.hash(&alias)
.await?
.ok_or(UploadError::MissingAlias)?;
let blurhash = ensure_blurhash(state, hash, Some(&details)).await?;
Ok(HttpResponse::Created().json(serde_json::json!({ Ok(HttpResponse::Created().json(serde_json::json!({
"msg": "ok", "msg": "ok",
"files": [{ "files": [{
"file": alias.to_string(), "file": alias.to_string(),
"delete_token": delete_token.to_string(), "delete_token": delete_token.to_string(),
"details": details.into_api_details(), "details": details.into_api_details(blurhash.to_string()),
}] }]
}))) })))
} }
@ -679,7 +700,7 @@ struct HashJson {
/// Get a page of hashes /// Get a page of hashes
#[tracing::instrument(name = "Hash Page", skip(state))] #[tracing::instrument(name = "Hash Page", skip(state))]
async fn page<S>( async fn page<S: Store + 'static>(
state: web::Data<State<S>>, state: web::Data<State<S>>,
web::Query(PageQuery { web::Query(PageQuery {
slug, slug,
@ -712,11 +733,13 @@ async fn page<S>(
let identifier = state.repo.identifier(hash.clone()).await?; let identifier = state.repo.identifier(hash.clone()).await?;
let details = if let Some(identifier) = identifier { let details = if let Some(identifier) = identifier {
state if let Some(details) = state.repo.details(&identifier).await? {
.repo let blurhash = ensure_blurhash(&state, hash.clone(), Some(&details)).await?;
.details(&identifier)
.await? Some(details.into_api_details(blurhash.to_string()))
.map(|d| d.into_api_details()) } else {
None
}
} else { } else {
None None
}; };
@ -800,7 +823,7 @@ fn prepare_process(
} }
#[tracing::instrument(name = "Fetching derived details", skip(state))] #[tracing::instrument(name = "Fetching derived details", skip(state))]
async fn process_details<S: Store>( async fn process_details<S: Store + 'static>(
web::Query(ProcessQuery { source, operations }): web::Query<ProcessQuery>, web::Query(ProcessQuery { source, operations }): web::Query<ProcessQuery>,
ext: web::Path<String>, ext: web::Path<String>,
state: web::Data<State<S>>, state: web::Data<State<S>>,
@ -824,7 +847,7 @@ async fn process_details<S: Store>(
let identifier = state let identifier = state
.repo .repo
.variant_identifier(hash, variant) .variant_identifier(hash.clone(), variant)
.await? .await?
.ok_or(UploadError::MissingAlias)?; .ok_or(UploadError::MissingAlias)?;
@ -832,7 +855,9 @@ async fn process_details<S: Store>(
let details = details.ok_or(UploadError::NoFiles)?; let details = details.ok_or(UploadError::NoFiles)?;
Ok(HttpResponse::Ok().json(details.into_api_details())) let blurhash = ensure_blurhash(&state, hash, Some(&details)).await?;
Ok(HttpResponse::Ok().json(details.into_api_details(blurhash.to_string())))
} }
async fn not_found_hash(repo: &ArcRepo) -> Result<Option<(Alias, Hash)>, Error> { async fn not_found_hash(repo: &ArcRepo) -> Result<Option<(Alias, Hash)>, Error> {
@ -1085,9 +1110,17 @@ async fn details_query<S: Store + 'static>(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let alias = alias_from_query(query, &state).await?; let alias = alias_from_query(query, &state).await?;
let details = ensure_details(&state, &alias).await?; let hash = state
.repo
.hash(&alias)
.await?
.ok_or(UploadError::MissingAlias)?;
Ok(HttpResponse::Ok().json(details.into_api_details())) let details = ensure_details_hash(&state, hash.clone()).await?;
let blurhash = ensure_blurhash(&state, hash, Some(&details)).await?;
Ok(HttpResponse::Ok().json(details.into_api_details(blurhash.to_string())))
} }
/// Fetch file details /// Fetch file details
@ -1096,9 +1129,17 @@ async fn details<S: Store + 'static>(
alias: web::Path<Serde<Alias>>, alias: web::Path<Serde<Alias>>,
state: web::Data<State<S>>, state: web::Data<State<S>>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let details = ensure_details(&state, &alias).await?; let hash = state
.repo
.hash(&alias)
.await?
.ok_or(UploadError::MissingAlias)?;
Ok(HttpResponse::Ok().json(details.into_api_details())) let details = ensure_details_hash(&state, hash.clone()).await?;
let blurhash = ensure_blurhash(&state, hash, Some(&details)).await?;
Ok(HttpResponse::Ok().json(details.into_api_details(blurhash.to_string())))
} }
/// Serve files based on alias query /// Serve files based on alias query
@ -1393,16 +1434,7 @@ async fn blurhash<S: Store + 'static>(
.await? .await?
.ok_or(UploadError::MissingAlias)?; .ok_or(UploadError::MissingAlias)?;
let blurhash = if let Some(blurhash) = state.repo.blurhash(hash.clone()).await? { let blurhash = ensure_blurhash(&state, hash, None).await?;
blurhash
} else {
let details = ensure_details_hash(&state, hash.clone()).await?;
let blurhash = blurhash::generate(&state, hash.clone(), &details).await?;
let blurhash: Arc<str> = Arc::from(blurhash);
state.repo.relate_blurhash(hash, blurhash.clone()).await?;
blurhash
};
Ok(HttpResponse::Ok().json(serde_json::json!({ Ok(HttpResponse::Ok().json(serde_json::json!({
"msg": "ok", "msg": "ok",
@ -1410,6 +1442,28 @@ async fn blurhash<S: Store + 'static>(
}))) })))
} }
async fn ensure_blurhash<S: Store + 'static>(
state: &State<S>,
hash: Hash,
details: Option<&Details>,
) -> Result<Arc<str>, Error> {
if let Some(blurhash) = state.repo.blurhash(hash.clone()).await? {
Ok(blurhash)
} else {
let blurhash = if let Some(details) = details {
blurhash::generate(state, hash.clone(), details).await?
} else {
let details = ensure_details_hash(state, hash.clone()).await?;
blurhash::generate(state, hash.clone(), &details).await?
};
let blurhash: Arc<str> = Arc::from(blurhash);
state.repo.relate_blurhash(hash, blurhash.clone()).await?;
Ok(blurhash)
}
}
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
struct PruneResponse { struct PruneResponse {
complete: bool, complete: bool,