Sync your own workout data from your "Strong" app
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

moved Response structs to json_response.rs

+53 -37
+25
strong-api-lib/src/json_response.rs
··· 1 + use std::fmt; 1 2 use serde::{Deserialize, Serialize}; 2 3 use serde_json::Value; 4 + 5 + #[derive(Debug, Deserialize)] 6 + pub struct ApiErrorResponse { 7 + pub code: String, 8 + pub description: String, 9 + } 10 + 11 + impl fmt::Display for ApiErrorResponse { 12 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 + write!(f, "{}: {}", self.code, self.description) 14 + } 15 + } 16 + 17 + impl std::error::Error for ApiErrorResponse {} 18 + 19 + #[derive(Debug, Deserialize)] 20 + pub struct LoginResponse { 21 + #[serde(rename = "accessToken")] 22 + pub access_token: Option<String>, 23 + #[serde(rename = "refreshToken")] 24 + pub refresh_token: Option<String>, 25 + #[serde(rename = "userId")] 26 + pub user_id: Option<String>, 27 + } 3 28 4 29 #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 5 30 pub struct UserResponse {
+28 -37
strong-api-lib/src/strong_api.rs
··· 1 - use crate::json_response::MeasurementsResponse; 1 + use crate::json_response::{ApiErrorResponse, LoginResponse, MeasurementsResponse}; 2 2 use crate::json_response::UserResponse; 3 3 use reqwest::{ 4 4 Client, Url, 5 5 header::{HeaderMap, HeaderName, HeaderValue}, 6 6 }; 7 - use serde::Deserialize; 8 7 use serde_json::json; 9 8 use std::fmt; 10 - 11 - #[derive(Debug, Deserialize)] 12 - struct ApiErrorResponse { 13 - code: String, 14 - description: String, 15 - } 16 - 17 - impl fmt::Display for ApiErrorResponse { 18 - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 - write!(f, "{}: {}", self.code, self.description) 20 - } 21 - } 22 - 23 - impl std::error::Error for ApiErrorResponse {} 24 9 25 10 #[derive(Debug)] 26 11 pub struct StrongApi { ··· 32 17 pub user_id: Option<String>, 33 18 } 34 19 35 - #[derive(Debug, Deserialize)] 36 - pub struct LoginResponse { 37 - #[serde(rename = "accessToken")] 38 - access_token: Option<String>, 39 - #[serde(rename = "refreshToken")] 40 - refresh_token: Option<String>, 41 - #[serde(rename = "userId")] 42 - user_id: Option<String>, 43 - } 44 - 45 20 #[derive(Debug)] 46 21 pub enum Includes { 47 22 Log, ··· 71 46 impl StrongApi { 72 47 /// Creates a new StrongApi instance with the provided backend URL. 73 48 pub fn new(url: Url) -> Self { 74 - let mut headers = HeaderMap::new(); 49 + Self { 50 + url, 51 + headers: Self::default_headers(), 52 + client: Client::new(), 53 + refresh_token: None, 54 + access_token: None, 55 + user_id: None, 56 + } 57 + } 58 + 59 + /// Creates the default headers used for API requests. 60 + fn default_headers() -> HeaderMap { 61 + let mut headers = HeaderMap::with_capacity(5); 75 62 headers.insert( 76 63 HeaderName::from_static("user-agent"), 77 64 HeaderValue::from_static("Strong Android"), ··· 92 79 HeaderName::from_static("x-client-platform"), 93 80 HeaderValue::from_static("android"), 94 81 ); 95 - 96 - Self { 97 - url, 98 - headers, 99 - client: Client::new(), 100 - refresh_token: None, 101 - access_token: None, 102 - user_id: None, 103 - } 82 + headers 104 83 } 105 84 106 85 /// Logs in to the Strong backend using the provided username/e-mail and password. ··· 201 180 limit: i16, 202 181 includes: Vec<Includes>, 203 182 ) -> Result<UserResponse, Box<dyn std::error::Error>> { 204 - let user_id = self.user_id.as_ref().ok_or("Missing user id")?; 183 + let user_id = self 184 + .user_id 185 + .as_ref() 186 + .ok_or("Missing user id. Use `login` before calling `get_user`")?; 205 187 let mut url = self.url.join(&format!("api/users/{user_id}"))?; 206 188 207 189 { ··· 225 207 // Capture the status before consuming the response. 226 208 let status = response.status(); 227 209 let response_text = response.text().await?; 210 + 211 + // write the response to a file, named after the timestamp 212 + let timestamp = std::time::SystemTime::now() 213 + .duration_since(std::time::UNIX_EPOCH) 214 + .unwrap() 215 + .as_secs(); 216 + 217 + let filename = format!("response_{}.json", timestamp); 218 + std::fs::write(&filename, &response_text)?; 228 219 229 220 if !status.is_success() { 230 221 let api_error: ApiErrorResponse = serde_json::from_str(&response_text)?;