librelink_client/
client.rs

1use reqwest::Client;
2
3use crate::{
4    connection::{ConnectionGraphResponse, ResponseConnections},
5    glucose::{GlucoseHistoryRequest, LogBookRequest},
6    login::try_get_access_token,
7};
8
9pub struct LibreLinkClient {
10    client: Client,
11    token: String,
12    base_url: Option<String>,
13    region: Option<String>,
14}
15
16pub struct Credentials {
17    pub username: String,
18    pub password: String,
19}
20
21impl LibreLinkClient {
22    pub async fn new(credentials: Credentials, region: Option<String>) -> Result<Self, Box<dyn std::error::Error>> {
23        let token = try_get_access_token(&credentials.username, &credentials.password).await;
24
25        match token {
26            Ok(token) => {
27                let mut client = LibreLinkClient {
28                    client: Client::new(),
29                    token,
30                    region,
31                    base_url: None
32                };
33                client.set_base_url();
34                Ok(client)
35            }
36            Err(e) => Err(e),
37        }
38    }
39
40    pub fn from_token(token: String, region: Option<String>) -> Self {
41        let mut client = LibreLinkClient {
42            client: Client::new(),
43            token,
44            region,
45            base_url: None
46        };
47        client.set_base_url();
48        client
49    }
50
51
52    fn set_base_url(&mut self) {
53        // if region is None then set https://api.libreview.io else set https://api-{region}.libreview.io
54        if let Some(region) = &self.region {
55            let url = format!("https://api-{}.libreview.io", region);
56            self.base_url = Some(url);
57        } else {
58            let url = "https://api.libreview.io".to_string();
59            self.base_url = Some(url);
60        }
61    }
62
63    pub async fn get_connections(&self) -> Result<ResponseConnections, Box<dyn std::error::Error>> {
64        let base_url = self.base_url.clone().unwrap();
65        let url = format!("{}/{}", &base_url, "llu/connections");
66
67        let response = self
68            .client
69            .get(url)
70            .header("version", "4.7.1")
71            .header("product", "llu.android")
72            .header("User-Agent", "Apidog/1.0.0 (https://apidog.com)")
73            .bearer_auth(&self.token)
74            .send()
75            .await?;
76
77        let api_response: Result<ResponseConnections, reqwest::Error> = response.json().await;
78
79        match api_response {
80            Ok(response_data) => Ok(response_data),
81            Err(e) => Err(Box::new(e)),
82        }
83    }
84
85    pub async fn get_connection_graph(
86        &self,
87        connection_id: &str,
88    ) -> Result<ConnectionGraphResponse, Box<dyn std::error::Error>> {
89        let base_url = self.base_url.clone().unwrap();
90        let url = format!(
91            "{}/{}/{}/{}",
92            &base_url, "llu/connections", connection_id, "graph"
93        );
94
95        let response = self
96            .client
97            .get(url)
98            .header("version", "4.7.1")
99            .header("product", "llu.android")
100            .header("User-Agent", "Apidog/1.0.0 (https://apidog.com)")
101            .bearer_auth(&self.token)
102            .send()
103            .await?;
104
105        let api_response: Result<ConnectionGraphResponse, reqwest::Error> = response.json().await;
106
107        match api_response {
108            Ok(response_data) => Ok(response_data),
109            Err(e) => Err(Box::new(e)),
110        }
111    }
112
113    pub async fn get_glucose_history(
114        &self,
115        num_periods: i32,
116        period: i32,
117    ) -> Result<GlucoseHistoryRequest, Box<dyn std::error::Error>> {
118        let base_url = self.base_url.clone().unwrap();
119        let url = format!(
120            "{}/{}?numPeriods={}&period={}",
121            &base_url, "glucoseHistory", num_periods, period
122        );
123
124        let response = self
125            .client
126            .get(url)
127            .header("User-Agent", "Apidog/1.0.0 (https://apidog.com)")
128            .bearer_auth(&self.token)
129            .send()
130            .await?;
131
132        let api_response: Result<GlucoseHistoryRequest, reqwest::Error> = response.json().await;
133
134        match api_response {
135            Ok(response_data) => Ok(response_data),
136            Err(e) => Err(Box::new(e)),
137        }
138    }
139
140    pub async fn get_log_book(
141        &self,
142        connection_id: &str,
143    ) -> Result<LogBookRequest, Box<dyn std::error::Error>> {
144        let base_url = self.base_url.clone().unwrap();
145        let url = format!(
146            "{}/{}/{}/{}",
147            &base_url, "llu/connections", connection_id, "logbook"
148        );
149
150        let response = self
151            .client
152            .get(url)
153            .header("version", "4.7.1")
154            .header("product", "llu.android")
155            .header("User-Agent", "Apidog/1.0.0 (https://apidog.com)")
156            .bearer_auth(&self.token)
157            .send()
158            .await?;
159
160        let api_response: Result<LogBookRequest, reqwest::Error> = response.json().await;
161
162        match api_response {
163            Ok(response_data) => Ok(response_data),
164            Err(e) => Err(Box::new(e)),
165        }
166    }
167}