use std::io::Write; use anyhow::Result; use base64::Engine; use base64::engine::{GeneralPurpose}; use crate::post::{Post, Posts}; use reqwest::header::{AUTHORIZATION, HeaderMap, HeaderValue, USER_AGENT}; #[derive(Clone, Debug)] pub struct Client<'a> { auth: Authentication<'a>, useragent: &'a str, host: &'static str, http_client: reqwest::Client } impl<'a> Client<'a> { pub fn new(auth: Authentication<'a>, useragent: &'a str) -> Result { let mut header_map = HeaderMap::new(); header_map.append(USER_AGENT, HeaderValue::from_str(useragent)?); if let Authentication::Authorized { username, apikey } = auth { let authorization = Self::get_authorization_value(username, apikey); header_map.append(AUTHORIZATION, HeaderValue::from_str(&authorization)?); } let http_client = reqwest::Client::builder() .default_headers(header_map) .build()?; Ok(Client { auth, useragent, host: "https://e621.net", http_client }) } fn get_authorization_value(username: &'a str, apikey: &'a str) -> String { let base64_engine = GeneralPurpose::new(&base64::alphabet::STANDARD, Default::default()); base64_engine.encode(format!("{username}:{apikey}")) } pub async fn list_posts(&mut self, limit: Option, tags: Option>, page: Option) -> Result> { let mut url = url::Url::parse(format!("{}/posts.json", self.host).as_str())?; let limit = limit.unwrap_or(320); let page = page.unwrap_or(0); let mut query_params = String::new(); query_params.push_str("limit="); query_params.push_str(limit.to_string().as_str()); query_params.push_str("page="); query_params.push_str(page.to_string().as_str()); if let Some(tags) = tags { if tags.len() > 0 { query_params.push_str("tags="); query_params.push_str(tags.join(",").as_str()); } } Ok(self.http_client.get(url.as_str()) .send() .await? .json::() .await?.into()) } } #[derive(Clone, Copy, Debug)] pub enum Authentication<'a> { Authorized {username: &'a str, apikey: &'a str}, Unauthorized }