Skip to content

Commit d0736e2

Browse files
committed
docs: rewrite readme around project reflection
1 parent a286b8e commit d0736e2

File tree

1 file changed

+14
-251
lines changed

1 file changed

+14
-251
lines changed

README.md

Lines changed: 14 additions & 251 deletions
Original file line numberDiff line numberDiff line change
@@ -1,255 +1,18 @@
1-
<h1 align="center">Always Attend</h1>
2-
<p align="center">
3-
<img src="https://img.shields.io/badge/python-3.11%2B-blue.svg">
4-
<img src="https://img.shields.io/badge/License-GPLv3-blue.svg">
5-
<img src="https://img.shields.io/github/last-commit/bunizao/always-attend">
6-
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg">
7-
<img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey">
8-
<p align="center">
9-
<img src="https://img.shields.io/badge/status-Public%20Beta-orange?style=for-the-badge">
10-
<p align="center">
11-
An automation helper to submit weekly attendance codes. Now in Public Beta.<br>
12-
⚠️ <b>Use responsibly and follow your institution’s policies.</b>
13-
</p>
1+
# Always Attend
142

15-
<p align="center">
16-
<a href="README_zh.md"><b>中文文档</b></a>
17-
</p>
18-
19-
> [!WARNING]
20-
> This project is currently in **Public Beta**. Features may change and bugs are expected.
21-
> Receive Feedback Here: [![Open Issue](https://img.shields.io/badge/Open-Issue-blue)](https://github.com/bunizao/always-attend/issues/new)
22-
23-
24-
25-
26-
27-
28-
29-
## 📥 Get Always Attend
30-
31-
Install the CLI using one of these two supported flows:
32-
33-
### Option 1 — `uv tool` (recommended)
34-
1. Install [uv](https://docs.astral.sh/uv/) if it is not already available:
35-
```bash
36-
curl -LsSf https://astral.sh/uv/install.sh | sh
37-
```
38-
2. Install `always-attend` and expose the bundled `playwright` executable:
39-
```bash
40-
uv tool install --with-executables-from playwright always-attend
41-
```
42-
3. Verify the CLI:
43-
```bash
44-
attend --help
45-
```
46-
47-
The app prefers your installed Chrome/Edge. If Playwright Chromium is needed and missing, it will be downloaded automatically on first run.
48-
49-
If `attend` is not on your shell `PATH` yet, run:
50-
51-
```bash
52-
uv tool update-shell
53-
```
54-
55-
### Option 2 — `pipx`
56-
1. Install [pipx](https://pipx.pypa.io/stable/installation/) if needed:
57-
```bash
58-
python3 -m pip install --user pipx
59-
python3 -m pipx ensurepath
60-
```
61-
2. Install `always-attend`:
62-
```bash
63-
pipx install always-attend
64-
```
65-
3. Expose the `playwright` executable from the injected package:
66-
```bash
67-
pipx inject --include-apps always-attend playwright
68-
```
69-
4. Verify the CLI:
70-
```bash
71-
attend --help
72-
```
73-
74-
## 🚀 Run The CLI
75-
76-
Public command:
77-
78-
- `attend`
79-
80-
## 🤖 Agents-First Workflow
81-
82-
`attend` is now the single agent-facing entrypoint. The intended execution model is:
83-
84-
1. `attend auth ...` delegates Okta login and session checks to the external `okta` CLI.
85-
2. `attend fetch ...` calls `moodle-cli`, `edstem`, or `gogcli` and passes shared Okta cookie context through environment variables.
86-
3. `attend resolve ...` normalizes an agent-authored submission plan into a stable JSON shape.
87-
4. `attend submit ...` materializes the resolved plan into the local codes store and reuses the Playwright submitter for the final portal submission.
88-
89-
### Quick Start
90-
91-
```bash
92-
# Inspect runtime locations for integrations
93-
attend paths --json
94-
95-
# Refresh or create the shared Okta session
96-
attend auth login https://attendance.example.edu --json
97-
98-
# Check whether the shared session is still valid
99-
attend auth check https://attendance.example.edu --json
100-
101-
# Fetch source data
102-
attend fetch --source edstem --json
103-
attend fetch --source edstem --course FIT2099 --kind threads --json
104-
105-
# Validate a submission plan
106-
attend resolve --plan plan.json --json
107-
108-
# Submit a validated plan
109-
attend submit --plan plan.json --portal-url https://attendance.example.edu --json
110-
```
111-
112-
### Shared Session Contract
113-
114-
When `attend fetch` runs, it exports the shared Okta session to child CLIs using these environment variables:
115-
116-
- `ALWAYS_ATTEND_OKTA_URL`
117-
- `ALWAYS_ATTEND_OKTA_COOKIES_JSON`
118-
- `ALWAYS_ATTEND_OKTA_COOKIE_HEADER`
119-
- `OKTA_COOKIES_JSON`
120-
- `OKTA_COOKIE_HEADER`
121-
122-
Adapters should consume these values instead of implementing their own interactive login flow.
123-
124-
Runtime files default to standard user directories:
125-
- Linux:
126-
`~/.config/always-attend/.env`,
127-
`~/.local/state/always-attend/`,
128-
`~/.local/share/always-attend/codes/`
129-
- macOS:
130-
`~/Library/Application Support/always-attend/config/.env`,
131-
`~/Library/Application Support/always-attend/state/`,
132-
`~/Library/Application Support/always-attend/data/codes/`
133-
- Windows:
134-
`%APPDATA%\\always-attend\\config\\.env`,
135-
`%LOCALAPPDATA%\\always-attend\\state\\`,
136-
`%LOCALAPPDATA%\\always-attend\\data\\codes\\`
137-
- Override any location with env vars such as `ENV_FILE`, `STORAGE_STATE`, `ATTENDANCE_STATS_FILE`, or `CODES_DB_PATH`
138-
139-
Integration contract:
140-
- CLI: `attend paths --json`
141-
- Python: `from always_attend import get_runtime_paths_dict`
142-
143-
## 📦 Attendance Database
144-
145-
Always Attend now reads attendance codes exclusively from `codes_db_path` (by default a dedicated `codes/` directory under the app data directory, or from `CODES_DB_PATH` if overridden). Each course gets its own subfolder and every week is represented by a JSON file:
146-
147-
```
148-
data/
149-
FIT1045/
150-
3.json # [{"slot": "Workshop 01", "code": "LCPPH"}, ...]
151-
FIT1047/
152-
7.json
153-
```
154-
155-
If you maintain your codes in a separate Git repository, point the tool at it:
156-
157-
```bash
158-
export CODES_DB_REPO="git@github.com:you/attendance-db.git"
159-
export CODES_DB_BRANCH="main"
160-
```
161-
162-
On every run the repository is cloned into `codes_db_path` (if missing) or updated in place before submission. Without a repository the tool simply reads whatever JSON files already exist there.
163-
164-
## 📊 Statistics Tracking
165-
166-
The tool now automatically tracks your attendance submission statistics:
167-
168-
```bash
169-
# View detailed statistics
170-
attend stats
171-
172-
# Or use the stats module directly
173-
python stats.py
174-
```
175-
176-
Statistics include:
177-
- Total runs and success rate
178-
- Codes submitted per course
179-
- Recent activity timeline
180-
- Error history
181-
182-
## Troubleshooting
183-
184-
- If login keeps asking for MFA: re-run the headed login to refresh the saved session state
185-
- If the browser fails to launch: make sure Google Chrome or Microsoft Edge is installed, or set `BROWSER_CHANNEL` to `chrome`/`msedge`.
186-
- If `attend` is not found after install: restart the terminal, then run `uv tool update-shell` or `python3 -m pipx ensurepath`.
187-
- When running, please do NOT use a VPN, as this may cause Okta to refuse the connection.
188-
189-
## FAQ (Windows)
190-
191-
- **Use `py` instead of `python`**: If `python` isn't found or points to another version, use `py` for bootstrap commands such as `py -m pip install --user pipx`.
192-
- **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.
193-
- **Path escaping issues**: PowerShell uses backslashes (`\`) and may treat them as escape characters. Wrap paths in quotes or use double backslashes like `C:\path\to\file`. Git Bash uses forward slashes (`/`).
194-
195-
## Command-Line Arguments
196-
197-
Primary command: `attend`
198-
199-
| Argument | Type | Description | Example |
200-
| --- | --- | --- | --- |
201-
| `--browser` | string | Browser engine (`chromium`/`firefox`/`webkit`) | `--browser chromium` |
202-
| `--channel` | string | System browser channel (chromium only: `chrome`, `chrome-beta`, `msedge`, etc.) | `--channel chrome` |
203-
| `--headed` | flag | Show browser UI (sets `HEADLESS=0`) | `--headed` |
204-
| `--dry-run` | flag | Print parsed codes and exit without submitting | `--dry-run` |
205-
| `--week` | int | Submit codes for a specific week (sets `WEEK_NUMBER`) | `--week 4` |
206-
| `--login-only` | flag | Refresh the session and exit without submitting | `--login-only` |
207-
| `--stats` | flag | Display cached attendance statistics and exit | `--stats` |
208-
| `--setup` | flag | Launch the configuration wizard interactively | `--setup` |
209-
| `--debug` | flag | Enable debug logging profile | `--debug` |
210-
| `--verbose` | flag | Enable verbose logging profile | `--verbose` |
211-
| `--skip-update` | flag | Skip the git update check before running | `--skip-update` |
212-
213-
## Release Automation
214-
215-
- Push a version tag such as `v0.1.1` to trigger `.github/workflows/release.yml`.
216-
- The workflow validates that the tag matches `pyproject.toml`, builds `sdist` and `wheel`, creates a GitHub Release, and publishes to PyPI.
217-
- 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.
3+
> This is something I wrote in my FIT1045 H3 report.
4+
>
5+
> Always-Attend is a work I refined with great care and one I am proud of.
6+
> No matter the outcome, I am still proud of it.
2187
2198
## Reflection
2209

221-
> I kept building, not to compete with AI, but to finish what I started. I kept adding new ideas, refactoring, polishing small things that no one else would notice. Slowly, the project became not just a tool but a reflection of my curiosity and patience. Finishing it reminded me that the value isn't only in what a program does, but in what I learn while making it.
222-
223-
## Environment Variables
224-
225-
| Variable | Type | Required | Description | Example |
226-
| --- | --- | --- | --- | --- |
227-
| `PORTAL_URL` | string URL | Yes | Attendance portal base URL | `https://attendance.monash.edu.my` |
228-
| `CODES_DB_PATH` | string path | No | Root folder containing `COURSE/WEEK.json` files | `/srv/attendance-data` |
229-
| `CODES_DB_REPO` | string URL | No | Git repository that mirrors the data tree | `git@github.com:you/attendance-db.git` |
230-
| `CODES_DB_BRANCH` | string | No | Branch to checkout when syncing the repository | `main` |
231-
| `WEEK_NUMBER` | int | No | Force a specific week instead of auto-detecting | `4` |
232-
| `SUBMIT_CONCURRENCY` | int | No | Maximum courses processed concurrently | `2` |
233-
| `SUBMIT_TARGET_CONCURRENCY` | int | No | Parallel submission workers per course | `3` |
234-
| `USERNAME` | string | No | Okta username for auto-login | `student@example.edu` |
235-
| `PASSWORD` | string | No | Okta password for auto-login | `correcthorsebattery` |
236-
| `TOTP_SECRET` | string (base32) | No | MFA TOTP secret for auto-login | `JBSWY3DPEHPK3PXP` |
237-
| `AUTO_LOGIN` | flag (0/1) | No | Toggle automatic login | `1` |
238-
| `BROWSER` | string | No | Engine override (`chromium`/`firefox`/`webkit`) | `chromium` |
239-
| `BROWSER_CHANNEL` | string | No | System channel (`chrome`/`msedge`/etc.) | `chrome` |
240-
| `HEADLESS` | flag (0/1 or true/false) | No | Run without UI (0 disables) | `0` |
241-
| `USER_DATA_DIR` | string path | No | Persistent browser profile directory | `~/.always-attend-profile` |
242-
| `LOG_PROFILE` | string | No | Logging profile (`user`/`quiet`/`debug`/`verbose`) | `verbose` |
243-
| `LOG_FILE` | string path | No | Optional log file destination | `/tmp/always-attend.log` |
244-
| `SKIP_UPDATE_CHECK` | flag (0/1 or true/false) | No | Skip remote git pull when set | `1` |
245-
246-
## Disclaimer
247-
248-
- 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.
249-
- 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.
250-
- 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.
251-
252-
## License
253-
254-
- This project is licensed under the GNU General Public License v3.0 (GPL‑3.0). See the full text in the `LICENSE` file.
255-
- You may copy, modify, and distribute this software under the terms of the GPL‑3.0. It is provided “as is”, without any warranty.
10+
> I've been developing Always-Attend for two months now. There are already more than 150+ commits, and the project has grown from a small 500-line script into something I'm genuinely proud of. Today it has over 30+ Python files and around 6000+ lines of code. It feels modern, elegant, and useful. It is something I believe many people would enjoy using.
11+
>
12+
> Along the way, I've had help from AI agents. Codex and Claude Code helped me set up test frameworks, edit files according to each iteration, and fix bugs that once took me hours to find. Always-Attend would not have reached this stage without them. Working with these tools also taught me how to think more clearly, how to describe a problem precisely, and how to review my own code with a calmer mind.
13+
>
14+
> Then ChatGPT Atlas arrived, and everything changed. I downloaded it the moment it was released and tried it right away. I asked it to find the week's attendance code in Gmail, open a GitHub issue, and submit the code on the website. It moved through my browser, filled the forms, and formatted text like a human. Watching it, I honestly felt a shock. For a moment, I thought Always-Attend no longer mattered. It felt like watching the story of so many startups I knew, small projects replaced by products from bigger, well-known companies. Maybe in this fast changing age of AI, that's the only ending for small projects like Always-Attend.
15+
>
16+
> Thinking about that made me feel truly discouraged, but I didn't stop. I kept building, not to compete with AI, but to finish what I started. I kept adding new ideas, refactoring, polishing small things that no one else would notice. Slowly, the project became not just a tool but a reflection of my curiosity and patience. Finishing it reminded me that the value isn't only in what a program does, but in what I learn while making it.
17+
>
18+
> AI will keep advancing. Tools will get faster, smarter, and more capable. What I keep is the part that does not ever change: the curiosity, the discipline, and the quiet satisfaction of watching something I built come alive line by line.

0 commit comments

Comments
 (0)