Skip to main content

attendance42lyon

Local HTTP API for the 42 Lyon attendance intranet.

PyPI Python License

The intranet gives you a web page. This gives you curl.

A small daemon holds your session and exposes your attendance data on 127.0.0.1:8420, so a waybar module, a GNOME extension or a shell script can read your hours without reimplementing the login.

$ curl -s -H "Authorization: Bearer $(cat ~/.config/attendance42/token)" \
    127.0.0.1:8420/v1/month | jq '{worked, requiredSoFar, balanceSoFar}'
{
  "worked": 82740,
  "requiredSoFar": 302400,
  "balanceSoFar": -219660
}

All durations are integer seconds.

Install

uv tool install attendance42lyon
attendance install

attendance install writes a --user systemd unit, starts it, and waits for the daemon to answer. It needs a graphical session: signing in opens a real browser window.

$ attendance install
· /home/you/.local/bin/attendance-daemon
✓ attendance42.service running on 127.0.0.1:8420

Then, once your session expires:

$ attendance login
→ browser opened, sign in there
✓ signed in

That is the whole CLI — install, login, uninstall. Reading data is the API's job.

Endpoints

Route Returns
GET /healthz liveness, no authentication
GET /v1/month current month
GET /v1/months/{YYYY-MM} a given month
POST /v1/login opens the browser, replies 202 immediately

Everything except /healthz needs Authorization: Bearer <token>.

Full reference, including every field and error state: docs/API.md.

Interactive docs

The daemon serves its own OpenAPI schema. With the service running:

Written reference: docs/API.md.

Credentials and storage

Your 42 password never reaches this tool. Signing in happens on the real 42 page, in a real browser. What comes back is a session cookie.

That cookie is stored in your system keyring — KWallet, GNOME Keyring, or whatever implements the Secret Service API on your desktop. It is encrypted at rest by the keyring, unlocked with your session.

If no keyring is available, the SDK falls back to ~/.local/state/attendance-42/state.json at mode 0600. On Linux that file is plaintext, protected by file permissions alone. If your desktop has no keyring, know that this is the trade-off.

The API token is a separate thing, and is not in the keyring: the daemon generates it on first start in ~/.config/attendance42/token, mode 0600, as plaintext. It has to be readable without unlocking anything, since the daemon starts with your session. It is not your 42 password — it only proves a local client is you, because anything on the machine can reach the loopback port.

It is read once at startup. To rotate it, delete the file and restart the service; every client then needs the new value.

How the session works

The daemon never opens a browser on its own. When your 42 session dies it answers 503 with a state a client can act on:

{ "state": "unauthenticated", "hint": "POST /v1/login" }

A GNOME extension shows a button, waybar shows a marker, you decide when to sign in. POST /v1/login then opens Chrome, you authenticate on the real 42 page, and the daemon keeps the cookie in your keyring. The tool never sees your password.

While a login is in progress, reads answer 503 logging_in instead of blocking for three minutes.

Requirements

  • Linux with systemd --user
  • Python 3.13+
  • X11. Wayland is untested for now — the unit imports DISPLAY and XAUTHORITY from the session. Chrome runs under XWayland, so it may well work, but nothing has been verified. Reports welcome.
  • A system keyring (KWallet, GNOME Keyring, …)
  • Google Chrome, for the login window

Troubleshooting

attendance install fails on /healthz — the daemon started and died. The last journal lines are printed with the error; a missing dependency is the usual cause.

{"state": "unauthorized"} — the local token is wrong. Check that your client reads ~/.config/attendance42/token, and that $XDG_CONFIG_HOME is the same for the daemon and for you.

{"state": "unauthenticated"} — the 42 session expired. Run attendance login.

Nothing on port 8420 after a uv tool upgrade — re-run attendance install to refresh the unit.

Contributing

git clone https://codeberg.org/Z-OxO/attendance-lyon-api
cd attendance-lyon-api
uv sync
uv run python -m attendance42lyon.daemon

Issues and patches: https://codeberg.org/Z-OxO/attendance-lyon-api/issues

License

MIT. Not affiliated with 42 or 42 Lyon.

Metadata

Release files for attendance42lyon 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for attendance42lyon 0.1.1
File Size Uploaded Provenance
attendance42lyon-0.1.1.tar.gz 16.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for attendance42lyon 0.1.1
File Interpreter ABI Platform
attendance42lyon-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 32.8 kB

Release files / attendance42lyon-0.1.1.tar.gz

Download URL attendance42lyon-0.1.1.tar.gz
Size 16.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5584753db721f099a3413f0c5a4a1c07d2c4ad9a2875b3298ae7d1fc8bd8f472
BLAKE2b-256 checksum
How to use checksums
8afa6e3dda914166bc5eac7eaba567379fd61b25f7a2c8f4a5ad827975d17e84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / attendance42lyon-0.1.1-py3-none-any.whl

Download URL attendance42lyon-0.1.1-py3-none-any.whl
Size 16.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80e7e5750c83ce9fe211441b3c3dde5426d015314e835eab585db39e25f0c897
BLAKE2b-256 checksum
How to use checksums
167e4f9eb21c806f33d5c3f3f982d02b4c2ceb44b05e3cc53c030166d32fcb4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for attendance42lyon 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page