1use std::time::Duration;
4
5use crate::error::{Error, Result};
6
7pub const DEFAULT_API_URL: &str = "http://service.tsetmc.com/tsev2/data/TseClient2.aspx";
8
9#[derive(Debug, Clone)]
11pub struct Requester {
12 client: reqwest::Client,
13 api_url: String,
14}
15
16impl Requester {
17 pub fn new(api_url: String) -> Self {
18 let client = reqwest::Client::builder()
19 .timeout(Duration::from_secs(120))
20 .build()
21 .expect("failed to build reqwest client");
22 Requester { client, api_url }
23 }
24
25 async fn make_request(&self, params: &[(&str, &str)]) -> Result<String> {
26 let res = self.client.get(&self.api_url).query(params).send().await?;
27 let status = res.status();
28 if status.as_u16() == 200 {
29 Ok(res.text().await?)
30 } else {
31 Err(Error::InvalidResponse(format!(
32 "{} {}",
33 status.as_u16(),
34 status.canonical_reason().unwrap_or("")
35 )))
36 }
37 }
38
39 pub async fn instrument(&self, deven: &str) -> Result<String> {
40 self.make_request(&[("t", "Instrument"), ("a", deven)])
41 .await
42 }
43
44 pub async fn instrument_and_share(&self, deven: &str, last_id: i64) -> Result<String> {
45 let last_id = last_id.to_string();
46 self.make_request(&[("t", "InstrumentAndShare"), ("a", deven), ("a2", &last_id)])
47 .await
48 }
49
50 pub async fn last_possible_deven(&self) -> Result<String> {
51 self.make_request(&[("t", "LastPossibleDeven")]).await
52 }
53
54 pub async fn closing_prices(&self, ins_codes: &str) -> Result<String> {
55 self.make_request(&[("t", "ClosingPrices"), ("a", ins_codes)])
56 .await
57 }
58}
59
60pub fn intraday_url(server: i32, inscode: &str, deven: &str) -> String {
62 let host = if server > 0 {
63 format!("cdn{server}.")
64 } else if server < 0 {
65 String::new()
66 } else {
67 "cdn.".to_string()
68 };
69 format!("http://{host}tsetmc.com/Loader.aspx?ParTree=15131P&i={inscode}&d={deven}")
70}