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.

refactor to own modules #9

+288 -273
+1 -1
Cargo.lock
··· 1245 1245 1246 1246 [[package]] 1247 1247 name = "strong-api-lib" 1248 - version = "0.2.0" 1248 + version = "0.3.0" 1249 1249 dependencies = [ 1250 1250 "reqwest", 1251 1251 "serde",
+1 -1
strong-api-fetch/src/main.rs
··· 6 6 use std::fs; 7 7 use std::path::Path; 8 8 use strong_api_lib::data_transformer::{DataTransformer, Workout}; 9 - use strong_api_lib::json_response::MeasurementsResponse; 9 + use strong_api_lib::models::measurement::MeasurementsResponse; 10 10 use strong_api_lib::strong_api::{Includes, StrongApi}; 11 11 12 12 #[tokio::main]
+1 -1
strong-api-lib/Cargo.toml
··· 1 1 [package] 2 2 name = "strong-api-lib" 3 - version = "0.2.0" 3 + version = "0.3.0" 4 4 edition = "2024" 5 5 6 6 [dependencies]
+4 -4
strong-api-lib/src/data_transformer.rs
··· 1 - use crate::json_response::{ 2 - CellSet, CellSetGroup, CellSetGroupLinks, Log, Measurement, MeasurementsResponse, 3 - }; 1 + use crate::models::measurement::{Measurement, MeasurementsResponse}; 2 + use crate::models::workout::{CellSet, CellSetGroup, CellSetGroupLinks, Log}; 4 3 use std::collections::HashMap; 5 4 6 5 #[derive(Debug)] ··· 193 192 194 193 #[cfg(test)] 195 194 mod test { 196 - use crate::json_response::{CellSetGroupLinks, Link}; 195 + use crate::models::common::Link; 196 + use crate::models::workout::CellSetGroupLinks; 197 197 use super::*; 198 198 199 199 #[test]
-263
strong-api-lib/src/json_response.rs
··· 1 - use serde::{Deserialize, Serialize}; 2 - use serde_json::Value; 3 - use std::fmt; 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 - } 28 - 29 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 30 - pub struct UserResponse { 31 - #[serde(rename = "_links")] 32 - pub links: Value, 33 - #[serde(rename = "_embedded")] 34 - pub embedded: Embedded, 35 - pub id: String, 36 - pub created: String, 37 - #[serde(rename = "lastChanged")] 38 - pub last_changed: String, 39 - pub username: String, 40 - pub email: String, 41 - #[serde(rename = "emailVerified")] 42 - pub email_verified: bool, 43 - pub name: Option<String>, 44 - pub avatar: Value, 45 - pub preferences: Value, 46 - #[serde(rename = "legacyPurchase")] 47 - pub legacy_purchase: Value, 48 - #[serde(rename = "legacyGoals")] 49 - pub legacy_goals: Value, 50 - #[serde(rename = "startHistoryFromDate")] 51 - pub start_history_from_date: String, 52 - #[serde(rename = "firstWeekDay")] 53 - pub first_week_day: String, 54 - #[serde(rename = "availableLogins")] 55 - pub available_logins: Vec<Value>, 56 - pub migrated: String, 57 - } 58 - 59 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 60 - pub struct Embedded { 61 - pub measurement: Option<Vec<Value>>, 62 - #[serde(rename = "measuredValue")] 63 - pub measured_value: Option<Vec<Value>>, 64 - pub template: Option<Vec<Value>>, 65 - pub log: Option<Vec<Log>>, 66 - pub tag: Option<Vec<Value>>, 67 - pub folder: Option<Vec<Value>>, 68 - pub widget: Option<Vec<Value>>, 69 - } 70 - 71 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 72 - pub struct Log { 73 - #[serde(rename = "_links")] 74 - pub links: Value, 75 - #[serde(rename = "_embedded")] 76 - pub embedded: LogEmbedded, 77 - #[serde(rename = "timezoneId")] 78 - pub timezone_id: Option<String>, 79 - pub id: String, 80 - pub created: String, 81 - #[serde(rename = "lastChanged")] 82 - pub last_changed: String, 83 - pub name: Option<Name>, 84 - pub access: String, 85 - #[serde(rename = "startDate")] 86 - pub start_date: Option<String>, 87 - #[serde(rename = "endDate")] 88 - pub end_date: Option<String>, 89 - #[serde(rename = "logType")] 90 - pub log_type: String, 91 - } 92 - 93 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 94 - pub struct Name { 95 - pub en: Option<String>, 96 - pub custom: Option<String>, 97 - } 98 - 99 - impl std::fmt::Display for Name { 100 - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 101 - match &self.en { 102 - Some(en) => write!(f, "{}", en), 103 - None => match &self.custom { 104 - Some(custom) => write!(f, "{}", custom), 105 - None => write!(f, "Unknown"), 106 - }, 107 - } 108 - } 109 - } 110 - 111 - impl From<Name> for String { 112 - fn from(name: Name) -> Self { 113 - match name.en { 114 - Some(en) => en, 115 - None => match name.custom { 116 - Some(custom) => custom, 117 - None => "Unknown".to_string(), 118 - }, 119 - } 120 - } 121 - } 122 - 123 - impl From<String> for Name { 124 - fn from(name: String) -> Self { 125 - Name { 126 - en: Some(name), 127 - custom: None, 128 - } 129 - } 130 - } 131 - 132 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 133 - pub struct LogEmbedded { 134 - #[serde(rename = "cellSetGroup")] 135 - pub cell_set_group: Vec<CellSetGroup>, 136 - } 137 - 138 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 139 - pub struct CellSetGroup { 140 - #[serde(rename = "_links")] 141 - pub links: CellSetGroupLinks, 142 - #[serde(rename = "_embedded")] 143 - pub embedded: CellSetGroupEmbedded, 144 - pub id: String, 145 - #[serde(rename = "cellSets")] 146 - pub cell_sets: Vec<CellSet>, 147 - } 148 - 149 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 150 - pub struct CellSetGroupLinks { 151 - pub measurement: Option<Link>, 152 - } 153 - 154 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 155 - pub struct CellSetGroupEmbedded {} 156 - 157 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 158 - pub struct CellSet { 159 - pub id: String, 160 - pub cells: Vec<Cell>, 161 - #[serde(rename = "isCompleted")] 162 - pub is_completed: Option<bool>, 163 - } 164 - 165 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 166 - pub struct Cell { 167 - pub id: String, 168 - #[serde(rename = "cellType")] 169 - pub cell_type: String, 170 - pub value: Option<String>, 171 - } 172 - 173 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 174 - pub struct Instructions { 175 - pub en: String, 176 - } 177 - 178 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 179 - pub struct Media { 180 - pub url: String, 181 - #[serde(rename = "type")] 182 - pub media_type: String, 183 - #[serde(rename = "contentType")] 184 - pub content_type: String, 185 - } 186 - 187 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 188 - pub struct CellTypeConfig { 189 - #[serde(rename = "cellType")] 190 - pub cell_type: String, 191 - pub mandatory: Option<bool>, 192 - #[serde(rename = "isExponent")] 193 - pub is_exponent: Option<bool>, 194 - } 195 - 196 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 197 - pub struct MeasurementLinks { 198 - #[serde(rename = "self")] 199 - pub self_link: Link, 200 - pub tag: Option<Vec<Link>>, 201 - } 202 - 203 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 204 - pub struct Measurement { 205 - #[serde(rename = "_links")] 206 - pub links: MeasurementLinks, 207 - pub id: String, 208 - pub created: String, 209 - #[serde(rename = "lastChanged")] 210 - pub last_changed: String, 211 - pub name: Name, 212 - pub instructions: Option<Instructions>, 213 - pub media: Vec<Media>, 214 - #[serde(rename = "cellTypeConfigs")] 215 - pub cell_type_configs: Vec<CellTypeConfig>, 216 - #[serde(rename = "isGlobal")] 217 - pub is_global: bool, 218 - #[serde(rename = "measurementType")] 219 - pub measurement_type: String, 220 - } 221 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 222 - pub struct MeasurementsResponse { 223 - #[serde(rename = "_links")] 224 - pub links: Links, 225 - pub total: u32, 226 - #[serde(rename = "_embedded")] 227 - pub embedded: EmbeddedMeasurements, 228 - } 229 - 230 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 231 - pub struct Links { 232 - #[serde(rename = "self")] 233 - pub self_link: Link, 234 - pub next: Option<Link>, 235 - } 236 - 237 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 238 - pub struct Link { 239 - pub href: String, 240 - } 241 - 242 - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 243 - pub struct EmbeddedMeasurements { 244 - #[serde(rename = "measurement")] 245 - pub measurements: Vec<Measurement>, 246 - } 247 - 248 - impl MeasurementsResponse { 249 - pub fn merge(self, other: Self) -> Self { 250 - MeasurementsResponse { 251 - links: self.links, 252 - total: self.total, 253 - // Concatenate the measurement vectors. 254 - embedded: EmbeddedMeasurements { 255 - measurements: { 256 - let mut merged = self.embedded.measurements; 257 - merged.extend(other.embedded.measurements); 258 - merged 259 - }, 260 - }, 261 - } 262 - } 263 - }
+1 -1
strong-api-lib/src/lib.rs
··· 1 1 pub mod data_transformer; 2 - pub mod json_response; 2 + pub mod models; 3 3 pub mod strong_api;
+11
strong-api-lib/src/models/auth.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Debug, Deserialize)] 4 + pub struct LoginResponse { 5 + #[serde(rename = "accessToken")] 6 + pub access_token: Option<String>, 7 + #[serde(rename = "refreshToken")] 8 + pub refresh_token: Option<String>, 9 + #[serde(rename = "userId")] 10 + pub user_id: Option<String>, 11 + }
+52
strong-api-lib/src/models/common.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + 3 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 4 + pub struct Link { 5 + pub href: String, 6 + } 7 + 8 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 9 + pub struct Links { 10 + #[serde(rename = "self")] 11 + pub self_link: Link, 12 + pub next: Option<Link>, 13 + } 14 + 15 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 16 + pub struct Name { 17 + pub en: Option<String>, 18 + pub custom: Option<String>, 19 + } 20 + 21 + impl std::fmt::Display for Name { 22 + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 23 + match &self.en { 24 + Some(en) => write!(f, "{}", en), 25 + None => match &self.custom { 26 + Some(custom) => write!(f, "{}", custom), 27 + None => write!(f, "Unknown"), 28 + }, 29 + } 30 + } 31 + } 32 + 33 + impl From<Name> for String { 34 + fn from(name: Name) -> Self { 35 + match name.en { 36 + Some(en) => en, 37 + None => match name.custom { 38 + Some(custom) => custom, 39 + None => "Unknown".to_string(), 40 + }, 41 + } 42 + } 43 + } 44 + 45 + impl From<String> for Name { 46 + fn from(name: String) -> Self { 47 + Name { 48 + en: Some(name), 49 + custom: None, 50 + } 51 + } 52 + }
+16
strong-api-lib/src/models/error.rs
··· 1 + use serde::Deserialize; 2 + use std::fmt; 3 + 4 + #[derive(Debug, Deserialize)] 5 + pub struct ApiErrorResponse { 6 + pub code: String, 7 + pub description: String, 8 + } 9 + 10 + impl fmt::Display for ApiErrorResponse { 11 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 12 + write!(f, "{}: {}", self.code, self.description) 13 + } 14 + } 15 + 16 + impl std::error::Error for ApiErrorResponse {}
+83
strong-api-lib/src/models/measurement.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + 3 + use super::common::{Link, Links, Name}; 4 + 5 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 6 + pub struct MeasurementsResponse { 7 + #[serde(rename = "_links")] 8 + pub links: Links, 9 + pub total: u32, 10 + #[serde(rename = "_embedded")] 11 + pub embedded: EmbeddedMeasurements, 12 + } 13 + 14 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 15 + pub struct EmbeddedMeasurements { 16 + #[serde(rename = "measurement")] 17 + pub measurements: Vec<Measurement>, 18 + } 19 + 20 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 21 + pub struct MeasurementLinks { 22 + #[serde(rename = "self")] 23 + pub self_link: Link, 24 + pub tag: Option<Vec<Link>>, 25 + } 26 + 27 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 28 + pub struct Measurement { 29 + #[serde(rename = "_links")] 30 + pub links: MeasurementLinks, 31 + pub id: String, 32 + pub created: String, 33 + #[serde(rename = "lastChanged")] 34 + pub last_changed: String, 35 + pub name: Name, 36 + pub instructions: Option<Instructions>, 37 + pub media: Vec<Media>, 38 + #[serde(rename = "cellTypeConfigs")] 39 + pub cell_type_configs: Vec<CellTypeConfig>, 40 + #[serde(rename = "isGlobal")] 41 + pub is_global: bool, 42 + #[serde(rename = "measurementType")] 43 + pub measurement_type: String, 44 + } 45 + 46 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 47 + pub struct Instructions { 48 + pub en: String, 49 + } 50 + 51 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 52 + pub struct Media { 53 + pub url: String, 54 + #[serde(rename = "type")] 55 + pub media_type: String, 56 + #[serde(rename = "contentType")] 57 + pub content_type: String, 58 + } 59 + 60 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 61 + pub struct CellTypeConfig { 62 + #[serde(rename = "cellType")] 63 + pub cell_type: String, 64 + pub mandatory: Option<bool>, 65 + #[serde(rename = "isExponent")] 66 + pub is_exponent: Option<bool>, 67 + } 68 + 69 + impl MeasurementsResponse { 70 + pub fn merge(self, other: Self) -> Self { 71 + MeasurementsResponse { 72 + links: self.links, 73 + total: self.total, 74 + embedded: EmbeddedMeasurements { 75 + measurements: { 76 + let mut merged = self.embedded.measurements; 77 + merged.extend(other.embedded.measurements); 78 + merged 79 + }, 80 + }, 81 + } 82 + } 83 + }
+5
strong-api-lib/src/models/mod.rs
··· 1 + pub mod auth; 2 + pub mod common; 3 + pub mod error; 4 + pub mod measurement; 5 + pub mod workout;
+109
strong-api-lib/src/models/workout.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + use serde_json::Value; 3 + 4 + use super::common::{Link, Name}; 5 + 6 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 7 + pub struct UserResponse { 8 + #[serde(rename = "_links")] 9 + pub links: Value, 10 + #[serde(rename = "_embedded")] 11 + pub embedded: Embedded, 12 + pub id: String, 13 + pub created: String, 14 + #[serde(rename = "lastChanged")] 15 + pub last_changed: String, 16 + pub username: String, 17 + pub email: String, 18 + #[serde(rename = "emailVerified")] 19 + pub email_verified: bool, 20 + pub name: Option<String>, 21 + pub avatar: Value, 22 + pub preferences: Value, 23 + #[serde(rename = "legacyPurchase")] 24 + pub legacy_purchase: Value, 25 + #[serde(rename = "legacyGoals")] 26 + pub legacy_goals: Value, 27 + #[serde(rename = "startHistoryFromDate")] 28 + pub start_history_from_date: String, 29 + #[serde(rename = "firstWeekDay")] 30 + pub first_week_day: String, 31 + #[serde(rename = "availableLogins")] 32 + pub available_logins: Vec<Value>, 33 + pub migrated: String, 34 + } 35 + 36 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 37 + pub struct Embedded { 38 + pub measurement: Option<Vec<Value>>, 39 + #[serde(rename = "measuredValue")] 40 + pub measured_value: Option<Vec<Value>>, 41 + pub template: Option<Vec<Value>>, 42 + pub log: Option<Vec<Log>>, 43 + pub tag: Option<Vec<Value>>, 44 + pub folder: Option<Vec<Value>>, 45 + pub widget: Option<Vec<Value>>, 46 + } 47 + 48 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 49 + pub struct Log { 50 + #[serde(rename = "_links")] 51 + pub links: Value, 52 + #[serde(rename = "_embedded")] 53 + pub embedded: LogEmbedded, 54 + #[serde(rename = "timezoneId")] 55 + pub timezone_id: Option<String>, 56 + pub id: String, 57 + pub created: String, 58 + #[serde(rename = "lastChanged")] 59 + pub last_changed: String, 60 + pub name: Option<Name>, 61 + pub access: String, 62 + #[serde(rename = "startDate")] 63 + pub start_date: Option<String>, 64 + #[serde(rename = "endDate")] 65 + pub end_date: Option<String>, 66 + #[serde(rename = "logType")] 67 + pub log_type: String, 68 + } 69 + 70 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 71 + pub struct LogEmbedded { 72 + #[serde(rename = "cellSetGroup")] 73 + pub cell_set_group: Vec<CellSetGroup>, 74 + } 75 + 76 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 77 + pub struct CellSetGroup { 78 + #[serde(rename = "_links")] 79 + pub links: CellSetGroupLinks, 80 + #[serde(rename = "_embedded")] 81 + pub embedded: CellSetGroupEmbedded, 82 + pub id: String, 83 + #[serde(rename = "cellSets")] 84 + pub cell_sets: Vec<CellSet>, 85 + } 86 + 87 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 88 + pub struct CellSetGroupLinks { 89 + pub measurement: Option<Link>, 90 + } 91 + 92 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 93 + pub struct CellSetGroupEmbedded {} 94 + 95 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 96 + pub struct CellSet { 97 + pub id: String, 98 + pub cells: Vec<Cell>, 99 + #[serde(rename = "isCompleted")] 100 + pub is_completed: Option<bool>, 101 + } 102 + 103 + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 104 + pub struct Cell { 105 + pub id: String, 106 + #[serde(rename = "cellType")] 107 + pub cell_type: String, 108 + pub value: Option<String>, 109 + }
+4 -2
strong-api-lib/src/strong_api.rs
··· 1 - use crate::json_response::UserResponse; 2 - use crate::json_response::{ApiErrorResponse, LoginResponse, MeasurementsResponse}; 1 + use crate::models::auth::LoginResponse; 2 + use crate::models::error::ApiErrorResponse; 3 + use crate::models::measurement::MeasurementsResponse; 4 + use crate::models::workout::UserResponse; 3 5 use reqwest::{ 4 6 Client, Url, 5 7 header::{HeaderMap, HeaderName, HeaderValue},