Add external session preference #3

Merged
kbe merged 5 commits from develop into main 2025-07-20 15:32:47 +00:00
4 changed files with 61 additions and 29 deletions
Showing only changes of commit a4226e0c6b - Show all commits

2
.gitignore vendored
View File

@@ -1,6 +1,8 @@
.env .env
log/ log/
!log/.gitkeep !log/.gitkeep
# Configuration files
preferred_sessions.json
# Created by https://www.toptal.com/developers/gitignore/api/python # Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python # Edit at https://www.toptal.com/developers/gitignore?templates=python

View File

@@ -30,6 +30,20 @@ docker-compose up --build
The application will automatically check for available sessions and book them based on your preferences. It will send notifications via email and Telegram when a booking is successful. The application will automatically check for available sessions and book them based on your preferences. It will send notifications via email and Telegram when a booking is successful.
### Configuring Preferred Sessions
You can configure your preferred sessions using the `preferred_sessions.json` file. This file should contain a JSON array of session names, for example:
```json
[
"Morning Class",
"Evening Class",
"Saturday Open Gym"
]
```
If the file is not found or contains invalid data, the application will use default hardcoded sessions.
### Environment Variables ### Environment Variables
The following environment variables are required: The following environment variables are required:
@@ -44,16 +58,36 @@ The following environment variables are required:
### Preferred Sessions ### Preferred Sessions
You can configure your preferred sessions in the `crossfit_booker.py` file. The preferred sessions are defined as a list of tuples, where each tuple contains the day of the week, start time, and session name. You can configure your preferred sessions in the `preferred_sessions.json` file. The preferred sessions are defined as a list of objects, where each object contains the day of the week, start time, and session name.
```python ```json
PREFERRED_SESSIONS = [ [
(4, "17:00", "WEIGHTLIFTING"), # Friday 17:00 WEIGHTLIFTING {
(5, "12:30", "HYROX"), # Saturday 12:30 HYROX "day_of_week": 4,
(2, "18:30", "CONDITIONING"), # Wednesday 18:30 CONDITIONING "start_time": "17:00",
"session_name_contains": "WEIGHTLIFTING"
},
{
"day_of_week": 5,
"start_time": "12:30",
"session_name_contains": "HYROX"
},
{
"day_of_week": 2,
"start_time": "18:30",
"session_name_contains": "CONDITIONING"
}
] ]
``` ```
The application will automatically load the preferred sessions from this file. If the file is not found or contains invalid data, it will fall back to the default hardcoded sessions.
#### Fields
- `day_of_week`: Integer representing the day of the week (0=Monday, 6=Sunday)
- `start_time`: String representing the start time in HH:MM format
- `session_name_contains`: String containing the name or part of the name of the session
## Files ## Files
- `Dockerfile`: Docker image definition - `Dockerfile`: Docker image definition
@@ -64,6 +98,7 @@ PREFERRED_SESSIONS = [
- `book_crossfit.py`: Main application script - `book_crossfit.py`: Main application script
- `crossfit_booker.py`: Crossfit booking script - `crossfit_booker.py`: Crossfit booking script
- `session_notifier.py`: Session notification script - `session_notifier.py`: Session notification script
- `preferred_sessions.json`: Configuration file for preferred sessions
- `requirements.txt`: Python dependencies - `requirements.txt`: Python dependencies
## Project Structure ## Project Structure
@@ -79,6 +114,7 @@ PREFERRED_SESSIONS = [
├── crossfit_booker.py ├── crossfit_booker.py
├── session_notifier.py ├── session_notifier.py
├── requirements.txt ├── requirements.txt
├── preferred_sessions.json
└── log └── log
└── crossfit_booking.log └── crossfit_booking.log
``` ```

View File

@@ -4,6 +4,20 @@ import traceback
from crossfit_booker import CrossFitBooker from crossfit_booker import CrossFitBooker
if __name__ == "__main__": if __name__ == "__main__":
# Configure logging once at script startup
logging.basicConfig(
level=logging.DEBUG, # Change to DEBUG for more detailed logs
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("log/crossfit_booking.log"),
logging.StreamHandler()
]
)
logging.getLogger("requests").setLevel(logging.WARNING)
logging.info("Logging enhanced with request library noise reduction")
# Start the main runner
booker = CrossFitBooker() booker = CrossFitBooker()
if not booker.login(): if not booker.login():
logging.error("Failed to login - Traceback: %s", traceback.format_exc()) logging.error("Failed to login - Traceback: %s", traceback.format_exc())

View File

@@ -18,6 +18,9 @@ from typing import List, Dict, Optional, Any
# Import the SessionNotifier class # Import the SessionNotifier class
from session_notifier import SessionNotifier from session_notifier import SessionNotifier
# Import the preferred sessions from the session_config module
from session_config import PREFERRED_SESSIONS
load_dotenv() load_dotenv()
# Configuration # Configuration
@@ -38,29 +41,6 @@ RETRY_MAX = 3
RETRY_BACKOFF = 1 RETRY_BACKOFF = 1
APP_VERSION = "5.09.21" APP_VERSION = "5.09.21"
# Define your preferred sessions
# Format: List of tuples (day_of_week, start_time, session_name_contains)
# day_of_week: 0=Monday, 6=Sunday
PREFERRED_SESSIONS = [
# (0, "17:00", "HYROX"), # Monday 17:00 HYROX
(2, "18:30", "CONDITIONING"), # Wednesday 18:30 CONDITIONING
(4, "17:00", "WEIGHTLIFTING"), # Friday 17:00 WEIGHTLIFTING
(5, "12:30", "HYROX"), # Saturday 12:30 HYROX
# (5, "15:15", "BIG WOD") # Saturday 15:15 BIG WOD
]
# Configure logging once at script startup
logging.basicConfig(
level=logging.DEBUG, # Change to DEBUG for more detailed logs
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("log/crossfit_booking.log"),
logging.StreamHandler()
]
)
logging.getLogger("requests").setLevel(logging.WARNING)
logging.info("Logging enhanced with request library noise reduction")
class CrossFitBooker: class CrossFitBooker:
def __init__(self) -> None: def __init__(self) -> None: