Compare commits
3 Commits
e4656eaf54
...
0c4a7224d3
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c4a7224d3 | |||
|
|
9b5dd8745b | ||
|
|
d71bfff10e |
@@ -2,6 +2,7 @@
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
import asyncio
|
||||
from crossfit_booker import CrossFitBooker
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -30,5 +31,5 @@ if __name__ == "__main__":
|
||||
exit(1)
|
||||
|
||||
# Start the continuous booking loop
|
||||
booker.run()
|
||||
asyncio.run(booker.run())
|
||||
logging.info("Script completed")
|
||||
|
||||
@@ -363,7 +363,9 @@ class CrossFitBooker:
|
||||
# First check if can_join is true (primary condition)
|
||||
if user_info.get("can_join", False):
|
||||
activity_name = session.get("name_activity")
|
||||
logging.debug(f"Session is bookable: {activity_name} can_join is True")
|
||||
activity_date = session.get("start_timestamp", "Unknown date")
|
||||
activity_time = activity_date.split(" ")[1] if " " in activity_date else "Unknown time"
|
||||
logging.debug(f"Session is bookable: {activity_name} on {activity_date} at {activity_time} - can_join is True")
|
||||
return True
|
||||
|
||||
# If can_join is False, check if there's a booking window
|
||||
@@ -435,7 +437,7 @@ class CrossFitBooker:
|
||||
logging.error(f"Failed to check session: {str(e)} - Session: {session}")
|
||||
return False
|
||||
|
||||
def run_booking_cycle(self, current_time: datetime) -> None:
|
||||
async def run_booking_cycle(self, current_time: datetime) -> None:
|
||||
"""
|
||||
Run one cycle of checking and booking sessions.
|
||||
|
||||
@@ -487,7 +489,7 @@ class CrossFitBooker:
|
||||
if not session_time.tzinfo:
|
||||
session_time = pytz.timezone(TIMEZONE).localize(session_time)
|
||||
session_details = f"{session['name_activity']} at {session_time.strftime('%Y-%m-%d %H:%M')}"
|
||||
self.notifier.notify_session_booking(session_details)
|
||||
await self.notifier.notify_session_booking(session_details)
|
||||
logging.info(f"Notified about found preferred session: {session_details}")
|
||||
|
||||
# Notify about upcoming sessions
|
||||
@@ -496,7 +498,7 @@ class CrossFitBooker:
|
||||
if not session_time.tzinfo:
|
||||
session_time = pytz.timezone(TIMEZONE).localize(session_time)
|
||||
session_details = f"{session['name_activity']} at {session_time.strftime('%Y-%m-%d %H:%M')}"
|
||||
self.notifier.notify_upcoming_session(session_details, 1) # Days until is 1 for tomorrow
|
||||
await self.notifier.notify_upcoming_session(session_details, 1) # Days until is 1 for tomorrow
|
||||
logging.info(f"Notified about upcoming session: {session_details}")
|
||||
|
||||
# Book sessions (preferred first)
|
||||
@@ -507,12 +509,12 @@ class CrossFitBooker:
|
||||
if self.book_session(session["id_activity_calendar"]):
|
||||
# Send notification after successful booking
|
||||
session_details = f"{session['name_activity']} at {session_time.strftime('%Y-%m-%d %H:%M')}"
|
||||
self.notifier.notify_session_booking(session_details)
|
||||
await self.notifier.notify_session_booking(session_details)
|
||||
logging.info(f"Successfully booked {session_type} session at {session_time}")
|
||||
else:
|
||||
logging.error(f"Failed to book {session_type} session at {session_time} - Session: {session}")
|
||||
|
||||
def run(self) -> None:
|
||||
async def run(self) -> None:
|
||||
"""
|
||||
Main execution loop.
|
||||
"""
|
||||
@@ -531,7 +533,7 @@ class CrossFitBooker:
|
||||
logging.info(f"Current time: {current_time}")
|
||||
|
||||
# Always run booking cycle to check for preferred sessions and notify
|
||||
self.run_booking_cycle(current_time)
|
||||
await self.run_booking_cycle(current_time)
|
||||
|
||||
# Run booking cycle at the target time for actual booking
|
||||
target_time_str = current_time.strftime("%H:%M")
|
||||
|
||||
@@ -6,6 +6,7 @@ services:
|
||||
dockerfile: Dockerfile
|
||||
container_name: crossfit-booker
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- CROSSFIT_USERNAME=${CROSSFIT_USERNAME}
|
||||
- CROSSFIT_PASSWORD=${CROSSFIT_PASSWORD}
|
||||
- SMTP_SERVER=${SMTP_SERVER}
|
||||
|
||||
72
docs/waiting_list.json
Normal file
72
docs/waiting_list.json
Normal file
@@ -0,0 +1,72 @@
|
||||
curl 'https://sport.nubapp.com/api/v4/activities/activity-calendar/19291431/basicInfo?app_version=5.09.21^&id_application=81560887' \
|
||||
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
|
||||
-H 'Accept: application/json, text/plain, */*' \
|
||||
-H 'Accept-Language: en-GB,en;q=0.8,fr-FR;q=0.5,fr;q=0.3' \
|
||||
-H 'Accept-Encoding: gzip, deflate, br, zstd' \
|
||||
-H 'Referer: https://box.resawod.com/' \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
-H 'Nubapp-Origin: user_apps' \
|
||||
-H 'Origin: https://box.resawod.com' \
|
||||
-H 'Sec-GPC: 1' \
|
||||
-H 'Connection: keep-alive' \
|
||||
-H 'Sec-Fetch-Dest: empty' \
|
||||
-H 'Sec-Fetch-Mode: cors' \
|
||||
-H 'Sec-Fetch-Site: cross-site' \
|
||||
-H 'Priority: u=0' \
|
||||
-H 'TE: trailers'
|
||||
|
||||
{
|
||||
"message": "All right! Here is your data.",
|
||||
"data": {
|
||||
"activity_calendar": {
|
||||
"id_activity_calendar": 19291431,
|
||||
"name_activity": "CONDITIONING LOUVRE 3",
|
||||
"description": "\\u003Cp\\u003EWod Condi, de la simplicit\\u00e9 mais beaucoup d\\u0027intensit\\u00e9... des erg mais pas seulement, des mouvements de CrossFit qui vous permettrons d\\u0027am\\u00e9liorer vos capacit\\u00e9s a\\u00e9robies\\u003C\\/p\\u003E",
|
||||
"id_activity": 43932,
|
||||
"id_category_activity": 677,
|
||||
"start_timestamp": "2025-07-23 18:30:00",
|
||||
"end_timestamp": "2025-07-23 19:15:00",
|
||||
"n_inscribed": 12,
|
||||
"n_capacity": 12,
|
||||
"n_waiting_list": 3,
|
||||
"n_capacity_waiting_list": 8,
|
||||
"id_trainer": null,
|
||||
"is_course": false,
|
||||
"cancelled": false,
|
||||
"guest_info": {
|
||||
"can_join": true,
|
||||
"available_booking_options": [],
|
||||
"errors": 0,
|
||||
"errors_by_memberships": [],
|
||||
"join_as_normal_user": false,
|
||||
"vouchers": [],
|
||||
"voucher_autopay": false,
|
||||
"unableToBookUntilDate": null,
|
||||
"unableToBookUntilTime": null,
|
||||
"best_booking_option": {
|
||||
"type": 2,
|
||||
"price": 0,
|
||||
"membershipId": null,
|
||||
"discountId": null,
|
||||
"discountValue": null
|
||||
},
|
||||
"price": 0,
|
||||
"price_befdis": 0,
|
||||
"user_attending": false,
|
||||
"user_waiting": false
|
||||
},
|
||||
"facilities": [],
|
||||
"image": null,
|
||||
"color": "#a74cd6",
|
||||
"max_guests": 0,
|
||||
"guest_prices": {
|
||||
"1": 0,
|
||||
"2": 0,
|
||||
"3": 0
|
||||
},
|
||||
"id_language": null
|
||||
}
|
||||
},
|
||||
"success": true,
|
||||
"status": 200
|
||||
}
|
||||
Reference in New Issue
Block a user