aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-03-08 21:06:39 +0300
committerA Farzat <a@farzat.xyz>2026-03-08 21:39:23 +0300
commitab5ce397987bd97c920101a8d393d0fde29b5f74 (patch)
tree3932882f3b741a491681fe8b24c9e74a01836647
parentd3c2e22de84428229c36a6b81722da40c85387ca (diff)
downloadoreilly-epub-ab5ce397987bd97c920101a8d393d0fde29b5f74.tar.gz
oreilly-epub-ab5ce397987bd97c920101a8d393d0fde29b5f74.zip
Allow cookies.json in config dir
This allows running the program from anywhere, given the cookies are placed in the config dir.
-rw-r--r--src/http_client.rs11
-rw-r--r--src/main.rs28
2 files changed, 30 insertions, 9 deletions
diff --git a/src/http_client.rs b/src/http_client.rs
index 6e06474..e8251d3 100644
--- a/src/http_client.rs
+++ b/src/http_client.rs
@@ -1,15 +1,16 @@
use anyhow::{Context, Result};
use reqwest::{Client, cookie::Jar};
-use std::{collections::HashMap, fs, sync::Arc};
+use std::{collections::HashMap, fs, path::PathBuf, sync::Arc};
/// Reads the cookies.json file and builds an authenticated reqwest client.
-pub fn build_authenticated_client(cookies_path: &str) -> Result<Client> {
+pub fn build_authenticated_client(cookies_path: &PathBuf) -> Result<Client> {
// Read the JSON file.
- let cookies_content = fs::read_to_string(cookies_path)
- .with_context(|| format!("Failed to read cookies file from: {}", cookies_path))?;
+ println!("Reading cookies from {cookies_path:?}...");
+ let cookies_content = fs::read(cookies_path)
+ .with_context(|| format!("Failed to read cookies file from {cookies_path:?}."))?;
// Parse the JSON into a Rust HashMap.
- let cookies_map: HashMap<String, String> = serde_json::from_str(&cookies_content)
+ let cookies_map: HashMap<String, String> = serde_json::from_slice(&cookies_content)
.context("Failed to parse cookies file. Ensure it is a flat key-value JSON object.")?;
// Create a Cookie Jar.
diff --git a/src/main.rs b/src/main.rs
index 2255b18..7b73bf3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,11 +4,13 @@ mod models;
mod xml;
use std::collections::HashMap;
+use std::env::current_dir;
+use std::path::PathBuf;
use crate::epub::{create_epub_archive, download_all_files};
use crate::http_client::build_authenticated_client;
use crate::models::{Chapter, EpubResponse, FileEntry, Paginated, SpineItem, TocNode};
-use anyhow::{Context, Result};
+use anyhow::{Context, Result, anyhow};
use clap::Parser;
use directories::{BaseDirs, UserDirs};
use reqwest::Client;
@@ -21,8 +23,8 @@ struct Args {
#[arg(required = true)]
bookid: String,
/// Path to the cookies.json file.
- #[arg(long, default_value = "cookies.json")]
- cookies: String,
+ #[arg(long)]
+ cookies: Option<String>,
/// Do not download files. Use if they were already downloaded in a previous run.
#[arg(long = "skip-download")]
skip_download: bool,
@@ -91,6 +93,7 @@ async fn main() -> Result<()> {
// Obtain relevant XDG base directories.
let base_dirs = BaseDirs::new().context("Could not get XDG base directories.")?;
let data_root = base_dirs.data_dir().join("oreilly-epub");
+ let config_root = base_dirs.config_dir().join("oreilly-epub");
// Parse the command line arguments
let args = Args::parse();
@@ -108,7 +111,24 @@ async fn main() -> Result<()> {
// Initialise the HTTP client.
println!("Loading cookies and initialising the HTTP client...");
- let client = build_authenticated_client(&args.cookies)?;
+ let candidate_cookies_paths = [
+ args.cookies.map(PathBuf::from),
+ Some(config_root.join("cookies.json")),
+ Some(current_dir()?.join("cookies.json")),
+ ];
+ let cookies_file = candidate_cookies_paths
+ .into_iter()
+ .flatten()
+ .find(|path| path.exists())
+ .ok_or_else(|| {
+ anyhow!(
+ "No cookies.json found. {}, {} {:?}.",
+ "Either provide one through the --cookies option",
+ "or create one in the current directory or at",
+ config_root
+ )
+ })?;
+ let client = build_authenticated_client(&cookies_file)?;
println!("Fetching book metadata...");
// Fetch from the EPUB API.