fediback 0.2.0

A mastodon account backup program
use {
    crate::*,
    reqwest::{blocking, header},
    serde::de::DeserializeOwned,
};

pub struct Client {
    requester: blocking::Client,
    pub verbose: bool,
}

const MAX_QUERIES_PER_LIST: usize = 100;

impl Client {

    pub fn new() -> Result<Self> {
        let mut headers = header::HeaderMap::new();
        headers.insert(
            header::ACCEPT,
            header::HeaderValue::from_static("application/activity+json"),
        );
        let requester = blocking::Client::builder()
            .default_headers(headers)
            .user_agent("fediback/0.1")
            .build()?;
        let verbose = false;
        Ok(Self { requester, verbose })
    }

    pub fn get<D>(&self, url: &str) -> Result<D>
    where
        D: DeserializeOwned,
    {
        if self.verbose {
            eprintln!("querying {}", url);
        }
        Ok(self.requester.get(url).send()?.json()?)
    }

    pub fn get_items<S, Item>(
        &self,
        url: S,
    ) -> Result<Vec<Item>>
        where
            S: Into<String>,
            Item: DeserializeOwned,
    {
        let mut url = url.into();
        let mut all = Vec::new();
        let mut queries = 0;
        loop {
            let mut page: Page<Item> = self.get(&url)?;
            queries += 1;
            if let Some(items) = &mut page.ordered_items {
                all.append(items);
            }
            if let Some(next) = page.next.take() {
                url = next;
            } else if let Some(first) = page.first.take() {
                url = first;
            } else {
                break;
            }
            if queries >= MAX_QUERIES_PER_LIST {
                warn!("too many queries");
                if self.verbose {
                    warn!("too many queries");
                }
                break;
            }
        }
        Ok(all)
    }

}