diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-06 12:11:58 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-06 12:11:58 +0200 |
| commit | 87ff20c96d9a8faa71b03eb0ca912d0ebf8aca7a (patch) | |
| tree | 34d33beb87d62062ca9781455b8f42b98360f1b7 /AGENTS.md | |
| download | wallhaven-dl-master.tar.gz wallhaven-dl-master.zip | |
Single-file PyQt6 app for wallhaven.cc:
- search with purity tabs, category checkboxes, per-monitor size filter
and a color swatch row; all filters sent explicitly so account
preferences never leak into keyed searches
- thumbnail grid with a downloaded overlay, preview panel with full
image, details and download
- API key from pass, sent only to the API in the X-API-Key header
- client-side rate limiter (40/min) with a status bar meter, and a
debounce on filter changes
- library-wide duplicate detection by wallhaven id under
~/Pictures/wallpapers
- low-res finder: flags images smaller than their monitor and searches
replacements by first tag or by locally extracted dominant color,
with a floating reference window and replace-to-trash
- desktop entry and Candy-style icon
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..41727e0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,82 @@ +# AGENTS.md + +Guidance for AI coding agents working in this repository. + +## What this is + +`wallhaven-dl`: single-file PyQt6 desktop app to search wallhaven.cc, preview +and download wallpapers, and find better-resolution replacements for low-res +images already on disk. The only dependency is PyQt6 (QtWidgets, QtNetwork); +everything else is stdlib. Keep it a single file and do not add dependencies. + +On the maintainer's machine the script, menu entry and icon are symlinks into +the repo, so edits are live on the next launch: + + ~/bin/wallhaven-dl -> wallhaven-dl + ~/.local/share/applications/wallhaven-dl.desktop -> wallhaven-dl.desktop + ~/.local/share/icons/hicolor/scalable/apps/wallhaven-dl.svg -> wallhaven-dl.svg + +## wallhaven API facts (verified, not in the docs) + +- Rate limit is 45 API calls per minute. The app caps itself at 40 + (`API_LIMIT`) with a sliding-window limiter in `get()`, and debounces filter + changes by 400 ms. Thumbnails (`th.wallhaven.cc`) and full images + (`w.wallhaven.cc`) do not count. Keep test runs cheap: stub + `Main.search` when no network is needed, and never loop over the API. +- With an API key, every parameter the request omits falls back to the + account's saved search settings (categories, resolutions, ...). That is why + `categories`, `purity` and `atleast` are always sent explicitly + (`atleast=1x1` for "any size"). +- The key goes in the `X-API-Key` header, only for URLs under `API`, never in + the query string. It is read from `pass` (`WALLHAVEN_PASS_ENTRY`, default + `wallhaven.cc/api-key`) at startup. +- `like:<id>` similarity search is behind a Cloudflare bot challenge (403, for + the API and the site alike). Do not try to get around it. The low-res + feature uses the wallpaper's first tag (`id:<tag id>`) instead, under the + wallpaper's own purity. +- `colors` accepts only the 29 palette values in `COLORS`. Each wallpaper + stores five colors and a color search matches any of the five. The local + extraction (`palette_histogram`, redmean distance) agrees with the site's + list well: measured on 72 wallpapers, the picked color was in the site's + list 72/72 times. +- There is no reverse image search on wallhaven. Sending local images to + third-party services was rejected for privacy. + +## Library and files + +- `LIBRARY` (`~/Pictures/wallpapers`, recursive, hidden dirs skipped) is what + "downloaded" means. Files are matched by the wallhaven id in their name + (`WALL_ID`, also `wallhaven-<id>_<WxH>.png` copies), never by path. +- Writes go to a `.part` file renamed into place. Replacing an original saves + the new file first and only then moves the old one to the desktop trash + (`QFile.moveToTrash`). Never delete user images outright. + +## Conventions + +- Non-GUI logic lives in module-level functions (`read_apikey`, `api_delay`, + `target`, `scan_library`, `nearest_color`, `search_pick`, ...) so it can be + tested without a display. +- Async replies check `gen` before touching grid items: `grid.clear()` deletes + them, and a stale callback would hit a dead C++ object. +- Do not name methods after `QWidget` ones (`show` once shadowed + `QWidget.show()` and broke startup). +- Placeholders only in code, docs, tests and commits: no real account names, + file names from the maintainer's library, or `pass` entry names beyond the + generic default. + +## Testing + + python3 test_wallhaven_dl.py + +Covers the non-GUI functions with plain asserts and a fake `pass` on `PATH`. +For GUI checks, run headless and keep settings away from the real config: + + XDG_CONFIG_HOME=/tmp/whdl-cfg QT_QPA_PLATFORM=offscreen python3 -I <script> + +loading the app with `importlib.machinery.SourceFileLoader` (the file has no +`.py` extension), and `w.grab().save(...)` for screenshots. + +## Repo facts + +- License: GPLv2 only (`LICENSE`, header in each source file). +- `origin` is the personal git server (cgit section "Generic Projects"). |
