feat: manage image captions and tags from the admin panel
This commit is contained in:
4 files changed
+409
-84
No files matched your search
@@ -39,6 +39,7 @@ Files are stored under sharded date/hash paths:
|
||||
```text
|
||||
data/
|
||||
index/memes.jsonl
|
||||
index/tags.json
|
||||
memes/YYYY/MM/DD/aa/bb/<sha256>.<ext>
|
||||
meta/YYYY/MM/DD/aa/bb/<sha256>.json
|
||||
```
|
||||
@@ -60,7 +61,8 @@ Set `SITE_URL` in production so canonical and API discovery URLs use the public
|
||||
|
||||
## Public API
|
||||
|
||||
- `GET /api/memes?page=1&pageSize=12`: lists approved memes only. `pageSize` is capped at `48`.
|
||||
- `GET /api/memes?page=1&pageSize=12`: lists approved memes with `caption` and `tags`. `pageSize` is capped at `48`. Add `q=angry%20cat` for ranked caption/topic search and `tag=cats` for a topic filter. Repeat `tag` to require all selected topics.
|
||||
- `GET /api/tags`: lists the available managed tag names.
|
||||
- `GET /api/memes/<sha256>`: returns public metadata for one approved meme.
|
||||
- `GET /meme/<sha256>`: opens an approved meme in the viewer and provides its shareable permalink.
|
||||
- `GET /media/<sha256>`: returns the normalized WebP image for one approved meme.
|
||||
@@ -70,6 +72,25 @@ API uploads use the exact same path as the browser form: persistent IP upload qu
|
||||
|
||||
Public API reads are rate-limited per IP and return `429` with `Retry-After` when exceeded. List and metadata responses include `RateLimit-*` headers and a `rateLimit` object.
|
||||
|
||||
## Captions, tags, and administration
|
||||
|
||||
The LLM moderation call also writes a factual searchable caption and chooses relevant tags from the admin-managed catalog. The server filters out invented tags. Uploaders cannot supply captions or tags; reads and search are public, while every metadata mutation requires the existing `X-Admin-Token` authentication.
|
||||
|
||||
Search is lexical: case/accent-insensitive words, prefixes, and small spelling corrections, ranked by relevance then newest first. All query words and all selected tags must match. It does not use embeddings or infer semantic synonyms. Limits: 200 query characters, 20 tag filters, 200 managed tags, 60 characters per tag, and 2000 caption characters.
|
||||
|
||||
Open `/admin/<ADMIN_TOKEN>` to manage pending, published, or all images; edit captions and assigned tags; and add or remove topics. Tag names are lowercase and accept letters, numbers, spaces, underscores, and hyphens. Removing a tag clears its assignments from every image.
|
||||
|
||||
Existing records load with empty captions/tags; no offline migration is needed. Define your topics, then use **GENERATE ALL MISSING CAPTIONS** to backfill all existing images. The browser processes images sequentially, saves each result immediately, and can stop after the current image. Re-running resumes missing captions. **GENERATE AI FOR SELECTED** can regenerate metadata for existing captions (for example after adding topics). Generation uses `OPENAI_API_KEY` and `OPENAI_MODERATION_MODEL`, incurs normal model usage, and leaves existing metadata and approval status intact on failure. Manual edits made while an AI request is running are preserved via a version check. Without an API key, uploads remain pending with empty metadata, and admins can still edit manually.
|
||||
|
||||
Authenticated admin endpoints (not part of the public OpenAPI):
|
||||
|
||||
- `GET /api/admin/memes?page=1&pageSize=12&status=all`: paginated image management; `status` accepts `pending`, `approved`, or `all`. Supports `q`, repeated `tag`, and `missingCaption=true`.
|
||||
- `PATCH /api/admin/memes/<sha256>` with `{ "caption": "...", "tags": ["cats"] }`: edit either or both metadata fields; unknown tags are rejected.
|
||||
- `POST /api/admin/memes/<sha256>/generate`: generate caption and tags without re-moderating; optional `{ "onlyMissing": true }` skips already-captioned images.
|
||||
- `GET /api/admin/tags`, `POST /api/admin/tags` with `{ "name": "cats" }`, and `DELETE /api/admin/tags/<URL-encoded-name>`: manage the catalog.
|
||||
|
||||
Admin responses use `Cache-Control: no-store`. Unauthenticated admin API requests return `404`.
|
||||
|
||||
## Docker
|
||||
|
||||
```sh
|
||||
|
||||
Reference in new issue
Block a user