Add a Random image endpoint and SPA page (with fastfetch mode)
Backend: GET /api/random/ (aliases /random and /random/) returns a random library image with: - rating=s,q,e filtering (comma separated, default any); - fastfetch mode (?fastfetch=1 or any User-Agent containing "fastfetch") that only considers png/jpg/gif - what terminal viewers can show; - JSON with j_id, filename, extension, rating, size, e621 id plus absolute url/download_url/thumbnail_url. Authenticated callers get signed URLs so fastfetch and image viewers can load them without headers; guests get unsigned URLs and never receive hidden_from_guests items. Tests: apps/library/tests/test_random.py (8 tests) covering the response contract, guest signatures, image-only default, the fastfetch format restriction (flag and User-Agent), rating filters, guest visibility and the short alias. Frontend: /random page with rating pills, R to roll, Open/Download and a library link, plus navigation and command palette entries; needs a backend, hidden in local mode. nginx: /random negotiates on Accept so browsers keep getting the SPA while scripts get the JSON (verified with the proxy and frontend containers). Also fixes a regression from the SSRF change: the guest download proxy still referenced the removed 'parsed' variable on its success path, so every proxied download would have 500'd. Redirect hops are now covered by tests with a mocked requests.get.
This commit is contained in:
@@ -5,7 +5,7 @@ Self-hosted media library and e621 archive manager, rebuilt as a **React SPA + D
|
||||
## Structure
|
||||
|
||||
```
|
||||
backend/ Django 6 + DRF API (SQLite in dev, MariaDB in production)
|
||||
backend/ Django 6 + DRF API (MariaDB + Redis via docker compose)
|
||||
frontend/ Vite + React + TypeScript SPA
|
||||
```
|
||||
|
||||
@@ -33,9 +33,44 @@ npm run dev # http://localhost:5173, proxies /api to
|
||||
|
||||
### Production
|
||||
|
||||
Not wired up yet — planned: Nginx serving the SPA build, `/media` and `/library` media
|
||||
directly, and proxying `/api` to Waitress/Django. See `frontend/` design docs for the UI
|
||||
specification.
|
||||
Docker: see [`deploy/`](deploy/README.md) for the two images (SPA on static
|
||||
nginx, API on gunicorn), the three compose variants (both / frontend-only /
|
||||
backend-only) behind a shared nginx service and a Tailscale sidecar, and the
|
||||
public-funnel or tailnet-only serve configs. `deploy/push_*.sh` builds and
|
||||
pushes the multi-arch images to the Gitea registry.
|
||||
|
||||
## Random image endpoint
|
||||
|
||||
Used by the SPA's Random page and by shell greetings (fish_greeting +
|
||||
fastfetch):
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Token <token>" \
|
||||
"https://j621.example.ts.net/api/random/?rating=s,q&fastfetch=1"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"j_id": "J-59",
|
||||
"filename": "J-59.jpg",
|
||||
"extension": "jpg",
|
||||
"rating": "e",
|
||||
"url": "https://j621.example.ts.net/api/files/J-59/raw/?sig=…",
|
||||
"download_url": "https://j621.example.ts.net/api/files/J-59/raw/?sig=…&download=1",
|
||||
"thumbnail_url": "https://j621.example.ts.net/api/files/J-59/thumbnail/?sig=…",
|
||||
"fastfetch": true
|
||||
}
|
||||
```
|
||||
|
||||
- `rating` — comma separated subset of `s`, `q`, `e` (default: any).
|
||||
- `fastfetch=1`, or any request whose User-Agent contains `fastfetch`, limits
|
||||
the roll to `png`/`jpg`/`gif` so terminals can display it. Images are the
|
||||
only candidates in both modes.
|
||||
- `url` is absolute, and signed for authenticated callers, so fastfetch can
|
||||
load it without headers. Guests get an unsigned URL and only see
|
||||
guest-visible items.
|
||||
- `/random` and `/random/` are aliases of `/api/random/` for scripts; 404 when
|
||||
nothing matches the filters.
|
||||
|
||||
## Licence
|
||||
|
||||
|
||||
Reference in New Issue
Block a user