Merge pull request 'Include blurhash in details json' (#75) from asonix/blurhash-in-details into main
All checks were successful
/ clippy (push) Successful in 1m36s
/ deny (push) Successful in 11s
/ tests (push) Successful in 1m56s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m5s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m5s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m0s
All checks were successful
/ clippy (push) Successful in 1m36s
/ deny (push) Successful in 11s
/ tests (push) Successful in 1m56s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m5s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m5s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m0s
Reviewed-on: #75
This commit is contained in:
commit
deafc89e72
2 changed files with 85 additions and 29 deletions
|
@ -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,
|
||||
|
|
110
src/lib.rs
110
src/lib.rs
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue