Serve EPUBs instead XTC in daily OPDS
It turns out it is currently impossible for the Xteink X4 to download XTC files from an OPDS server. So I switched the built-in OPDS server in this binary (daily.hallada.net/opds) to serve the EPUB files instead of the XTC files. The X4 is pretty capable of reading the X4 edition of the EPUB that was optimized for it anyways, and I prefer the flexibility of EPUB, so I might end up eventually deleting the XTC conversion. For now, I kept the conversion step (in case I ever want to ever try manually copying them to the device) and I keep a limited number of XTC issues on the server since they are quite big in filesize. The BookOrbit integration is now optional since the built-in OPDS server is able to serve the EPUBs. In my installation, I serve the EPUBs through both. The daily.hallada.net/opds server is just a little quicker to navigate and download the EPUBs on the X4 since the BookOrbit OPDS requires diving into a couple layers of folders before you get to the files.
This commit is contained in:
+36
-6
@@ -51,8 +51,13 @@ pub struct Config {
|
||||
pub target_article_count: usize,
|
||||
/// How many articles survive the heuristic pre-filter (§3.5).
|
||||
pub prefilter_keep: usize,
|
||||
/// Days of published files kept in the publish dirs (§3.11).
|
||||
/// Days of published EPUBs kept in `publish.epub_dir` (§3.11).
|
||||
pub retention_days: u32,
|
||||
/// How many XTC issues to keep in `publish.xtc_dir` (§3.11).
|
||||
///
|
||||
/// Counted, not dated, because an XTCH issue is ~80–100 MB of pre-rendered
|
||||
/// page bitmaps: the constraint is disk, not age.
|
||||
pub xtc_retention_count: u32,
|
||||
/// Hard cost ceiling per run (§3.6 guardrail).
|
||||
pub max_daily_usd: f64,
|
||||
/// Include the Wikipedia Current Events section (§3.8).
|
||||
@@ -81,6 +86,7 @@ impl Default for Config {
|
||||
target_article_count: 20,
|
||||
prefilter_keep: 120,
|
||||
retention_days: 21,
|
||||
xtc_retention_count: 5,
|
||||
max_daily_usd: 2.0,
|
||||
world_briefing: true,
|
||||
database_path: PathBuf::from("/var/lib/daily-epub/daily-epub.db"),
|
||||
@@ -195,16 +201,20 @@ impl Default for CurationConfig {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
pub struct PublishConfig {
|
||||
/// BookOrbit "The Daily EPUB" library watched folder.
|
||||
pub bookorbit_dir: PathBuf,
|
||||
/// Directory served at `/files/xtc/`.
|
||||
/// Where both EPUB editions land: the source of the OPDS feed, served at
|
||||
/// `/files/epub/`, and a BookOrbit watched folder if one is configured.
|
||||
///
|
||||
/// Renamed from `bookorbit_dir` once the built-in feed started serving this
|
||||
/// directory directly — BookOrbit is optional, the directory is not.
|
||||
pub epub_dir: PathBuf,
|
||||
/// Directory served at `/files/xtc/`. Not listed in the OPDS feed (§3.11).
|
||||
pub xtc_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for PublishConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bookorbit_dir: PathBuf::from("/srv/bookorbit/libraries/daily-epub"),
|
||||
epub_dir: PathBuf::from("/srv/bookorbit/libraries/daily-epub"),
|
||||
xtc_dir: PathBuf::from("/var/lib/daily-epub/xtc"),
|
||||
}
|
||||
}
|
||||
@@ -274,7 +284,7 @@ pub struct ServerConfig {
|
||||
pub public_url: String,
|
||||
/// HMAC key for rating tokens; supply via `DAILY_EPUB_SERVER__HMAC_SECRET`.
|
||||
pub hmac_secret: Option<String>,
|
||||
/// Optional Basic auth for `/opds/xtc.xml` and `/files/xtc/`.
|
||||
/// Optional Basic auth for `/opds/*` and `/files/*`.
|
||||
pub basic_auth_user: Option<String>,
|
||||
pub basic_auth_pass: Option<String>,
|
||||
}
|
||||
@@ -431,6 +441,26 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
/// `publish.bookorbit_dir` was renamed to `publish.epub_dir`. A config still
|
||||
/// using the old key must fail loudly and name both — silently falling back
|
||||
/// to the default would publish the issue into the wrong directory, where
|
||||
/// the OPDS feed would then find nothing.
|
||||
#[test]
|
||||
fn the_renamed_publish_key_fails_loudly() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("config.toml");
|
||||
std::fs::write(
|
||||
&path,
|
||||
"[publish]\nbookorbit_dir = \"/srv/books\"\nxtc_dir = \"/srv/xtc\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let err = Config::load(Some(&path)).expect_err("the stale key must be rejected");
|
||||
let message = err.to_string();
|
||||
assert!(message.contains("bookorbit_dir"), "{message}");
|
||||
assert!(message.contains("epub_dir"), "{message}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shipped_example_config_parses() {
|
||||
let example = Path::new(env!("CARGO_MANIFEST_DIR")).join("config.example.toml");
|
||||
|
||||
Reference in New Issue
Block a user