Elective - 北大选课网 CLI
A CLI client for PKU's course selection system with auto-enrollment automation.
Architecture
- Crate location:
crates/elective/ - Auth flow: IAAA SSO (
app_id="elective") → elective SSO endpoint callback - API: HTML scraping + CAPTCHA handling (base64 image recognition)
- Automation: Polling loop for auto-enrollment with configurable interval
Key Source Files
src/main.rs— Clap CLI with subcommandssrc/commands.rs— Command implementations including auto-enroll loopsrc/api.rs— HTML scraping, CAPTCHA image extractionsrc/display.rs— Terminal output formattingsrc/client.rs— reqwest client builders
CLI Commands
| Command | Alias | Function |
|---|---|---|
login |
IAAA login (supports --dual for dual-degree students) |
|
logout / status |
Session management | |
show |
View current course selections | |
list |
ls |
Browse available courses for add/drop |
set |
Add a course to auto-enroll target list | |
unset |
Remove from auto-enroll targets | |
config-captcha |
Configure CAPTCHA solver backend | |
launch |
Start auto-enrollment polling loop | |
otp |
TOTP 2FA management |
CAPTCHA Backends
The config-captcha command supports multiple recognition backends:
manual— Display CAPTCHA image, user inputs answerutool— UTool OCR servicettshitu— TTShiTu recognition APIyunma— Yunma recognition API
Auto-Login for AI Agents
# Check session status
info-auth check
# Auto-login (reads credentials from OS keyring, no password needed)
elective login -p # single degree
elective login -p --dual major # dual degree - major
elective login -p --dual minor # dual degree - minor
Note: Dual-degree students MUST specify --dual major or --dual minor, otherwise login will fail with an error.
Development Notes
- Auto-enrollment loop: configurable check interval (default 15s), polls for open slots
- Dual-degree students use
--dualflag at login for separate session - CAPTCHA images are base64-encoded, decoded and sent to recognition backend
- All user-facing strings in Chinese
- Error handling:
anyhow::Resultwith.context("中文描述") - Session persisted to
~/.config/info/elective/ - Credentials resolved via
info_common::credential(keyring → env → interactive)
