From c3bc6895c407d64265206f32b7648d58dbbde522 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Wed, 4 Feb 2026 16:52:38 +0000 Subject: [PATCH] Add AGENTS.md with codebase documentation for AI agents Co-Authored-By: Claude Opus 4.5 --- AGENTS.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..86993d4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,91 @@ +# Agent Guidelines for Flickr Mail + +This document provides context for AI agents working on this codebase. + +## Project Overview + +Flickr Mail is a Flask web application that helps users find photos on Flickr +for Wikipedia articles and contact photographers to request Creative Commons +licensing. + +## Architecture + +- **main.py**: Single-file Flask application containing all routes and logic +- **templates/**: Jinja2 templates using Bootstrap 5 for styling + - `base.html`: Base template with Bootstrap CSS/JS + - `combined.html`: Main UI template for search, results, and message composition + - `message.jinja`: Template for the permission request message body + - `show_error.html`: Error display template + +## Key Components + +### Flickr Search (`search_flickr`, `parse_flickr_search_results`) + +Searches Flickr by scraping the search results page. The page embeds JSON data +in a `modelExport` JavaScript variable which contains photo metadata. + +- Uses browser-like headers (`BROWSER_HEADERS`) to avoid blocks +- Parses embedded JSON by counting braces (not regex) to handle nested structures +- Returns `FlickrPhoto` dataclass instances with id, title, username, license, URLs + +### FlickrPhoto Dataclass + +Represents a photo with: +- `id`, `title`, `path_alias`, `owner_nsid`, `username`, `realname` +- `license` (int): Flickr license code (0=ARR, 4=CC BY, 5=CC BY-SA, etc.) +- `thumb_url`, `medium_url`: Static image URLs +- `flickr_url` property: URL to photo page +- `license_name` property: Human-readable license name + +### License Codes + +Wikipedia-compatible licenses (can be used): 4 (CC BY), 5 (CC BY-SA), 7 (No +known copyright), 8 (US Government), 9 (CC0), 10 (Public Domain). + +Not compatible: 0 (All Rights Reserved), 1-3 (NC variants), 6 (ND). + +### URL Validation (`is_valid_flickr_image_url`) + +Validates that image URLs passed via query params are from legitimate Flickr +static image servers: +- `live.staticflickr.com` +- `farm*.staticflickr.com` +- `c1.staticflickr.com`, `c2.staticflickr.com` + +### NSID Lookup (`flickr_usrename_to_nsid`) + +Converts a Flickr username/path alias to the NSID (internal user ID) needed +for the Flickr mail URL. Scrapes the user's profile page for embedded params. + +## Request Flow + +1. User enters Wikipedia article title/URL → `start()` extracts article name +2. `search_flickr()` fetches and parses Flickr search results +3. Results displayed as clickable photo grid with license badges +4. User clicks photo → page reloads with `flickr` and `img` params +5. `flickr_usrename_to_nsid()` looks up the photographer's NSID +6. Message template rendered with photo details +7. User copies message and clicks link to Flickr's mail compose page + +## Testing Changes + +Run the Flask app locally: +```bash +python3 main.py +``` +Then visit http://localhost:5000/ + +Test search functionality: +```python +from main import search_flickr +photos = search_flickr("Big Ben") +print(len(photos), photos[0].title, photos[0].license_name) +``` + +## Potential Improvements + +- Add pagination for search results (currently shows ~25 photos) +- Cache search results to reduce Flickr requests +- Add filtering by license type +- Handle Flickr rate limiting/blocks more gracefully +- Add tests for the parsing logic