Brave errors (e.g. its spending limit being hit) now fall back to Bing
like empty results do, with the error in a Brave Unavailable alert. If
Bing fails too (HTTP error or a page without results, which for Bing
means it's blocking us), a new papercraft donate.webp is served instead
of an AI image, and nothing is cached so the query works once either
search is back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A search's result URLs are kept in SurrealDB (results table) for 1 hour,
fetched in the same transaction as the rate limit. Other ?i= of the query
then skip the Brave/Bing search and don't count toward the daily limit.
The record also tracks which results worked (pos) and how far it got
(next), so an already-known ?i= downloads only its own image and a new one
carries on from where the last left off. free.* searches Openverse and
Wikimedia together so its whole list can be cached. Empty results aren't
cached, since they can mean Brave and Bing failed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
safesearch=moderate isn't a Bing parameter. Bing's filter is set by the
SRCHHPGUSR=ADLT=OFF cookie, so send that (plus adlt=off).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ai.direct-img.link serves images from the AuroraIMG-6M API on our Dokploy
server (github.com/direct-img/AuroraIMG-6M) instead of searching. It takes
?src= (auroraimg-6m, case-insensitive, the default and only source for now)
and ?i=, where each i gets its own seed derived from the query, so it's a
different image of the same prompt. It has its own daily limit
(AI_DAILY_LIMIT) and AI: cache keys / ai/ R2 prefix. Failed generations
aren't cached, since they're likely temporary.
On direct-img.link and free.direct-img.link, a search that finds nothing (or
fewer than i working images) now serves an AI image of the query instead of
bad.webp. It's kept for 24h like failures were, so a later search can still
find a real image; bad.webp is only served if the AI image fails too. Its ttl
is stored in KV and R2 metadata so cache hits and deduped waiters send a
matching max-age.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add _routes.json so /, /robots.txt and /assets/* skip the worker and
don't count against the Functions request quota. rate-limit.js moves to
assets/ so the homepage reads it client-side instead of via HTMLRewriter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- free.direct-img.link serves only unrestricted (public domain/CC0) images
from Openverse (license=cc0,pdm) and Wikimedia Commons
(haslicense:unrestricted), with optional ?src=openverse|wikimedia
- ?i=1..20 picks the i-th working image on both sites; broken links are
skipped so every index is a different image
- Openverse OAuth token is cached in KV and refreshed automatically
- Skip Flickr "photo unavailable" placeholders (served with HTTP 200)
- Free/indexed cache keys use uppercase prefixes; plain main-site keys
are unchanged so existing cache entries stay valid
- Update README, homepage, privacy policy and terms
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>