use chrono::Local;
use crate::{flex_statement};
const FLEX_URL: &str = "https://gdcdyn.interactivebrokers.com/Universal/servlet/";
const REQUEST_ENDPOINT: &str = "FlexStatementService.SendRequest";
const STMT_ENDPOINT: &str = "FlexStatementService.GetStatement";
#[derive(Debug, Default)]
pub struct DownloadParams {
pub query_id: Option<u32>,
pub token: Option<String>,
}
impl DownloadParams {
pub fn new(query_id: Option<u32>, token: &Option<String>) -> Self {
Self {
query_id,
token: match token {
Some(tkn) => Some(tkn.to_owned()),
None => None,
},
}
}
}
pub async fn download(params: DownloadParams) -> String {
let query_id = match params.query_id {
Some(qid) => qid.to_string(),
None => panic!("The query id is mandatory for the report download!"),
};
let token = match params.token {
Some(tkn) => tkn,
None => panic!("The token is mandatory for the report download!"),
};
let report = download_report(&query_id, &token).await;
let today_date = Local::now().date_naive();
let today = today_date.format("%Y-%m-%d");
let output_filename = format!("{today}_cash-tx.xml");
std::fs::write(&output_filename, report).expect("successfully saved");
output_filename
}
async fn download_report(query_id: &str, token: &str) -> String {
let resp = request_statement(query_id, token).await;
let stmt_resp = flex_statement::parse_response_text(&resp);
let stmt_text = download_statement_text(&stmt_resp.reference_code, token).await;
stmt_text
}
async fn request_statement(query_id: &str, token: &str) -> String {
let url = format!("{FLEX_URL}{REQUEST_ENDPOINT}?v=3&t={token}&q={query_id}");
let client = reqwest::Client::new();
let res = client
.get(url)
.header("User-Agent", "Java")
.send()
.await
.expect("response received");
res.text().await.expect("contents of the response")
}
async fn download_statement_text(ref_code: &String, token: &str) -> String {
let url = format!("{FLEX_URL}{STMT_ENDPOINT}?v=3&q={ref_code}&t={token}");
reqwest::get(url)
.await
.expect("downloaded statement")
.text()
.await
.expect("text response (xml)")
}
#[cfg(test)]
mod tests {
use crate::{download::{FLEX_URL, REQUEST_ENDPOINT, request_statement, DownloadParams}};
#[test]
fn constants_test() {
let actual = format!("{FLEX_URL}{REQUEST_ENDPOINT}");
assert_eq!("https://gdcdyn.interactivebrokers.com/Universal/servlet/FlexStatementService.SendRequest",
actual);
}
#[allow(unused)]
async fn request_report_test() {
let cfg = DownloadParams::default();
let actual = request_statement(&cfg.query_id.unwrap().to_string(),
&cfg.token.unwrap()).await;
println!("received: {:?}", actual);
assert_ne!(String::default(), actual);
assert!(!actual.contains("ERROR"));
assert!(false);
}
}