use super::models::{
ChapterDetail,
Response,
};
use crate::{
Chapter,
Error,
Page,
Result,
};
use url::Url;
pub(super) fn extract_from_response<'a>(
response: &Response<ChapterDetail>,
chapter: &'a Chapter<'_>,
) -> Result<Vec<Page<'a>>> {
response
.data
.pages
.iter()
.enumerate()
.map(|(idx, page)| {
let server_url = &response.data.server;
let fallback_url = &response.data.server_fallback;
let path = format!("{}/{}", response.data.hash, page);
#[allow(clippy::cast_possible_truncation)] Ok(Page {
id: (idx + 1) as u16,
chapter,
main: urljoin(server_url, &path)?,
fallback: Some(urljoin(fallback_url, &path)?),
})
})
.collect()
}
fn urljoin(base: &Url, suffix: &str) -> Result<Url> {
base.join(&suffix).map_err(|err| {
Error::Scraping(format!(
"failed to join {} with {}: {}",
base.as_str(),
suffix,
err
))
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
types::Pagination,
Series,
};
use std::path::PathBuf;
#[test]
fn test_scraping() {
let series = Series {
title: "Example".to_owned(),
url: Url::parse("http://example.com/").unwrap(),
pagination: Pagination::new(0, 0),
};
let chapter = Chapter {
id: 10.0,
series: &series,
volume: None,
url: Url::parse("http://example.com/10/").unwrap(),
};
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("testdata/mangadex.org/chapter.json");
let json = std::fs::read_to_string(&path).expect("test data");
let response = serde_json::from_str(&json).expect("invalid JSON");
let pages = extract_from_response(&response, &chapter).unwrap();
assert_eq!(pages.len(), 62);
}
}