Include blurhash in details json
All checks were successful
/ tests (pull_request) Successful in 2m21s
/ deny (pull_request) Successful in 15s
/ clippy (pull_request) Successful in 2m22s
/ check (aarch64-unknown-linux-musl) (pull_request) Successful in 3m10s
/ check (armv7-unknown-linux-musleabihf) (pull_request) Successful in 3m11s
/ check (x86_64-unknown-linux-musl) (pull_request) Successful in 2m6s

This commit is contained in:
asonix 2024-11-23 16:15:19 -06:00
parent 89161d03c9
commit 267309cd5d
2 changed files with 85 additions and 29 deletions

View file

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

View file

@ -357,12 +357,20 @@ async fn handle_upload<S: Store + 'static>(
tracing::debug!("Uploaded {} as {:?}", image.filename, alias);
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!({
"file": alias.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 {
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!({
"msg": "ok",
"files": [{
"file": alias.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 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!({
"msg": "ok",
"files": [{
"file": alias.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
#[tracing::instrument(name = "Hash Page", skip(state))]
async fn page<S>(
async fn page<S: Store + 'static>(
state: web::Data<State<S>>,
web::Query(PageQuery {
slug,
@ -712,11 +733,13 @@ async fn page<S>(
let identifier = state.repo.identifier(hash.clone()).await?;
let details = if let Some(identifier) = identifier {
state
.repo
.details(&identifier)
.await?
.map(|d| d.into_api_details())
if let Some(details) = state.repo.details(&identifier).await? {
let blurhash = ensure_blurhash(&state, hash.clone(), Some(&details)).await?;
Some(details.into_api_details(blurhash.to_string()))
} else {
None
}
} else {
None
};
@ -800,7 +823,7 @@ fn prepare_process(
}
#[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>,
ext: web::Path<String>,
state: web::Data<State<S>>,
@ -824,7 +847,7 @@ async fn process_details<S: Store>(
let identifier = state
.repo
.variant_identifier(hash, variant)
.variant_identifier(hash.clone(), variant)
.await?
.ok_or(UploadError::MissingAlias)?;
@ -832,7 +855,9 @@ async fn process_details<S: Store>(
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> {
@ -1085,9 +1110,17 @@ async fn details_query<S: Store + 'static>(
) -> Result<HttpResponse, Error> {
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
@ -1096,9 +1129,17 @@ async fn details<S: Store + 'static>(
alias: web::Path<Serde<Alias>>,
state: web::Data<State<S>>,
) -> 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
@ -1393,16 +1434,7 @@ async fn blurhash<S: Store + 'static>(
.await?
.ok_or(UploadError::MissingAlias)?;
let blurhash = if let Some(blurhash) = state.repo.blurhash(hash.clone()).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
};
let blurhash = ensure_blurhash(&state, hash, None).await?;
Ok(HttpResponse::Ok().json(serde_json::json!({
"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)]
struct PruneResponse {
complete: bool,