Add interaction logging and tighten model NOT NULL constraints

Log searches (article/category) and message-generation events to a new
interaction_log table, capturing IP address and User-Agent.

Also apply NOT NULL constraints to Contribution, SentMessage, FlickrUpload,
and ThumbnailCache fields that are always populated, and remove stale
continue_token references from category.html.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-02-08 12:34:04 +00:00
parent 252a854e76
commit 08f5128e8d
5 changed files with 160 additions and 76 deletions

View file

@ -92,6 +92,8 @@ those obtained via Flickr mail requests.
- `flickr_uploads`: derived table built by `update_flickr_uploads.py` by
matching Commons uploads to Flickr URLs
- `thumbnail_cache`: cached Commons API thumbnail URLs (7-day TTL)
- `interaction_log`: written by the web app to record searches and message
generation events (see below)
**Key functions**:
- `get_recent_commons_uploads()`: Loads uploads, filters by sent mail match,
@ -115,6 +117,24 @@ Builds/updates `flickr_uploads` from `contributions` and links to
- Extracts Flickr URL from contribution comment when present
- Falls back to Commons `extmetadata.Credit` lookup when comment has no URL
### Interaction Logging (`log_interaction`)
The `log_interaction()` helper writes a row to `interaction_log` on each
meaningful user action:
- `"search_article"` user submits a Wikipedia article search (page 1 only,
to avoid logging every pagination hit)
- `"search_category"` user submits a Wikipedia category search
- `"generate_message"` a non-free CC message is generated after clicking a photo
Each row captures: Unix `timestamp`, `interaction_type`, `ip_address`
(prefers `X-Forwarded-For` for proxy setups), `user_agent`, `query` (article
title or category name), and optionally `flickr_url` / `wikipedia_url`.
The table is created by `init_db()` (called via `python3 -c "from
flickr_mail.database import init_db; init_db()"` or any of the maintenance
scripts). The web app never calls `init_db()` itself.
### Category Search (`/category` route)
Finds Wikipedia articles in a category that don't have images.