An automation helper to submit weekly attendance codes. Now in Public Beta.
Warning
This project is currently in Public Beta. Features may change and bugs are expected.
Receive Feedback Here:
Choose one method to get the folder onto your computer:
- Install Git: https://git-scm.com/downloads
- macOS/Linux:
git clone https://github.com/bunizao/always-attend.git
cd always-attend- Windows (PowerShell or Command Prompt):
git clone https://github.com/bunizao/always-attend.git
cd always-attend- Open the project page: https://github.com/bunizao/always-attend
- Click the green "Code" button → "Download ZIP"
- Or direct ZIP link: https://github.com/bunizao/always-attend/archive/refs/heads/main.zip
- Extract the ZIP:
- Windows: right‑click the ZIP → "Extract All..."
- macOS: double‑click the ZIP to extract
- Open the extracted
always-attendfolder
- macOS: double‑click
Always-Attend.command - Windows: double‑click
Always-Attend.bator right‑clickAlways-Attend.ps1→ Run with PowerShell - The first run will guide setup automatically
Double‑click to run with the enhanced first‑time setup:
- macOS: double‑click
Always-Attend.command - Windows: double‑click
Always-Attend.bat(or runAlways-Attend.ps1)
Want to drop a single file on another machine and get going? Run the bundled launch.py script:
- Prompts for the install location (defaults to the current folder)
- Clones
always-attend, creates/updates.venv, installs dependencies, and copies.env.example - Lets you choose UI login, headless mode, or
--dry-run, then runsmain.pyor prints the launch command - Perfect for rapid sharing in chats or classrooms—just send
launch.py, then runpython launch.py
The application follows a structured 4-step workflow with multiple execution modes:
- Environment Setup - Bootstrap and install dependencies
- Python Check - Verify Python environment and packages
- App Start - Load config, privacy policy, and first-run setup
- Choose Mode - Select execution mode:
- 🔍 Stats (
--stats) - View attendance statistics (read-only) - 📤 Submit (default) - Main workflow for code submission
- 🔑 Login Only (
--login-only) - Refresh session and exit
When using Submit mode, the application follows this sequence:
- Session Check → Sign-in if needed
- Submission → Dry-run or submit codes
- Done → Save results and exit
When using Login Only mode:
- Session Check → Sign-in if needed
- Done → Exit after refreshing session
# Basic execution
python main.py
# View statistics
python main.py --stats
# Refresh login session
python main.py --login-only
# Run specific week
python main.py --week 4
# Show browser (headed mode)
python main.py --headedWhy uv?
- 🔒 Deterministic installs via
uv.lockso every machine shares the same dependency graph. - ⚡ Rust-powered resolver/installer that is noticeably faster than
pip+venv. - 🧪
uv synckeeps the virtual env fresh without manual activation juggling (uv run …handles it). - 🌍 Handles Python download/management when the requested interpreter is missing.
- Install uv if it is not already available:
curl -LsSf https://astral.sh/uv/install.sh | sh - From the project root, sync dependencies and refresh the local virtual environment:
uv sync
- Install the Chromium browser bundle for Playwright:
uv run python -m playwright install chromium
- Launch the CLI (examples):
uv run python main.py --dry-run uv run python main.py --login-only
python3 -m venv .venv
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
pip install -U pip
pip install -r requirements.txt
python -m playwright install chromium
python main.pyWhat the launchers do:
- Check for Python (and Git if available)
- Create/activate a virtualenv and install dependencies on first run
- Run a first‑time setup wizard (portal URL, credentials, week, browser)
- Auto‑detect the latest week from
data/*/*.jsonand setWEEK_NUMBER
Update later:
git pullAlways Attend now reads attendance codes exclusively from the data/ directory (or the folder specified by CODES_DB_PATH). Each course gets its own subfolder and every week is represented by a JSON file:
data/
FIT1045/
3.json # [{"slot": "Workshop 01", "code": "LCPPH"}, ...]
FIT1047/
7.json
If you maintain your codes in a separate Git repository, point the tool at it:
export CODES_DB_REPO="git@github.com:you/attendance-db.git"
export CODES_DB_BRANCH="main"On every run the repository is cloned (if missing) or updated before submission. Without a repository the tool simply reads whatever JSON files already exist under data/.
The tool now automatically tracks your attendance submission statistics:
# View detailed statistics
python main.py --stats
# Or use the stats module directly
python stats.pyStatistics include:
- Total runs and success rate
- Codes submitted per course
- Recent activity timeline
- Error history
Always Attend ships with a polished terminal UI powered by Rich:
- Animated Monash-blue typewriter banner with optional spark highlights (auto-disables on non-TTY output).
- Live, single-line progress bars with square block fills and cached ASCII spinners when
CLI_PROGRESS_RICH=1. - Animated logging for major workflow steps without leaking ANSI fragments when launched via
.command/.bat.
| Variable | Values | Effect |
|---|---|---|
CLI_STYLE |
fancy (default), simple, minimal |
Toggle banner + log animations |
FORCE_ANIMATIONS |
true / false |
Override TTY detection (useful for debugging) |
CLI_PROGRESS_RICH |
1 / 0 |
Enable/disable Rich live progress tracker |
# Full experience: animated banner, live block progress
CLI_STYLE=fancy CLI_PROGRESS_RICH=1 python main.py --dry-run
# Quiet fallback suitable for basic terminals
CLI_STYLE=minimal CLI_PROGRESS_RICH=0 python main.pySet these in your .env to persist the chosen style across runs.
- If login keeps asking for MFA: re-run the headed login to refresh
storage_state.json - If the browser fails to launch: make sure Google Chrome or Microsoft Edge is installed, or set
BROWSER_CHANNELtochrome/msedge. - On Windows, if activation fails, run PowerShell as Administrator once, then try
.venv\Scripts\Activate.ps1again. - When running, please do NOT use a VPN, as this may cause Okta to refuse the connection.
- Use
pyinstead ofpython: Ifpythonisn't found or points to another version, usepy(e.g.,py -m venv .venv,py main.py). - Switching between Git Bash and PowerShell: In terminals like VS Code, use the dropdown to open a new Git Bash or PowerShell window. Some commands (e.g.,
source) only work in Git Bash, while PowerShell uses.\for scripts. - Path escaping issues: PowerShell uses backslashes (
\) and may treat them as escape characters. Wrap paths in quotes or use double backslashes likeC:\path\to\file. Git Bash uses forward slashes (/).
main.py
| Argument | Type | Description | Example |
|---|---|---|---|
--browser |
string | Browser engine (chromium/firefox/webkit) |
--browser chromium |
--channel |
string | System browser channel (chromium only: chrome, chrome-beta, msedge, etc.) |
--channel chrome |
--headed |
flag | Show browser UI (sets HEADLESS=0) |
--headed |
--dry-run |
flag | Print parsed codes and exit without submitting | --dry-run |
--week |
int | Submit codes for a specific week (sets WEEK_NUMBER) |
--week 4 |
--login-only |
flag | Refresh the session and exit without submitting | --login-only |
--stats |
flag | Display cached attendance statistics and exit | --stats |
--setup |
flag | Launch the configuration wizard interactively | --setup |
--debug |
flag | Enable debug logging profile | --debug |
--verbose |
flag | Enable verbose logging profile | --verbose |
--skip-update |
flag | Skip the git update check before running | --skip-update |
| Variable | Type | Required | Description | Example |
|---|---|---|---|---|
PORTAL_URL |
string URL | Yes | Attendance portal base URL | https://attendance.monash.edu.my |
CODES_DB_PATH |
string path | No | Root folder containing COURSE/WEEK.json files |
/srv/attendance-data |
CODES_DB_REPO |
string URL | No | Git repository that mirrors the data tree | git@github.com:you/attendance-db.git |
CODES_DB_BRANCH |
string | No | Branch to checkout when syncing the repository | main |
WEEK_NUMBER |
int | No | Force a specific week instead of auto-detecting | 4 |
SUBMIT_CONCURRENCY |
int | No | Maximum courses processed concurrently | 2 |
SUBMIT_TARGET_CONCURRENCY |
int | No | Parallel submission workers per course | 3 |
USERNAME |
string | No | Okta username for auto-login | student@example.edu |
PASSWORD |
string | No | Okta password for auto-login | correcthorsebattery |
TOTP_SECRET |
string (base32) | No | MFA TOTP secret for auto-login | JBSWY3DPEHPK3PXP |
AUTO_LOGIN |
flag (0/1) | No | Toggle automatic login | 1 |
BROWSER |
string | No | Engine override (chromium/firefox/webkit) |
chromium |
BROWSER_CHANNEL |
string | No | System channel (chrome/msedge/etc.) |
chrome |
HEADLESS |
flag (0/1 or true/false) | No | Run without UI (0 disables) | 0 |
USER_DATA_DIR |
string path | No | Persistent browser profile directory | ~/.always-attend-profile |
LOG_PROFILE |
string | No | Logging profile (user/quiet/debug/verbose) |
verbose |
LOG_FILE |
string path | No | Optional log file destination | /tmp/always-attend.log |
SKIP_UPDATE_CHECK |
flag (0/1 or true/false) | No | Skip remote git pull when set | 1 |
- This project is for educational and personal use only. Use it responsibly and follow your institution’s policies and the website’s terms of use.
- This project is not affiliated with, endorsed by, or sponsored by any university or service provider. All product names, logos, and brands are property of their respective owners.
- You are solely responsible for any use of this tool and any consequences that may arise. The authors provide no guarantee that it will work for your specific setup.
- This project is licensed under the GNU General Public License v3.0 (GPL‑3.0). See the full text in the
LICENSEfile. - You may copy, modify, and distribute this software under the terms of the GPL‑3.0. It is provided “as is”, without any warranty.