-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(examples_sync): add example scripts for challenge tracker, class…
… bookings, studio, and workout functionalities Add example scripts to demonstrate the usage of the OtfSync API for various functionalities including challenge tracking, class bookings, studio information, and workout data. These examples serve as a guide for users to understand how to interact with the API and retrieve relevant data. feat(otf_api): introduce OtfSync class for synchronous API interactions Add a new OtfSync class to the otf_api module to facilitate synchronous interactions with the Orangetheory Fitness API. This class provides methods for booking classes, retrieving member details, accessing performance summaries, and more. It aims to simplify the process of making API requests and handling responses in a synchronous manner.
- Loading branch information
1 parent
e67f187
commit c0cbce3
Showing
6 changed files
with
1,451 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import os | ||
from getpass import getpass | ||
|
||
from otf_api import OtfSync | ||
from otf_api.models import ChallengeType, EquipmentType | ||
|
||
USERNAME = os.getenv("OTF_EMAIL") or input("Enter your OTF email: ") | ||
PASSWORD = os.getenv("OTF_PASSWORD") or getpass("Enter your OTF password: ") | ||
|
||
|
||
def main(): | ||
with OtfSync(USERNAME, PASSWORD) as otf: | ||
# challenge tracker content is an overview of the challenges OTF runs | ||
# and your participation in them | ||
challenge_tracker_content = otf.get_challenge_tracker_content() | ||
print(challenge_tracker_content.benchmarks[0].model_dump_json(indent=4)) | ||
|
||
""" | ||
{ | ||
"equipment_id": 2, | ||
"equipment_name": "Treadmill", | ||
"years": [ | ||
{ | ||
"year": "2024", | ||
"is_participated": false, | ||
"in_progress": false | ||
}, | ||
... | ||
], | ||
"logo_url": "https://otf-icons.s3.amazonaws.com/benchmarks/Treadmill.png" | ||
} | ||
""" | ||
|
||
print(challenge_tracker_content.challenges[0].model_dump_json(indent=4)) | ||
""" | ||
{ | ||
"challenge_category_id": 10, | ||
"challenge_sub_category_id": 8, | ||
"challenge_name": "Catch Me If You Can 3G", | ||
"years": [ | ||
{ | ||
"year": "2024", | ||
"is_participated": false, | ||
"in_progress": false | ||
}, | ||
... | ||
], | ||
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png" | ||
} | ||
""" | ||
|
||
# challenge tracker details are detailed information about specific challenges | ||
# this endpoint takes an equipment type and a challenge type as arguments | ||
tread_challenge_details = otf.get_challenge_tracker_detail(EquipmentType.Treadmill, ChallengeType.Other) | ||
print(tread_challenge_details.details[0].model_dump_json(indent=4)) | ||
|
||
""" | ||
{ | ||
"challenge_category_id": 10, | ||
"challenge_sub_category_id": null, | ||
"equipment_id": 2, | ||
"equipment_name": "Treadmill", | ||
"metric_entry": { | ||
"title": "22 MIN", | ||
"equipment_id": 2, | ||
"entry_type": "Distance", | ||
"metric_key": "22MIN", | ||
"min_value": "0.16093440000000003", | ||
"max_value": "8.04672" | ||
}, | ||
"challenge_name": "Catch me If You Can", | ||
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png", | ||
"best_record": 1.40012928, | ||
"last_record": 1.40012928, | ||
"previous_record": 1.40012928, | ||
"unit": "km", | ||
"goals": null, | ||
"challenge_histories": [ | ||
{ | ||
"challenge_objective": "None", | ||
"challenge_id": 449906, | ||
"studio_id": 1267, | ||
"studio_name": "AnyTown OH - East", | ||
"start_date": "2024-02-06 00:00:00", | ||
"end_date": "2024-02-06 23:59:00", | ||
"total_result": 1.40012928, | ||
"is_finished": true, | ||
"benchmark_histories": [ | ||
{ | ||
"studio_name": "AnyTown OH - East", | ||
"equipment_id": 2, | ||
"result": 1.40012928, | ||
"date_created": "2024-02-06 16:01:26", | ||
"date_updated": "2024-02-06 16:01:26", | ||
"class_time": "2024-02-06 09:45:00", | ||
"challenge_sub_category_id": null, | ||
"class_id": 86842386, | ||
"substitute_id": 1, | ||
"weight_lbs": 0, | ||
"workout_type_id": null, | ||
"workout_id": null, | ||
"linked_challenges": [] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
""" | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import os | ||
from datetime import datetime | ||
from getpass import getpass | ||
|
||
from otf_api import OtfSync | ||
from otf_api.models.classes import DoW | ||
|
||
USERNAME = os.getenv("OTF_EMAIL") or input("Enter your OTF email: ") | ||
PASSWORD = os.getenv("OTF_PASSWORD") or getpass("Enter your OTF password: ") | ||
|
||
|
||
def main(): | ||
with OtfSync(USERNAME, PASSWORD) as otf: | ||
resp = otf.get_bookings(start_date=datetime.today().date()) | ||
print(resp.model_dump_json(indent=4)) | ||
|
||
studios = otf.search_studios_by_geo(40.7831, 73.9712, distance=100) | ||
|
||
studio_uuids = [studio.studio_uuid for studio in studios.studios] | ||
|
||
# To get upcoming classes you can call the `get_classes` method | ||
# You can pass a list of studio_uuids or, if you want to get classes from your home studio, leave it empty | ||
# this also takes a start date, end date, and limit - these are not sent to the API, they are used in the | ||
# client to filter the results | ||
classes = otf.get_classes(studio_uuids, day_of_week=[DoW.TUESDAY, DoW.THURSDAY, DoW.SATURDAY]) | ||
|
||
print(classes.classes[0].model_dump_json(indent=4)) | ||
|
||
""" | ||
{ | ||
"id": "0e39ef70-7403-49c1-8605-4a72643bd201", | ||
"ot_base_class_uuid": "08cebfdb-e127-48d4-8a7f-e6ea4dd85c18", | ||
"starts_at": "2024-06-13 10:00:00+00:00", | ||
"starts_at_local": "2024-06-13 05:00:00", | ||
"ends_at": "2024-06-13 11:00:00+00:00", | ||
"ends_at_local": "2024-06-13 06:00:00", | ||
"name": "Orange 3G", | ||
"type": "ORANGE_60", | ||
"studio": ..., | ||
"coach": ..., | ||
"max_capacity": 36, | ||
"booking_capacity": 36, | ||
"waitlist_size": 0, | ||
"full": false, | ||
"waitlist_available": false, | ||
"canceled": false, | ||
"mbo_class_id": "30809", | ||
"mbo_class_schedule_id": "2655", | ||
"mbo_class_description_id": "102", | ||
"created_at": "2024-05-14 10:33:32.406000+00:00", | ||
"updated_at": "2024-06-13 01:58:55.233000+00:00" | ||
} | ||
""" | ||
|
||
# You can also get the classes that you have booked | ||
# You can pass a start_date, end_date, status, and limit as arguments | ||
|
||
bookings = otf.get_bookings() | ||
|
||
print("Latest Upcoming Class:") | ||
print(bookings.bookings[-1].model_dump_json(indent=4)) | ||
|
||
""" | ||
{ | ||
"class_booking_id": 870700285, | ||
"class_booking_uuid": "a36d76b1-0a55-4143-b96b-646e7520ca39", | ||
"studio_id": 1234, | ||
"class_id": 376344282, | ||
"is_intro": false, | ||
"member_id": 234488148, | ||
"status": "Booked", | ||
"booked_date": "2024-09-10T04:26:11Z", | ||
"checked_in_date": null, | ||
"cancelled_date": null, | ||
"created_date": "2024-09-10T04:26:11Z", | ||
"updated_date": "2024-09-10T04:26:13Z", | ||
"is_deleted": false, | ||
"waitlist_position": null, | ||
"otf_class": { | ||
"starts_at_local": "2024-09-28T10:30:00", | ||
"ends_at_local": "2024-09-28T11:20:00", | ||
"name": "Tread 50", | ||
"class_uuid": "82ec9b55-950a-484f-818f-cd2344ce83fd", | ||
"is_available": true, | ||
"is_cancelled": false, | ||
"program_name": "Group Fitness", | ||
"coach_id": 1204786, | ||
"studio": { | ||
"studio_uuid": "49e360d1-f8ef-4091-a23f-61b321cb283c", | ||
"studio_name": "AnyTown OH - East", | ||
"description": "", | ||
"status": "Active", | ||
"time_zone": "America/Chicago", | ||
"studio_id": 1267, | ||
"allows_cr_waitlist": true | ||
}, | ||
"coach": { | ||
"coach_uuid": "973516a8-0c6b-41ec-916c-1da9913b9a16", | ||
"name": "Friendly", | ||
"first_name": "Friendly", | ||
"last_name": "Coach" | ||
}, | ||
"location": { | ||
"address_one": "123 S Main St", | ||
"address_two": null, | ||
"city": "AnyTown", | ||
"country": null, | ||
"distance": null, | ||
"latitude": 91.73407745, | ||
"location_name": null, | ||
"longitude": -80.92264626, | ||
"phone_number": "2042348963", | ||
"postal_code": "11111", | ||
"state": "Ohio" | ||
}, | ||
"virtual_class": null | ||
}, | ||
"is_home_studio": true | ||
} | ||
""" | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import os | ||
from getpass import getpass | ||
|
||
from otf_api import OtfSync | ||
|
||
USERNAME = os.getenv("OTF_EMAIL") or input("Enter your OTF email: ") | ||
PASSWORD = os.getenv("OTF_PASSWORD") or getpass("Enter your OTF password: ") | ||
|
||
|
||
def main(): | ||
with OtfSync(USERNAME, PASSWORD) as otf: | ||
# if you need to figure out what studios are in an area, you can call `search_studios_by_geo` | ||
# which takes latitude, longitude, distance, page_index, and page_size as arguments | ||
# but you'll generally just need the first 3 | ||
# same as with classes, you can leave it blank and get the studios within 50 miles of your home studio | ||
studios_by_geo = otf.search_studios_by_geo() | ||
print(studios_by_geo.studios[0].model_dump_json(indent=4)) | ||
|
||
""" | ||
{ | ||
"studio_id": 1297, | ||
"studio_uuid": "8645fb2b-ef66-4d9d-bda1-f508091ec891", | ||
"mbo_studio_id": 8612481, | ||
"studio_number": "05414", | ||
"studio_name": "AnyTown OH - East", | ||
"studio_physical_location_id": 494, | ||
"time_zone": "America/Chicago", | ||
"contact_email": "[email protected]", | ||
"studio_token": "ec2459b2-32b5-4b7e-9759-55270626925a", | ||
"environment": "PROD", | ||
"pricing_level": "", | ||
"tax_rate": "0.000000", | ||
"accepts_visa_master_card": true, | ||
"accepts_american_express": true, | ||
"accepts_discover": true, | ||
"accepts_ach": false, | ||
"is_integrated": true, | ||
"description": "", | ||
"studio_version": "", | ||
"studio_status": "Active", | ||
"open_date": "2017-01-13 00:00:00", | ||
"re_open_date": "2020-05-26 00:00:00", | ||
"studio_type_id": 2, | ||
"sms_package_enabled": false, | ||
"allows_dashboard_access": false, | ||
"allows_cr_waitlist": true, | ||
"cr_waitlist_flag_last_updated": "2020-07-09 02:43:55+00:00", | ||
"royalty_rate": 0, | ||
"marketing_fund_rate": 0, | ||
"commission_percent": 0, | ||
"is_mobile": null, | ||
"is_otbeat": null, | ||
"distance": 0.0, | ||
"studio_location": ..., | ||
"studio_location_localized": ..., | ||
"studio_profiles": { | ||
"is_web": true, | ||
"intro_capacity": 1, | ||
"is_crm": true | ||
}, | ||
"social_media_links": ... | ||
} | ||
""" | ||
|
||
# if you need to get detailed information about a studio, you can call `get_studio_detail` | ||
# which takes a studio_uuid as an argument, but you can leave it blank to get details about your home studio | ||
# this one has a result structure very much like the previous one | ||
studio_detail = otf.get_studio_detail() | ||
print(studio_detail.model_dump_json(indent=4)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.