diff options
| author | A Farzat <a@farzat.xyz> | 2026-02-12 14:23:43 +0300 |
|---|---|---|
| committer | A Farzat <a@farzat.xyz> | 2026-02-12 14:23:43 +0300 |
| commit | 57bc69a7f9af497526695e5a0bfbc60939f667e9 (patch) | |
| tree | 10d70a1334128cf8894d0c759b8dac2b3d752968 /src | |
| parent | 2d9314aa3145ec7948341f38164e13c2a2d945ad (diff) | |
| download | safaribooks-rs-57bc69a7f9af497526695e5a0bfbc60939f667e9.tar.gz safaribooks-rs-57bc69a7f9af497526695e5a0bfbc60939f667e9.zip | |
Add the ability to fetch book info
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 11 | ||||
| -rw-r--r-- | src/orly.rs | 29 |
2 files changed, 38 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index f79f191..d393a55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,8 +10,7 @@ use cli::Args; use cookies::CookieStore; use display::Display; use http_client::HttpClient; -use orly::check_login; -use reqwest::Client; +use orly::{check_login, fetch_book_info}; #[tokio::main] async fn main() { @@ -60,6 +59,14 @@ async fn main() { Err(e) => ui.error_and_exit(&format!("Login check failed: {e}")), }; + // Retrieve book info. + ui.info("Retrieving book info..."); + let bookinfo = match fetch_book_info(&client, &args.bookid).await { + Ok(info) => info, + Err(e) => ui.error_and_exit(&format!("Failed to fetch book info: {}", e)), + }; + ui.info(&format!("{:#?}", bookinfo)); + let output_dir = config::books_root().join(format!("(pending) ({})", args.bookid)); ui.set_output_dir(output_dir); diff --git a/src/orly.rs b/src/orly.rs index cd8b645..0e34e5c 100644 --- a/src/orly.rs +++ b/src/orly.rs @@ -1,8 +1,16 @@ use crate::http_client::HttpClient; use anyhow::{bail, Result}; +use serde::Deserialize; pub const PROFILE_URL: &str = "https://learning.oreilly.com/profile/"; +/// Minimal subset of the book that we care about. +#[derive(Debug, Deserialize)] +pub struct BookInfo { + pub title: String, + pub web_url: String, +} + /// Check whether cookies keep us logged in by fetching the profile page. /// Returns: /// - Ok(true) => HTTP 200 (assume logged in) @@ -20,3 +28,24 @@ pub async fn check_login(client: &HttpClient) -> Result<bool> { bail!("Profile request returned unexpected status {}", status) } } + +/// Build the v1 API URL for the book. +pub fn book_api_url(bookid: &str) -> String { + format!("https://learning.oreilly.com/api/v1/book/{bookid}") +} + +/// Fetch book metadata from the website. +pub async fn fetch_book_info(client: &HttpClient, bookid: &str) -> Result<BookInfo> { + let url = book_api_url(bookid); + let res = client.client().get(url).send().await?; + let status = res.status(); + + if status == 200 { + let info = res.json::<BookInfo>().await?; + return Ok(info); + } + if status == 404 { + bail!("Book not found (HTTP 404). Please double-check the book ID provided") + } + bail!("Got status: {}", status) +} |
