use super::models::ApiParams;
use chrono::{Duration, Utc};
use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue, USER_AGENT};
use reqwest::Url;
use std::error::Error;
use std::thread::sleep;
use std::time::Duration as StdDuration;
use sysinfo::{System, SystemExt};
const PKG_NAME : &str = env!("CARGO_PKG_NAME");
const PKG_VERSION : &str = env!("CARGO_PKG_VERSION");
fn get_headers() -> Result<HeaderMap, InvalidHeaderValue> {
let mut system = System::new_all();
system.refresh_all();
let mut headers = HeaderMap::new();
let user_agent_name = format!(
"{}/{} ({} {} +{})",
PKG_NAME,
PKG_VERSION,
system.name().unwrap_or("Unknown OS".to_string()),
system.os_version().unwrap_or("Unknown Version".to_string()),
system.host_name().unwrap_or("Unknown Host".to_string())
);
let user_agent_value = HeaderValue::from_str(&user_agent_name)?;
headers.insert(USER_AGENT, user_agent_value);
Ok(headers)
}
#[tokio::main]
pub async fn products(api_params:ApiParams) -> Result<Vec<[f64; 6]>, Box<dyn Error>> {
const KLINE_MAX: i64 = 300;
let headers = get_headers()?;
let client = reqwest::Client::builder()
.default_headers(headers)
.build()?;
let mut url = Url::parse(api_params.base_url)?;
if let Some(product_id) = api_params.product_id {
url.path_segments_mut().unwrap().push("products").push(product_id);
}
if let Some(resource) = api_params.resource {
url.path_segments_mut().unwrap().push(resource);
}
let mut query_param_static_arr: Vec<String> = api_params.params.as_ref().map_or(Vec::new(), |params| {
params.iter()
.map(|(key, value)| format!("{}={}", key, value))
.collect()
});
query_param_static_arr.push(format!("{}={}", "granularity", api_params.granularity));
let query_param_static_str = query_param_static_arr.join("&");
let chunks = (api_params.limit as f64 / KLINE_MAX as f64).ceil() as i32;
let mut end_time = Utc::now();
let cp_granularity= api_params.granularity as i64;
let mut klines: Vec<[f64; 6]> = vec![];
for _ in 0..chunks {
let start_time = end_time - Duration::seconds(cp_granularity * KLINE_MAX);
url.set_query(Some(&query_param_static_str));
url.query_pairs_mut()
.append_pair("start", start_time.to_rfc3339().as_str())
.append_pair("end", end_time.to_rfc3339().as_str());
let resp: Vec<[f64; 6]> = client.get(url.clone()).send().await?.json().await?;
klines.extend(resp);
sleep(StdDuration::from_secs(1));
end_time = start_time;
}
klines.truncate(api_params.limit as usize);
Ok(klines)
}