bring back full covers if needed
All checks were successful
Build Multiarch Container Image / call-reusable-workflow (push) Successful in 30m2s

This commit is contained in:
Sebastian Hugentobler 2024-06-26 22:35:03 +02:00
parent b77b1bc139
commit 7deb8e5bfc
Signed by: shu
GPG Key ID: BB32CF3CA052C2F0
9 changed files with 142 additions and 84 deletions

86
Cargo.lock generated
View File

@ -150,12 +150,6 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.5.0"
@ -251,9 +245,9 @@ dependencies = [
[[package]] [[package]]
name = "chrono-tz" name = "chrono-tz"
version = "0.8.6" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
dependencies = [ dependencies = [
"chrono", "chrono",
"chrono-tz-build", "chrono-tz-build",
@ -262,9 +256,9 @@ dependencies = [
[[package]] [[package]]
name = "chrono-tz-build" name = "chrono-tz-build"
version = "0.2.1" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
dependencies = [ dependencies = [
"parse-zoneinfo", "parse-zoneinfo",
"phf", "phf",
@ -273,9 +267,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.4" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -283,9 +277,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.2" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -295,9 +289,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.4" version = "4.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -619,11 +613,11 @@ dependencies = [
[[package]] [[package]]
name = "globwalk" name = "globwalk"
version = "0.8.1" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags",
"ignore", "ignore",
"walkdir", "walkdir",
] ]
@ -944,7 +938,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "little-hesinde" name = "little-hesinde"
version = "0.2.3" version = "0.3.0"
dependencies = [ dependencies = [
"calibre-db", "calibre-db",
"clap", "clap",
@ -1039,7 +1033,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@ -1242,9 +1236,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]] [[package]]
name = "poem" name = "poem"
version = "3.0.0" version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b735eaaaa6bc7ed2dcbcab1d5373afe1f6d03a37d8695ba3c42101f733a8455" checksum = "e88b6912ed1e8833d7c22c9c986c517f4518d7d37e3c04566d917c789aaea591"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-util", "futures-util",
@ -1416,7 +1410,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
] ]
[[package]] [[package]]
@ -1463,7 +1457,7 @@ version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
"fallible-iterator", "fallible-iterator",
"fallible-streaming-iterator", "fallible-streaming-iterator",
"hashlink", "hashlink",
@ -1474,9 +1468,9 @@ dependencies = [
[[package]] [[package]]
name = "rust-embed" name = "rust-embed"
version = "8.3.0" version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb78f46d0066053d16d4ca7b898e9343bc3530f71c61d5ad84cd404ada068745" checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a"
dependencies = [ dependencies = [
"rust-embed-impl", "rust-embed-impl",
"rust-embed-utils", "rust-embed-utils",
@ -1485,9 +1479,9 @@ dependencies = [
[[package]] [[package]]
name = "rust-embed-impl" name = "rust-embed-impl"
version = "8.3.0" version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91ac2a3c6c0520a3fb3dd89321177c3c692937c4eb21893378219da10c44fc8" checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1498,9 +1492,9 @@ dependencies = [
[[package]] [[package]]
name = "rust-embed-utils" name = "rust-embed-utils"
version = "8.3.0" version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f69089032567ffff4eada41c573fc43ff466c7db7c5688b2e7969584345581" checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32"
dependencies = [ dependencies = [
"sha2", "sha2",
"walkdir", "walkdir",
@ -1518,7 +1512,7 @@ version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -1557,18 +1551,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.200" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.200" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1577,9 +1571,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.116" version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1761,9 +1755,9 @@ dependencies = [
[[package]] [[package]]
name = "tera" name = "tera"
version = "1.19.1" version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" checksum = "ab9d851b45e865f178319da0abdbfe6acbc4328759ff18dafc3a41c16b4cd2ee"
dependencies = [ dependencies = [
"chrono", "chrono",
"chrono-tz", "chrono-tz",
@ -1844,9 +1838,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.37.0" version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -1862,9 +1856,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.2.0" version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2052,9 +2046,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.8.0" version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"rand", "rand",

View File

@ -5,8 +5,8 @@ members = [
] ]
[workspace.dependencies] [workspace.dependencies]
serde = "1.0.200" serde = "1.0.203"
thiserror = "1.0.59" thiserror = "1.0.61"
time = { version = "0.3.36", features = ["macros", "serde", "formatting", "parsing" ] } time = { version = "0.3.36", features = ["macros", "serde", "formatting", "parsing" ] }
[workspace.package] [workspace.package]

View File

@ -1,5 +1,8 @@
FROM docker.io/rust:1-alpine3.20 AS builder FROM docker.io/rust:1-alpine3.20 AS builder
RUN mkdir /tmp/tmp
RUN echo "hesinde:x:2222:2222:Linux User,,,:/:/app" > /passwd
RUN apk --no-cache add \ RUN apk --no-cache add \
musl-dev musl-dev
@ -13,12 +16,16 @@ COPY . .
RUN cargo build --release --target=$(arch)-unknown-linux-musl RUN cargo build --release --target=$(arch)-unknown-linux-musl
RUN cp "./target/$(arch)-unknown-linux-musl/release/little-hesinde" /app RUN cp "./target/$(arch)-unknown-linux-musl/release/little-hesinde" /app
FROM scratch FROM scratch
COPY --from=builder /passwd /etc/passwd
COPY --from=builder /app /app COPY --from=builder /app /app
CMD ["/app", "--listen-address", "[::]:3000", "--", "/library"] COPY --from=builder --chown=2222: /tmp/tmp /tmp
ENV TMPDIR=/ USER hesinde
VOLUME ["/library"]
CMD ["/app", "--listen-address", "[::]:3000", "--cache-path", "/tmp/cache", "--", "/library"]
ENV TMPDIR=/tmp
VOLUME ["/library", "/tmp"]
EXPOSE 3000 EXPOSE 3000

View File

@ -37,12 +37,17 @@ From there on `cargo run` and `cargo build` and so on can be used.
Usage: little-hesinde [OPTIONS] -- <LIBRARY_PATH> Usage: little-hesinde [OPTIONS] -- <LIBRARY_PATH>
Arguments: Arguments:
<LIBRARY_PATH> Calibre library path <LIBRARY_PATH> Calibre library path [env: LIBRARY_PATH=]
Options: Options:
-l, --listen-address <LISTEN_ADDRESS> Address to listen on [default: [::1]:3000] -l, --listen-address <LISTEN_ADDRESS>
-h, --help Print help Address to listen on [env: LISTEN_ADDRESS=] [default: [::1]:3000]
-V, --version Print version -c, --cache-path <CACHE_PATH>
Cache path ($TMP cascades through $XDG_CACHE_HOME, $TMPDIR and /tmp) [env: CACHE_PATH=] [default: $TMP/little-hesinde]
-h, --help
Print help
-V, --version
Print version
``` ```
Example: `little-hesinde -l [::]4000 -- ~/Documents/library/` Example: `little-hesinde -l [::]4000 -- ~/Documents/library/`

View File

@ -1,6 +1,6 @@
[package] [package]
name = "little-hesinde" name = "little-hesinde"
version = "0.2.3" version = "0.3.0"
edition = "2021" edition = "2021"
license = { workspace = true } license = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@ -9,23 +9,23 @@ description = "A very simple ebook server for a calibre library, providing a htm
[dependencies] [dependencies]
calibre-db = { path = "../calibre-db/", version = "0.1.0" } calibre-db = { path = "../calibre-db/", version = "0.1.0" }
clap = { version = "4.5.4", features = ["derive", "env"] } clap = { version = "4.5.7", features = ["derive", "env"] }
image = { version = "0.25.1", default-features = false, features = ["jpeg", "rayon"] } image = { version = "0.25.1", default-features = false, features = ["jpeg", "rayon"] }
once_cell = "1.19.0" once_cell = "1.19.0"
poem = { version = "3.0.0", features = ["embed", "static-files"] } poem = { version = "3.0.1", features = ["embed", "static-files"] }
rust-embed = "8.3.0" rust-embed = "8.4.0"
sha2 = "0.10.8" sha2 = "0.10.8"
serde = { workspace = true } serde = { workspace = true }
serde_json = "1.0.116" serde_json = "1.0.118"
serde_with = "3.8.1" serde_with = "3.8.1"
tera = "1.19.1" tera = "1.20.0"
thiserror = { workspace = true } thiserror = { workspace = true }
time = { workspace = true } time = { workspace = true }
tokio = { version = "1.37.0", features = ["signal", "rt-multi-thread", "macros"] } tokio = { version = "1.38.0", features = ["signal", "rt-multi-thread", "macros"] }
tokio-util = "0.7.11" tokio-util = "0.7.11"
tracing = "0.1.40" tracing = "0.1.40"
tracing-subscriber = "0.3.18" tracing-subscriber = "0.3.18"
uuid = { version = "1.8.0", features = ["v4", "fast-rng"] } uuid = { version = "1.9.1", features = ["v4", "fast-rng"] }
quick-xml = { version = "0.34.0", features = ["serialize"] } quick-xml = { version = "0.34.0", features = ["serialize"] }
[build-dependencies] [build-dependencies]

View File

@ -1,7 +1,7 @@
//! Handle caching of files, specifically book covers. //! Handle caching of files, specifically book covers.
use std::{ use std::{
fs, fs::{self, File},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -11,7 +11,6 @@ use sha2::{
}; };
use std::fmt::Write; use std::fmt::Write;
use thiserror::Error; use thiserror::Error;
use tokio::fs::File;
use tracing::debug; use tracing::debug;
/// Errors from dealing with file caching. /// Errors from dealing with file caching.
@ -59,8 +58,9 @@ fn create_thumbnail(cover_path: &Path, thumbnail_path: &Path) -> Result<(), Cach
.ok_or_else(|| CacheError::ThumbnailPathError(thumbnail_path.to_path_buf()))?; .ok_or_else(|| CacheError::ThumbnailPathError(thumbnail_path.to_path_buf()))?;
fs::create_dir_all(folders)?; fs::create_dir_all(folders)?;
const THUMBNAIL_SIZE: u32 = 512;
let img = image::open(cover_path)?; let img = image::open(cover_path)?;
let thumbnail = img.thumbnail(512, 512); let thumbnail = img.thumbnail(THUMBNAIL_SIZE, THUMBNAIL_SIZE);
thumbnail.save_with_format(thumbnail_path, image::ImageFormat::Jpeg)?; thumbnail.save_with_format(thumbnail_path, image::ImageFormat::Jpeg)?;
debug!("saved thumbnail to {}", thumbnail_path.to_string_lossy()); debug!("saved thumbnail to {}", thumbnail_path.to_string_lossy());
@ -70,7 +70,7 @@ fn create_thumbnail(cover_path: &Path, thumbnail_path: &Path) -> Result<(), Cach
/// Get the thumbnail for a book cover. /// Get the thumbnail for a book cover.
/// ///
/// If a thumbnail does not yet exist, create it. /// If a thumbnail does not yet exist, create it.
pub async fn get_thumbnail(cover_path: &Path, cache_path: &Path) -> Result<File, CacheError> { pub fn get_thumbnail(cover_path: &Path, cache_path: &Path) -> Result<File, CacheError> {
let path_str = cover_path.to_string_lossy(); let path_str = cover_path.to_string_lossy();
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hasher.update(path_str.as_bytes()); hasher.update(path_str.as_bytes());
@ -82,5 +82,5 @@ pub async fn get_thumbnail(cover_path: &Path, cache_path: &Path) -> Result<File,
create_thumbnail(cover_path, &thumbnail_path)?; create_thumbnail(cover_path, &thumbnail_path)?;
} }
Ok(File::open(thumbnail_path).await?) Ok(File::open(thumbnail_path)?)
} }

View File

@ -1,26 +1,74 @@
//! Handle requests for cover images. //! Handle requests for cover images.
use std::sync::Arc; use std::{fs::File, path::Path as FilePath, sync::Arc};
use crate::{app_state::AppState, cache, handlers::error::HandlerError}; use crate::{
app_state::AppState,
cache::{self, CacheError},
config::Config,
handlers::error::HandlerError,
};
use calibre_db::calibre::Calibre;
use poem::{ use poem::{
error::NotFoundError, error::NotFoundError,
handler, handler,
web::{headers::ContentType, Data, Path}, web::{headers::ContentType, Data, Path},
Response, Response,
}; };
use thiserror::Error;
use tokio::fs::File as AsyncFile;
/// Errors from fetching cover images.
#[derive(Error, Debug)]
pub enum CoverError {
/// Error fetching a cover thumbnail.
#[error("failed to access thumbnail")]
ThumbnailError(#[from] CacheError),
/// Error fetching a full cover.
#[error("failed access cover")]
FullCoverError(#[from] std::io::Error),
}
/// Handle a request for the cover thumbnail of book with id `id`.
#[handler]
pub async fn handler_thumbnail(
id: Path<u64>,
state: Data<&Arc<AppState>>,
) -> Result<Response, poem::Error> {
cover(
&state.calibre,
&state.config,
*id,
|cover_path, cache_path| Ok(cache::get_thumbnail(cover_path, cache_path)?),
)
.await
}
/// Handle a request for the cover image of book with id `id`. /// Handle a request for the cover image of book with id `id`.
#[handler] #[handler]
pub async fn handler(id: Path<u64>, state: Data<&Arc<AppState>>) -> Result<Response, poem::Error> { pub async fn handler_full(
let book = state id: Path<u64>,
.calibre state: Data<&Arc<AppState>>,
.scalar_book(*id) ) -> Result<Response, poem::Error> {
.map_err(HandlerError::DataError)?; cover(&state.calibre, &state.config, *id, |cover_path, _| {
let cover_path = state.config.library_path.join(book.path).join("cover.jpg"); Ok(File::open(cover_path)?)
})
.await
}
let mut cover = cache::get_thumbnail(&cover_path, &state.config.cache_path) async fn cover<F>(
.await calibre: &Calibre,
.map_err(|_| NotFoundError)?; config: &Config,
id: u64,
f: F,
) -> Result<Response, poem::Error>
where
F: Fn(&FilePath, &FilePath) -> Result<File, CoverError>,
{
let book = calibre.scalar_book(id).map_err(HandlerError::DataError)?;
let cover_path = config.library_path.join(book.path).join("cover.jpg");
let cover = f(&cover_path, &config.cache_path).map_err(|_| NotFoundError)?;
let cover = AsyncFile::from_std(cover);
crate::handlers::download::handler("cover.jpg", cover, &ContentType::jpeg().to_string()).await crate::handlers::download::handler("cover.jpg", cover, &ContentType::jpeg().to_string()).await
} }

View File

@ -77,7 +77,7 @@ pub mod opds {
pub mod templates; pub mod templates;
pub const APP_NAME: &str = "little-hesinde"; pub const APP_NAME: &str = "little-hesinde";
pub const VERSION: &str = "0.2.3"; pub const VERSION: &str = "0.3.0";
/// Internal marker data in lieu of a proper `Accept` header. /// Internal marker data in lieu of a proper `Accept` header.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -117,7 +117,11 @@ pub async fn run(config: Config) -> Result<(), std::io::Error> {
"/authors/:cursor/:sort_order", "/authors/:cursor/:sort_order",
get(handlers::authors::handler), get(handlers::authors::handler),
) )
.at("/cover/:id", get(handlers::cover::handler)) .at("/cover/:id", get(handlers::cover::handler_full))
.at(
"/cover/:id/thumbnail",
get(handlers::cover::handler_thumbnail),
)
.at("/book/:id/:format", get(handlers::books::handler_download)) .at("/book/:id/:format", get(handlers::books::handler_download))
.at("/archive", get(handlers::source_archive::handler)) .at("/archive", get(handlers::source_archive::handler))
.at("/search", get(handlers::search::handler)) .at("/search", get(handlers::search::handler))
@ -143,7 +147,7 @@ pub async fn run(config: Config) -> Result<(), std::io::Error> {
.with(Tracing); .with(Tracing);
let server = Server::new(TcpListener::bind(config.listen_address)) let server = Server::new(TcpListener::bind(config.listen_address))
.name("cops-web") .name("little-hesinde")
.run(app); .run(app);
tokio::select! { tokio::select! {

View File

@ -14,7 +14,7 @@
{% endif %} {% endif %}
</hgroup> </hgroup>
</header> </header>
<img class="cover" src="/cover/{{ book.data.id }}" alt="book cover"> <img class="cover" src="/cover/{{ book.data.id }}/thumbnail" alt="book cover">
<footer> <footer>
<form> <form>
<fieldset role="group"> <fieldset role="group">