mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 11:21:24 +00:00
Include blurhash in details json
This commit is contained in:
parent
89161d03c9
commit
267309cd5d
2 changed files with 85 additions and 29 deletions
|
@ -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,
|
||||||
|
|
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);
|
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,
|
||||||
|
|
Loading…
Reference in a new issue