1mod roliefeed;
2
3pub use roliefeed::*;
4
5use crate::source::HttpSourceError;
6use time::OffsetDateTime;
7use url::{ParseError, Url};
8use walker_common::fetcher::Json;
9use walker_common::{fetcher, fetcher::Fetcher};
10
11#[derive(Debug, thiserror::Error)]
12pub enum Error {
13 #[error("Fetch error: {0}")]
14 Fetcher(#[from] fetcher::Error),
15 #[error("URL error: {0}")]
16 Url(#[from] ParseError),
17 #[error("JSON parse error: {0}")]
18 Json(#[from] serde_json::Error),
19}
20
21impl From<Error> for HttpSourceError {
22 fn from(value: Error) -> Self {
23 match value {
24 Error::Fetcher(err) => Self::Fetcher(err),
25 Error::Url(err) => Self::Url(err),
26 Error::Json(err) => Self::Json(err),
27 }
28 }
29}
30
31#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
32pub struct SourceFile {
33 pub file: String,
35 #[serde(with = "time::serde::iso8601")]
37 pub timestamp: OffsetDateTime,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
41pub struct RolieSource {
42 #[serde(default, skip_serializing_if = "Vec::is_empty")]
43 pub files: Vec<SourceFile>,
44}
45
46impl RolieSource {
47 pub async fn retrieve(fetcher: &Fetcher, base_url: Url) -> Result<Self, Error> {
48 let mut files = vec![];
49 let Json(result) = fetcher.fetch::<Json<RolieFeed>>(base_url).await?;
50 for url in result.feed.entry {
51 for link in url.link {
52 files.push(SourceFile {
53 file: link.href,
54 timestamp: url.updated,
55 })
56 }
57 }
58
59 log::debug!("found {:?} files", files.len());
60
61 Ok(Self { files })
62 }
63}