Skip to main content

open_library_api_rs/api/
covers.rs

1// v0.0.1
2use url::Url;
3
4use crate::client::OpenLibraryClient;
5use crate::error::Result;
6use crate::models::common::{CoverKey, ImageSize};
7use crate::models::covers::CoverMeta;
8use crate::validation::validate_author_id;
9
10impl OpenLibraryClient {
11    /// Build a cover image URL without making an HTTP request.
12    ///
13    /// Example: `cover_url(CoverKey::Id, "5428012", ImageSize::Large)`
14    /// → `https://covers.openlibrary.org/b/id/5428012-L.jpg`
15    pub fn cover_url(&self, key: CoverKey, value: &str, size: ImageSize) -> Url {
16        let path = format!(
17            "b/{}/{}-{}.jpg",
18            key.as_str(),
19            value,
20            size.as_str()
21        );
22        // Parsing here is safe because we control all components.
23        self.covers_url.join(&path).expect("cover URL construction failed")
24    }
25
26    /// Build an author photo URL without making an HTTP request.
27    ///
28    /// `olid` must be a valid author OLID (e.g. `"OL23919A"`).
29    pub fn author_photo_url(&self, olid: &str, size: ImageSize) -> Result<Url> {
30        validate_author_id(olid)?;
31        let path = format!("a/olid/{olid}-{}.jpg", size.as_str());
32        Ok(self.covers_url.join(&path).expect("author photo URL construction failed"))
33    }
34
35    /// Fetch JSON metadata for a cover image.
36    ///
37    /// Note: the covers API returns an object whose single key is the bibkey.
38    pub async fn cover_meta(
39        &self,
40        key: CoverKey,
41        value: &str,
42    ) -> Result<Vec<CoverMeta>> {
43        let path = format!("b/{}/{}.json", key.as_str(), value);
44        let url = self.covers_url.join(&path)?;
45        // The response is { "KEY:VALUE": [...] } — we extract the inner array.
46        let raw: serde_json::Value = self.get_covers_json(url).await?;
47        let metas: Vec<CoverMeta> = raw
48            .as_object()
49            .and_then(|m| m.values().next())
50            .and_then(|v| serde_json::from_value(v.clone()).ok())
51            .unwrap_or_default();
52        Ok(metas)
53    }
54}