Commit Graph
46 Commits
Author SHA1 Message Date
multipleof4andClaude Opus 5.5 223150650c Feat: Cache search results for an hour so other ?i= are free and fast
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>
2026-10-12 14:07:51 +00:00
multipleof4andClaude Opus 5.5 bd8ef51591 Fix: Turn off Bing SafeSearch to match Brave
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>
2026-10-12 13:45:20 +00:00
multipleof4andClaude Opus 5.5 1784e2972a Fix: Include the full request URL in every ntfy alert
Bing fallback, rate limit, fetch error and SurrealDB alerts now end with the
request URL (site, query, ?i= and ?src=), like New Search and Deduped already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:29:32 +00:00
multipleof4andClaude Opus 5.5 865b9d951d Fix: Cache AI fallback images for 90 days like every other image
They were kept for 24h so a later search could replace them, but that
regenerated them daily for no real gain. Searches where the AI image also
fails are still remembered for 24h as bad.webp. With one TTL for all images
again, the per-image ttl stored in KV and R2 is no longer needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:06:31 +00:00
multipleof4andClaude Opus 5.5 6fb64e9d7b Feat: AI images on ai.direct-img.link, and as the fallback when a search finds nothing
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>
2026-10-12 02:56:39 +00:00
multipleof4andClaude Opus 5.5 07564bade2 Fix: Finish searches when the client disconnects, and download candidates in parallel
A reload during a slow first-time search (seen on mobile Chrome and Safari)
made the runtime cancel the search mid-way. Its result was never stored and
its lock never released, so the reload waited out the 45s lock and then
served bad.webp. Logs show this as clientDisconnected invocations followed by
a bad.webp. The search now runs under waitUntil, so it still stores its
result and releases the lock, and the waiting reload serves the image.

Image candidates were downloaded one at a time, so each dead or slow host
could stall the search for its full 5s timeout. Up to 4 now download at once
but are checked in result order, so ?i= picks the same image. Downloads still
in flight are aborted once the image is found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:14:20 +00:00
multipleof4andClaude Opus 5.5 fd5694669a Fix: Dedupe concurrent searches for the same query with a SurrealDB lock
Two misses for the same query at once each ran their own search (ntfy
showed Search #24 and #25 for one image). An in-memory fix wouldn't
hold: a test of concurrent same-query requests on this project found
they share an isolate only ~25% of the time.

The rate-limit query is now one transaction that also claims a
per-query lock, so it's still a single SurrealDB round trip. Requests
that find the lock held write nothing (so aren't counted), poll until
it's released, then serve the image from R2. Write conflicts roll the
whole transaction back and are retried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:00:28 -07:00
multipleof4andClaude Opus 5.5 1ebcfc777e Perf: Serve homepage and assets without invoking Functions
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>
2026-10-06 16:43:25 -07:00
multipleof4andClaude Opus 5.5 c76b1ba5f7 Feat: Homepage reads daily limits from rate-limit.js
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:35:46 -07:00
multipleof4andClaude Opus 5.5 826e0cd2dd Refactor: Move daily search limits into rate-limit.js
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:29:49 -07:00
multipleof4andClaude Opus 5.5 0ab01d6e66 Feat: Give free.direct-img.link its own 100/day search limit
Free searches never spend Brave credits, so they no longer share the
main site's 35/day counter. Main-site rate ids are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:23:56 -07:00
multipleof4andClaude Opus 5.5 2941397180 Fix: Serve bad.webp for unknown query params
Scanner probes like /userfiles?path=../../.env were treated as real
searches since extra params were ignored, wasting searches and rate limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 11:37:51 -07:00
multipleof4andClaude Opus 5.5 8b49ebdf71 Feat: Raise daily search limit to 35
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:42:17 -07:00
multipleof4andClaude Opus 5.5 029b259f05 Feat: Add free.direct-img.link and ?i= result picker (#1)
- 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>
2026-09-26 12:00:54 -07:00
multipleof4andClaude Opus 5.5 023f4d132c Feat: Add GoatCounter analytics, Terms & Privacy pages, prompt copy button
- Update AI system prompt example (README + index)
- Add copy button for the prompt on the index page
- Add GoatCounter to homepage; report image hits server-side via
  waitUntil (optional GOATCOUNTER_URL/GOATCOUNTER_TOKEN)
- Add TERMS.md and PRIVACY.md, linked in the index footer
- Remove dead c.planetrenox.com tracker

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 08:51:48 -07:00
multipleof4andClaude Opus 5.5 2976236c00 Feat: Add logo, favicon and bad.webp; move images to /assets
- New logo (svg + jpg) and multi-size favicon.ico
- /favicon.ico still served at root so direct image views get the icon
- Generated missing bad.webp placeholder
- Moved limit.webp into /assets and routed error images via helper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:49:18 -07:00
multipleof4andClaude Opus 5.5 21b85acff5 Refactor: Move SurrealDB init to /_setup endpoint
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:46:31 -07:00
multipleof4andClaude Opus 5.5 f1e894d1bb Fix: Lower daily search limit to 20
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:10:02 -07:00
multipleof4 9fae3f0ec9 Fix: Expire image cache after 90 days 2026-09-10 18:20:48 -07:00
multipleof4 44ed25b654 Fix: Change ntfy priority for new searches to 2 2026-04-15 19:17:12 -07:00
multipleof4 6ee698b868 Refactor: Import search functions from utils 2026-03-12 14:31:57 -07:00
multipleof4 1fe9935fca Refactor: Extract Bing image search logic 2026-03-12 14:31:53 -07:00
multipleof4 deb931b466 Refactor: Extract Brave image search logic 2026-03-12 14:31:50 -07:00
multipleof4 6a2f7baa01 Feat: Add Bing Image Search fallback for empty results 2026-03-11 17:12:59 -07:00
multipleof4 cd3a9a5446 Feat: Add detailed fetch failure logging to ntfy 2026-03-10 14:41:05 -07:00
multipleof4 47710f30dd Refactor: Increase cache TTL to 60 days 2026-03-10 14:26:16 -07:00
multipleof4 c02a615c9e Feat: Increase daily search rate limit to 35 2026-02-25 12:24:29 -08:00
multipleof4 a2040381b3 Fix: SurrealDB rate limiting - headers, upsert, logging 2026-02-23 10:51:47 -08:00
multipleof4 86f97ed406 Feat: Cache error state and serve bad.webp on fail 2026-02-23 10:39:47 -08:00
multipleof4 d763f06415 Feat: Add async garbage collection to SurrealDB rate limits 2026-02-23 10:20:45 -08:00
multipleof4 406dd41258 Feat: Increase search result count to 50 2026-02-23 08:57:53 -08:00
multipleof4 f7232b61e6 Fix: Reject literal dots and slashes in pathname 2026-02-17 19:51:50 -08:00
multipleof4 0cbcc73326 Refactor: Reduce rate-limit TTL to 25 hours 2026-02-15 11:00:07 -08:00
multipleof4 e5b167d731 Feat: Reject queries with slashes, serve bad.webp 2026-02-15 09:02:54 -08:00
multipleof4 509a1d7269 Fix: Update daily search rate limit to 15 2026-02-14 19:03:52 -08:00
multipleof4 c6a7ad6960 Fix: Atomic rate limiting via individual KV keys 2026-02-14 18:58:10 -08:00
multipleof4 b4d515a9c7 Feat: Serve limit.webp meme on rate limit instead of JSON 2026-02-14 11:55:28 -08:00
multipleof4 de6fec20ca Feat: Include full URL in search notifications 2026-02-14 09:19:34 -08:00
multipleof4 ede0bfe459 Feat: Increase daily search rate limit from 10 to 25 2026-02-14 08:48:35 -08:00
multipleof4 ac74ce6cbe Fix: Sanitize queries, limit length, normalize slashes 2026-02-13 21:49:53 -08:00
multipleof4 2bb96a5789 Fix: Add global 20s deadline with dynamic per-attempt timeout 2026-02-13 18:36:30 -08:00
multipleof4 62e683ad9f Fix: Replace setTimeout with AbortSignal.timeout 2026-02-13 18:28:52 -08:00
multipleof4 86e55cc222 Fix: Move body consumption inside fetchImage timeout scope 2026-02-13 18:24:25 -08:00
multipleof4 1d434afaf1 Feat: Add ntfy notifications and robust search loop 2026-02-13 17:53:19 -08:00
multipleof4 333b29e0a5 Fix: Update safesearch parameter to valid value 2026-02-13 16:34:31 -08:00
multipleof4 f05c642e65 Refactor: Remove redundant TTL logic and simplify cache check 2026-02-13 16:26:15 -08:00