jozamudi 778bf2bfc1 status: consolidate CDN/upstream status into the header pill + tap panel
- pill label now shows KB/s when degraded ('cdn 23 KB/s'); tap opens a
  panel (replaces the transient toast) with origin/CDN state, KB/s,
  a sparkline of the ~1h /api/cdn hist, and last-updated age
- 60s poll while the page is visible (was: load/play/failure only)
- playback failure overlay appends CDN context when degraded/down
- buffer gauge + spinner untouched: client buffer state, not CDN state
- server unchanged: /api/cdn already returned everything
- tests: 3 hermetic browser tests (mocked /api/cdn via page.route —
  the throwaway server's probe runs live upstream, so its data is
  mocked out of the assertions); 37 passed
- docs: README + SPEC synced
2026-09-20 23:53:47 +00:00

ani-web

Web front-end for anime streaming: search, browse, and stream anime in the browser (hianime.at primary; anidb.app and anikototv.to as fallbacks). Multi-user, with per-user watch history and HLS playback proxied through the backend. Tuned for phone as much as desktop.

login

Quick start

uv venv .venv
uv pip install --python .venv/bin/python -r requirements.txt
.venv/bin/python -m server.users add <you>   # create your account (one-time)
./run.sh

Open it through your HTTPS proxy (or http://localhost:8321 from the host itself — browsers treat localhost as trusted). run.sh restarts cleanly if the server is already running; logs go to server.log.

Accounts are CLI-created only (no self-signup):

.venv/bin/python -m server.users add <name>    # add user (prompted password)
.venv/bin/python -m server.users rm <name>     # remove user + their history
.venv/bin/python -m server.users list          # list users

Passwords are PBKDF2-SHA256 in server/data/aniweb.db (SQLite, 0600); sessions are signed 30-day HttpOnly SameSite=Lax cookies, Secure via run.sh, so remote plain-HTTP can't hold a session — the HTTPS proxy is the way in. See SPEC.md for the rest.

Features

  • History — server-side and per-user: a new device picks up your exact watch state after login. Entries show poster, progress, and a per-entry delete.

    history

  • Home — continue-watching hero (poster, position, Resume) plus a recently-played grid with progress bars.

    home

  • Search — poster-grid results from the active source; your last 8 searches (per user) in a live-filtering dropdown. Results open the detail view (synopsis, season tabs, filler badges).

    search

  • Player — resume at the saved position, skip intro (MAL timings), dub/sub toggle, playback speed, hide fillers, auto-next with a 5-second countdown, ✓ on completed episodes. Playback goes through a backend HLS proxy (the CDN sends no CORS headers); segments are pulled across parallel byte-range lanes so a slow connection doesn't stall.

    detail

  • Status — the header pill shows upstream/CDN health (dots + label); tap opens a panel with detail + the ~1h throughput trend. A failure overlay names the CDN when it's the likely culprit.

  • Stats — ?stats: watch minutes, episodes, streaks, sub/dub split, weekday/per-day heatmaps, top-10 shows, top searches (30–365 day windows).

Layout

server/   FastAPI app (app.py), source providers (providers/: hianime,
          anidb, anikoto) over shared HTTP + dispatch (upstream.py)
static/   front-end: index.html, login.html, app.js, hls.min.js (vendored)
tests/    pytest suite: hermetic default, live browser e2e opt-in
docs/img/  README screenshots
run.sh    launch/restart the server (sets ANIWEB_SECURE=1)
SPEC.md   design, verified anidb.app data flow, security + runbook notes

Dev

  • .venv/bin/pytest tests/ -q — hermetic suite against a throwaway server (never touches real data). Live-upstream browser e2e is opt-in: ANIWEB_LIVE_TESTS=1 .venv/bin/pytest tests/ -q (needs playwright chromium).
  • ANI_SOURCE=anidb .venv/bin/python -m server.upstream — live self-check of the anidb fetchers (must be the -m form; plain script execution breaks the providers' relative imports).
  • Everything else (Cloudflare/impersonation, HLS proxy, CDN probe, auth hardening, cache-busting): SPEC.md.
S
Description
No description provided
Readme
8 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 65.2%
JavaScript 25.9%
CSS 5.9%
HTML 2.1%
Shell 0.9%