Automation assistant for attendance management.
Project description
Always Attend
An automation helper to submit weekly attendance codes. Now in Public Beta.
⚠️ Use responsibly and follow your institution’s policies.
[!WARNING]
This project is currently in Public Beta. Features may change and bugs are expected.
Receive Feedback Here:
📥 Download This Project
Choose one method to get the folder onto your computer:
Option 1 — Git (recommended)
- 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
Option 2 — Download ZIP (no Git needed)
- 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
After download
- 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
🚀 Easy Launch
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)
🪄 Quick Share Launcher (launch.py)
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
📋 Application Workflow
The application follows a structured 4-step workflow with multiple execution modes:
Core Workflow
- 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:
Execution Modes
- 🔍 Stats (
--stats) - View attendance statistics (read-only) - 📤 Submit (default) - Main workflow for code submission
- 🔑 Login Only (
--login-only) - Refresh session and exit
Submit Workflow Path
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
Login Only Workflow Path
When using Login Only mode:
- Session Check → Sign-in if needed
- Done → Exit after refreshing session
Quick Start
# Basic execution
attend
# View statistics
attend stats
# Refresh login session
attend login
# Run specific week
attend week 4
# Show browser (headed mode)
attend --headed
Install from PyPI:
pip install always-attend
attend --help
python main.py remains available as a compatibility launcher inside the repository checkout.
🧰 CLI Environment Setup
Option A — uv (recommended)
Why 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 attend --dry-run uv run attend login
Option B — Standard venv + pip
python3 -m venv .venv
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
pip install -U pip
pip install -e .
python -m playwright install chromium
attend
What 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 pull
📦 Attendance Database
Always 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/.
📊 Statistics Tracking
The tool now automatically tracks your attendance submission statistics:
# View detailed statistics
attend stats
# Or use the stats module directly
python stats.py
Statistics include:
- Total runs and success rate
- Codes submitted per course
- Recent activity timeline
- Error history
✨ Rich CLI Experience
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.
UI Control Flags
| 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 |
Examples
# Full experience: animated banner, live block progress
CLI_STYLE=fancy CLI_PROGRESS_RICH=1 attend --dry-run
# Quiet fallback suitable for basic terminals
CLI_STYLE=minimal CLI_PROGRESS_RICH=0 attend
Set these in your .env to persist the chosen style across runs.
Troubleshooting
- 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.
FAQ (Windows)
- 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 (/).
Command-Line Arguments
Primary command: attend
| 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 |
Release Automation
- Push a version tag such as
v0.1.0to trigger.github/workflows/release.yml. - The workflow validates that the tag matches
pyproject.toml, buildssdistandwheel, creates a GitHub Release, and publishes to PyPI. - PyPI publishing is configured for Trusted Publishing, so the GitHub repository still needs to be registered as a trusted publisher in the target PyPI project.
Environment Variables
| 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 |
Disclaimer
- 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.
License
- 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file always_attend-0.1.0.tar.gz.
File metadata
- Download URL: always_attend-0.1.0.tar.gz
- Upload date:
- Size: 79.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52c5fb63f3c745cf8bafeed89591ec551312f13f3c298beab0e2f7e32f7b4ae7
|
|
| MD5 |
e33050214d5febd52a82f7bf86a34364
|
|
| BLAKE2b-256 |
a4d320e530a501028ce78e901cf0108f4f65d4a876ac925742d6cb2505d9b60c
|
Provenance
The following attestation bundles were made for always_attend-0.1.0.tar.gz:
Publisher:
release.yml on bunizao/always-attend
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
always_attend-0.1.0.tar.gz -
Subject digest:
52c5fb63f3c745cf8bafeed89591ec551312f13f3c298beab0e2f7e32f7b4ae7 - Sigstore transparency entry: 1081673108
- Sigstore integration time:
-
Permalink:
bunizao/always-attend@ca69460530a1cf700770ebcf6326f87fc920273c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bunizao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ca69460530a1cf700770ebcf6326f87fc920273c -
Trigger Event:
push
-
Statement type:
File details
Details for the file always_attend-0.1.0-py3-none-any.whl.
File metadata
- Download URL: always_attend-0.1.0-py3-none-any.whl
- Upload date:
- Size: 87.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ca3765944ca9f0c223457a9ce681b2a01e14b3df130e8e0b77609efa2eaa741
|
|
| MD5 |
540ffde416fb05c0a421af6e0c97b2fb
|
|
| BLAKE2b-256 |
6b179e4597a5182ded17e868dcbfb5325bf1955b21de115da099213e3b9a2800
|
Provenance
The following attestation bundles were made for always_attend-0.1.0-py3-none-any.whl:
Publisher:
release.yml on bunizao/always-attend
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
always_attend-0.1.0-py3-none-any.whl -
Subject digest:
4ca3765944ca9f0c223457a9ce681b2a01e14b3df130e8e0b77609efa2eaa741 - Sigstore transparency entry: 1081673165
- Sigstore integration time:
-
Permalink:
bunizao/always-attend@ca69460530a1cf700770ebcf6326f87fc920273c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bunizao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ca69460530a1cf700770ebcf6326f87fc920273c -
Trigger Event:
push
-
Statement type: