├── .github └── workflows │ ├── ai-responder.yml │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── api ├── create-workout.md ├── delete-session.md ├── delete-workout.md ├── get-exercises.md ├── get-total-workouts.md ├── get-workout-history.md ├── get-workout.md ├── log-session.md ├── login.md ├── parsewidget.md ├── update-user.md └── update-workout.md ├── go └── strong.go ├── img └── sample.png ├── java └── strong.java ├── javascript └── strong.js ├── perl └── strong.pl ├── php └── strong.php ├── python └── strong.py ├── sample ├── 1.login.py ├── 2.workout-history.py ├── 3.create-charts.py ├── 4.create-stats.py ├── 5.chart.html ├── README.md ├── graphs │ ├── Bench Press (Barbell)-reps.png │ ├── Bench Press (Barbell)-volume.png │ ├── Bench Press (Barbell)-weight.png │ ├── Bench Press (Dumbbell)-reps.png │ ├── Bench Press (Dumbbell)-volume.png │ ├── Bench Press (Dumbbell)-weight.png │ ├── Bent Over One Arm Row (Dumbbell)-reps.png │ ├── Bent Over One Arm Row (Dumbbell)-volume.png │ ├── Bent Over One Arm Row (Dumbbell)-weight.png │ ├── Bent Over Row (Barbell)-reps.png │ ├── Bent Over Row (Barbell)-volume.png │ ├── Bent Over Row (Barbell)-weight.png │ ├── Bicep Curl (Barbell)-reps.png │ ├── Bicep Curl (Barbell)-volume.png │ ├── Bicep Curl (Barbell)-weight.png │ ├── Bicep Curl (Dumbbell)-reps.png │ ├── Bicep Curl (Dumbbell)-volume.png │ ├── Bicep Curl (Dumbbell)-weight.png │ ├── Cable Twist-reps.png │ ├── Cable Twist-volume.png │ ├── Cable Twist-weight.png │ ├── Chest Fly (Dumbbell)-reps.png │ ├── Chest Fly (Dumbbell)-volume.png │ ├── Chest Fly (Dumbbell)-weight.png │ ├── Chest Fly-reps.png │ ├── Chest Fly-volume.png │ ├── Chest Fly-weight.png │ ├── Decline Crunch-reps.png │ ├── Decline Crunch-volume.png │ ├── Decline Crunch-weight.png │ ├── Face Pull (Cable)-reps.png │ ├── Face Pull (Cable)-volume.png │ ├── Face Pull (Cable)-weight.png │ ├── Front Raise (Cable)-reps.png │ ├── Front Raise (Cable)-volume.png │ ├── Front Raise (Cable)-weight.png │ ├── Front Raise (Dumbbell)-reps.png │ ├── Front Raise (Dumbbell)-volume.png │ ├── Front Raise (Dumbbell)-weight.png │ ├── Hack Squat-reps.png │ ├── Hack Squat-volume.png │ ├── Hack Squat-weight.png │ ├── Hammer Curl (Cable)-reps.png │ ├── Hammer Curl (Cable)-volume.png │ ├── Hammer Curl (Cable)-weight.png │ ├── Hip Abductor (Machine)-reps.png │ ├── Hip Abductor (Machine)-volume.png │ ├── Hip Abductor (Machine)-weight.png │ ├── Hip Thrust (Barbell)-reps.png │ ├── Hip Thrust (Barbell)-volume.png │ ├── Hip Thrust (Barbell)-weight.png │ ├── Incline Row (Dumbbell)-reps.png │ ├── Incline Row (Dumbbell)-volume.png │ ├── Incline Row (Dumbbell)-weight.png │ ├── Kettlebell Swing-reps.png │ ├── Kettlebell Swing-volume.png │ ├── Kettlebell Swing-weight.png │ ├── Lat Pulldown (Cable)-reps.png │ ├── Lat Pulldown (Cable)-volume.png │ ├── Lat Pulldown (Cable)-weight.png │ ├── Lateral Raise (Cable)-reps.png │ ├── Lateral Raise (Cable)-volume.png │ ├── Lateral Raise (Cable)-weight.png │ ├── Lateral Raise (Dumbbell)-reps.png │ ├── Lateral Raise (Dumbbell)-volume.png │ ├── Lateral Raise (Dumbbell)-weight.png │ ├── Leg Extension (Machine)-reps.png │ ├── Leg Extension (Machine)-volume.png │ ├── Leg Extension (Machine)-weight.png │ ├── Leg Press-reps.png │ ├── Leg Press-volume.png │ ├── Leg Press-weight.png │ ├── Lunge (Dumbbell)-reps.png │ ├── Lunge (Dumbbell)-volume.png │ ├── Lunge (Dumbbell)-weight.png │ ├── Overhead Press (Barbell)-reps.png │ ├── Overhead Press (Barbell)-volume.png │ ├── Overhead Press (Barbell)-weight.png │ ├── Overhead Press (Dumbbell)-reps.png │ ├── Overhead Press (Dumbbell)-volume.png │ ├── Overhead Press (Dumbbell)-weight.png │ ├── Pec Deck (Machine)-reps.png │ ├── Pec Deck (Machine)-volume.png │ ├── Pec Deck (Machine)-weight.png │ ├── Pullover (Dumbbell)-reps.png │ ├── Pullover (Dumbbell)-volume.png │ ├── Pullover (Dumbbell)-weight.png │ ├── Seated Calf Raise (Plate Loaded)-reps.png │ ├── Seated Calf Raise (Plate Loaded)-volume.png │ ├── Seated Calf Raise (Plate Loaded)-weight.png │ ├── Seated Leg Curl (Machine)-reps.png │ ├── Seated Leg Curl (Machine)-volume.png │ ├── Seated Leg Curl (Machine)-weight.png │ ├── Seated Leg Press (Machine)-reps.png │ ├── Seated Leg Press (Machine)-volume.png │ ├── Seated Leg Press (Machine)-weight.png │ ├── Seated Row (Cable)-reps.png │ ├── Seated Row (Cable)-volume.png │ ├── Seated Row (Cable)-weight.png │ ├── Standing Calf Raise (Machine)-reps.png │ ├── Standing Calf Raise (Machine)-volume.png │ ├── Standing Calf Raise (Machine)-weight.png │ ├── Triceps Extension (Barbell)-reps.png │ ├── Triceps Extension (Barbell)-volume.png │ ├── Triceps Extension (Barbell)-weight.png │ ├── Triceps Extension (Cable)-reps.png │ ├── Triceps Extension (Cable)-volume.png │ └── Triceps Extension (Cable)-weight.png ├── stats.json └── workouts.json └── version /.github/workflows/ai-responder.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: AI Issue Responder 3 | 4 | on: 5 | issues: 6 | types: [opened] 7 | 8 | permissions: 9 | issues: write 10 | 11 | jobs: 12 | ai-respond: 13 | if: github.actor != 'dependabot[bot]' 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Download AI responder script 18 | run: | 19 | curl -sSL "https://raw.githubusercontent.com/dmzoneill/dmzoneill/main/ai-responder.py" -o ai-responder.py 20 | chmod +x ai-responder.py 21 | 22 | - name: Run AI responder 23 | env: 24 | OPENAI_API_KEY: ${{ secrets.AI_API_KEY }} 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | GITHUB_REPOSITORY: ${{ github.repository }} 27 | ISSUE_NUMBER: ${{ github.event.issue.number }} 28 | ISSUE_REPO_URL: "https://github.com/${{ github.repository }}" 29 | run: ./ai-responder.py 30 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CICD 3 | 4 | on: 5 | push: 6 | branches: [ "main" ] 7 | pull_request: 8 | branches: [ "main" ] 9 | 10 | permissions: write-all 11 | 12 | jobs: 13 | cicd: 14 | secrets: inherit 15 | uses: dmzoneill/dmzoneill/.github/workflows/dispatch.yaml@main 16 | with: 17 | basic: "true" 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sample/exports.sh 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # strong-api 2 | 3 | I'm not currently developing this any more. I leave this here for reference purposes only. 4 | This should not be used unless you plan on getting your account terminated or other possible consequences. 5 | Unlawful use of an API could be determined illegal depending on your durisdiction, like unlawful entery into a house with an open door. 6 | 7 | Since strong don't want me making this public, I've decided to move on to a competitor app and accept the termination. 8 | I've cancelled my subscription with strong and I've switched to using hevy. 9 | I'm no longer using the strong service and only used this for a short period of time. 10 | At the time of writing the API, there was no expressed defintion of access to their API or otherwise, in their terms of service. 11 | As per my email below to Cameron. 12 | 13 | Since i've switched to using Hevy, i may do some work over there. 14 | [https://github.com/dmzoneill/hevyapp-api](https://github.com/dmzoneill/hevyapp-api) 15 | 16 | Adios! 17 | 18 | ![Bench press](https://github.com/dmzoneill/strongapp-api/blob/main/img/sample.png?raw=true) 19 | 20 | ## Samples 21 | 22 | - [Samples](https://github.com/dmzoneill/strongapp-api/tree/main/sample) 23 | - [Python pyplot example](https://dmzoneill.github.io/strongapp-api/sample/chart.html) 24 | - [Chart js example](https://dmzoneill.github.io/strongapp-api/sample/5.chart.html) 25 | 26 | ## Overviews 27 | 28 | - [create-workout.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/create-workout.md) 29 | - [delete-workout.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/delete-workout.md) 30 | - [get-total-workouts.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/get-total-workouts.md) 31 | - [get-workout.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/get-workout.md) 32 | - [login.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/login.md) 33 | - [parsewidget.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/parsewidget.md) 34 | - [update-workout.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/update-workout.md) 35 | - [delete-session.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/delete-session.md) 36 | - [get-exercises.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/get-exercises.md) 37 | - [get-workout-history.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/get-workout-history.md) 38 | - [log-session.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/log-session.md) 39 | - [update-user.md](https://github.com/dmzoneill/strongapp-api/blob/main/api/update-user.md) 40 | 41 | ## How to dissect https calls for yourself 42 | 43 | ### Download 44 | 45 | - Android studio 46 | - [Charles proxy](https://www.charlesproxy.com/) 47 | - [apk-mitm](https://www.npmjs.com/package/apk-mitm/) 48 | - [io.strongapp.strong apk](https://m.apkpure.com/strong-workout-tracker-gym-log/io.strongapp.strong) 49 | 50 | ### Setup 51 | 52 | 1. Open android studio 53 | 2. Create an android virtual device 54 | 3. Boot the device 55 | 4. Download the strong app apk 56 | 5. Download apk-mitm 57 | 6. Patch the apk as described on [apk-mitm](https://www.npmjs.com/package/apk-mitm/) 58 | 7. Install charles proxy 59 | 8. Install the certificate and setup the proxy on the android device as described here: 60 | https://blog.logrocket.com/test-debug-android-apps-with-charles-web-proxy/ 61 | 9. Using androind studio upload the patched APK to the android device and then install it 62 | 10. open strong app and login 63 | 64 | Strong should use the proxy with the previously installed certificate and in charles you can now see the decrypted https requests. 65 | 66 | ## Strong conversation 67 | ![image](https://user-images.githubusercontent.com/15192260/223532596-83b5856b-a620-41e5-aa61-ed257e9ab939.png) 68 | -------------------------------------------------------------------------------- /api/create-workout.md: -------------------------------------------------------------------------------- 1 | ## Create workout 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cxxxxxxxxe0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNxxxxxxxxT0XtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'bodyWeightKilograms': 0, 23 | 'notes': '', 24 | 'build': 'a257', 25 | 'name': 'Delete this', 26 | 'isGlobal': False, 27 | 'parseSetGroups': [ 28 | { 29 | '__type': 'Pointer', 30 | 'className': 'ParseSetGroup', 31 | 'objectId': '1zZDNFzDnD', 32 | }, 33 | { 34 | '__type': 'Pointer', 35 | 'className': 'ParseSetGroup', 36 | 'objectId': 'Rg0QpEiinw', 37 | }, 38 | ], 39 | 'parseRoutine': { 40 | '__type': 'Pointer', 41 | 'className': 'ParseRoutine', 42 | 'objectId': '9OqRnExHuJ', 43 | }, 44 | 'user': { 45 | '__type': 'Pointer', 46 | 'className': '_User', 47 | 'objectId': 'XXXXXXXX', 48 | }, 49 | 'uniqueId': '9d7f1579-a591-46b8-be65-58c1daa76fdd', 50 | 'isHidden': 0, 51 | } 52 | 53 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseWorkout', headers=headers, json=json_data) 54 | 55 | ``` 56 | 57 | ### Reponse 58 | ``` 59 | { 60 | "objectId": "MjzqRbuLH5", 61 | "createdAt": "2023-02-27T17:26:20.536Z" 62 | } 63 | ``` -------------------------------------------------------------------------------- /api/delete-session.md: -------------------------------------------------------------------------------- 1 | ## Delete session 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2ce3xxxxxxxxxxxxxxx0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1xxxxxxxxxxxxxvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'requests': [ 23 | { 24 | 'method': 'PUT', 25 | 'path': '/parse/classes/ParseWorkout/tRIg9CdQ3B', 26 | 'body': { 27 | 'notes': '', 28 | 'isHidden': 1, 29 | 'bodyWeightKilograms': 0, 30 | 'build': 'a257', 31 | 'parseOriginRoutine': { 32 | '__type': 'Pointer', 33 | 'className': 'ParseRoutine', 34 | 'objectId': 'd7wTyA1uX0', 35 | }, 36 | 'name': '5. Hamstrings/Glutes', 37 | 'isGlobal': False, 38 | 'parseSetGroups': [ 39 | { 40 | '__type': 'Pointer', 41 | 'className': 'ParseSetGroup', 42 | 'objectId': 'wYW4GH5uUG', 43 | }, 44 | ], 45 | 'timezoneId': 'Europe/Dublin', 46 | 'completionDate': { 47 | '__type': 'Date', 48 | 'iso': '2023-02-27T17:54:03.409Z', 49 | }, 50 | 'user': { 51 | '__type': 'Pointer', 52 | 'className': '_User', 53 | 'objectId': 'XXXXXXXX', 54 | }, 55 | 'uniqueId': '022fca24-9fde-4a00-8ee7-7fff510cc5ad', 56 | 'startDate': { 57 | '__type': 'Date', 58 | 'iso': '2023-02-27T17:51:08.931Z', 59 | }, 60 | 'objectId': 'tRIg9CdQ3B', 61 | }, 62 | }, 63 | ....... 64 | ], 65 | } 66 | 67 | response = requests.post('https://ws13.strongapp.co/parse/batch', headers=headers, json=json_data) 68 | ``` 69 | 70 | ### response 71 | ``` 72 | { 73 | "updatedAt": "2023-02-26T22:16:53.074Z" 74 | } 75 | ``` 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /api/delete-workout.md: -------------------------------------------------------------------------------- 1 | ## Delete workout 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cxxxxxxxxxxxxe0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1xxxxxxxxxxxtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'requests': [ 23 | { 24 | 'method': 'PUT', 25 | 'path': '/parse/classes/ParseWorkout/MjzqRbuLH5', 26 | 'body': { 27 | 'bodyWeightKilograms': 0, 28 | 'notes': '', 29 | 'build': 'a257', 30 | 'name': 'Delete this', 31 | 'isGlobal': False, 32 | 'parseSetGroups': [ 33 | { 34 | '__type': 'Pointer', 35 | 'className': 'ParseSetGroup', 36 | 'objectId': '1zZDNFzDnD', 37 | }, 38 | { 39 | '__type': 'Pointer', 40 | 'className': 'ParseSetGroup', 41 | 'objectId': 'Rg0QpEiinw', 42 | }, 43 | ], 44 | 'parseRoutine': { 45 | '__type': 'Pointer', 46 | 'className': 'ParseRoutine', 47 | 'objectId': '9OqRnExHuJ', 48 | }, 49 | 'user': { 50 | '__type': 'Pointer', 51 | 'className': '_User', 52 | 'objectId': 'XXXXXXXX', 53 | }, 54 | 'uniqueId': '9d7f1579-a591-46b8-be65-58c1daa76fdd', 55 | 'isHidden': 1, 56 | 'objectId': 'MjzqRbuLH5', 57 | }, 58 | }, 59 | ... 60 | ... 61 | ], 62 | } 63 | 64 | response = requests.post('https://ws13.strongapp.co/parse/batch', headers=headers, json=json_data) 65 | 66 | ``` 67 | 68 | ### Reponse 69 | ``` 70 | [{ 71 | "success": { 72 | "updatedAt": "2023-02-27T17:33:59.580Z" 73 | } 74 | } 75 | ... 76 | .. 77 | ] 78 | ``` -------------------------------------------------------------------------------- /api/get-exercises.md: -------------------------------------------------------------------------------- 1 | ## Get exercises 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cexxxxxx465e0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNxxxxxxxrPT0XtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | data = '{"limit":"1000","where":"{\\isGlobal\\:true,\\user\\:{\\$exists\\:false}}","_method":"GET"}' 22 | 23 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseExercise', headers=headers, data=data) 24 | ``` 25 | 26 | ### response 27 | ``` 28 | { 29 | "results": [{ 30 | "name": "Side Bend (Band)", 31 | "createdAt": "2018-05-02T08:34:36.034Z", 32 | "updatedAt": "2018-06-20T06:29:28.172Z", 33 | "exerciseType": 5, 34 | "bodyParts": 1, 35 | "uniqueId": "3b8b97d5-57eb-427c-85b1-4e9222593a97", 36 | "instructions": "Secure band to an elevated object so that it is taunt at shoulder level and hold the handle in the left hand.||Bend the torso and contract the obliques while exhaling.||Return slowly to the starting position while inhaling.||Repeat for reps.", 37 | "isGlobal": true, 38 | "ACL": { 39 | "*": { 40 | "read": true 41 | } 42 | }, 43 | "objectId": "1vZhW35Igd" 44 | }, { 45 | "name": "Toes To Bar", 46 | "createdAt": "2018-04-27T09:35:34.207Z", 47 | "updatedAt": "2018-10-15T06:17:06.884Z", 48 | "exerciseType": 5, 49 | "bodyParts": 1, 50 | "uniqueId": "e0b1aa09-f4c5-4ead-95de-03a2f7530c87", 51 | "isHidden": false, 52 | "instructions": "NOTE: You can perform this with your knees bent or your legs straight, but use the latter for better core activation.||Grasp the pull up bar with a shoulder-width grip. You can perform this movement with your palms facing away from you or towards you. This is your starting position.||From the hanging position, bring both of your feet up so your toes make contact with the bar.||Lower yourself down to the starting position.||Repeat for reps.", 53 | "isGlobal": true, 54 | "ACL": { 55 | "*": { 56 | "read": true 57 | } 58 | }, 59 | "objectId": "ZVwtvLdWzZ" 60 | }, 61 | ....... 62 | ] 63 | } 64 | ``` -------------------------------------------------------------------------------- /api/get-total-workouts.md: -------------------------------------------------------------------------------- 1 | ## Get total workouts 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cxxxxxxxef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNxxxxxxT0XtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-xxxxx-4df5-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | data = '{"include":"parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise","limit":"0","count":"1","where":"{\\user\\:{\\__type\\:\\Pointer\\,\\className\\:\\_User\\,\\objectId\\:\\XXXXXXXX\\},\\updatedAt\\:{\\$gt\\:{\\__type\\:\\Date\\,\\iso\\:\\1970-01-01T00:00:00.000Z\\}}}","_method":"GET"}' 22 | 23 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseWorkout', headers=headers, data=data) 24 | ``` 25 | 26 | ### Reponse 27 | ``` 28 | { 29 | "results": [], 30 | "count": 183 31 | } 32 | ``` -------------------------------------------------------------------------------- /api/get-workout-history.md: -------------------------------------------------------------------------------- 1 | 2 | ## Parse workouts 3 | 4 | ### request 5 | ``` 6 | import requests 7 | 8 | headers = { 9 | 'Host': 'ws13.strongapp.co', 10 | 'x-parse-session-token': 'r:8fc69c9a2ce38xxxxxx0adef26d6f27', 11 | 'x-parse-application-id': 'QbtVgYzi9iU1GNxxxxxT0XtvRKMajvuYLLmTW', 12 | 'x-parse-app-build-version': '257', 13 | 'x-parse-app-display-version': '2.7.9', 14 | 'x-parse-os-version': '13', 15 | 'user-agent': 'Parse Android SDK API Level 33', 16 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 17 | 'content-type': 'application/json', 18 | 'pragma': 'no-cache', 19 | 'cache-control': 'no-cache', 20 | } 21 | 22 | data = '{"include":"parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise","limit":"200","where":"{\\user\\:{\\__type\\:\\Pointer\\,\\className\\:\\_User\\,\\objectId\\:\\NMmxxxxFZG\\},\\updatedAt\\:{\\$gt\\:{\\__type\\:\\Date\\,\\iso\\:\\1970-01-01T00:00:00.000Z\\}}}","_method":"GET"}' 23 | 24 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseWorkout', headers=headers, data=data) 25 | ``` 26 | ### response 27 | ``` 28 | { 29 | "results": [{ 30 | "parseSetGroups": [{ 31 | "parseSetsDictionary": [{ 32 | "isPersonalRecord": false, 33 | "reps": 8, 34 | "tagsValue": 0, 35 | "exerciseTypeValue": 3, 36 | "isChecked": false 37 | }, { 38 | "isPersonalRecord": false, 39 | "reps": 8, 40 | "tagsValue": 0, 41 | "exerciseTypeValue": 3, 42 | "isChecked": true 43 | }, { 44 | "isPersonalRecord": false, 45 | "reps": 8, 46 | "tagsValue": 0, 47 | "exerciseTypeValue": 3, 48 | "isChecked": true 49 | }, { 50 | "isPersonalRecord": false, 51 | "reps": 8, 52 | "tagsValue": 0, 53 | "exerciseTypeValue": 3, 54 | "isChecked": true 55 | }, { 56 | "isPersonalRecord": false, 57 | "reps": 8, 58 | "tagsValue": 0, 59 | "exerciseTypeValue": 3, 60 | "isChecked": true 61 | }], 62 | "superSetOrder": null, 63 | "notes": "", 64 | "build": "a252", 65 | "parseExercise": { 66 | "createdAt": "2016-02-19T05:42:34.996Z", 67 | "updatedAt": "2017-12-15T07:31:15.989Z", 68 | "name": "Squat (Bodyweight)", 69 | "exerciseType": 3, 70 | "isGlobal": true, 71 | "bodyParts": 16, 72 | "uniqueId": "752349B3-8813-48D2-B315-6EF4D9B4F3CB", 73 | "instructions": "Standing with feed shoulder width apart, sit back with the hips while flexing hips and keeping knees pointed slightly outward.||Continue down to the bottom position, while making sure you are maintaining a straight back and keeping weight evenly distributed throughout the foot.||Exhale as you push upward from the bottom position, pushing the knees outward.||Repeat for reps.", 74 | "ACL": { 75 | "*": { 76 | "read": true 77 | } 78 | }, 79 | "objectId": "bsnljXHBgr", 80 | "__type": "Object", 81 | "className": "ParseExercise" 82 | }, 83 | "user": { 84 | "__type": "Pointer", 85 | "className": "_User", 86 | "objectId": "XXXXXXXX" 87 | }, 88 | "uniqueId": "c59b450d-2b52-450a-88e3-730eebad5172", 89 | "isHidden": 0, 90 | "createdAt": "2022-03-18T18:32:37.810Z", 91 | "updatedAt": "2022-03-18T18:32:37.810Z", 92 | "objectId": "MWanG144U7", 93 | "__type": "Object", 94 | "className": "ParseSetGroup" 95 | }, { 96 | "parseSetsDictionary": [{ 97 | "isPersonalRecord": false, 98 | "reps": 8, 99 | "tagsValue": 0, 100 | "exerciseTypeValue": 3, 101 | "isChecked": false 102 | }, { 103 | "isPersonalRecord": false, 104 | "reps": 8, 105 | "tagsValue": 0, 106 | "exerciseTypeValue": 3, 107 | "isChecked": true 108 | }, { 109 | "isPersonalRecord": false, 110 | "reps": 8, 111 | "tagsValue": 0, 112 | "exerciseTypeValue": 3, 113 | "isChecked": true 114 | }, { 115 | "isPersonalRecord": false, 116 | "reps": 8, 117 | "tagsValue": 0, 118 | "exerciseTypeValue": 3, 119 | "isChecked": true 120 | }, { 121 | "isPersonalRecord": false, 122 | "reps": 8, 123 | "tagsValue": 0, 124 | "exerciseTypeValue": 3, 125 | "isChecked": true 126 | }], 127 | "superSetOrder": null, 128 | "notes": "", 129 | "build": "a252", 130 | "parseExercise": { 131 | "createdAt": "2016-02-19T05:42:34.977Z", 132 | "updatedAt": "2017-12-15T07:28:18.457Z", 133 | "name": "Push Up", 134 | "exerciseType": 3, 135 | "isGlobal": true, 136 | "isPopular": true, 137 | "bodyParts": 8, 138 | "uniqueId": "F0F86563-85FC-49A8-9EC7-F95DDD318AB4", 139 | "instructions": "Lie prone on floor with hands slightly wider than shoulder width.||Raise body up off floor by extending arms with body straight.||Keeping body straight, lower body to floor by bending arms. Push body up until arms are extended.||Repeat for reps.", 140 | "ACL": { 141 | "*": { 142 | "read": true 143 | } 144 | }, 145 | "objectId": "LDa0I05c38", 146 | "__type": "Object", 147 | "className": "ParseExercise" 148 | }, 149 | "user": { 150 | "__type": "Pointer", 151 | "className": "_User", 152 | "objectId": "XXXXXXXX" 153 | }, 154 | "uniqueId": "918bde2a-c1cc-48c7-b596-d79191260a8c", 155 | "isHidden": 0, 156 | "createdAt": "2022-03-18T18:32:37.810Z", 157 | "updatedAt": "2022-03-18T18:32:37.810Z", 158 | "objectId": "nfx0ENb3wI", 159 | "__type": "Object", 160 | "className": "ParseSetGroup" 161 | }, { 162 | "parseSetGroups": [{ 163 | "parseSetsDictionary": [{ 164 | "isPersonalRecord": false, 165 | "seconds": 15, 166 | "tagsValue": 0, 167 | "rpe": 0, 168 | "exerciseTypeValue": 6, 169 | "isChecked": true 170 | }], 171 | "completionDate": { 172 | "__type": "Date", 173 | "iso": "2023-02-26T11:25:40.845Z" 174 | }, 175 | "startDate": { 176 | "__type": "Date", 177 | "iso": "2023-02-26T09:13:02.080Z" 178 | }, 179 | "superSetOrder": null, 180 | "notes": "", 181 | "build": "a257", 182 | "parseExercise": { 183 | "name": "Elliptical Machine", 184 | "createdAt": "2018-04-27T07:05:25.460Z", 185 | "updatedAt": "2018-09-27T09:12:52.100Z", 186 | "uniqueId": "4464e3b1-c412-4047-a5b9-8cdb7c8fe7b3", 187 | "exerciseType": 6, 188 | "bodyParts": 512, 189 | "isHidden": false, 190 | "isGlobal": true, 191 | "ACL": { 192 | "*": { 193 | "read": true 194 | } 195 | }, 196 | "objectId": "SuGuVl8OYz", 197 | "__type": "Object", 198 | "className": "ParseExercise" 199 | }, 200 | "user": { 201 | "__type": "Pointer", 202 | "className": "_User", 203 | "objectId": "XXXXXXXX" 204 | }, 205 | "uniqueId": "63fe9351-e0ea-454b-921b-bc434e5d5b0c", 206 | "isHidden": 0, 207 | "createdAt": "2023-02-26T16:22:45.809Z", 208 | "updatedAt": "2023-02-26T16:22:45.809Z", 209 | "objectId": "EYPmI4MO2H", 210 | "__type": "Object", 211 | "className": "ParseSetGroup" 212 | }, { 213 | "parseSetsDictionary": [{ 214 | "isPersonalRecord": false, 215 | "reps": 8, 216 | "tagsValue": 0, 217 | "rpe": 0, 218 | "exerciseTypeValue": 2, 219 | "kilograms": 59, 220 | "isChecked": true, 221 | "expectedKilograms": 64 222 | }, { 223 | "isPersonalRecord": false, 224 | "reps": 8, 225 | "tagsValue": 0, 226 | "rpe": 0, 227 | "exerciseTypeValue": 2, 228 | "kilograms": 59, 229 | "isChecked": true, 230 | "expectedKilograms": 64 231 | }, { 232 | "isPersonalRecord": false, 233 | "reps": 8, 234 | "tagsValue": 0, 235 | "rpe": 0, 236 | "exerciseTypeValue": 2, 237 | "kilograms": 91, 238 | "isChecked": true, 239 | "expectedKilograms": 59 240 | }, { 241 | "isPersonalRecord": false, 242 | "reps": 8, 243 | "tagsValue": 0, 244 | "rpe": 0, 245 | "exerciseTypeValue": 2, 246 | "kilograms": 91, 247 | "isChecked": true, 248 | "expectedKilograms": 59 249 | }, { 250 | "isPersonalRecord": false, 251 | "reps": 8, 252 | "tagsValue": 0, 253 | "rpe": 0, 254 | "exerciseTypeValue": 2, 255 | "kilograms": 91, 256 | "isChecked": true, 257 | "expectedKilograms": 54 258 | }, { 259 | "isPersonalRecord": false, 260 | "reps": 8, 261 | "tagsValue": 0, 262 | "rpe": 0, 263 | "exerciseTypeValue": 2, 264 | "kilograms": 91, 265 | "isChecked": true, 266 | "expectedKilograms": 54 267 | }], 268 | "completionDate": { 269 | "__type": "Date", 270 | "iso": "2023-02-26T11:25:40.845Z" 271 | }, 272 | "startDate": { 273 | "__type": "Date", 274 | "iso": "2023-02-26T09:13:02.080Z" 275 | }, 276 | "superSetOrder": null, 277 | "notes": "", 278 | "build": "a257", 279 | "parseExercise": { 280 | "createdAt": "2016-02-19T05:42:34.882Z", 281 | "updatedAt": "2018-09-21T09:45:38.674Z", 282 | "name": "Seated Row (Cable)", 283 | "exerciseType": 2, 284 | "isGlobal": true, 285 | "bodyParts": 4, 286 | "uniqueId": "143F848F-3A01-40BD-88D1-613C3A88309E", 287 | "instructions": "Grip the handle attachment with both hands and sit with chest upright and back straight.||With shoulders retracted, pull the handle towards the mid torso.||Squeeze the back muscles as the handle approaches the torso and hold before returning to the starting position.||Repeat for reps.", 288 | "ACL": { 289 | "*": { 290 | "read": true 291 | } 292 | }, 293 | "objectId": "hnhGpeIPU5", 294 | "__type": "Object", 295 | "className": "ParseExercise" 296 | }, 297 | "user": { 298 | "__type": "Pointer", 299 | "className": "_User", 300 | "objectId": "XXXXXXXX" 301 | }, 302 | "uniqueId": "c430fce5-0d11-4c5b-9bf4-816bae6f4faa", 303 | "isHidden": 0, 304 | "createdAt": "2023-02-26T16:22:45.809Z", 305 | "updatedAt": "2023-02-26T16:22:45.809Z", 306 | "objectId": "z0dCeeaGiw", 307 | "__type": "Object", 308 | "className": "ParseSetGroup" 309 | }, { 310 | "parseSetsDictionary": [{ 311 | "isPersonalRecord": false, 312 | "reps": 8, 313 | "tagsValue": 0, 314 | "rpe": 0, 315 | "exerciseTypeValue": 1, 316 | "kilograms": 20, 317 | "isChecked": true, 318 | "expectedKilograms": 20 319 | }, { 320 | "isPersonalRecord": false, 321 | "reps": 4, 322 | "tagsValue": 0, 323 | "rpe": 0, 324 | "exerciseTypeValue": 1, 325 | "kilograms": 35, 326 | "isChecked": true, 327 | "expectedKilograms": 37.5 328 | }, { 329 | "isPersonalRecord": false, 330 | "reps": 8, 331 | "tagsValue": 0, 332 | "rpe": 0, 333 | "personalRecords": "MAX_VOLUME", 334 | "exerciseTypeValue": 1, 335 | "kilograms": 35, 336 | "isChecked": true, 337 | "expectedKilograms": 35 338 | }, { 339 | "isPersonalRecord": false, 340 | "reps": 8, 341 | "tagsValue": 0, 342 | "rpe": 0, 343 | "exerciseTypeValue": 1, 344 | "kilograms": 35, 345 | "isChecked": true, 346 | "expectedKilograms": 32.5 347 | }, { 348 | "isPersonalRecord": false, 349 | "reps": 8, 350 | "tagsValue": 0, 351 | "rpe": 0, 352 | "exerciseTypeValue": 1, 353 | "kilograms": 32.5, 354 | "isChecked": true, 355 | "expectedKilograms": 30 356 | }, { 357 | "isPersonalRecord": false, 358 | "reps": 4, 359 | "tagsValue": 0, 360 | "rpe": 0, 361 | "exerciseTypeValue": 1, 362 | "kilograms": 32.5, 363 | "isChecked": true, 364 | "expectedKilograms": 30 365 | }], 366 | "completionDate": { 367 | "__type": "Date", 368 | "iso": "2023-02-26T11:25:40.845Z" 369 | }, 370 | "startDate": { 371 | "__type": "Date", 372 | "iso": "2023-02-26T09:13:02.080Z" 373 | }, 374 | "superSetOrder": null, 375 | "notes": "", 376 | "build": "a257", 377 | "parseExercise": { 378 | "name": "Pullover (Dumbbell)", 379 | "createdAt": "2018-01-22T05:37:53.811Z", 380 | "updatedAt": "2018-09-20T08:27:09.667Z", 381 | "uniqueId": "1a9537c6-f56a-4d4e-a491-c5c172cfa5ed", 382 | "exerciseType": 1, 383 | "bodyParts": 8, 384 | "instructions": "Placing the upper back against the bench with a dumbbell placed on the chest.||Grasp the dumbbell with both hands pressing against one end and hold straight over the chest.||Lower the dumbbell in an arc above the head until you feel a stretch in the chest muscles.||Return to starting position while breathing out.||Repeat for reps.", 385 | "isHidden": false, 386 | "isGlobal": true, 387 | "ACL": { 388 | "*": { 389 | "read": true 390 | } 391 | }, 392 | "objectId": "CnG27VmK9U", 393 | "__type": "Object", 394 | "className": "ParseExercise" 395 | }, 396 | "user": { 397 | "__type": "Pointer", 398 | "className": "_User", 399 | "objectId": "XXXXXXXX" 400 | }, 401 | "uniqueId": "9071c2ee-5199-474a-9bc3-522b5fcc4a12", 402 | "isHidden": 0, 403 | "createdAt": "2023-02-26T16:22:45.809Z", 404 | "updatedAt": "2023-02-26T16:22:45.809Z", 405 | "objectId": "OZ604UX2m1", 406 | "__type": "Object", 407 | "className": "ParseSetGroup" 408 | }, { 409 | "parseSetsDictionary": [{ 410 | "isPersonalRecord": false, 411 | "reps": 8, 412 | "tagsValue": 0, 413 | "rpe": 0, 414 | "exerciseTypeValue": 2, 415 | "kilograms": 36, 416 | "isChecked": true, 417 | "expectedKilograms": 50 418 | }, { 419 | "isPersonalRecord": false, 420 | "reps": 8, 421 | "tagsValue": 0, 422 | "rpe": 0, 423 | "exerciseTypeValue": 2, 424 | "kilograms": 50, 425 | "isChecked": true, 426 | "expectedKilograms": 50 427 | }, { 428 | "isPersonalRecord": false, 429 | "reps": 8, 430 | "tagsValue": 0, 431 | "rpe": 0, 432 | "exerciseTypeValue": 2, 433 | "kilograms": 50, 434 | "isChecked": true, 435 | "expectedKilograms": 50 436 | }, { 437 | "isPersonalRecord": false, 438 | "reps": 8, 439 | "tagsValue": 0, 440 | "rpe": 0, 441 | "exerciseTypeValue": 2, 442 | "kilograms": 50, 443 | "isChecked": true, 444 | "expectedKilograms": 50 445 | }, { 446 | "isPersonalRecord": false, 447 | "reps": 7, 448 | "tagsValue": 0, 449 | "rpe": 0, 450 | "exerciseTypeValue": 2, 451 | "kilograms": 50, 452 | "isChecked": true, 453 | "expectedKilograms": 50 454 | }], 455 | "completionDate": { 456 | "__type": "Date", 457 | "iso": "2023-02-26T11:25:40.845Z" 458 | }, 459 | "startDate": { 460 | "__type": "Date", 461 | "iso": "2023-02-26T09:13:02.080Z" 462 | }, 463 | "superSetOrder": null, 464 | "notes": "", 465 | "build": "a257", 466 | "parseExercise": { 467 | "name": "Hammer Curl (Cable)", 468 | "createdAt": "2018-01-22T05:34:01.598Z", 469 | "updatedAt": "2018-09-27T07:19:48.381Z", 470 | "uniqueId": "4a304d9a-9a7a-440f-bb9a-9fd5cde6b590", 471 | "exerciseType": 2, 472 | "bodyParts": 2, 473 | "instructions": "Stand facing machine with elbows touching the side of the torso. Grasp the handles with a palm in grip.||Using biceps, pull forearms and hands upward until fully contracted.||Squeeze biceps and slowly lower back to the starting position.||Repeat for reps.", 474 | "isHidden": false, 475 | "isGlobal": true, 476 | "ACL": { 477 | "*": { 478 | "read": true 479 | } 480 | }, 481 | "objectId": "93H8TNQg4C", 482 | "__type": "Object", 483 | "className": "ParseExercise" 484 | }, 485 | "user": { 486 | "__type": "Pointer", 487 | "className": "_User", 488 | "objectId": "XXXXXXXX" 489 | }, 490 | "uniqueId": "185a28d7-0da9-4f4b-b1c2-9e73e36dc6e5", 491 | "isHidden": 0, 492 | "createdAt": "2023-02-26T16:22:45.809Z", 493 | "updatedAt": "2023-02-26T16:22:45.809Z", 494 | "objectId": "pbefcWbY2A", 495 | "__type": "Object", 496 | "className": "ParseSetGroup" 497 | }, { 498 | "parseSetsDictionary": [{ 499 | "isPersonalRecord": false, 500 | "reps": 8, 501 | "tagsValue": 0, 502 | "rpe": 0, 503 | "exerciseTypeValue": 2, 504 | "kilograms": 68, 505 | "isChecked": true, 506 | "expectedKilograms": 68 507 | }, { 508 | "isPersonalRecord": false, 509 | "reps": 8, 510 | "tagsValue": 0, 511 | "rpe": 0, 512 | "exerciseTypeValue": 2, 513 | "kilograms": 68, 514 | "isChecked": true, 515 | "expectedKilograms": 64 516 | }, { 517 | "isPersonalRecord": false, 518 | "reps": 8, 519 | "tagsValue": 0, 520 | "rpe": 0, 521 | "exerciseTypeValue": 2, 522 | "kilograms": 64, 523 | "isChecked": true, 524 | "expectedKilograms": 64 525 | }, { 526 | "isPersonalRecord": false, 527 | "reps": 8, 528 | "tagsValue": 4, 529 | "rpe": 0, 530 | "exerciseTypeValue": 2, 531 | "kilograms": 59, 532 | "isChecked": true, 533 | "expectedKilograms": 59 534 | }, { 535 | "isPersonalRecord": false, 536 | "reps": 8, 537 | "tagsValue": 0, 538 | "rpe": 0, 539 | "exerciseTypeValue": 2, 540 | "kilograms": 54, 541 | "isChecked": true, 542 | "expectedKilograms": 59 543 | }], 544 | "completionDate": { 545 | "__type": "Date", 546 | "iso": "2023-02-26T11:25:40.845Z" 547 | }, 548 | "startDate": { 549 | "__type": "Date", 550 | "iso": "2023-02-26T09:13:02.080Z" 551 | }, 552 | "superSetOrder": null, 553 | "notes": "", 554 | "build": "a257", 555 | "parseExercise": { 556 | "createdAt": "2016-02-19T05:42:34.859Z", 557 | "updatedAt": "2018-09-21T09:54:25.578Z", 558 | "exerciseType": 2, 559 | "name": "Lat Pulldown (Cable)", 560 | "isGlobal": true, 561 | "isPopular": true, 562 | "bodyParts": 4, 563 | "uniqueId": "B92AA3DD-98E1-4E99-A229-434BE54C1AE5", 564 | "instructions": "Sit on the pull down machine with knee pads adjusted to provide support, preventing your body from being pulled out of position.||Grip the pull down bar with a pronated grip slightly outside of shoulder width.||As you exhale, pull the bar down until it touches the upper chest.||Pause and squeeze the back muscles.||Slowly bring the bar back to the starting position with the lats fully stretched.||Repeat for reps.", 565 | "ACL": { 566 | "*": { 567 | "read": true 568 | } 569 | }, 570 | "objectId": "Da5swzH5xc", 571 | "__type": "Object", 572 | "className": "ParseExercise" 573 | }, 574 | "user": { 575 | "__type": "Pointer", 576 | "className": "_User", 577 | "objectId": "XXXXXXXX" 578 | }, 579 | "uniqueId": "90d422c8-71fb-42ea-9cc8-fd87134240b6", 580 | "isHidden": 0, 581 | "createdAt": "2023-02-26T16:22:45.810Z", 582 | "updatedAt": "2023-02-26T16:22:45.810Z", 583 | "objectId": "zkqvpGvyyK", 584 | "__type": "Object", 585 | "className": "ParseSetGroup" 586 | }, { 587 | "parseSetsDictionary": [{ 588 | "isPersonalRecord": false, 589 | "reps": 8, 590 | "tagsValue": 0, 591 | "rpe": 0, 592 | "exerciseTypeValue": 1, 593 | "kilograms": 50, 594 | "isChecked": true, 595 | "expectedKilograms": 60 596 | }, { 597 | "isPersonalRecord": false, 598 | "reps": 8, 599 | "tagsValue": 0, 600 | "rpe": 0, 601 | "exerciseTypeValue": 1, 602 | "kilograms": 50, 603 | "isChecked": true, 604 | "expectedKilograms": 60 605 | }, { 606 | "isPersonalRecord": false, 607 | "reps": 8, 608 | "tagsValue": 0, 609 | "rpe": 0, 610 | "exerciseTypeValue": 1, 611 | "kilograms": 50, 612 | "isChecked": true, 613 | "expectedKilograms": 60 614 | }, { 615 | "isPersonalRecord": false, 616 | "reps": 8, 617 | "tagsValue": 0, 618 | "rpe": 0, 619 | "exerciseTypeValue": 1, 620 | "kilograms": 50, 621 | "isChecked": true, 622 | "expectedKilograms": 55 623 | }, { 624 | "isPersonalRecord": false, 625 | "reps": 8, 626 | "tagsValue": 0, 627 | "rpe": 0, 628 | "exerciseTypeValue": 1, 629 | "kilograms": 45, 630 | "isChecked": true, 631 | "expectedKilograms": 50 632 | }], 633 | "completionDate": { 634 | "__type": "Date", 635 | "iso": "2023-02-26T11:25:40.845Z" 636 | }, 637 | "startDate": { 638 | "__type": "Date", 639 | "iso": "2023-02-26T09:13:02.080Z" 640 | }, 641 | "superSetOrder": null, 642 | "notes": "", 643 | "build": "a257", 644 | "parseExercise": { 645 | "name": "Incline Row (Dumbbell)", 646 | "createdAt": "2018-04-27T07:06:35.138Z", 647 | "updatedAt": "2018-10-15T06:32:22.125Z", 648 | "uniqueId": "ed06489a-f597-4cc1-81d0-eef7804f1fc5", 649 | "exerciseType": 1, 650 | "bodyParts": 4, 651 | "isHidden": false, 652 | "instructions": "NOTE: This exercise can be done one arm at a time or two arms at the same time.||Adjust the bench so that it's at a 30 to 45 degree angle and lean into it.||Hold a dumbbell on each hand and let your arms hang down. This is your starting position.||Row the dumbbells up to your side by retracting your shoulder blades and pulling at the elbows.||Pause at the top of the exercise, and then return to the starting position.||Repeat for reps.", 653 | "isGlobal": true, 654 | "ACL": { 655 | "*": { 656 | "read": true 657 | } 658 | }, 659 | "objectId": "uAFBYeQy5e", 660 | "__type": "Object", 661 | "className": "ParseExercise" 662 | }, 663 | "user": { 664 | "__type": "Pointer", 665 | "className": "_User", 666 | "objectId": "XXXXXXXX" 667 | }, 668 | "uniqueId": "9810fd56-6066-47de-8dea-ba73bdafd2a6", 669 | "isHidden": 0, 670 | "createdAt": "2023-02-26T16:22:45.810Z", 671 | "updatedAt": "2023-02-26T16:22:45.810Z", 672 | "objectId": "8xT6nYc44P", 673 | "__type": "Object", 674 | "className": "ParseSetGroup" 675 | }, { 676 | "parseSetsDictionary": [{ 677 | "isPersonalRecord": false, 678 | "reps": 16, 679 | "tagsValue": 0, 680 | "rpe": 0, 681 | "exerciseTypeValue": 3, 682 | "kilograms": 0, 683 | "isChecked": true, 684 | "expectedKilograms": 0 685 | }, { 686 | "isPersonalRecord": false, 687 | "reps": 8, 688 | "tagsValue": 0, 689 | "rpe": 0, 690 | "exerciseTypeValue": 3, 691 | "kilograms": 15, 692 | "isChecked": true, 693 | "expectedKilograms": 0 694 | }, { 695 | "isPersonalRecord": false, 696 | "reps": 10, 697 | "tagsValue": 0, 698 | "rpe": 0, 699 | "exerciseTypeValue": 3, 700 | "kilograms": 0, 701 | "isChecked": true, 702 | "expectedKilograms": 0 703 | }], 704 | "completionDate": { 705 | "__type": "Date", 706 | "iso": "2023-02-26T11:25:40.845Z" 707 | }, 708 | "startDate": { 709 | "__type": "Date", 710 | "iso": "2023-02-26T09:13:02.080Z" 711 | }, 712 | "superSetOrder": null, 713 | "notes": "", 714 | "build": "a257", 715 | "parseExercise": { 716 | "createdAt": "2016-02-19T05:42:34.953Z", 717 | "updatedAt": "2017-12-15T07:15:58.468Z", 718 | "exerciseType": 3, 719 | "name": "Decline Crunch", 720 | "isGlobal": true, 721 | "bodyParts": 1, 722 | "uniqueId": "B17772DE-F3EC-471B-8485-08ECFFE4A595", 723 | "instructions": "Lie on a decline bench, securing legs on the end of the bench. Place fingers at the side of the head with shoulders lifted slightly above the bench.||Contract the abdominal muscles and raise the shoulders off the bench about 4 to 6 inches.||Hold the position at the top and slowly lower back to the starting position while breathing out.||Repeat for reps.", 724 | "ACL": { 725 | "*": { 726 | "read": true 727 | } 728 | }, 729 | "objectId": "kHu0Bgp515", 730 | "__type": "Object", 731 | "className": "ParseExercise" 732 | }, 733 | "user": { 734 | "__type": "Pointer", 735 | "className": "_User", 736 | "objectId": "XXXXXXXX" 737 | }, 738 | "uniqueId": "c389e007-71a3-4ade-b8ec-419c70a052c7", 739 | "isHidden": 0, 740 | "createdAt": "2023-02-26T16:22:45.809Z", 741 | "updatedAt": "2023-02-26T16:22:45.809Z", 742 | "objectId": "UPVJRQ2234", 743 | "__type": "Object", 744 | "className": "ParseSetGroup" 745 | }, { 746 | "parseSetsDictionary": [{ 747 | "isPersonalRecord": false, 748 | "reps": 8, 749 | "tagsValue": 0, 750 | "rpe": 0, 751 | "exerciseTypeValue": 3, 752 | "isChecked": true 753 | }, { 754 | "isPersonalRecord": false, 755 | "reps": 6, 756 | "tagsValue": 0, 757 | "rpe": 0, 758 | "exerciseTypeValue": 3, 759 | "isChecked": true 760 | }, { 761 | "isPersonalRecord": false, 762 | "reps": 4, 763 | "tagsValue": 0, 764 | "rpe": 0, 765 | "exerciseTypeValue": 3, 766 | "isChecked": true 767 | }], 768 | "completionDate": { 769 | "__type": "Date", 770 | "iso": "2023-02-26T11:25:40.845Z" 771 | }, 772 | "startDate": { 773 | "__type": "Date", 774 | "iso": "2023-02-26T09:13:02.080Z" 775 | }, 776 | "superSetOrder": null, 777 | "notes": "", 778 | "build": "a257", 779 | "parseExercise": { 780 | "createdAt": "2016-02-19T05:42:34.958Z", 781 | "updatedAt": "2017-12-15T07:17:35.270Z", 782 | "exerciseType": 3, 783 | "name": "Hanging Leg Raise", 784 | "isGlobal": true, 785 | "bodyParts": 1, 786 | "uniqueId": "8EBA64E0-5E50-4F85-AD66-7FAEB87E5BB0", 787 | "instructions": "Hang from a bar with arms extended and legs straight down.||Contract abs and raise legs until torso creates a 90 degree angle with the thighs.||Hold position while keeping core tight, then return to the starting position.||Repeat for reps.", 788 | "ACL": { 789 | "*": { 790 | "read": true 791 | } 792 | }, 793 | "objectId": "6NQgjnb0vI", 794 | "__type": "Object", 795 | "className": "ParseExercise" 796 | }, 797 | "user": { 798 | "__type": "Pointer", 799 | "className": "_User", 800 | "objectId": "XXXXXXXX" 801 | }, 802 | "uniqueId": "fb1a3c33-26f0-4a8b-bee4-9d960690227e", 803 | "isHidden": 0, 804 | "createdAt": "2023-02-26T16:22:45.809Z", 805 | "updatedAt": "2023-02-26T16:22:45.809Z", 806 | "objectId": "aUPEOMmu4T", 807 | "__type": "Object", 808 | "className": "ParseSetGroup" 809 | }, { 810 | "parseSetsDictionary": [{ 811 | "isPersonalRecord": false, 812 | "reps": 8, 813 | "tagsValue": 0, 814 | "rpe": 0, 815 | "exerciseTypeValue": 1, 816 | "kilograms": 42.5, 817 | "isChecked": true 818 | }, { 819 | "isPersonalRecord": false, 820 | "reps": 8, 821 | "tagsValue": 0, 822 | "rpe": 0, 823 | "exerciseTypeValue": 1, 824 | "kilograms": 42.5, 825 | "isChecked": true, 826 | "expectedKilograms": 42.5 827 | }, { 828 | "isPersonalRecord": false, 829 | "reps": 8, 830 | "tagsValue": 0, 831 | "rpe": 0, 832 | "exerciseTypeValue": 1, 833 | "kilograms": 40, 834 | "isChecked": true, 835 | "expectedKilograms": 42.5 836 | }, { 837 | "isPersonalRecord": false, 838 | "reps": 8, 839 | "tagsValue": 0, 840 | "rpe": 0, 841 | "exerciseTypeValue": 1, 842 | "kilograms": 40, 843 | "isChecked": true, 844 | "expectedKilograms": 42.5 845 | }, { 846 | "isPersonalRecord": false, 847 | "reps": 8, 848 | "tagsValue": 0, 849 | "rpe": 0, 850 | "exerciseTypeValue": 1, 851 | "kilograms": 40, 852 | "isChecked": true, 853 | "expectedKilograms": 40 854 | }, { 855 | "isPersonalRecord": false, 856 | "reps": 8, 857 | "tagsValue": 0, 858 | "rpe": 0, 859 | "exerciseTypeValue": 1, 860 | "kilograms": 40, 861 | "isChecked": true, 862 | "expectedKilograms": 40 863 | }, { 864 | "isPersonalRecord": false, 865 | "reps": 8, 866 | "tagsValue": 0, 867 | "rpe": 0, 868 | "exerciseTypeValue": 1, 869 | "kilograms": 40, 870 | "isChecked": true, 871 | "expectedKilograms": 40 872 | }, { 873 | "isPersonalRecord": false, 874 | "reps": 8, 875 | "tagsValue": 0, 876 | "rpe": 0, 877 | "exerciseTypeValue": 1, 878 | "kilograms": 40, 879 | "isChecked": true, 880 | "expectedKilograms": 40 881 | }], 882 | "completionDate": { 883 | "__type": "Date", 884 | "iso": "2023-02-26T11:25:40.845Z" 885 | }, 886 | "startDate": { 887 | "__type": "Date", 888 | "iso": "2023-02-26T09:13:02.080Z" 889 | }, 890 | "superSetOrder": null, 891 | "notes": "", 892 | "build": "a257", 893 | "parseExercise": { 894 | "name": "Bent Over One Arm Row (Dumbbell)", 895 | "createdAt": "2018-04-27T07:01:46.786Z", 896 | "updatedAt": "2018-10-15T05:50:45.983Z", 897 | "uniqueId": "860bcb49-7f45-4212-9441-e9497e1220fc", 898 | "exerciseType": 1, 899 | "bodyParts": 4, 900 | "isHidden": false, 901 | "instructions": "Kneel over side of bench by placing knee and hand of supporting arm on bench.||Grab the dumbbell from the floor while keeping a straight back.||Flexing the core, keep head in neutral position and pull the dumbbell towards your stomach.||Squeeze your back as you breath out at the top position.||Lower the barbell to the starting position.||Repeat for reps.", 902 | "isGlobal": true, 903 | "ACL": { 904 | "*": { 905 | "read": true 906 | } 907 | }, 908 | "objectId": "Rkvrk4wzTd", 909 | "__type": "Object", 910 | "className": "ParseExercise" 911 | }, 912 | "user": { 913 | "__type": "Pointer", 914 | "className": "_User", 915 | "objectId": "XXXXXXXX" 916 | }, 917 | "uniqueId": "0b2d97ee-8bdd-4914-a869-5b9e3209ede1", 918 | "isHidden": 0, 919 | "createdAt": "2023-02-26T16:22:45.809Z", 920 | "updatedAt": "2023-02-26T16:22:45.809Z", 921 | "objectId": "4hZVuPuoIg", 922 | "__type": "Object", 923 | "className": "ParseSetGroup" 924 | }], 925 | "completionDate": { 926 | "__type": "Date", 927 | "iso": "2023-02-26T11:25:40.845Z" 928 | }, 929 | "startDate": { 930 | "__type": "Date", 931 | "iso": "2023-02-26T09:13:02.080Z" 932 | }, 933 | "notes": "", 934 | "googleFitUUID": "f97ef74a-937f-4e4e-9ded-769bff1b3204", 935 | "isHidden": 0, 936 | "bodyWeightKilograms": 0, 937 | "build": "a257", 938 | "parseOriginRoutine": { 939 | "build": "a257", 940 | "isArchived": 0, 941 | "isGlobal": 0, 942 | "index": 5, 943 | "user": { 944 | "__type": "Pointer", 945 | "className": "_User", 946 | "objectId": "XXXXXXXX" 947 | }, 948 | "isHidden": 0, 949 | "createdAt": "2022-11-13T15:14:09.649Z", 950 | "updatedAt": "2023-02-26T16:22:45.827Z", 951 | "objectId": "1txowNsTAw", 952 | "__type": "Object", 953 | "className": "ParseRoutine" 954 | }, 955 | "name": "1. Shoulders/Lats", 956 | "isGlobal": false, 957 | "timezoneId": "Europe/Dublin", 958 | "user": { 959 | "__type": "Pointer", 960 | "className": "_User", 961 | "objectId": "XXXXXXXX" 962 | }, 963 | "uniqueId": "3cc44fb7-4d22-46ec-8bfa-dc960a7e3712", 964 | "createdAt": "2023-02-26T16:22:46.401Z", 965 | "updatedAt": "2023-02-26T16:22:46.401Z", 966 | "objectId": "X8mLZvHkcE" 967 | }, { 968 | "parseSetGroups": [{ 969 | "parseSetsDictionary": [{ 970 | "isPersonalRecord": false, 971 | "seconds": 15, 972 | "tagsValue": 0, 973 | "rpe": 0, 974 | "exerciseTypeValue": 6, 975 | "isChecked": false 976 | }], 977 | "superSetOrder": null, 978 | "notes": "", 979 | "build": "a257", 980 | "parseExercise": { 981 | "name": "Elliptical Machine", 982 | "createdAt": "2018-04-27T07:05:25.460Z", 983 | "updatedAt": "2018-09-27T09:12:52.100Z", 984 | "uniqueId": "4464e3b1-c412-4047-a5b9-8cdb7c8fe7b3", 985 | "exerciseType": 6, 986 | "bodyParts": 512, 987 | "isHidden": false, 988 | "isGlobal": true, 989 | "ACL": { 990 | "*": { 991 | "read": true 992 | } 993 | }, 994 | "objectId": "SuGuVl8OYz", 995 | "__type": "Object", 996 | "className": "ParseExercise" 997 | }, 998 | "user": { 999 | "__type": "Pointer", 1000 | "className": "_User", 1001 | "objectId": "XXXXXXXX" 1002 | }, 1003 | "uniqueId": "4ea52fc2-ce64-4bc5-81c0-50e858b4622b", 1004 | "isHidden": 0, 1005 | "createdAt": "2023-02-26T16:22:45.810Z", 1006 | "updatedAt": "2023-02-26T16:22:45.810Z", 1007 | "objectId": "ZmacnvD4fu", 1008 | "__type": "Object", 1009 | "className": "ParseSetGroup" 1010 | }, { 1011 | "parseSetsDictionary": [{ 1012 | "isPersonalRecord": false, 1013 | "reps": 8, 1014 | "tagsValue": 0, 1015 | "rpe": 0, 1016 | "exerciseTypeValue": 2, 1017 | "kilograms": 59, 1018 | "isChecked": false 1019 | }, { 1020 | "isPersonalRecord": false, 1021 | "reps": 8, 1022 | "tagsValue": 0, 1023 | "rpe": 0, 1024 | "exerciseTypeValue": 2, 1025 | "kilograms": 59, 1026 | "isChecked": false 1027 | }, { 1028 | "isPersonalRecord": false, 1029 | "reps": 8, 1030 | "tagsValue": 0, 1031 | "rpe": 0, 1032 | "exerciseTypeValue": 2, 1033 | "kilograms": 91, 1034 | "isChecked": false 1035 | }, { 1036 | "isPersonalRecord": false, 1037 | "reps": 8, 1038 | "tagsValue": 0, 1039 | "rpe": 0, 1040 | "exerciseTypeValue": 2, 1041 | "kilograms": 91, 1042 | "isChecked": false 1043 | }, { 1044 | "isPersonalRecord": false, 1045 | "reps": 8, 1046 | "tagsValue": 0, 1047 | "rpe": 0, 1048 | "exerciseTypeValue": 2, 1049 | "kilograms": 91, 1050 | "isChecked": false 1051 | }, { 1052 | "isPersonalRecord": false, 1053 | "reps": 8, 1054 | "tagsValue": 0, 1055 | "rpe": 0, 1056 | "exerciseTypeValue": 2, 1057 | "kilograms": 91, 1058 | "isChecked": false 1059 | }], 1060 | "superSetOrder": null, 1061 | "notes": "", 1062 | "build": "a257", 1063 | "parseExercise": { 1064 | "createdAt": "2016-02-19T05:42:34.882Z", 1065 | "updatedAt": "2018-09-21T09:45:38.674Z", 1066 | "name": "Seated Row (Cable)", 1067 | "exerciseType": 2, 1068 | "isGlobal": true, 1069 | "bodyParts": 4, 1070 | "uniqueId": "143F848F-3A01-40BD-88D1-613C3A88309E", 1071 | "instructions": "Grip the handle attachment with both hands and sit with chest upright and back straight.||With shoulders retracted, pull the handle towards the mid torso.||Squeeze the back muscles as the handle approaches the torso and hold before returning to the starting position.||Repeat for reps.", 1072 | "ACL": { 1073 | "*": { 1074 | "read": true 1075 | } 1076 | }, 1077 | "objectId": "hnhGpeIPU5", 1078 | "__type": "Object", 1079 | "className": "ParseExercise" 1080 | }, 1081 | "user": { 1082 | "__type": "Pointer", 1083 | "className": "_User", 1084 | "objectId": "XXXXXXXX" 1085 | }, 1086 | "uniqueId": "1d0e5861-b4b7-4cfa-abc0-b33ff1ed9a80", 1087 | "isHidden": 0, 1088 | "createdAt": "2023-02-26T16:22:45.809Z", 1089 | "updatedAt": "2023-02-26T16:22:45.809Z", 1090 | "objectId": "was9Orupvj", 1091 | "__type": "Object", 1092 | "className": "ParseSetGroup" 1093 | }, { 1094 | "parseSetsDictionary": [{ 1095 | "isPersonalRecord": false, 1096 | "reps": 8, 1097 | "tagsValue": 0, 1098 | "rpe": 0, 1099 | "exerciseTypeValue": 1, 1100 | "kilograms": 20, 1101 | "isChecked": false 1102 | }, { 1103 | "isPersonalRecord": false, 1104 | "reps": 4, 1105 | "tagsValue": 0, 1106 | "rpe": 0, 1107 | "exerciseTypeValue": 1, 1108 | "kilograms": 35, 1109 | "isChecked": false 1110 | }, { 1111 | "isPersonalRecord": false, 1112 | "reps": 8, 1113 | "tagsValue": 0, 1114 | "rpe": 0, 1115 | "exerciseTypeValue": 1, 1116 | "kilograms": 35, 1117 | "isChecked": false 1118 | }, { 1119 | "isPersonalRecord": false, 1120 | "reps": 8, 1121 | "tagsValue": 0, 1122 | "rpe": 0, 1123 | "exerciseTypeValue": 1, 1124 | "kilograms": 35, 1125 | "isChecked": false 1126 | }, { 1127 | "isPersonalRecord": false, 1128 | "reps": 8, 1129 | "tagsValue": 0, 1130 | "rpe": 0, 1131 | "exerciseTypeValue": 1, 1132 | "kilograms": 32.5, 1133 | "isChecked": false 1134 | }, { 1135 | "isPersonalRecord": false, 1136 | "reps": 4, 1137 | "tagsValue": 0, 1138 | "rpe": 0, 1139 | "exerciseTypeValue": 1, 1140 | "kilograms": 32.5, 1141 | "isChecked": false 1142 | }], 1143 | "superSetOrder": null, 1144 | "notes": "", 1145 | "build": "a257", 1146 | "parseExercise": { 1147 | "name": "Pullover (Dumbbell)", 1148 | "createdAt": "2018-01-22T05:37:53.811Z", 1149 | "updatedAt": "2018-09-20T08:27:09.667Z", 1150 | "uniqueId": "1a9537c6-f56a-4d4e-a491-c5c172cfa5ed", 1151 | "exerciseType": 1, 1152 | "bodyParts": 8, 1153 | "instructions": "Placing the upper back against the bench with a dumbbell placed on the chest.||Grasp the dumbbell with both hands pressing against one end and hold straight over the chest.||Lower the dumbbell in an arc above the head until you feel a stretch in the chest muscles.||Return to starting position while breathing out.||Repeat for reps.", 1154 | "isHidden": false, 1155 | "isGlobal": true, 1156 | "ACL": { 1157 | "*": { 1158 | "read": true 1159 | } 1160 | }, 1161 | "objectId": "CnG27VmK9U", 1162 | "__type": "Object", 1163 | "className": "ParseExercise" 1164 | }, 1165 | "user": { 1166 | "__type": "Pointer", 1167 | "className": "_User", 1168 | "objectId": "XXXXXXXX" 1169 | }, 1170 | "uniqueId": "c751ac6b-53c0-4ff5-8a93-795eed1e024c", 1171 | "isHidden": 0, 1172 | "createdAt": "2023-02-26T16:22:45.809Z", 1173 | "updatedAt": "2023-02-26T16:22:45.809Z", 1174 | "objectId": "YD1knBax4U", 1175 | "__type": "Object", 1176 | "className": "ParseSetGroup" 1177 | }, { 1178 | "parseSetsDictionary": [{ 1179 | "isPersonalRecord": false, 1180 | "reps": 8, 1181 | "tagsValue": 0, 1182 | "rpe": 0, 1183 | "exerciseTypeValue": 2, 1184 | "kilograms": 36, 1185 | "isChecked": false 1186 | }, { 1187 | "isPersonalRecord": false, 1188 | "reps": 8, 1189 | "tagsValue": 0, 1190 | "rpe": 0, 1191 | "exerciseTypeValue": 2, 1192 | "kilograms": 50, 1193 | "isChecked": false 1194 | }, { 1195 | "isPersonalRecord": false, 1196 | "reps": 8, 1197 | "tagsValue": 0, 1198 | "rpe": 0, 1199 | "exerciseTypeValue": 2, 1200 | "kilograms": 50, 1201 | "isChecked": false 1202 | }, { 1203 | "isPersonalRecord": false, 1204 | "reps": 8, 1205 | "tagsValue": 0, 1206 | "rpe": 0, 1207 | "exerciseTypeValue": 2, 1208 | "kilograms": 50, 1209 | "isChecked": false 1210 | }, { 1211 | "isPersonalRecord": false, 1212 | "reps": 7, 1213 | "tagsValue": 0, 1214 | "rpe": 0, 1215 | "exerciseTypeValue": 2, 1216 | "kilograms": 50, 1217 | "isChecked": false 1218 | }], 1219 | "superSetOrder": null, 1220 | "notes": "", 1221 | "build": "a257", 1222 | "parseExercise": { 1223 | "name": "Hammer Curl (Cable)", 1224 | "createdAt": "2018-01-22T05:34:01.598Z", 1225 | "updatedAt": "2018-09-27T07:19:48.381Z", 1226 | "uniqueId": "4a304d9a-9a7a-440f-bb9a-9fd5cde6b590", 1227 | "exerciseType": 2, 1228 | "bodyParts": 2, 1229 | "instructions": "Stand facing machine with elbows touching the side of the torso. Grasp the handles with a palm in grip.||Using biceps, pull forearms and hands upward until fully contracted.||Squeeze biceps and slowly lower back to the starting position.||Repeat for reps.", 1230 | "isHidden": false, 1231 | "isGlobal": true, 1232 | "ACL": { 1233 | "*": { 1234 | "read": true 1235 | } 1236 | }, 1237 | "objectId": "93H8TNQg4C", 1238 | "__type": "Object", 1239 | "className": "ParseExercise" 1240 | }, 1241 | "user": { 1242 | "__type": "Pointer", 1243 | "className": "_User", 1244 | "objectId": "XXXXXXXX" 1245 | }, 1246 | "uniqueId": "00271a6f-e8d5-4fb4-a6ec-dce3c0fddb6b", 1247 | "isHidden": 0, 1248 | "createdAt": "2023-02-26T16:22:45.809Z", 1249 | "updatedAt": "2023-02-26T16:22:45.809Z", 1250 | "objectId": "WD1CB8tBzY", 1251 | "__type": "Object", 1252 | "className": "ParseSetGroup" 1253 | }, { 1254 | "parseSetsDictionary": [{ 1255 | "isPersonalRecord": false, 1256 | "reps": 8, 1257 | "tagsValue": 0, 1258 | "rpe": 0, 1259 | "exerciseTypeValue": 2, 1260 | "kilograms": 68, 1261 | "isChecked": false 1262 | }, { 1263 | "isPersonalRecord": false, 1264 | "reps": 8, 1265 | "tagsValue": 0, 1266 | "rpe": 0, 1267 | "exerciseTypeValue": 2, 1268 | "kilograms": 68, 1269 | "isChecked": false 1270 | }, { 1271 | "isPersonalRecord": false, 1272 | "reps": 8, 1273 | "tagsValue": 0, 1274 | "rpe": 0, 1275 | "exerciseTypeValue": 2, 1276 | "kilograms": 64, 1277 | "isChecked": false 1278 | }, { 1279 | "isPersonalRecord": false, 1280 | "reps": 8, 1281 | "tagsValue": 4, 1282 | "rpe": 0, 1283 | "exerciseTypeValue": 2, 1284 | "kilograms": 59, 1285 | "isChecked": false 1286 | }, { 1287 | "isPersonalRecord": false, 1288 | "reps": 8, 1289 | "tagsValue": 0, 1290 | "rpe": 0, 1291 | "exerciseTypeValue": 2, 1292 | "kilograms": 54, 1293 | "isChecked": false 1294 | }], 1295 | "superSetOrder": null, 1296 | "notes": "", 1297 | "build": "a257", 1298 | "parseExercise": { 1299 | "createdAt": "2016-02-19T05:42:34.859Z", 1300 | "updatedAt": "2018-09-21T09:54:25.578Z", 1301 | "exerciseType": 2, 1302 | "name": "Lat Pulldown (Cable)", 1303 | "isGlobal": true, 1304 | "isPopular": true, 1305 | "bodyParts": 4, 1306 | "uniqueId": "B92AA3DD-98E1-4E99-A229-434BE54C1AE5", 1307 | "instructions": "Sit on the pull down machine with knee pads adjusted to provide support, preventing your body from being pulled out of position.||Grip the pull down bar with a pronated grip slightly outside of shoulder width.||As you exhale, pull the bar down until it touches the upper chest.||Pause and squeeze the back muscles.||Slowly bring the bar back to the starting position with the lats fully stretched.||Repeat for reps.", 1308 | "ACL": { 1309 | "*": { 1310 | "read": true 1311 | } 1312 | }, 1313 | "objectId": "Da5swzH5xc", 1314 | "__type": "Object", 1315 | "className": "ParseExercise" 1316 | }, 1317 | "user": { 1318 | "__type": "Pointer", 1319 | "className": "_User", 1320 | "objectId": "XXXXXXXX" 1321 | }, 1322 | "uniqueId": "c07ca347-f7be-4d57-af88-ce71ac405a2d", 1323 | "isHidden": 0, 1324 | "createdAt": "2023-02-26T16:22:45.809Z", 1325 | "updatedAt": "2023-02-26T16:22:45.809Z", 1326 | "objectId": "Z4QrvAx0uE", 1327 | "__type": "Object", 1328 | "className": "ParseSetGroup" 1329 | }, { 1330 | "parseSetsDictionary": [{ 1331 | "isPersonalRecord": false, 1332 | "reps": 8, 1333 | "tagsValue": 0, 1334 | "rpe": 0, 1335 | "exerciseTypeValue": 1, 1336 | "kilograms": 50, 1337 | "isChecked": false 1338 | }, { 1339 | "isPersonalRecord": false, 1340 | "reps": 8, 1341 | "tagsValue": 0, 1342 | "rpe": 0, 1343 | "exerciseTypeValue": 1, 1344 | "kilograms": 50, 1345 | "isChecked": false 1346 | }, { 1347 | "isPersonalRecord": false, 1348 | "reps": 8, 1349 | "tagsValue": 0, 1350 | "rpe": 0, 1351 | "exerciseTypeValue": 1, 1352 | "kilograms": 50, 1353 | "isChecked": false 1354 | }, { 1355 | "isPersonalRecord": false, 1356 | "reps": 8, 1357 | "tagsValue": 0, 1358 | "rpe": 0, 1359 | "exerciseTypeValue": 1, 1360 | "kilograms": 50, 1361 | "isChecked": false 1362 | }, { 1363 | "isPersonalRecord": false, 1364 | "reps": 8, 1365 | "tagsValue": 0, 1366 | "rpe": 0, 1367 | "exerciseTypeValue": 1, 1368 | "kilograms": 45, 1369 | "isChecked": false 1370 | }], 1371 | "superSetOrder": null, 1372 | "notes": "", 1373 | "build": "a257", 1374 | "parseExercise": { 1375 | "name": "Incline Row (Dumbbell)", 1376 | "createdAt": "2018-04-27T07:06:35.138Z", 1377 | "updatedAt": "2018-10-15T06:32:22.125Z", 1378 | "uniqueId": "ed06489a-f597-4cc1-81d0-eef7804f1fc5", 1379 | "exerciseType": 1, 1380 | "bodyParts": 4, 1381 | "isHidden": false, 1382 | "instructions": "NOTE: This exercise can be done one arm at a time or two arms at the same time.||Adjust the bench so that it's at a 30 to 45 degree angle and lean into it.||Hold a dumbbell on each hand and let your arms hang down. This is your starting position.||Row the dumbbells up to your side by retracting your shoulder blades and pulling at the elbows.||Pause at the top of the exercise, and then return to the starting position.||Repeat for reps.", 1383 | "isGlobal": true, 1384 | "ACL": { 1385 | "*": { 1386 | "read": true 1387 | } 1388 | }, 1389 | "objectId": "uAFBYeQy5e", 1390 | "__type": "Object", 1391 | "className": "ParseExercise" 1392 | }, 1393 | "user": { 1394 | "__type": "Pointer", 1395 | "className": "_User", 1396 | "objectId": "XXXXXXXX" 1397 | }, 1398 | "uniqueId": "034d7b41-01f7-4caa-93e6-d4bc36344a32", 1399 | "isHidden": 0, 1400 | "createdAt": "2023-02-26T16:22:45.810Z", 1401 | "updatedAt": "2023-02-26T16:22:45.810Z", 1402 | "objectId": "PPyoP9nwf3", 1403 | "__type": "Object", 1404 | "className": "ParseSetGroup" 1405 | }, { 1406 | "parseSetsDictionary": [{ 1407 | "isPersonalRecord": false, 1408 | "reps": 16, 1409 | "tagsValue": 0, 1410 | "rpe": 0, 1411 | "exerciseTypeValue": 3, 1412 | "kilograms": 0, 1413 | "isChecked": false 1414 | }, { 1415 | "isPersonalRecord": false, 1416 | "reps": 8, 1417 | "tagsValue": 0, 1418 | "rpe": 0, 1419 | "exerciseTypeValue": 3, 1420 | "kilograms": 15, 1421 | "isChecked": false 1422 | }, { 1423 | "isPersonalRecord": false, 1424 | "reps": 10, 1425 | "tagsValue": 0, 1426 | "rpe": 0, 1427 | "exerciseTypeValue": 3, 1428 | "kilograms": 0, 1429 | "isChecked": false 1430 | }], 1431 | "superSetOrder": null, 1432 | "notes": "", 1433 | "build": "a257", 1434 | "parseExercise": { 1435 | "createdAt": "2016-02-19T05:42:34.953Z", 1436 | "updatedAt": "2017-12-15T07:15:58.468Z", 1437 | "exerciseType": 3, 1438 | "name": "Decline Crunch", 1439 | "isGlobal": true, 1440 | "bodyParts": 1, 1441 | "uniqueId": "B17772DE-F3EC-471B-8485-08ECFFE4A595", 1442 | "instructions": "Lie on a decline bench, securing legs on the end of the bench. Place fingers at the side of the head with shoulders lifted slightly above the bench.||Contract the abdominal muscles and raise the shoulders off the bench about 4 to 6 inches.||Hold the position at the top and slowly lower back to the starting position while breathing out.||Repeat for reps.", 1443 | "ACL": { 1444 | "*": { 1445 | "read": true 1446 | } 1447 | }, 1448 | "objectId": "kHu0Bgp515", 1449 | "__type": "Object", 1450 | "className": "ParseExercise" 1451 | }, 1452 | "user": { 1453 | "__type": "Pointer", 1454 | "className": "_User", 1455 | "objectId": "XXXXXXXX" 1456 | }, 1457 | "uniqueId": "94a635c1-84ce-43d4-8002-0669f0638309", 1458 | "isHidden": 0, 1459 | "createdAt": "2023-02-26T16:22:45.809Z", 1460 | "updatedAt": "2023-02-26T16:22:45.809Z", 1461 | "objectId": "epdldPwD8h", 1462 | "__type": "Object", 1463 | "className": "ParseSetGroup" 1464 | }, { 1465 | "parseSetsDictionary": [{ 1466 | "isPersonalRecord": false, 1467 | "reps": 8, 1468 | "tagsValue": 0, 1469 | "rpe": 0, 1470 | "exerciseTypeValue": 3, 1471 | "isChecked": false 1472 | }, { 1473 | "isPersonalRecord": false, 1474 | "reps": 6, 1475 | "tagsValue": 0, 1476 | "rpe": 0, 1477 | "exerciseTypeValue": 3, 1478 | "isChecked": false 1479 | }, { 1480 | "isPersonalRecord": false, 1481 | "reps": 4, 1482 | "tagsValue": 0, 1483 | "rpe": 0, 1484 | "exerciseTypeValue": 3, 1485 | "isChecked": false 1486 | }], 1487 | "superSetOrder": null, 1488 | "notes": "", 1489 | "build": "a257", 1490 | "parseExercise": { 1491 | "createdAt": "2016-02-19T05:42:34.958Z", 1492 | "updatedAt": "2017-12-15T07:17:35.270Z", 1493 | "exerciseType": 3, 1494 | "name": "Hanging Leg Raise", 1495 | "isGlobal": true, 1496 | "bodyParts": 1, 1497 | "uniqueId": "8EBA64E0-5E50-4F85-AD66-7FAEB87E5BB0", 1498 | "instructions": "Hang from a bar with arms extended and legs straight down.||Contract abs and raise legs until torso creates a 90 degree angle with the thighs.||Hold position while keeping core tight, then return to the starting position.||Repeat for reps.", 1499 | "ACL": { 1500 | "*": { 1501 | "read": true 1502 | } 1503 | }, 1504 | "objectId": "6NQgjnb0vI", 1505 | "__type": "Object", 1506 | "className": "ParseExercise" 1507 | }, 1508 | "user": { 1509 | "__type": "Pointer", 1510 | "className": "_User", 1511 | "objectId": "XXXXXXXX" 1512 | }, 1513 | "uniqueId": "373d0660-415a-43f9-882b-4980cf4fcb72", 1514 | "isHidden": 0, 1515 | "createdAt": "2023-02-26T16:22:45.809Z", 1516 | "updatedAt": "2023-02-26T16:22:45.809Z", 1517 | "objectId": "fqFPmNu0nx", 1518 | "__type": "Object", 1519 | "className": "ParseSetGroup" 1520 | }, { 1521 | "parseSetsDictionary": [{ 1522 | "isPersonalRecord": false, 1523 | "reps": 8, 1524 | "tagsValue": 0, 1525 | "rpe": 0, 1526 | "exerciseTypeValue": 1, 1527 | "kilograms": 42.5, 1528 | "isChecked": false 1529 | }, { 1530 | "isPersonalRecord": false, 1531 | "reps": 8, 1532 | "tagsValue": 0, 1533 | "rpe": 0, 1534 | "exerciseTypeValue": 1, 1535 | "kilograms": 42.5, 1536 | "isChecked": false 1537 | }, { 1538 | "isPersonalRecord": false, 1539 | "reps": 8, 1540 | "tagsValue": 0, 1541 | "rpe": 0, 1542 | "exerciseTypeValue": 1, 1543 | "kilograms": 40, 1544 | "isChecked": false 1545 | }, { 1546 | "isPersonalRecord": false, 1547 | "reps": 8, 1548 | "tagsValue": 0, 1549 | "rpe": 0, 1550 | "exerciseTypeValue": 1, 1551 | "kilograms": 40, 1552 | "isChecked": false 1553 | }, { 1554 | "isPersonalRecord": false, 1555 | "reps": 8, 1556 | "tagsValue": 0, 1557 | "rpe": 0, 1558 | "exerciseTypeValue": 1, 1559 | "kilograms": 40, 1560 | "isChecked": false 1561 | }, { 1562 | "isPersonalRecord": false, 1563 | "reps": 8, 1564 | "tagsValue": 0, 1565 | "rpe": 0, 1566 | "exerciseTypeValue": 1, 1567 | "kilograms": 40, 1568 | "isChecked": false 1569 | }, { 1570 | "isPersonalRecord": false, 1571 | "reps": 8, 1572 | "tagsValue": 0, 1573 | "rpe": 0, 1574 | "exerciseTypeValue": 1, 1575 | "kilograms": 40, 1576 | "isChecked": false 1577 | }, { 1578 | "isPersonalRecord": false, 1579 | "reps": 8, 1580 | "tagsValue": 0, 1581 | "rpe": 0, 1582 | "exerciseTypeValue": 1, 1583 | "kilograms": 40, 1584 | "isChecked": false 1585 | }], 1586 | "superSetOrder": null, 1587 | "notes": "", 1588 | "build": "a257", 1589 | "parseExercise": { 1590 | "name": "Bent Over One Arm Row (Dumbbell)", 1591 | "createdAt": "2018-04-27T07:01:46.786Z", 1592 | "updatedAt": "2018-10-15T05:50:45.983Z", 1593 | "uniqueId": "860bcb49-7f45-4212-9441-e9497e1220fc", 1594 | "exerciseType": 1, 1595 | "bodyParts": 4, 1596 | "isHidden": false, 1597 | "instructions": "Kneel over side of bench by placing knee and hand of supporting arm on bench.||Grab the dumbbell from the floor while keeping a straight back.||Flexing the core, keep head in neutral position and pull the dumbbell towards your stomach.||Squeeze your back as you breath out at the top position.||Lower the barbell to the starting position.||Repeat for reps.", 1598 | "isGlobal": true, 1599 | "ACL": { 1600 | "*": { 1601 | "read": true 1602 | } 1603 | }, 1604 | "objectId": "Rkvrk4wzTd", 1605 | "__type": "Object", 1606 | "className": "ParseExercise" 1607 | }, 1608 | "user": { 1609 | "__type": "Pointer", 1610 | "className": "_User", 1611 | "objectId": "XXXXXXXX" 1612 | }, 1613 | "uniqueId": "5f22f5a7-91c4-4449-b6d6-4e8ad9227c49", 1614 | "isHidden": 0, 1615 | "createdAt": "2023-02-26T16:22:45.809Z", 1616 | "updatedAt": "2023-02-26T16:22:45.809Z", 1617 | "objectId": "Cq79ffqWE8", 1618 | "__type": "Object", 1619 | "className": "ParseSetGroup" 1620 | }], 1621 | "bodyWeightKilograms": 0, 1622 | "notes": "", 1623 | "build": "a257", 1624 | "name": "1. Shoulders/Lats", 1625 | "isGlobal": false, 1626 | "parseRoutine": { 1627 | "build": "a257", 1628 | "isArchived": 0, 1629 | "isGlobal": 0, 1630 | "index": 5, 1631 | "user": { 1632 | "__type": "Pointer", 1633 | "className": "_User", 1634 | "objectId": "XXXXXXXX" 1635 | }, 1636 | "isHidden": 0, 1637 | "createdAt": "2022-11-13T15:14:09.649Z", 1638 | "updatedAt": "2023-02-26T16:22:45.827Z", 1639 | "objectId": "1txowNsTAw", 1640 | "__type": "Object", 1641 | "className": "ParseRoutine" 1642 | }, 1643 | "user": { 1644 | "__type": "Pointer", 1645 | "className": "_User", 1646 | "objectId": "XXXXXXXX" 1647 | }, 1648 | "uniqueId": "597efd79-0758-4a2a-8350-b6fcbe6d112a", 1649 | "isHidden": 0, 1650 | "createdAt": "2022-11-13T15:14:09.797Z", 1651 | "updatedAt": "2023-02-26T16:22:46.404Z", 1652 | "objectId": "3rYbX4nogp" 1653 | }, 1654 | ............. 1655 | , 1656 | ................ 1657 | , 1658 | ...........] 1659 | } 1660 | ``` 1661 | -------------------------------------------------------------------------------- /api/log-session.md: -------------------------------------------------------------------------------- 1 | ## log session 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2xxxxxxxxxe0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iUxxxxxxxxxXtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'notes': '', 23 | 'isHidden': 0, 24 | 'bodyWeightKilograms': 0, 25 | 'build': 'a257', 26 | 'parseOriginRoutine': { 27 | '__type': 'Pointer', 28 | 'className': 'ParseRoutine', 29 | 'objectId': 'd7wTyA1uX0', 30 | }, 31 | 'name': '5. Hamstrings/Glutes', 32 | 'isGlobal': False, 33 | 'parseSetGroups': [ 34 | { 35 | '__type': 'Pointer', 36 | 'className': 'ParseSetGroup', 37 | 'objectId': 'wYW4GH5uUG', 38 | }, 39 | ], 40 | 'timezoneId': 'Europe/Dublin', 41 | 'completionDate': { 42 | '__type': 'Date', 43 | 'iso': '2023-02-27T17:54:03.409Z', 44 | }, 45 | 'user': { 46 | '__type': 'Pointer', 47 | 'className': '_User', 48 | 'objectId': 'XXXXXXXX', 49 | }, 50 | 'uniqueId': '022fca24-9fde-4a00-8ee7-7fff510cc5ad', 51 | 'startDate': { 52 | '__type': 'Date', 53 | 'iso': '2023-02-27T17:51:08.931Z', 54 | }, 55 | } 56 | 57 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseWorkout', headers=headers, json=json_data) 58 | 59 | ``` 60 | 61 | ### Reponse 62 | ``` 63 | { 64 | "objectId": "tRIg9CdQ3B", 65 | "createdAt": "2023-02-27T17:54:12.144Z" 66 | } 67 | ``` -------------------------------------------------------------------------------- /api/login.md: -------------------------------------------------------------------------------- 1 | ## login 2 | 3 | ### request 4 | 5 | ``` 6 | import requests 7 | 8 | headers = { 9 | 'Host': 'ws13.strongapp.co', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNBFaGs6rPT0XtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-4df5-80b4-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | data = '{"password":".....,"username":"bitwiseshift","_method":"GET"} --compressed' 22 | 23 | response = requests.post('https://ws13.strongapp.co/parse/login', headers=headers, data=data) 24 | ``` 25 | 26 | ### response 27 | ``` 28 | { 29 | "objectId": "NMmxxxxFZG", 30 | "lastVersion": "2.7.9 (257)", 31 | "hasPurchasedUnlockStrong": false, 32 | "distanceUnitValue": 14, 33 | "firstWeekday": 2, 34 | "hasPurchasedComboPack": false, 35 | "timerDuration": 120, 36 | "lengthUnitValue": 9, 37 | "build": "a257", 38 | "lastOSVersion": "Android 12", 39 | "hasPurchasedPowerPack": false, 40 | "email": "dmz.oneill@gmail.com", 41 | "uniqueId": "44fbba75-8d0f-xxx-xxxx-1f0b33b20bd6", 42 | "username": "bitwiseshift", 43 | "weightUnitValue": 14, 44 | "createdAt": "2022-03-16T08:46:26.354Z", 45 | "updatedAt": "2023-02-26T16:22:45.823Z", 46 | "exerciseBars": { 47 | "pTV7Q84sJW": "our_little_un-deletable_no_weight_bar", 48 | "EWm19pmMjX": "our_little_un-deletable_no_weight_bar", 49 | "uodPjbv9AD": "our_little_un-deletable_no_weight_bar", 50 | ... 51 | "qg1ric4s1t": "our_little_un-deletable_no_weight_bar", 52 | "8UKC0MjWJ0": "our_little_un-deletable_no_weight_bar" 53 | }, 54 | "exerciseWeightUnitValues": {}, 55 | "goals": "{}", 56 | "hasPurchasedPROForever": false, 57 | "image": { 58 | "__type": "File", 59 | "name": "a4b91159cb04fd89d698b634c0d578f8_avatar.jpg", 60 | "url": "https://strong-prod.s3.amazonaws.com/a4b91159cb04fd89d698b634c0d578f8_avatar.jpg" 61 | }, 62 | "persistentNotes": {}, 63 | "workoutsPerWeekGoal": 0, 64 | "proExpirationDate": { 65 | "__type": "Date", 66 | "iso": "2023-04-17T14:02:11.173Z" 67 | }, 68 | "name": "", 69 | "ACL": { 70 | "NMmPxxxFZG": { 71 | "read": true, 72 | "write": true 73 | }, 74 | "*": { 75 | "read": true 76 | } 77 | }, 78 | "sessionToken": "r:jjjjjjjjjjjjjjjjj" 79 | } 80 | ``` -------------------------------------------------------------------------------- /api/parsewidget.md: -------------------------------------------------------------------------------- 1 | 2 | ## Parse Widget 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cexxxxxxxxx5e0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GxxxxxxxT0XtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | data = '{"where":"{\\user\\:{\\__type\\:\\Pointer\\,\\className\\:\\_User\\,\\objectId\\:\\NMmPxxxxxFZG\\}}","_method":"GET"}' 22 | 23 | response = requests.post('https://ws13.strongapp.co/parse/classes/ParseWidget', headers=headers, data=data) 24 | ``` 25 | 26 | ### Response 27 | ``` 28 | { 29 | "results": [{ 30 | "index": 0, 31 | "type": "WORKOUTS_PER_WEEK", 32 | "user": { 33 | "__type": "Pointer", 34 | "className": "_User", 35 | "objectId": "NMmxxxxx7FZG" 36 | }, 37 | "parameters": "{}", 38 | "uniqueId": "60318bb8-2dd5-xxxx-xxxx-b95273c5d392", 39 | "isHidden": false, 40 | "createdAt": "2022-03-16T10:43:35.270Z", 41 | "updatedAt": "2022-03-16T10:43:35.270Z", 42 | "objectId": "8wxxxx44d0" 43 | }] 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /api/update-user.md: -------------------------------------------------------------------------------- 1 | ## Update user 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2ce38exxxxe0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNBFxxxxtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-4df5-80b4-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'lastVersion': '2.7.9 (257)', 23 | 'persistentNotes': {}, 24 | 'hasPurchasedUnlockStrong': False, 25 | 'ACL': { 26 | 'NMmxxxxFZG': { 27 | 'read': True, 28 | 'write': True, 29 | }, 30 | '*': { 31 | 'read': True, 32 | }, 33 | }, 34 | 'workoutsPerWeekGoal': 0, 35 | 'distanceUnitValue': 14, 36 | 'firstWeekday': 2, 37 | 'hasPurchasedComboPack': False, 38 | 'exerciseWeightUnitValues': {}, 39 | 'exerciseBars': { 40 | 'pTV7Q84sJW': 'our_little_un-deletable_no_weight_bar', 41 | 'EWm19pmMjX': 'our_little_un-deletable_no_weight_bar', 42 | 'uodPjbv9AD': 'our_little_un-deletable_no_weight_bar', 43 | .... 44 | 'fXW7WHcUn8': 'our_little_un-deletable_no_weight_bar', 45 | 'qg1ric4s1t': 'our_little_un-deletable_no_weight_bar', 46 | '8UKC0MjWJ0': 'our_little_un-deletable_no_weight_bar', 47 | }, 48 | 'timerDuration': 120, 49 | 'lengthUnitValue': 9, 50 | 'build': 'a257', 51 | 'proExpirationDate': { 52 | '__type': 'Date', 53 | 'iso': '2023-04-17T14:02:11.173Z', 54 | }, 55 | 'lastOSVersion': 'Android 13', 56 | 'hasPurchasedPowerPack': False, 57 | 'hasPurchasedPROForever': False, 58 | 'uniqueId': '44fbba75-8d0f-xxx-xxx-1f0b33b20bd6', 59 | 'weightUnitValue': 14, 60 | 'username': 'bitwiseshift', 61 | 'goals': '{}', 62 | 'objectId': 'NMmPxxxFZG', 63 | } 64 | 65 | response = requests.put('https://ws13.strongapp.co/parse/classes/_User/NMmPxxxFZG', headers=headers, json=json_data) 66 | ``` 67 | 68 | ### response 69 | ``` 70 | { 71 | "updatedAt": "2023-02-26T22:16:53.074Z" 72 | } 73 | ``` -------------------------------------------------------------------------------- /api/update-workout.md: -------------------------------------------------------------------------------- 1 | ## Update workout 2 | 3 | ### request 4 | ``` 5 | import requests 6 | 7 | headers = { 8 | 'Host': 'ws13.strongapp.co', 9 | 'x-parse-session-token': 'r:8fc69c9a2cexxxxxxxxxx0adef26d6f27', 10 | 'x-parse-application-id': 'QbtVgYzi9iU1GNBxxxxxxxxxxtvRKMajvuYLLmTW', 11 | 'x-parse-app-build-version': '257', 12 | 'x-parse-app-display-version': '2.7.9', 13 | 'x-parse-os-version': '13', 14 | 'user-agent': 'Parse Android SDK API Level 33', 15 | 'x-parse-installation-id': '0767c726-ca92-xxxx-xxxx-554119d22e1c', 16 | 'content-type': 'application/json', 17 | 'pragma': 'no-cache', 18 | 'cache-control': 'no-cache', 19 | } 20 | 21 | json_data = { 22 | 'requests': [ 23 | { 24 | 'method': 'PUT', 25 | 'path': '/parse/classes/ParseWorkout/8KrMJWiWdf', 26 | 'body': { 27 | 'bodyWeightKilograms': 0, 28 | 'notes': '', 29 | 'build': 'a257', 30 | 'name': '6. Shoulders/Arms', 31 | 'isGlobal': False, 32 | 'parseSetGroups': [ 33 | { 34 | '__type': 'Pointer', 35 | 'className': 'ParseSetGroup', 36 | 'objectId': 'HFJNuTnwrU', 37 | }, 38 | { 39 | '__type': 'Pointer', 40 | 'className': 'ParseSetGroup', 41 | 'objectId': '2aFGyMtOGr', 42 | }, 43 | { 44 | '__type': 'Pointer', 45 | 'className': 'ParseSetGroup', 46 | 'objectId': 'O1eZqPKw6K', 47 | }, 48 | { 49 | '__type': 'Pointer', 50 | 'className': 'ParseSetGroup', 51 | 'objectId': 'wOZiv671pu', 52 | }, 53 | { 54 | '__type': 'Pointer', 55 | 'className': 'ParseSetGroup', 56 | 'objectId': 'lRrh4IVXgn', 57 | }, 58 | { 59 | '__type': 'Pointer', 60 | 'className': 'ParseSetGroup', 61 | 'objectId': '0SRAApZvQJ', 62 | }, 63 | { 64 | '__type': 'Pointer', 65 | 'className': 'ParseSetGroup', 66 | 'objectId': 'xQA6HVV1yF', 67 | }, 68 | { 69 | '__type': 'Pointer', 70 | 'className': 'ParseSetGroup', 71 | 'objectId': 'ViDoOCx7YG', 72 | }, 73 | ], 74 | 'parseRoutine': { 75 | '__type': 'Pointer', 76 | 'className': 'ParseRoutine', 77 | 'objectId': 'gMBFTfTU1K', 78 | }, 79 | 'user': { 80 | '__type': 'Pointer', 81 | 'className': '_User', 82 | 'objectId': 'XXXXXXXX', 83 | }, 84 | 'uniqueId': '4874e63b-4177-4edc-9e84-d50fb7412692', 85 | 'isHidden': 0, 86 | 'objectId': '8KrMJWiWdf', 87 | }, 88 | }, 89 | { 90 | 'method': 'PUT', 91 | 'path': '/parse/classes/ParseSetGroup/O1eZqPKw6K', 92 | 'body': { 93 | 'parseSetsDictionary': [ 94 | { 95 | 'isPersonalRecord': False, 96 | 'reps': 8, 97 | 'tagsValue': 0, 98 | 'rpe': 0, 99 | 'exerciseTypeValue': 1, 100 | 'kilograms': 20, 101 | 'isChecked': False, 102 | 'expectedKilograms': 20, 103 | }, 104 | { 105 | 'isPersonalRecord': False, 106 | 'reps': 8, 107 | 'tagsValue': 0, 108 | 'rpe': 0, 109 | 'exerciseTypeValue': 1, 110 | 'kilograms': 25, 111 | 'isChecked': False, 112 | 'expectedKilograms': 25, 113 | }, 114 | { 115 | 'isPersonalRecord': False, 116 | 'reps': 8, 117 | 'tagsValue': 0, 118 | 'rpe': 0, 119 | 'exerciseTypeValue': 1, 120 | 'kilograms': 25, 121 | 'isChecked': False, 122 | 'expectedKilograms': 30, 123 | }, 124 | ], 125 | 'superSetOrder': None, 126 | 'notes': '', 127 | 'build': 'a257', 128 | 'parseExercise': { 129 | '__type': 'Pointer', 130 | 'className': 'ParseExercise', 131 | 'objectId': 'gmuuQgiVFC', 132 | }, 133 | 'user': { 134 | '__type': 'Pointer', 135 | 'className': '_User', 136 | 'objectId': 'XXXXXXXX', 137 | }, 138 | 'uniqueId': '39d2ddd0-0dfa-406f-aa17-3520daad4165', 139 | 'isHidden': 0, 140 | 'objectId': 'O1eZqPKw6K', 141 | }, 142 | }, 143 | { 144 | 'method': 'PUT', 145 | 'path': '/parse/classes/ParseRoutine/gMBFTfTU1K', 146 | 'body': { 147 | 'build': 'a257', 148 | 'isArchived': 0, 149 | 'isGlobal': 0, 150 | 'index': 0, 151 | 'user': { 152 | '__type': 'Pointer', 153 | 'className': '_User', 154 | 'objectId': 'XXXXXXXX', 155 | }, 156 | 'isHidden': 0, 157 | 'objectId': 'gMBFTfTU1K', 158 | }, 159 | }, 160 | { 161 | 'method': 'PUT', 162 | 'path': '/parse/classes/ParseSetGroup/0SRAApZvQJ', 163 | 'body': { 164 | 'parseSetsDictionary': [ 165 | { 166 | 'isPersonalRecord': False, 167 | 'reps': 8, 168 | 'tagsValue': 0, 169 | 'rpe': 0, 170 | 'exerciseTypeValue': 3, 171 | 'kilograms': 20, 172 | 'isChecked': False, 173 | 'expectedKilograms': 10, 174 | }, 175 | { 176 | 'isPersonalRecord': False, 177 | 'reps': 8, 178 | 'tagsValue': 0, 179 | 'rpe': 0, 180 | 'exerciseTypeValue': 3, 181 | 'kilograms': 20, 182 | 'isChecked': False, 183 | 'expectedKilograms': 10, 184 | }, 185 | { 186 | 'isPersonalRecord': False, 187 | 'reps': 8, 188 | 'tagsValue': 0, 189 | 'rpe': 0, 190 | 'exerciseTypeValue': 3, 191 | 'kilograms': 20, 192 | 'isChecked': False, 193 | 'expectedKilograms': 10, 194 | }, 195 | ], 196 | 'superSetOrder': None, 197 | 'notes': '', 198 | 'build': 'a257', 199 | 'parseExercise': { 200 | '__type': 'Pointer', 201 | 'className': 'ParseExercise', 202 | 'objectId': 'kHu0Bgp515', 203 | }, 204 | 'user': { 205 | '__type': 'Pointer', 206 | 'className': '_User', 207 | 'objectId': 'XXXXXXXX', 208 | }, 209 | 'uniqueId': 'ffd55399-5bdc-4009-960e-f69dbdeaa2e7', 210 | 'isHidden': 0, 211 | 'objectId': '0SRAApZvQJ', 212 | }, 213 | }, 214 | { 215 | 'method': 'PUT', 216 | 'path': '/parse/classes/ParseSetGroup/wOZiv671pu', 217 | 'body': { 218 | 'parseSetsDictionary': [ 219 | { 220 | 'isPersonalRecord': False, 221 | 'reps': 8, 222 | 'tagsValue': 1, 223 | 'rpe': 0, 224 | 'exerciseTypeValue': 2, 225 | 'kilograms': 36, 226 | 'isChecked': False, 227 | 'expectedKilograms': 36, 228 | }, 229 | { 230 | 'isPersonalRecord': False, 231 | 'reps': 8, 232 | 'tagsValue': 0, 233 | 'rpe': 0, 234 | 'exerciseTypeValue': 2, 235 | 'kilograms': 46, 236 | 'isChecked': False, 237 | 'expectedKilograms': 45, 238 | }, 239 | { 240 | 'isPersonalRecord': False, 241 | 'reps': 8, 242 | 'tagsValue': 0, 243 | 'rpe': 0, 244 | 'exerciseTypeValue': 2, 245 | 'kilograms': 50, 246 | 'isChecked': False, 247 | 'expectedKilograms': 41, 248 | }, 249 | { 250 | 'isPersonalRecord': False, 251 | 'reps': 8, 252 | 'tagsValue': 0, 253 | 'rpe': 0, 254 | 'exerciseTypeValue': 2, 255 | 'kilograms': 50, 256 | 'isChecked': False, 257 | 'expectedKilograms': 41, 258 | }, 259 | { 260 | 'isPersonalRecord': False, 261 | 'reps': 4, 262 | 'tagsValue': 0, 263 | 'rpe': 0, 264 | 'exerciseTypeValue': 2, 265 | 'kilograms': 50, 266 | 'isChecked': False, 267 | 'expectedKilograms': 41, 268 | }, 269 | ], 270 | 'superSetOrder': None, 271 | 'notes': '', 272 | 'build': 'a257', 273 | 'parseExercise': { 274 | '__type': 'Pointer', 275 | 'className': 'ParseExercise', 276 | 'objectId': 'RemEUYjkoZ', 277 | }, 278 | 'user': { 279 | '__type': 'Pointer', 280 | 'className': '_User', 281 | 'objectId': 'XXXXXXXX', 282 | }, 283 | 'uniqueId': '94e48277-ef3b-4a98-b7e4-d4859d1d7936', 284 | 'isHidden': 0, 285 | 'objectId': 'wOZiv671pu', 286 | }, 287 | }, 288 | { 289 | 'method': 'PUT', 290 | 'path': '/parse/classes/ParseSetGroup/ViDoOCx7YG', 291 | 'body': { 292 | 'parseSetsDictionary': [ 293 | { 294 | 'isPersonalRecord': False, 295 | 'reps': 6, 296 | 'tagsValue': 0, 297 | 'rpe': 0, 298 | 'exerciseTypeValue': 3, 299 | 'isChecked': False, 300 | }, 301 | { 302 | 'isPersonalRecord': False, 303 | 'reps': 6, 304 | 'tagsValue': 0, 305 | 'rpe': 0, 306 | 'exerciseTypeValue': 3, 307 | 'isChecked': False, 308 | }, 309 | { 310 | 'isPersonalRecord': False, 311 | 'reps': 6, 312 | 'tagsValue': 0, 313 | 'rpe': 0, 314 | 'exerciseTypeValue': 3, 315 | 'isChecked': False, 316 | }, 317 | { 318 | 'isPersonalRecord': False, 319 | 'reps': 6, 320 | 'tagsValue': 0, 321 | 'rpe': 0, 322 | 'exerciseTypeValue': 3, 323 | 'isChecked': False, 324 | }, 325 | ], 326 | 'superSetOrder': None, 327 | 'notes': '', 328 | 'build': 'a257', 329 | 'parseExercise': { 330 | '__type': 'Pointer', 331 | 'className': 'ParseExercise', 332 | 'objectId': '6NQgjnb0vI', 333 | }, 334 | 'user': { 335 | '__type': 'Pointer', 336 | 'className': '_User', 337 | 'objectId': 'XXXXXXXX', 338 | }, 339 | 'uniqueId': '5e5375dc-d1f2-4a65-a9df-81976d7e088b', 340 | 'isHidden': 0, 341 | 'objectId': 'ViDoOCx7YG', 342 | }, 343 | }, 344 | { 345 | 'method': 'PUT', 346 | 'path': '/parse/classes/ParseSetGroup/lRrh4IVXgn', 347 | 'body': { 348 | 'parseSetsDictionary': [ 349 | { 350 | 'isPersonalRecord': False, 351 | 'reps': 8, 352 | 'tagsValue': 0, 353 | 'rpe': 0, 354 | 'exerciseTypeValue': 2, 355 | 'kilograms': 54, 356 | 'isChecked': False, 357 | 'expectedKilograms': 64, 358 | }, 359 | { 360 | 'isPersonalRecord': False, 361 | 'reps': 8, 362 | 'tagsValue': 0, 363 | 'rpe': 0, 364 | 'exerciseTypeValue': 2, 365 | 'kilograms': 64, 366 | 'isChecked': False, 367 | 'expectedKilograms': 64, 368 | }, 369 | { 370 | 'isPersonalRecord': False, 371 | 'reps': 8, 372 | 'tagsValue': 1, 373 | 'rpe': 0, 374 | 'exerciseTypeValue': 2, 375 | 'kilograms': 72, 376 | 'isChecked': False, 377 | 'expectedKilograms': 59, 378 | }, 379 | { 380 | 'isPersonalRecord': False, 381 | 'reps': 7, 382 | 'tagsValue': 0, 383 | 'rpe': 0, 384 | 'exerciseTypeValue': 2, 385 | 'kilograms': 55, 386 | 'isChecked': False, 387 | }, 388 | ], 389 | 'superSetOrder': None, 390 | 'notes': '', 391 | 'build': 'a257', 392 | 'parseExercise': { 393 | '__type': 'Pointer', 394 | 'className': 'ParseExercise', 395 | 'objectId': 'tklNHrWzOF', 396 | }, 397 | 'user': { 398 | '__type': 'Pointer', 399 | 'className': '_User', 400 | 'objectId': 'XXXXXXXX', 401 | }, 402 | 'uniqueId': 'b3502172-c9a8-4fb0-83dd-f14f3154a63c', 403 | 'isHidden': 0, 404 | 'objectId': 'lRrh4IVXgn', 405 | }, 406 | }, 407 | { 408 | 'method': 'PUT', 409 | 'path': '/parse/classes/ParseSetGroup/2aFGyMtOGr', 410 | 'body': { 411 | 'parseSetsDictionary': [ 412 | { 413 | 'isPersonalRecord': False, 414 | 'reps': 8, 415 | 'tagsValue': 1, 416 | 'rpe': 0, 417 | 'exerciseTypeValue': 1, 418 | 'kilograms': 30, 419 | 'isChecked': False, 420 | 'expectedKilograms': 30, 421 | }, 422 | { 423 | 'isPersonalRecord': False, 424 | 'reps': 8, 425 | 'tagsValue': 0, 426 | 'rpe': 0, 427 | 'exerciseTypeValue': 1, 428 | 'kilograms': 40, 429 | 'isChecked': False, 430 | 'expectedKilograms': 40, 431 | }, 432 | { 433 | 'isPersonalRecord': False, 434 | 'reps': 8, 435 | 'tagsValue': 0, 436 | 'rpe': 0, 437 | 'exerciseTypeValue': 1, 438 | 'kilograms': 40, 439 | 'isChecked': False, 440 | 'expectedKilograms': 40, 441 | }, 442 | { 443 | 'isPersonalRecord': False, 444 | 'reps': 8, 445 | 'tagsValue': 0, 446 | 'rpe': 0, 447 | 'exerciseTypeValue': 1, 448 | 'kilograms': 40, 449 | 'isChecked': False, 450 | 'expectedKilograms': 40, 451 | }, 452 | { 453 | 'isPersonalRecord': False, 454 | 'reps': 8, 455 | 'tagsValue': 0, 456 | 'rpe': 0, 457 | 'exerciseTypeValue': 1, 458 | 'kilograms': 40, 459 | 'isChecked': False, 460 | 'expectedKilograms': 35, 461 | }, 462 | ], 463 | 'superSetOrder': None, 464 | 'notes': '', 465 | 'build': 'a257', 466 | 'parseExercise': { 467 | '__type': 'Pointer', 468 | 'className': 'ParseExercise', 469 | 'objectId': 'qIo8zgd0EA', 470 | }, 471 | 'user': { 472 | '__type': 'Pointer', 473 | 'className': '_User', 474 | 'objectId': 'XXXXXXXX', 475 | }, 476 | 'uniqueId': '709e1f4d-6a3c-4aae-9240-2c7139c4562b', 477 | 'isHidden': 0, 478 | 'objectId': '2aFGyMtOGr', 479 | }, 480 | }, 481 | { 482 | 'method': 'PUT', 483 | 'path': '/parse/classes/ParseSetGroup/xQA6HVV1yF', 484 | 'body': { 485 | 'parseSetsDictionary': [ 486 | { 487 | 'isPersonalRecord': False, 488 | 'reps': 4, 489 | 'tagsValue': 0, 490 | 'rpe': 0, 491 | 'exerciseTypeValue': 5, 492 | 'isChecked': False, 493 | }, 494 | { 495 | 'isPersonalRecord': False, 496 | 'reps': 8, 497 | 'tagsValue': 0, 498 | 'rpe': 0, 499 | 'exerciseTypeValue': 5, 500 | 'isChecked': False, 501 | }, 502 | { 503 | 'isPersonalRecord': False, 504 | 'reps': 8, 505 | 'tagsValue': 0, 506 | 'rpe': 0, 507 | 'exerciseTypeValue': 5, 508 | 'isChecked': False, 509 | }, 510 | ], 511 | 'superSetOrder': None, 512 | 'notes': '', 513 | 'build': 'a257', 514 | 'parseExercise': { 515 | '__type': 'Pointer', 516 | 'className': 'ParseExercise', 517 | 'objectId': 'hp9cgKc7nt', 518 | }, 519 | 'user': { 520 | '__type': 'Pointer', 521 | 'className': '_User', 522 | 'objectId': 'XXXXXXXX', 523 | }, 524 | 'uniqueId': '9e44cee3-b12e-46e9-8bbd-6643ac46d65c', 525 | 'isHidden': 0, 526 | 'objectId': 'xQA6HVV1yF', 527 | }, 528 | }, 529 | { 530 | 'method': 'PUT', 531 | 'path': '/parse/classes/_User/XXXXXXXX', 532 | 'body': { 533 | 'lastVersion': '2.7.9 (257)', 534 | 'persistentNotes': {}, 535 | 'hasPurchasedUnlockStrong': False, 536 | 'ACL': { 537 | 'XXXXXXXX': { 538 | 'read': True, 539 | 'write': True, 540 | }, 541 | '*': { 542 | 'read': True, 543 | }, 544 | }, 545 | 'workoutsPerWeekGoal': 0, 546 | 'distanceUnitValue': 14, 547 | 'firstWeekday': 2, 548 | 'hasPurchasedComboPack': False, 549 | 'exerciseWeightUnitValues': {}, 550 | 'exerciseBars': { 551 | 'pTV7Q84sJW': 'our_little_un-deletable_no_weight_bar', 552 | 'EWm19pmMjX': 'our_little_un-deletable_no_weight_bar', 553 | 'uodPjbv9AD': 'our_little_un-deletable_no_weight_bar', 554 | 'jKzMeLT1MI': 'our_little_un-deletable_no_weight_bar', 555 | 'Fr5Z4hQjuj': 'our_little_un-deletable_no_weight_bar', 556 | 'KIr1hSNTNF': 'our_little_un-deletable_no_weight_bar', 557 | '100TqWO3tI': 'our_little_un-deletable_no_weight_bar', 558 | 'NF7ZnLEaCo': 'our_little_un-deletable_no_weight_bar', 559 | 'wfCkYtT3FK': 'our_little_un-deletable_no_weight_bar', 560 | '8i5WGtS0oO': 'our_little_un-deletable_no_weight_bar', 561 | 'Da5swzH5xc': 'our_little_un-deletable_no_weight_bar', 562 | 'KRODWQlTsz': 'our_little_un-deletable_no_weight_bar', 563 | 'NyW1k6j3hV': 'our_little_un-deletable_no_weight_bar', 564 | 'FLkiUDr4re': 'our_little_un-deletable_no_weight_bar', 565 | 'egksi44eRc': 'our_little_un-deletable_no_weight_bar', 566 | 'oENANmzmDz': 'our_little_un-deletable_no_weight_bar', 567 | 'ON6HTP38c8': 'our_little_un-deletable_no_weight_bar', 568 | 'rzZXMmjXrg': 'our_little_un-deletable_no_weight_bar', 569 | 'RemEUYjkoZ': 'our_little_un-deletable_no_weight_bar', 570 | '5QD729I5Fc': 'our_little_un-deletable_no_weight_bar', 571 | 'eCtchyihUy': 'our_little_un-deletable_no_weight_bar', 572 | 'nDh8Us74T8': 'our_little_un-deletable_no_weight_bar', 573 | '949NJCigex': 'our_little_un-deletable_no_weight_bar', 574 | 'EtNiOHW0ra': 'our_little_un-deletable_no_weight_bar', 575 | 'ZrU2uhPxBU': 'our_little_un-deletable_no_weight_bar', 576 | 'BwAaRYiaI1': 'our_little_un-deletable_no_weight_bar', 577 | 'SPZT7Bbm4I': 'our_little_un-deletable_no_weight_bar', 578 | 'IsQD1RLCAw': 'our_little_un-deletable_no_weight_bar', 579 | 'wXGOcAHqfS': 'our_little_un-deletable_no_weight_bar', 580 | 'f9oYdoIaWy': 'our_little_un-deletable_no_weight_bar', 581 | '4389vcZicE': 'our_little_un-deletable_no_weight_bar', 582 | 'GBVEhxLCp8': 'our_little_un-deletable_no_weight_bar', 583 | 'uLlUVLylTn': 'our_little_un-deletable_no_weight_bar', 584 | '93H8TNQg4C': 'our_little_un-deletable_no_weight_bar', 585 | 'zlMK4Z3iT2': 'our_little_un-deletable_no_weight_bar', 586 | 'ssAHfgQRgf': 'our_little_un-deletable_no_weight_bar', 587 | 'ioCO1kXB9v': 'our_little_un-deletable_no_weight_bar', 588 | 'khcDDtHI64': 'our_little_un-deletable_no_weight_bar', 589 | 'F0pHgvERle': 'our_little_un-deletable_no_weight_bar', 590 | 'uEMx4aDD3G': 'our_little_un-deletable_no_weight_bar', 591 | '4sfUiNyZEv': 'our_little_un-deletable_no_weight_bar', 592 | 'vt2ZDMDLZG': 'our_little_un-deletable_no_weight_bar', 593 | '4RNzidD7Vp': 'our_little_un-deletable_no_weight_bar', 594 | 'lhcK0ygXoJ': 'our_little_un-deletable_no_weight_bar', 595 | 'lEoprkFYZo': 'our_little_un-deletable_no_weight_bar', 596 | '3oL8QpU0W8': 'our_little_un-deletable_no_weight_bar', 597 | 'tklNHrWzOF': 'our_little_un-deletable_no_weight_bar', 598 | 'nljfNLqe2S': 'our_little_un-deletable_no_weight_bar', 599 | 'hYfjsSriQD': 'our_little_un-deletable_no_weight_bar', 600 | 'ZYLas8lazD': 'our_little_un-deletable_no_weight_bar', 601 | 'ENycNTGojT': 'our_little_un-deletable_no_weight_bar', 602 | 'opctrOWR15': 'our_little_un-deletable_no_weight_bar', 603 | 'XxhrxlBEsp': 'our_little_un-deletable_no_weight_bar', 604 | 'C3J3MzGLLv': 'our_little_un-deletable_no_weight_bar', 605 | 'pTOKLwUGZP': 'our_little_un-deletable_no_weight_bar', 606 | 'mdGvg7lBkt': 'our_little_un-deletable_no_weight_bar', 607 | 'A02el3s1qm': 'our_little_un-deletable_no_weight_bar', 608 | 'nPSMbunT1f': 'our_little_un-deletable_no_weight_bar', 609 | 'VrNwEmBTP0': 'our_little_un-deletable_no_weight_bar', 610 | 'c134qTzvU7': 'our_little_un-deletable_no_weight_bar', 611 | 'IyDTukznLV': 'our_little_un-deletable_no_weight_bar', 612 | 'SMTIowUBKy': 'our_little_un-deletable_no_weight_bar', 613 | 'yw5V7e2goL': 'our_little_un-deletable_no_weight_bar', 614 | '6fU6TC4mgC': 'our_little_un-deletable_no_weight_bar', 615 | 'hnhGpeIPU5': 'our_little_un-deletable_no_weight_bar', 616 | 'G4mxCu6iaZ': 'our_little_un-deletable_no_weight_bar', 617 | '98OBEiUvrk': 'our_little_un-deletable_no_weight_bar', 618 | 'ARFhriXsPy': 'our_little_un-deletable_no_weight_bar', 619 | 'SQD7WLePEq': 'our_little_un-deletable_no_weight_bar', 620 | 'VD2qcujHDC': 'our_little_un-deletable_no_weight_bar', 621 | '9qJYWokfTb': 'our_little_un-deletable_no_weight_bar', 622 | 'ufcBWkr5Bg': 'our_little_un-deletable_no_weight_bar', 623 | 'fXW7WHcUn8': 'our_little_un-deletable_no_weight_bar', 624 | 'qg1ric4s1t': 'our_little_un-deletable_no_weight_bar', 625 | '8UKC0MjWJ0': 'our_little_un-deletable_no_weight_bar', 626 | }, 627 | 'timerDuration': 120, 628 | 'lengthUnitValue': 9, 629 | 'build': 'a257', 630 | 'proExpirationDate': { 631 | '__type': 'Date', 632 | 'iso': '2023-04-17T14:02:11.173Z', 633 | }, 634 | 'lastOSVersion': 'Android 13', 635 | 'hasPurchasedPowerPack': False, 636 | 'hasPurchasedPROForever': False, 637 | 'uniqueId': '44fbba75-8d0f-44fd-8902-1f0b33b20bd6', 638 | 'weightUnitValue': 14, 639 | 'username': 'bitwiseshift', 640 | 'goals': '{}', 641 | 'objectId': 'XXXXXXXX', 642 | }, 643 | }, 644 | { 645 | 'method': 'PUT', 646 | 'path': '/parse/classes/ParseSetGroup/HFJNuTnwrU', 647 | 'body': { 648 | 'parseSetsDictionary': [ 649 | { 650 | 'isPersonalRecord': False, 651 | 'seconds': 16, 652 | 'tagsValue': 0, 653 | 'rpe': 0, 654 | 'exerciseTypeValue': 6, 655 | 'isChecked': True, 656 | }, 657 | ], 658 | 'superSetOrder': None, 659 | 'notes': '', 660 | 'build': 'a257', 661 | 'parseExercise': { 662 | '__type': 'Pointer', 663 | 'className': 'ParseExercise', 664 | 'objectId': 'SuGuVl8OYz', 665 | }, 666 | 'user': { 667 | '__type': 'Pointer', 668 | 'className': '_User', 669 | 'objectId': 'XXXXXXXX', 670 | }, 671 | 'uniqueId': 'fd61b7e0-e6cb-4e6e-ab45-a8454fb8fb37', 672 | 'isHidden': 0, 673 | 'objectId': 'HFJNuTnwrU', 674 | }, 675 | }, 676 | ], 677 | } 678 | 679 | response = requests.post('https://ws13.strongapp.co/parse/batch', headers=headers, json=json_data) 680 | ``` 681 | 682 | ### Reponse 683 | ``` 684 | [{ 685 | "success": { 686 | "updatedAt": "2023-02-27T18:11:47.557Z" 687 | } 688 | }, { 689 | "success": { 690 | "updatedAt": "2023-02-27T18:11:47.559Z" 691 | } 692 | }, { 693 | "success": { 694 | "updatedAt": "2023-02-27T18:11:47.556Z" 695 | } 696 | }, { 697 | "success": { 698 | "updatedAt": "2023-02-27T18:11:47.564Z" 699 | } 700 | }, { 701 | "success": { 702 | "updatedAt": "2023-02-27T18:11:47.560Z" 703 | } 704 | }, { 705 | "success": { 706 | "updatedAt": "2023-02-27T18:11:47.562Z" 707 | } 708 | }, { 709 | "success": { 710 | "updatedAt": "2023-02-27T18:11:47.558Z" 711 | } 712 | }, { 713 | "success": { 714 | "updatedAt": "2023-02-27T18:11:47.563Z" 715 | } 716 | }, { 717 | "success": { 718 | "updatedAt": "2023-02-27T18:11:47.561Z" 719 | } 720 | }, { 721 | "success": { 722 | "updatedAt": "2023-02-27T18:11:47.555Z" 723 | } 724 | }, { 725 | "success": { 726 | "updatedAt": "2023-02-27T18:11:47.561Z" 727 | } 728 | }] 729 | ``` -------------------------------------------------------------------------------- /go/strong.go: -------------------------------------------------------------------------------- 1 | package strong 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | type Strong struct { 12 | endpoint string 13 | strongUsername string 14 | strongPassword string 15 | strongDeviceUUID string 16 | strongApplicationID string 17 | debug bool 18 | headers http.Header 19 | response *http.Response 20 | sessionToken string 21 | userObjectID string 22 | } 23 | 24 | func NewStrong() (*Strong, error) { 25 | s := &Strong{} 26 | s.endpoint = "https://ws13.strongapp.co" 27 | s.strongUsername = os.Getenv("strong_username") 28 | s.strongPassword = os.Getenv("strong_password") 29 | s.strongDeviceUUID = os.Getenv("strong_device_uuid") 30 | s.strongApplicationID = os.Getenv("strong_application_id") 31 | s.debug = false 32 | 33 | if s.strongUsername == "" { 34 | return nil, fmt.Errorf("Missing: strong_username") 35 | } 36 | 37 | if s.strongPassword == "" { 38 | return nil, fmt.Errorf("Missing: strong_password") 39 | } 40 | 41 | if s.strongDeviceUUID == "" { 42 | return nil, fmt.Errorf("Missing: strong_device_uuid") 43 | } 44 | 45 | if s.strongApplicationID == "" { 46 | return nil, fmt.Errorf("Missing: strong_application_id") 47 | } 48 | 49 | s.headers = make(http.Header) 50 | s.headers.Add("Host", "ws13.strongapp.co") 51 | s.headers.Add("x-parse-application-id", s.strongApplicationID) 52 | s.headers.Add("x-parse-app-build-version", "257") 53 | s.headers.Add("x-parse-app-display-version", "2.7.9") 54 | s.headers.Add("x-parse-os-version", "13") 55 | s.headers.Add("user-agent", "Parse Android SDK API Level 33") 56 | s.headers.Add("x-parse-installation-id", s.strongDeviceUUID) 57 | s.headers.Add("content-type", "application/json") 58 | s.headers.Add("pragma", "no-cache") 59 | s.headers.Add("cache-control", "no-cache") 60 | 61 | return s, nil 62 | } 63 | 64 | func (s *Strong) WebRequest(method, query string, data interface{}) bool { 65 | var req *http.Request 66 | var err error 67 | if data != nil { 68 | reqBody, err := json.Marshal(data) 69 | if err != nil { 70 | fmt.Println(err) 71 | return false 72 | } 73 | req, err = http.NewRequest(strings.ToUpper(method), s.endpoint+query, strings.NewReader(string(reqBody))) 74 | if err != nil { 75 | fmt.Println(err) 76 | return false 77 | } 78 | } else { 79 | req, err = http.NewRequest(strings.ToUpper(method), s.endpoint+query, nil) 80 | if err != nil { 81 | fmt.Println(err) 82 | return false 83 | } 84 | } 85 | 86 | req.Header = s.headers 87 | 88 | client := &http.Client{} 89 | s.response, err = client.Do(req) 90 | if err != nil { 91 | fmt.Println(err) 92 | return false 93 | } 94 | 95 | defer s.response.Body.Close() 96 | 97 | if s.debug { 98 | // d, err := dumpResponse(s.response) 99 | // if err != nil { 100 | // fmt.Println(err) 101 | // return false 102 | // } 103 | // fmt.Println(d) 104 | fmt.Println(s.response.StatusCode) 105 | fmt.Println(s.response.Body) 106 | } 107 | 108 | if s.response.StatusCode >= 200 && s.response.StatusCode < 300 { 109 | return true 110 | } 111 | 112 | return false 113 | 114 | } 115 | 116 | func (s *Strong) Login() bool { 117 | data := map[string]string{ 118 | "password": s.strongPassword, 119 | "username": s.strongUsername, 120 | "_method": "GET", 121 | } 122 | 123 | if !s.WebRequest("POST", "/parse/login", data) { 124 | return false 125 | } 126 | 127 | var js map[string]interface{} 128 | err := json.NewDecoder(s.response.Body).Decode(&js) 129 | if err != nil { 130 | fmt.Println(err) 131 | return false 132 | } 133 | 134 | return true 135 | } 136 | 137 | func (s *Strong) GetUser() bool { 138 | res := s.WebRequest("GET", "/parse/classes/_User/"+s.userObjectID, nil) 139 | return res 140 | } 141 | 142 | func (s *Strong) GetWorkouts() bool { 143 | where := make(map[string]interface{}) 144 | where["user"] = make(map[string]interface{}) 145 | where["user"]["__type"] = "Pointer" 146 | where["user"]["className"] = "_User" 147 | where["user"]["objectId"] = s.userObjectID 148 | where["updatedAt"] = make(map[string]interface{}) 149 | where["updatedAt"]["$gt"] = make(map[string]interface{}) 150 | where["updatedAt"]["$gt"]["__type"] = "Date" 151 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z" 152 | 153 | data := make(map[string]interface{}) 154 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise" 155 | data["limit"] = "200" 156 | data["where"] = strings.ReplaceAll(json.Marshal(where), "\"", "\\\"") 157 | data["_method"] = "GET" 158 | 159 | res := s.WebRequest("POST", "/parse/classes/ParseWorkout", data) 160 | return res 161 | } 162 | 163 | func (s *Strong) GetWorkOutsPerWeek() bool { 164 | where := make(map[string]interface{}) 165 | where["user"] = make(map[string]interface{}) 166 | where["user"]["__type"] = "Pointer" 167 | where["user"]["className"] = "_User" 168 | where["user"]["objectId"] = s.userObjectID 169 | 170 | data := make(map[string]interface{}) 171 | data["_method"] = "GET" 172 | data["where"] = strings.ReplaceAll(json.Marshal(where), "\"", "\\\"") 173 | 174 | res := s.WebRequest("POST", "/parse/classes/ParseWidget", data) 175 | return res 176 | } 177 | -------------------------------------------------------------------------------- /img/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/img/sample.png -------------------------------------------------------------------------------- /java/strong.java: -------------------------------------------------------------------------------- 1 | import java.util.Map; 2 | import java.util.HashMap; 3 | 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonObject; 6 | 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | import okhttp3.RequestBody; 10 | import okhttp3.MediaType; 11 | import okhttp3.Response; 12 | import okhttp3.Headers; 13 | 14 | public class Strong { 15 | private String endpoint = "https://ws13.strongapp.co"; 16 | private String strong_username = System.getenv("strong_username"); 17 | private String strong_password = System.getenv("strong_password"); 18 | private String strong_device_uuid = System.getenv("strong_device_uuid"); 19 | private String strong_application_id = System.getenv("strong_application_id"); 20 | private boolean debug = false; 21 | private String session_token; 22 | private String user_object_id; 23 | private OkHttpClient client; 24 | private Headers headers; 25 | 26 | public Strong() { 27 | if (strong_username == null) { 28 | System.out.println("Missing: strong_username"); 29 | System.exit(1); 30 | } 31 | 32 | if (strong_password == null) { 33 | System.out.println("Missing: strong_password"); 34 | System.exit(2); 35 | } 36 | 37 | if (strong_device_uuid == null) { 38 | System.out.println("Missing: strong_device_uuid"); 39 | System.exit(3); 40 | } 41 | 42 | if (strong_application_id == null) { 43 | System.out.println("Missing: strong_application_id"); 44 | System.exit(4); 45 | } 46 | 47 | this.headers = new Headers.Builder() 48 | .add("Host", "ws13.strongapp.co") 49 | .add("x-parse-application-id", strong_application_id) 50 | .add("x-parse-app-build-version", "257") 51 | .add("x-parse-app-display-version", "2.7.9") 52 | .add("x-parse-os-version", "13") 53 | .add("user-agent", "Parse Android SDK API Level 33") 54 | .add("x-parse-installation-id", strong_device_uuid) 55 | .add("content-type", "application/json") 56 | .add("pragma", "no-cache") 57 | .add("cache-control", "no-cache") 58 | .build(); 59 | 60 | this.client = new OkHttpClient(); 61 | } 62 | 63 | public void setDebug(boolean debug) { 64 | this.debug = debug; 65 | } 66 | 67 | private boolean webRequest(String method, String query, JsonObject data) { 68 | try { 69 | Request.Builder requestBuilder = new Request.Builder() 70 | .url(endpoint + query) 71 | .headers(this.headers); 72 | 73 | if (method.equals("POST")) { 74 | RequestBody body = RequestBody.create(MediaType.parse("application/json"), data.toString()); 75 | requestBuilder.post(body); 76 | } else { 77 | requestBuilder.get(); 78 | } 79 | 80 | Response response = this.client.newCall(requestBuilder.build()).execute(); 81 | 82 | if (debug) { 83 | System.out.println(response.headers()); 84 | System.out.println(response.code()); 85 | System.out.println(response.body().string()); 86 | } 87 | 88 | if (response.isSuccessful()) { 89 | return true; 90 | } 91 | 92 | return false; 93 | } catch (Exception e) { 94 | System.out.println(e.getMessage()); 95 | return false; 96 | } 97 | } 98 | 99 | public boolean login() { 100 | try { 101 | JsonObject data = new JsonObject(); 102 | data.addProperty("password", strong_password); 103 | data.addProperty("username", strong_username); 104 | data.addProperty("_method", "GET"); 105 | 106 | boolean res = this.webRequest("POST", "/parse/login", data); 107 | 108 | Gson gson = new Gson(); 109 | JsonObject responseJson = gson.fromJson(res, JsonObject.class); 110 | 111 | session_token = responseJson.get("sessionToken").getAsString(); 112 | user_object_id = responseJson.get("objectId").getAsString(); 113 | 114 | this.headers = this.headers.newBuilder().add("x-parse-session-token", session_token).build(); 115 | 116 | return res; 117 | } catch (Exception e) { 118 | System.out.println(e.getMessage()); 119 | return false; 120 | } 121 | } 122 | 123 | public boolean GetUser() { 124 | try { 125 | String path = "/parse/classes/_User/" + this.user_object_id; 126 | boolean res = this.WebRequest("GET", path); 127 | return res; 128 | } catch (Exception e) { 129 | System.out.println(e.toString()); 130 | return false; 131 | } 132 | } 133 | 134 | public boolean GetWorkouts() { 135 | try { 136 | JSONObject where = new JSONObject(); 137 | JSONObject user = new JSONObject(); 138 | user.put("__type", "Pointer"); 139 | user.put("className", "_User"); 140 | user.put("objectId", this.user_object_id); 141 | where.put("user", user); 142 | JSONObject updatedAt = new JSONObject(); 143 | JSONObject gt = new JSONObject(); 144 | gt.put("__type", "Date"); 145 | gt.put("iso", "1970-01-01T00:00:00.000Z"); 146 | updatedAt.put("$gt", gt); 147 | where.put("updatedAt", updatedAt); 148 | 149 | JSONObject data = new JSONObject(); 150 | data.put("include", "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise"); 151 | data.put("limit", "200"); 152 | data.put("where", where.toString()); 153 | 154 | boolean res = this.WebRequest("POST", "/parse/classes/ParseWorkout", data.toString()); 155 | 156 | return res; 157 | } catch (Exception e) { 158 | System.out.println(e.toString()); 159 | return false; 160 | } 161 | } 162 | 163 | public boolean GetWorkOutsPerWeek() { 164 | try { 165 | JSONObject where = new JSONObject(); 166 | JSONObject user = new JSONObject(); 167 | user.put("__type", "Pointer"); 168 | user.put("className", "_User"); 169 | user.put("objectId", this.user_object_id); 170 | where.put("user", user); 171 | 172 | JSONObject data = new JSONObject(); 173 | data.put("_method", "GET"); 174 | data.put("where", where.toString()); 175 | 176 | boolean res = this.WebRequest("POST", "/parse/classes/ParseWidget", data.toString()); 177 | return res; 178 | } catch (Exception e) { 179 | System.out.println(e.toString()); 180 | return false; 181 | } 182 | } 183 | 184 | public boolean GetWorkOutsCount() { 185 | try { 186 | JSONObject where = new JSONObject(); 187 | JSONObject user = new JSONObject(); 188 | user.put("__type", "Pointer"); 189 | user.put("className", "_User"); 190 | user.put("objectId", this.user_object_id); 191 | where.put("user", user); 192 | JSONObject updatedAt = new JSONObject(); 193 | JSONObject gt = new JSONObject(); 194 | gt.put("__type", "Date"); 195 | gt.put("iso", "1970-01-01T00:00:00.000Z"); 196 | updatedAt.put("$gt", gt); 197 | where.put("updatedAt", updatedAt); 198 | 199 | JSONObject data = new JSONObject(); 200 | data.put("include", "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise"); 201 | data.put("limit", "0"); 202 | data.put("count", "1"); 203 | data.put("where", where.toString()); 204 | data.put("_method", "GET"); 205 | 206 | boolean res = this.WebRequest("POST", "/parse/classes/ParseWorkout", data.toString()); 207 | return res; 208 | } catch (Exception e) { 209 | System.out.println(e.toString()); 210 | return false; 211 | } 212 | } 213 | 214 | public JSONObject GetJSON() { 215 | return this.response.getJSONObject(); 216 | } 217 | 218 | public String GetText() { 219 | return this.response.toString(); 220 | } 221 | 222 | public boolean SaveResponseToFile(String filename) { 223 | try { 224 | FileWriter save_file = new FileWriter(filename); 225 | save_file.write(this.response.toString()); 226 | save_file.close(); 227 | return true; 228 | } catch (Exception e) { 229 | System.out.println(e.toString()); 230 | return false; 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /javascript/strong.js: -------------------------------------------------------------------------------- 1 | import { env } from 'process'; 2 | import request from 'request'; 3 | 4 | class Strong { 5 | constructor() { 6 | this.endpoint = "https://ws13.strongapp.co"; 7 | this.strong_username = env.strong_username; 8 | this.strong_password = env.strong_password; 9 | this.strong_device_uuid = env.strong_device_uuid; 10 | this.strong_application_id = env.strong_application_id; 11 | this.debug = false; 12 | 13 | if (!this.strong_username) { 14 | console.log("Missing: strong_username"); 15 | process.exit(1); 16 | } 17 | 18 | if (!this.strong_password) { 19 | console.log("Missing: strong_password"); 20 | process.exit(2); 21 | } 22 | 23 | if (!this.strong_device_uuid) { 24 | console.log("Missing: strong_device_uuid"); 25 | process.exit(3); 26 | } 27 | 28 | if (!this.strong_application_id) { 29 | console.log("Missing: strong_application_id"); 30 | process.exit(4); 31 | } 32 | 33 | this.headers = { 34 | 'Host': 'ws13.strongapp.co', 35 | 'x-parse-application-id': this.strong_application_id, 36 | 'x-parse-app-build-version': '257', 37 | 'x-parse-app-display-version': '2.7.9', 38 | 'x-parse-os-version': '13', 39 | 'user-agent': 'Parse Android SDK API Level 33', 40 | 'x-parse-installation-id': this.strong_device_uuid, 41 | 'content-type': 'application/json', 42 | 'pragma': 'no-cache', 43 | 'cache-control': 'no-cache' 44 | }; 45 | } 46 | 47 | async WebRequest(method, query, data = null) { 48 | try { 49 | if (method === "POST") { 50 | this.response = await request.post({ 51 | url: this.endpoint + query, 52 | json: data, 53 | headers: this.headers 54 | }); 55 | } else { 56 | this.response = await request.get({ 57 | url: this.endpoint + query, 58 | headers: this.headers 59 | }); 60 | } 61 | 62 | if (this.debug) { 63 | const data = this.response.toJSON(); 64 | console.log(data.body); 65 | console.log(this.response.statusCode); 66 | console.log(this.response.text); 67 | } 68 | 69 | if (this.response.ok) { 70 | return true; 71 | } 72 | 73 | return false; 74 | } catch (e) { 75 | console.log(e.toString()); 76 | return false; 77 | } 78 | } 79 | 80 | async Login() { 81 | try { 82 | const data = {}; 83 | data["password"] = this.strong_password; 84 | data["username"] = this.strong_username; 85 | data["_method"] = "GET"; 86 | 87 | const res = await this.WebRequest("POST", "/parse/login", data); 88 | 89 | const js = this.response.json(); 90 | this.session_token = js["sessionToken"]; 91 | this.user_object_id = js["objectId"]; 92 | 93 | this.headers['x-parse-session-token'] = this.session_token; 94 | return res; 95 | } catch (e) { 96 | console.log(e.toString()); 97 | return false; 98 | } 99 | } 100 | 101 | async GetUser() { 102 | try { 103 | var res = WebRequest("GET", "/parse/classes/_User/" + this.user_object_id); 104 | return res; 105 | } catch (e) { 106 | console.log(e.toString()); 107 | return false; 108 | } 109 | } 110 | 111 | async GetWorkouts() { 112 | try { 113 | var where = {}; 114 | where["user"] = {}; 115 | where["user"]["__type"] = "Pointer"; 116 | where["user"]["className"] = "_User"; 117 | where["user"]["objectId"] = this.user_object_id; 118 | where["updatedAt"] = {}; 119 | where["updatedAt"]["$gt"] = {}; 120 | where["updatedAt"]["$gt"]["__type"] = "Date"; 121 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z"; 122 | 123 | var data = {}; 124 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise"; 125 | data["limit"] = "200"; 126 | data["where"] = JSON.stringify(where).replace('"', '\"'); 127 | data["_method"] = "GET"; 128 | 129 | var res = WebRequest("POST", "/parse/classes/ParseWorkout", data); 130 | 131 | return res; 132 | } catch (e) { 133 | console.log(e.toString()); 134 | return false; 135 | } 136 | } 137 | 138 | async GetWorkOutsPerWeek() { 139 | try { 140 | var where = {}; 141 | where["user"] = {}; 142 | where["user"]["__type"] = "Pointer"; 143 | where["user"]["className"] = "_User"; 144 | where["user"]["objectId"] = this.user_object_id; 145 | 146 | var data = {}; 147 | data["_method"] = "GET"; 148 | data["where"] = JSON.stringify(where).replace('"', '\"'); 149 | 150 | var res = WebRequest("POST", "/parse/classes/ParseWidget", data); 151 | return res; 152 | } catch (e) { 153 | console.log(e.toString()); 154 | return false; 155 | } 156 | } 157 | 158 | async GetWorkOutsCount() { 159 | try { 160 | let where = {}; 161 | where.user = {}; 162 | where.user.__type = "Pointer"; 163 | where.user.className = "_User"; 164 | where.user.objectId = this.user_object_id; 165 | where.updatedAt = {}; 166 | where.updatedAt.$gt = {}; 167 | where.updatedAt.$gt.__type = "Date"; 168 | where.updatedAt.$gt.iso = "1970-01-01T00:00:00.000Z"; 169 | 170 | let data = {}; 171 | data.include = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise"; 172 | data.limit = "0"; 173 | data.count = "1"; 174 | data.where = JSON.stringify(where); 175 | 176 | let options = {}; 177 | options.method = "POST"; 178 | options.body = JSON.stringify(data); 179 | 180 | let res = await this.WebRequest("/parse/classes/ParseWorkout", options); 181 | return res; 182 | } catch (e) { 183 | console.log(e); 184 | return false; 185 | } 186 | } 187 | 188 | async GetJSON() { 189 | return this.response.json(); 190 | } 191 | 192 | async GetText() { 193 | return this.response.text; 194 | } 195 | 196 | async SaveResponseToFile(filename) { 197 | try { 198 | let save_file = fs.createWriteStream(filename); 199 | save_file.write(this.response.text); 200 | save_file.close(); 201 | return true; 202 | } catch (e) { 203 | console.log(e); 204 | return false; 205 | } 206 | } 207 | } 208 | 209 | export default Strong; -------------------------------------------------------------------------------- /perl/strong.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use LWP::UserAgent; 4 | use HTTP::Request::Common qw(POST GET); 5 | use JSON; 6 | use Data::Dump qw(dump); 7 | 8 | package Strong; 9 | 10 | sub new { 11 | my $class = shift; 12 | my $self = { 13 | endpoint => "https://ws13.strongapp.co", 14 | strong_username => $ENV{strong_username}, 15 | strong_password => $ENV{strong_password}, 16 | strong_device_uuid => $ENV{strong_device_uuid}, 17 | strong_application_id => $ENV{strong_application_id}, 18 | debug => 0, 19 | headers => { 20 | Host => 'ws13.strongapp.co', 21 | 'x-parse-application-id' => $ENV{strong_application_id}, 22 | 'x-parse-app-build-version' => '257', 23 | 'x-parse-app-display-version' => '2.7.9', 24 | 'x-parse-os-version' => '13', 25 | 'user-agent' => 'Parse Android SDK API Level 33', 26 | 'x-parse-installation-id' => $ENV{strong_device_uuid}, 27 | 'content-type' => 'application/json', 28 | pragma => 'no-cache', 29 | 'cache-control' => 'no-cache' 30 | } 31 | }; 32 | if (!defined $self->{strong_username}) { 33 | print "Missing: strong_username\n"; 34 | exit(1); 35 | } 36 | if (!defined $self->{strong_password}) { 37 | print "Missing: strong_password\n"; 38 | exit(2); 39 | } 40 | if (!defined $self->{strong_device_uuid}) { 41 | print "Missing: strong_device_uuid\n"; 42 | exit(3); 43 | } 44 | if (!defined $self->{strong_application_id}) { 45 | print "Missing: strong_application_id\n"; 46 | exit(4); 47 | } 48 | bless $self, $class; 49 | return $self; 50 | } 51 | 52 | sub WebRequest { 53 | my ($self, $method, $query, $data) = @_; 54 | my $ua = LWP::UserAgent->new; 55 | my $url = $self->{endpoint} . $query; 56 | my $req; 57 | if ($method eq "POST") { 58 | $req = POST($url, Content_Type => 'application/json', Content => encode_json($data), %{$self->{headers}}); 59 | } else { 60 | $req = GET($url, %{$self->{headers}}); 61 | } 62 | my $res = $ua->request($req); 63 | if ($self->{debug}) { 64 | print dump($req->as_string); 65 | print dump($res->as_string); 66 | print $res->status_line, "\n"; 67 | print $res->content, "\n"; 68 | } 69 | if ($res->is_success) { 70 | return 1; 71 | } 72 | return 0; 73 | } 74 | 75 | sub Login { 76 | my $self = shift; 77 | my $data = { 78 | username => $self->{strong_username}, 79 | password => $self->{strong_password}, 80 | _method => "GET" 81 | }; 82 | my $res = $self->WebRequest("POST", "/parse/login", $data); 83 | my $js = decode_json($res->content); 84 | $self->{session_token} = $js->{sessionToken}; 85 | $self->{user_object_id} = $js->{objectId}; 86 | $self->{headers}->{'x-parse-session-token'} = $self->{session_token}; 87 | return $res->is_success; 88 | } 89 | 90 | sub GetUser { 91 | my $self = shift; 92 | eval { 93 | my $res = $self->WebRequest("GET", "/parse/classes/_User/" . $self->{user_object_id}); 94 | return $res; 95 | } or do { 96 | my $e = $@; 97 | print "$e"; 98 | return 0; 99 | }; 100 | } 101 | 102 | sub GetWorkouts { 103 | my $self = shift; 104 | eval { 105 | my %where = ( 106 | user => { 107 | __type => "Pointer", 108 | className => "_User", 109 | objectId => $self->{user_object_id} 110 | }, 111 | updatedAt => { 112 | '$gt' => { 113 | __type => "Date", 114 | iso => "1970-01-01T00:00:00.000Z" 115 | } 116 | } 117 | ); 118 | my %data = ( 119 | include => "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise", 120 | limit => "200", 121 | where => encode_json(\%where), 122 | _method => "GET" 123 | ); 124 | my $res = $self->WebRequest("POST", "/parse/classes/ParseWorkout", \%data); 125 | return $res; 126 | } or do { 127 | my $e = $@; 128 | print "$e"; 129 | return 0; 130 | }; 131 | } 132 | 133 | sub GetWorkOutsPerWeek { 134 | my $self = shift; 135 | eval { 136 | my %where = ( 137 | user => { 138 | __type => "Pointer", 139 | className => "_User", 140 | objectId => $self->{user_object_id} 141 | } 142 | ); 143 | my %data = ( 144 | _method => "GET", 145 | where => encode_json(\%where) 146 | ); 147 | my $res = $self->WebRequest("POST", "/parse/classes/ParseWidget", \%data); 148 | return $res; 149 | } or do { 150 | my $e = $@; 151 | print "$e"; 152 | return 0; 153 | }; 154 | } 155 | 156 | 157 | sub GetWorkOutsCount { 158 | my $self = shift; 159 | my $where = { 160 | user => { 161 | __type => "Pointer", 162 | className => "_User", 163 | objectId => $self->{user_object_id} 164 | }, 165 | updatedAt => { 166 | '$gt' => { 167 | __type => "Date", 168 | iso => "1970-01-01T00:00:00.000Z" 169 | } 170 | } 171 | }; 172 | 173 | my $data = { 174 | include => "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise", 175 | limit => 0, 176 | count => 1, 177 | where => JSON::encode_json($where) 178 | }; 179 | 180 | my $res = $self->WebRequest("POST", "/parse/classes/ParseWorkout", $data); 181 | return $res; 182 | } 183 | 184 | sub GetJSON { 185 | my $self = shift; 186 | return $self->{response}->json(); 187 | } 188 | 189 | sub GetText { 190 | my $self = shift; 191 | return $self->{response}->text(); 192 | } 193 | 194 | sub SaveResponseToFile { 195 | my ($self, $filename) = @_; 196 | eval { 197 | open(my $save_file, ">", $filename) or die "Cannot open file $filename: $!"; 198 | print $save_file $self->{response}->text(); 199 | close($save_file); 200 | return 1; 201 | } or do { 202 | my $error = $@ || "Unknown error"; 203 | print "$error\n"; 204 | return 0; 205 | }; 206 | } 207 | 208 | 1; -------------------------------------------------------------------------------- /php/strong.php: -------------------------------------------------------------------------------- 1 | endpoint = 'https://ws13.strongapp.co'; 23 | $this->strong_username = getenv('strong_username'); 24 | $this->strong_password = getenv('strong_password'); 25 | $this->strong_device_uuid = getenv('strong_device_uuid'); 26 | $this->strong_application_id = getenv('strong_application_id'); 27 | $this->debug = false; 28 | 29 | if (!$this->strong_username) { 30 | echo 'Missing: strong_username'; 31 | exit(1); 32 | } 33 | 34 | if (!$this->strong_password) { 35 | echo 'Missing: strong_password'; 36 | exit(2); 37 | } 38 | 39 | if (!$this->strong_device_uuid) { 40 | echo 'Missing: strong_device_uuid'; 41 | exit(3); 42 | } 43 | 44 | if (!$this->strong_application_id) { 45 | echo 'Missing: strong_application_id'; 46 | exit(4); 47 | } 48 | 49 | $this->headers = [ 50 | 'Host' => 'ws13.strongapp.co', 51 | 'x-parse-application-id' => $this->strong_application_id, 52 | 'x-parse-app-build-version' => '257', 53 | 'x-parse-app-display-version' => '2.7.9', 54 | 'x-parse-os-version' => '13', 55 | 'user-agent' => 'Parse Android SDK API Level 33', 56 | 'x-parse-installation-id' => $this->strong_device_uuid, 57 | 'content-type' => 'application/json', 58 | 'pragma' => 'no-cache', 59 | 'cache-control' => 'no-cache' 60 | ]; 61 | } 62 | 63 | public function WebRequest($method, $query, $data = null) 64 | { 65 | try { 66 | $client = new Client(['base_uri' => $this->endpoint]); 67 | $options = [ 68 | 'headers' => $this->headers, 69 | 'http_errors' => false 70 | ]; 71 | 72 | if ($method === 'POST') { 73 | $options['json'] = $data; 74 | $this->response = $client->post($query, $options); 75 | } else { 76 | $this->response = $client->get($query, $options); 77 | } 78 | 79 | if ($this->debug) { 80 | $body = (string) $this->response->getBody(); 81 | $statusCode = $this->response->getStatusCode(); 82 | var_dump($statusCode); 83 | var_dump($body); 84 | } 85 | 86 | if ($this->response->getStatusCode() >= 200 && $this->response->getStatusCode() < 300) { 87 | return true; 88 | } 89 | 90 | return false; 91 | } catch (ClientException $e) { 92 | echo $e->getMessage(); 93 | return false; 94 | } 95 | } 96 | 97 | public function login() 98 | { 99 | try { 100 | $data = array(); 101 | $data["password"] = $this->strong_password; 102 | $data["username"] = $this->strong_username; 103 | $data["_method"] = "GET"; 104 | 105 | $res = $this->webRequest("POST", "/parse/login", $data); 106 | 107 | $js = json_decode($this->response, true); 108 | $this->session_token = $js["sessionToken"]; 109 | $this->user_object_id = $js["objectId"]; 110 | 111 | $this->headers['x-parse-session-token'] = $this->session_token; 112 | return $res; 113 | } catch (Exception $e) { 114 | echo $e->getMessage(); 115 | return false; 116 | } 117 | } 118 | 119 | public function getUser() 120 | { 121 | try { 122 | $res = $this->webRequest("GET", "/parse/classes/_User/" . $this->user_object_id); 123 | return $res; 124 | } catch (Exception $e) { 125 | echo $e->getMessage(); 126 | return false; 127 | } 128 | } 129 | 130 | public function getWorkouts() 131 | { 132 | try { 133 | $where = array(); 134 | $where["user"] = array(); 135 | $where["user"]["__type"] = "Pointer"; 136 | $where["user"]["className"] = "_User"; 137 | $where["user"]["objectId"] = $this->user_object_id; 138 | $where["updatedAt"] = array(); 139 | $where["updatedAt"]["$gt"] = array(); 140 | $where["updatedAt"]["$gt"]["__type"] = "Date"; 141 | $where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z"; 142 | 143 | $data = array(); 144 | $data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise"; 145 | $data["limit"] = "200"; 146 | $data["where"] = json_encode($where); 147 | 148 | $res = $this->webRequest("POST", "/parse/classes/ParseWorkout", $data); 149 | return $res; 150 | } catch (Exception $e) { 151 | echo $e->getMessage(); 152 | return false; 153 | } 154 | } 155 | 156 | public function getWorkoutsPerWeek() 157 | { 158 | try { 159 | $where = array(); 160 | $where["user"] = array(); 161 | $where["user"]["__type"] = "Pointer"; 162 | $where["user"]["className"] = "_User"; 163 | $where["user"]["objectId"] = $this->user_object_id; 164 | 165 | $data = array(); 166 | $data["_method"] = "GET"; 167 | $data["where"] = json_encode($where); 168 | 169 | $res = $this->webRequest("POST", "/parse/classes/ParseWidget", $data); 170 | return $res; 171 | } catch (Exception $e) { 172 | echo $e->getMessage(); 173 | return false; 174 | } 175 | } 176 | 177 | public function GetWorkOutsCount() 178 | { 179 | try { 180 | $where = array( 181 | "user" => array( 182 | "__type" => "Pointer", 183 | "className" => "_User", 184 | "objectId" => $this->user_object_id 185 | ), 186 | "updatedAt" => array( 187 | "$gt" => array( 188 | "__type" => "Date", 189 | "iso" => "1970-01-01T00:00:00.000Z" 190 | ) 191 | ) 192 | ); 193 | 194 | $data = array( 195 | "include" => "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise", 196 | "limit" => "0", 197 | "count" => "1", 198 | "where" => json_encode($where) 199 | ); 200 | 201 | $data["_method"] = "GET"; 202 | 203 | $res = $this->WebRequest("POST", "/parse/classes/ParseWorkout", $data); 204 | 205 | return $res; 206 | } catch (Exception $e) { 207 | echo $e->getMessage(); 208 | return false; 209 | } 210 | } 211 | 212 | public function GetJSON() 213 | { 214 | return json_decode($this->response, true); 215 | } 216 | 217 | public function GetText() 218 | { 219 | return $this->response; 220 | } 221 | 222 | public function SaveResponseToFile($filename) 223 | { 224 | try { 225 | $save_file = fopen($filename, "w"); 226 | fwrite($save_file, $this->response); 227 | fclose($save_file); 228 | return true; 229 | } catch (Exception $e) { 230 | echo $e->getMessage(); 231 | return false; 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /python/strong.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | import requests 3 | from requests_toolbelt.utils import dump 4 | import os 5 | import sys 6 | import json 7 | 8 | 9 | class Strong: 10 | def __init__(self): 11 | self.endpoint = "https://ws13.strongapp.co" 12 | self.strong_username = os.environ.get('strong_username') 13 | self.strong_password = os.environ.get('strong_password') 14 | self.strong_device_uuid = os.environ.get('strong_device_uuid') 15 | self.strong_application_id = os.environ.get('strong_application_id') 16 | self.debug = False 17 | 18 | if self.strong_username is None: 19 | print("Missing: strong_username") 20 | sys.exit(1) 21 | 22 | if self.strong_password is None: 23 | print("Missing: strong_password") 24 | sys.exit(2) 25 | 26 | if self.strong_device_uuid is None: 27 | print("Missing: strong_device_uuid") 28 | sys.exit(3) 29 | 30 | if self.strong_application_id is None: 31 | print("Missing: strong_application_id") 32 | sys.exit(4) 33 | 34 | self.headers = { 35 | 'Host': 'ws13.strongapp.co', 36 | 'x-parse-application-id': self.strong_application_id, 37 | 'x-parse-app-build-version': '257', 38 | 'x-parse-app-display-version': '2.7.9', 39 | 'x-parse-os-version': '13', 40 | 'user-agent': 'Parse Android SDK API Level 33', 41 | 'x-parse-installation-id': self.strong_device_uuid, 42 | 'content-type': 'application/json', 43 | 'pragma': 'no-cache', 44 | 'cache-control': 'no-cache' 45 | } 46 | 47 | def WebRequest(self, method, query, data=None): 48 | try: 49 | if method == "POST": 50 | self.response = requests.post( 51 | self.endpoint + query, json=data, headers=self.headers) 52 | else: 53 | self.response = requests.get( 54 | self.endpoint + query, headers=self.headers) 55 | 56 | if self.debug: 57 | data = dump.dump_all(self.response) 58 | print(data.decode('utf-8')) 59 | print(self.response.status_code) 60 | pprint(self.response.text) 61 | 62 | if self.response.ok: 63 | return True 64 | 65 | return False 66 | except Exception as e: 67 | print(str(e)) 68 | return False 69 | 70 | def Login(self): 71 | try: 72 | data = {} 73 | data["password"] = self.strong_password 74 | data["username"] = self.strong_username 75 | data["_method"] = "GET" 76 | 77 | res = self.WebRequest("POST", "/parse/login", data) 78 | 79 | js = self.response.json() 80 | self.session_token = js["sessionToken"] 81 | self.user_object_id = js["objectId"] 82 | 83 | self.headers['x-parse-session-token'] = self.session_token 84 | return res 85 | except Exception as e: 86 | print(str(e)) 87 | return False 88 | 89 | def GetUser(self): 90 | try: 91 | res = self.WebRequest( 92 | "GET", "/parse/classes/_User/" + self.user_object_id) 93 | return res 94 | except Exception as e: 95 | print(str(e)) 96 | return False 97 | 98 | def GetWorkouts(self): 99 | try: 100 | where = {} 101 | where["user"] = {} 102 | where["user"]["__type"] = "Pointer" 103 | where["user"]["className"] = "_User" 104 | where["user"]["objectId"] = self.user_object_id 105 | where["updatedAt"] = {} 106 | where["updatedAt"]["$gt"] = {} 107 | where["updatedAt"]["$gt"]["__type"] = "Date" 108 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z" 109 | 110 | data = {} 111 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise" 112 | data["limit"] = "200" 113 | data["where"] = json.dumps(where).replace('"', '\"') 114 | data["_method"] = "GET" 115 | 116 | res = self.WebRequest("POST", "/parse/classes/ParseWorkout", data) 117 | 118 | return res 119 | except Exception as e: 120 | print(str(e)) 121 | return False 122 | 123 | def GetWorkOutsPerWeek(self): 124 | try: 125 | where = {} 126 | where["user"] = {} 127 | where["user"]["__type"] = "Pointer" 128 | where["user"]["className"] = "_User" 129 | where["user"]["objectId"] = self.user_object_id 130 | 131 | data = {} 132 | data["_method"] = "GET" 133 | data["where"] = json.dumps(where).replace('"', '\"') 134 | 135 | res = self.WebRequest("POST", "/parse/classes/ParseWidget", data) 136 | return res 137 | except Exception as e: 138 | print(str(e)) 139 | return False 140 | 141 | def GetWorkOutsCount(self): 142 | try: 143 | where = {} 144 | where["user"] = {} 145 | where["user"]["__type"] = "Pointer" 146 | where["user"]["className"] = "_User" 147 | where["user"]["objectId"] = self.user_object_id 148 | where["updatedAt"] = {} 149 | where["updatedAt"]["$gt"] = {} 150 | where["updatedAt"]["$gt"]["__type"] = "Date" 151 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z" 152 | 153 | data = {} 154 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise" 155 | data["limit"] = "0" 156 | data["count"] = "1" 157 | data["where"] = json.dumps(where).replace('"', '\"') 158 | data["_method"] = "GET" 159 | 160 | res = self.WebRequest("POST", "/parse/classes/ParseWorkout", data) 161 | return res 162 | except Exception as e: 163 | print(str(e)) 164 | return False 165 | 166 | def GetJSON(self): 167 | return self.response.json() 168 | 169 | def GetText(self): 170 | return self.response.text 171 | 172 | def SaveResponseToFile(self, filename): 173 | try: 174 | save_file = open(filename, "w") 175 | save_file.write(self.response.text) 176 | save_file.close() 177 | return True 178 | except Exception as e: 179 | print(str(e)) 180 | return False 181 | -------------------------------------------------------------------------------- /sample/1.login.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | import requests 3 | import os 4 | import sys 5 | 6 | strong_username = os.getenv('strong_username') 7 | strong_password = os.environ.get('strong_password') 8 | strong_device_uuid = os.environ.get('strong_device_uuid') 9 | strong_application_id = os.environ.get('strong_application_id') 10 | 11 | if strong_username is None: 12 | sys.exit(1) 13 | 14 | if strong_password is None: 15 | sys.exit(2) 16 | 17 | if strong_device_uuid is None: 18 | sys.exit(3) 19 | 20 | if strong_application_id is None: 21 | sys.exit(4) 22 | 23 | headers = { 24 | 'Host': 'ws13.strongapp.co', 25 | 'x-parse-application-id': strong_application_id, 26 | 'x-parse-app-build-version': '257', 27 | 'x-parse-app-display-version': '2.7.9', 28 | 'x-parse-os-version': '13', 29 | 'user-agent': 'Parse Android SDK API Level 33', 30 | 'x-parse-installation-id': strong_device_uuid, 31 | 'content-type': 'application/json', 32 | 'pragma': 'no-cache', 33 | 'cache-control': 'no-cache' 34 | } 35 | 36 | data = '{"password":"' + strong_password + '","username":"' + strong_username + '","_method":"GET"}' 37 | endpoint = "https://ws13.strongapp.co/parse/login" 38 | 39 | response = requests.post(endpoint, headers=headers, data=data) 40 | 41 | pprint(headers) 42 | pprint(data) 43 | pprint(response.json()) 44 | pprint(response.ok) 45 | pprint(response.status_code) -------------------------------------------------------------------------------- /sample/2.workout-history.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | import requests 3 | from requests_toolbelt.utils import dump 4 | import os 5 | import sys 6 | import json 7 | 8 | 9 | class Strong: 10 | def __init__(self): 11 | self.endpoint = "https://ws13.strongapp.co" 12 | self.strong_username = os.environ.get('strong_username') 13 | self.strong_password = os.environ.get('strong_password') 14 | self.strong_device_uuid = os.environ.get('strong_device_uuid') 15 | self.strong_application_id = os.environ.get('strong_application_id') 16 | self.request_no = 0 17 | 18 | if self.strong_username is None: 19 | sys.exit(1) 20 | 21 | if self.strong_password is None: 22 | sys.exit(2) 23 | 24 | if self.strong_device_uuid is None: 25 | sys.exit(3) 26 | 27 | if self.strong_application_id is None: 28 | sys.exit(4) 29 | 30 | self.headers = { 31 | 'Host': 'ws13.strongapp.co', 32 | 'x-parse-application-id': self.strong_application_id, 33 | 'x-parse-app-build-version': '257', 34 | 'x-parse-app-display-version': '2.7.9', 35 | 'x-parse-os-version': '13', 36 | 'user-agent': 'Parse Android SDK API Level 33', 37 | 'x-parse-installation-id': self.strong_device_uuid, 38 | 'content-type': 'application/json', 39 | 'pragma': 'no-cache', 40 | 'cache-control': 'no-cache' 41 | } 42 | 43 | 44 | def WebRequest(self, method, query, data=None): 45 | self.request_no += 1 46 | print("==================" + str(self.request_no) + "===================") 47 | 48 | if method == "POST": 49 | self.response = requests.post(self.endpoint + query, json=data, headers=self.headers) 50 | else: 51 | self.response = requests.get(self.endpoint + query, headers=self.headers) 52 | 53 | data = dump.dump_all(self.response) 54 | print(data.decode('utf-8')) 55 | 56 | print(self.response.status_code) 57 | pprint(self.response.text) 58 | 59 | 60 | def Login(self): 61 | data = {} 62 | data["password"] = self.strong_password 63 | data["username"] = self.strong_username 64 | data["_method"] = "GET" 65 | 66 | self.WebRequest("POST", "/parse/login", data) 67 | 68 | js = self.response.json() 69 | self.session_token = js["sessionToken"] 70 | self.user_object_id = js["objectId"] 71 | 72 | self.headers['x-parse-session-token'] = self.session_token 73 | 74 | def GetUser(self): 75 | self.WebRequest("GET", "/parse/classes/_User/" + self.user_object_id) 76 | 77 | def GetWorkouts(self): 78 | where = {} 79 | where["user"] = {} 80 | where["user"]["__type"] = "Pointer" 81 | where["user"]["className"] = "_User" 82 | where["user"]["objectId"] = self.user_object_id 83 | where["updatedAt"] = {} 84 | where["updatedAt"]["$gt"] = {} 85 | where["updatedAt"]["$gt"]["__type"] = "Date" 86 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z" 87 | 88 | data = {} 89 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise" 90 | data["limit"] = "200" 91 | data["where"] = json.dumps(where).replace('"', '\"') 92 | data["_method"] = "GET" 93 | 94 | self.WebRequest("POST", "/parse/classes/ParseWorkout", data) 95 | 96 | save_file = open("workouts.json", "w") 97 | save_file.write(self.response.text) 98 | save_file.close() 99 | 100 | def GetWorkOutsPerWeek(self): 101 | where = {} 102 | where["user"] = {} 103 | where["user"]["__type"] = "Pointer" 104 | where["user"]["className"] = "_User" 105 | where["user"]["objectId"] = self.user_object_id 106 | 107 | data = {} 108 | data["_method"] = "GET" 109 | data["where"] = json.dumps(where).replace('"', '\"') 110 | 111 | self.WebRequest("POST", "/parse/classes/ParseWidget", data) 112 | 113 | def GetWorkOutsCount(self): 114 | where = {} 115 | where["user"] = {} 116 | where["user"]["__type"] = "Pointer" 117 | where["user"]["className"] = "_User" 118 | where["user"]["objectId"] = self.user_object_id 119 | where["updatedAt"] = {} 120 | where["updatedAt"]["$gt"] = {} 121 | where["updatedAt"]["$gt"]["__type"] = "Date" 122 | where["updatedAt"]["$gt"]["iso"] = "1970-01-01T00:00:00.000Z" 123 | 124 | data = {} 125 | data["include"] = "parseOriginRoutine,parseRoutine,parseSetGroups.parseExercise" 126 | data["limit"] = "0" 127 | data["count"] = "1" 128 | data["where"] = json.dumps(where).replace('"', '\"') 129 | data["_method"] = "GET" 130 | 131 | self.WebRequest("POST", "/parse/classes/ParseWorkout", data) 132 | 133 | 134 | s = Strong() 135 | s.Login() 136 | s.GetUser() 137 | s.GetWorkouts() 138 | s.GetWorkOutsCount() 139 | s.GetWorkOutsPerWeek() 140 | -------------------------------------------------------------------------------- /sample/3.create-charts.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pandas as pd 3 | import json 4 | 5 | path = "graphs/" 6 | 7 | plt.style.use( 8 | 'https://github.com/dhaitz/matplotlib-stylesheets/raw/master/pitayasmoothie-dark.mplstyle') 9 | 10 | stats = { 11 | "skip": { 12 | "date": { 13 | "total_volume": "(kilo * reps) + set", 14 | "total_reps": "add up all repos from each set", 15 | "max_weight": "max", 16 | "average_weight": "average", 17 | "median": "" 18 | } 19 | } 20 | } 21 | 22 | del (stats["skip"]) 23 | 24 | workouts = open("workouts.json").read() 25 | workouts_obj = json.loads(workouts) 26 | sessions_obj = workouts_obj["results"] 27 | 28 | for session in sessions_obj: 29 | for exercise in session["parseSetGroups"]: 30 | 31 | name = exercise["parseExercise"]["name"] 32 | 33 | if name not in stats: 34 | stats[name] = {} 35 | 36 | date = exercise["createdAt"].split("T")[0] 37 | 38 | if name not in stats: 39 | stats[name] = {} 40 | 41 | if date not in stats[name]: 42 | stats[name][date] = {} 43 | stats[name][date]["total_volume"] = 0 44 | stats[name][date]["total_reps"] = 0 45 | stats[name][date]["max_weight"] = 0 46 | stats[name][date]["average_weight"] = 0 47 | 48 | average_count = 0 49 | average = 0 50 | 51 | for set in exercise["parseSetsDictionary"]: 52 | if set["isChecked"]: 53 | if "kilograms" in set and set["kilograms"] != 0: 54 | stats[name][date]["total_volume"] += set["reps"] * \ 55 | set["kilograms"] 56 | stats[name][date]["total_reps"] += set["reps"] 57 | stats[name][date]["max_weight"] = set["kilograms"] if set["kilograms"] > stats[ 58 | name][date]["max_weight"] else stats[name][date]["max_weight"] 59 | average_count += set["reps"] 60 | average += set["reps"] * set["kilograms"] 61 | if average_count > 0: 62 | stats[name][date]["average_weight"] = round( 63 | average / average_count) 64 | 65 | if stats[name][date]["total_volume"] == 0 or stats[name][date]["total_reps"] == 0: 66 | del (stats[name][date]) 67 | 68 | 69 | for exercise in stats.keys(): 70 | if len(list(stats[exercise].keys())) < 10: 71 | continue 72 | if all(x["total_volume"] == 0 for x in stats[exercise].values()): 73 | continue 74 | 75 | pdate = list(stats[exercise].keys()) 76 | pdate = pdate[len(pdate) - 20:] if len(pdate) > 19 else pdate 77 | pvolume = [x["total_volume"] for x in stats[exercise].values()] 78 | pvolume = pvolume[len(pvolume) - 20:] if len(pvolume) > 19 else pvolume 79 | 80 | data = { 81 | 'date': pdate, 82 | 'volume': pvolume 83 | } 84 | 85 | df = pd.DataFrame(data) 86 | plt.figure() 87 | plt.plot(df['date'], df['volume'], color='red', marker='o') 88 | plt.title(exercise + ' volume', fontsize=14) 89 | plt.xlabel('Date', fontsize=12) 90 | plt.ylabel('Kilos', fontsize=12) 91 | plt.xticks(rotation=45, ha='right') 92 | plt.grid(True) 93 | # plt.show() 94 | plt.savefig(path + exercise + '-volume.png', bbox_inches='tight') 95 | plt.close() 96 | 97 | 98 | for exercise in stats.keys(): 99 | if len(list(stats[exercise].keys())) < 10: 100 | continue 101 | if all(x["total_reps"] == 0 for x in stats[exercise].values()): 102 | continue 103 | 104 | pdate = list(stats[exercise].keys()) 105 | pdate = pdate[len(pdate) - 20:] if len(pdate) > 19 else pdate 106 | preps = [x["total_reps"] for x in stats[exercise].values()] 107 | preps = preps[len(preps) - 20:] if len(preps) > 19 else preps 108 | 109 | data = { 110 | 'date': pdate, 111 | 'reps': preps 112 | } 113 | 114 | df = pd.DataFrame(data) 115 | plt.figure() 116 | plt.plot(df['date'], df['reps'], color='red', marker='o') 117 | plt.title(exercise + ' reps', fontsize=14) 118 | plt.xlabel('Date', fontsize=12) 119 | plt.ylabel('Reps', fontsize=12) 120 | plt.xticks(rotation=45, ha='right') 121 | plt.grid(True) 122 | # plt.show() 123 | plt.savefig(path + exercise + '-reps.png', bbox_inches='tight') 124 | plt.close() 125 | 126 | 127 | for exercise in stats.keys(): 128 | if len(list(stats[exercise].keys())) < 10: 129 | continue 130 | if all(x["max_weight"] == 0 for x in stats[exercise].values()): 131 | continue 132 | 133 | pdate = list(stats[exercise].keys()) 134 | pdate = pdate[len(pdate) - 20:] if len(pdate) > 19 else pdate 135 | pweight = [x["max_weight"] for x in stats[exercise].values()] 136 | pweight = pweight[len(pweight) - 20:] if len(pweight) > 19 else pweight 137 | 138 | data = { 139 | 'date': pdate, 140 | 'weight': pweight 141 | } 142 | 143 | df = pd.DataFrame(data) 144 | plt.figure() 145 | plt.plot(df['date'], df['weight'], color='red', marker='o') 146 | plt.title(exercise + ' max weight', fontsize=14) 147 | plt.xlabel('Date', fontsize=12) 148 | plt.ylabel('Kilos', fontsize=12) 149 | plt.xticks(rotation=45, ha='right') 150 | plt.grid(True) 151 | # plt.show() 152 | plt.savefig(path + exercise + '-weight.png', bbox_inches='tight') 153 | plt.close() 154 | -------------------------------------------------------------------------------- /sample/4.create-stats.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | stats = {} 4 | 5 | workouts = open("workouts.json").read() 6 | workouts_obj = json.loads(workouts) 7 | sessions_obj = workouts_obj["results"] 8 | 9 | for session in sessions_obj: 10 | for exercise in session["parseSetGroups"]: 11 | 12 | name = exercise["parseExercise"]["name"] 13 | 14 | if name not in stats: 15 | stats[name] = {} 16 | 17 | date = exercise["createdAt"].split("T")[0] 18 | 19 | if name not in stats: 20 | stats[name] = {} 21 | 22 | if date not in stats[name]: 23 | stats[name][date] = {} 24 | stats[name][date]["total_volume"] = 0 25 | stats[name][date]["total_reps"] = 0 26 | stats[name][date]["max_weight"] = 0 27 | stats[name][date]["average_weight"] = 0 28 | average_count = 0 29 | average = 0 30 | 31 | for set in exercise["parseSetsDictionary"]: 32 | if set["isChecked"]: 33 | if "kilograms" in set and set["kilograms"] != 0: 34 | stats[name][date]["total_volume"] += set["reps"] * \ 35 | set["kilograms"] 36 | stats[name][date]["total_reps"] += set["reps"] 37 | stats[name][date]["max_weight"] = set["kilograms"] if set["kilograms"] > stats[ 38 | name][date]["max_weight"] else stats[name][date]["max_weight"] 39 | average_count += set["reps"] 40 | average += set["reps"] * set["kilograms"] 41 | if average_count > 0: 42 | stats[name][date]["average_weight"] = round( 43 | average / average_count) 44 | 45 | if stats[name][date]["total_volume"] == 0 or stats[name][date]["total_reps"] == 0: 46 | del (stats[name][date]) 47 | 48 | 49 | save_file = open("stats.json", "w") 50 | save_file.write(json.dumps(stats)) 51 | save_file.close() -------------------------------------------------------------------------------- /sample/5.chart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Strong Stats 5 | 6 | 7 |
8 |
9 | 10 | 11 | 147 | 148 | -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # strong-api 2 | 3 | ## Welcome 4 | 5 | - 1.login.py - fairly self explanatory 6 | - 2.workout-history.py - slightly larger exmaple, also saves workouts.json, used for the following examples 7 | - 3.create-charts.py - uses workouts.json and matplotlib.pyplot to create charts found in graphs/ 8 | - 4.create-stats.py - takes workouts and simplifies the data 9 | - 5.chart.html - uses stats.json and chartjs to give and clean example of use in webpage. 10 | 11 | ## You will need to define these: 12 | 13 | - export strong_device_uuid=$(uuidgen) 14 | - export strong_application_id=$(date | sha1sum | awk '{print $1}') 15 | - export strong_username="ddddddddddddddddd" 16 | - export strong_password="gggggggggggggggggg" -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bench Press (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bench Press (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over One Arm Row (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over One Arm Row (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over One Arm Row (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over One Arm Row (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over One Arm Row (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over One Arm Row (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over Row (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over Row (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over Row (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over Row (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bent Over Row (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bent Over Row (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Bicep Curl (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Bicep Curl (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Cable Twist-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Cable Twist-reps.png -------------------------------------------------------------------------------- /sample/graphs/Cable Twist-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Cable Twist-volume.png -------------------------------------------------------------------------------- /sample/graphs/Cable Twist-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Cable Twist-weight.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly-reps.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly-volume.png -------------------------------------------------------------------------------- /sample/graphs/Chest Fly-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Chest Fly-weight.png -------------------------------------------------------------------------------- /sample/graphs/Decline Crunch-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Decline Crunch-reps.png -------------------------------------------------------------------------------- /sample/graphs/Decline Crunch-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Decline Crunch-volume.png -------------------------------------------------------------------------------- /sample/graphs/Decline Crunch-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Decline Crunch-weight.png -------------------------------------------------------------------------------- /sample/graphs/Face Pull (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Face Pull (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Face Pull (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Face Pull (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Face Pull (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Face Pull (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Front Raise (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Front Raise (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Hack Squat-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hack Squat-reps.png -------------------------------------------------------------------------------- /sample/graphs/Hack Squat-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hack Squat-volume.png -------------------------------------------------------------------------------- /sample/graphs/Hack Squat-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hack Squat-weight.png -------------------------------------------------------------------------------- /sample/graphs/Hammer Curl (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hammer Curl (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Hammer Curl (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hammer Curl (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Hammer Curl (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hammer Curl (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Hip Abductor (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Abductor (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Hip Abductor (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Abductor (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Hip Abductor (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Abductor (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Hip Thrust (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Thrust (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Hip Thrust (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Thrust (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Hip Thrust (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Hip Thrust (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Incline Row (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Incline Row (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Incline Row (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Incline Row (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Incline Row (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Incline Row (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Kettlebell Swing-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Kettlebell Swing-reps.png -------------------------------------------------------------------------------- /sample/graphs/Kettlebell Swing-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Kettlebell Swing-volume.png -------------------------------------------------------------------------------- /sample/graphs/Kettlebell Swing-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Kettlebell Swing-weight.png -------------------------------------------------------------------------------- /sample/graphs/Lat Pulldown (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lat Pulldown (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Lat Pulldown (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lat Pulldown (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Lat Pulldown (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lat Pulldown (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Lateral Raise (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lateral Raise (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Leg Extension (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Extension (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Leg Extension (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Extension (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Leg Extension (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Extension (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Leg Press-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Press-reps.png -------------------------------------------------------------------------------- /sample/graphs/Leg Press-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Press-volume.png -------------------------------------------------------------------------------- /sample/graphs/Leg Press-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Leg Press-weight.png -------------------------------------------------------------------------------- /sample/graphs/Lunge (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lunge (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Lunge (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lunge (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Lunge (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Lunge (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Overhead Press (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Overhead Press (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Pec Deck (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pec Deck (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Pec Deck (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pec Deck (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Pec Deck (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pec Deck (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Pullover (Dumbbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pullover (Dumbbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Pullover (Dumbbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pullover (Dumbbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Pullover (Dumbbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Pullover (Dumbbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Seated Calf Raise (Plate Loaded)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Calf Raise (Plate Loaded)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Seated Calf Raise (Plate Loaded)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Calf Raise (Plate Loaded)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Seated Calf Raise (Plate Loaded)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Calf Raise (Plate Loaded)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Curl (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Curl (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Curl (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Curl (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Curl (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Curl (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Press (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Press (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Press (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Press (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Seated Leg Press (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Leg Press (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Seated Row (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Row (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Seated Row (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Row (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Seated Row (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Seated Row (Cable)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Standing Calf Raise (Machine)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Standing Calf Raise (Machine)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Standing Calf Raise (Machine)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Standing Calf Raise (Machine)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Standing Calf Raise (Machine)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Standing Calf Raise (Machine)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Barbell)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Barbell)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Barbell)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Barbell)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Barbell)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Barbell)-weight.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Cable)-reps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Cable)-reps.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Cable)-volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Cable)-volume.png -------------------------------------------------------------------------------- /sample/graphs/Triceps Extension (Cable)-weight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmzoneill/strongapp-api/d54a4b4d8c96aeec3862912a925077b6d1070e6b/sample/graphs/Triceps Extension (Cable)-weight.png -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | version=0.0.18 2 | --------------------------------------------------------------------------------