You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.6 KiB
Markdown
186 lines
4.6 KiB
Markdown
# harbor-bot
|
|
|
|
Pickleball court reservation bot for Harbor Isles Tennis & Fitness Club.
|
|
|
|
## Setup
|
|
|
|
1. Install dependencies:
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
2. Configure `config.json` with your settings (see Configuration section below).
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
# Show configuration and next trigger times
|
|
python harbor_bot.py --show-config
|
|
|
|
# Test login
|
|
python harbor_bot.py --test-login
|
|
|
|
# Run as daemon (recommended - runs continuously)
|
|
python harbor_bot.py --daemon
|
|
|
|
# Run daemon in live mode (actually makes reservations at scheduled times)
|
|
python harbor_bot.py --daemon --live
|
|
|
|
# Run once and check for reservations (one-shot mode)
|
|
python harbor_bot.py --run
|
|
|
|
# Test booking a specific court (dry run)
|
|
python harbor_bot.py --test-book Court_1 Saleh 2026-01-19 "19:00:00-08:00"
|
|
|
|
# Test booking a specific court (live - actually books!)
|
|
python harbor_bot.py --test-book Court_1 Saleh 2026-01-19 "19:00:00-08:00" --live
|
|
```
|
|
|
|
## Daemon Mode
|
|
|
|
The recommended way to run the bot is in daemon mode (`--daemon`). It will:
|
|
|
|
1. Run continuously, checking for reservations every minute
|
|
2. Wait for the exact scheduled times in the ReservationBehavior before attempting
|
|
3. Automatically refresh authentication when needed
|
|
4. Track successful reservations to avoid duplicates
|
|
|
|
To run in production with auto-restart on crash, use a process manager like systemd:
|
|
|
|
```ini
|
|
# /etc/systemd/system/harbor-bot.service
|
|
[Unit]
|
|
Description=Harbor Bot Pickleball Reservation Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=your-user
|
|
WorkingDirectory=/path/to/harbor-bot
|
|
ExecStart=/usr/bin/python3 harbor_bot.py --daemon --live
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Then enable and start:
|
|
```bash
|
|
sudo systemctl enable harbor-bot
|
|
sudo systemctl start harbor-bot
|
|
sudo journalctl -u harbor-bot -f # View logs
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The `config.json` file contains:
|
|
|
|
### API Settings
|
|
- `BaseAPIUrl`: API endpoint URL
|
|
- `CompanyId`: Club company ID
|
|
- `ClubId`: Club ID
|
|
- `AppointmentItemId`: Item ID for pickleball reservations
|
|
|
|
### Login
|
|
- `Username`: Your login username
|
|
- `Password`: Your password (stored as-is, e.g., "Goliath00!!@")
|
|
|
|
### Accounts
|
|
List of accounts that can be used for reservations:
|
|
```json
|
|
{"Name": "ToniB", "Id": 6964}
|
|
```
|
|
|
|
### Courts
|
|
List of available courts:
|
|
```json
|
|
{
|
|
"Court": "Court_1",
|
|
"Id": 1,
|
|
"Name": "Pickleball Court - 1",
|
|
"ResourceTypeId": 2,
|
|
"AssignedResourceId": 130,
|
|
"IsAssignedResourceSelectable": true
|
|
}
|
|
```
|
|
|
|
### Reservation Behaviors
|
|
Defines how reservations are attempted. **Important: Times must be in ascending order.**
|
|
|
|
```json
|
|
{
|
|
"Name": "Weekday_Reservation_Type",
|
|
"DaysInAdvance": 7,
|
|
"AttemptSchedule": [
|
|
{"Time": "04:29:00-08:00", "Attempts": 2, "DelaySeconds": 10},
|
|
{"Time": "04:30:00-08:00", "Attempts": 10, "DelaySeconds": 10},
|
|
{"Time": "04:35:00-08:00", "Attempts": 1, "DelaySeconds": 0}
|
|
]
|
|
}
|
|
```
|
|
|
|
- `DaysInAdvance`: How many days before the reservation date to attempt booking
|
|
- `AttemptSchedule`: List of attempt windows (must be in chronological order)
|
|
- `Time`: When to start attempting (in timezone format like "04:30:00-08:00")
|
|
- `Attempts`: Number of booking attempts in this window
|
|
- `DelaySeconds`: Delay between attempts
|
|
|
|
### Reservations
|
|
Scheduled reservation configurations:
|
|
```json
|
|
{
|
|
"Day": "Wednesday",
|
|
"Time": "19:00:00-08:00",
|
|
"ReservationBehavior": "Weekday_Reservation_Type",
|
|
"Courts": [
|
|
{"Court": "Court_1", "Account": "Saleh"},
|
|
{"Court": "Court_2", "Account": "ToniB"}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Email Notifications (Optional)
|
|
Configure email notifications to receive alerts when courts are successfully booked:
|
|
|
|
```json
|
|
{
|
|
"Email": {
|
|
"Enabled": true,
|
|
"SmtpServer": "smtp.gmail.com",
|
|
"SmtpPort": 587,
|
|
"SmtpUsername": "your-email@gmail.com",
|
|
"SmtpPassword": "your-app-password",
|
|
"FromAddress": "your-email@gmail.com",
|
|
"ToAddresses": [
|
|
"recipient1@example.com",
|
|
"recipient2@example.com"
|
|
],
|
|
"UseTLS": true
|
|
}
|
|
}
|
|
```
|
|
|
|
**Gmail Setup:**
|
|
1. Enable 2-factor authentication on your Google account
|
|
2. Generate an App Password: Google Account → Security → App Passwords
|
|
3. Use the 16-character app password as `SmtpPassword`
|
|
|
|
**Other SMTP Providers:**
|
|
- Outlook: `smtp.office365.com`, port 587
|
|
- Yahoo: `smtp.mail.yahoo.com`, port 587
|
|
- Custom SMTP: Use your provider's settings
|
|
|
|
## Files
|
|
|
|
- `config.json` - Main configuration
|
|
- `token_data.json` - Stored authentication token (auto-generated)
|
|
- `reservation_success.json` - Tracks successful reservations (auto-generated)
|
|
|
|
## Token Management
|
|
|
|
- Tokens are automatically saved and reused
|
|
- Token refresh occurs when:
|
|
- Token is expired
|
|
- Token is older than 3 days
|