Commit Graph
14 Commits
Author SHA1 Message Date
bobandClaude Fable 5.1 3b3c87e608 Record an album or tag write immich refused
immich answers a bulk album or tag write with HTTP 200 and one result per
asset, so a key without album permission produced "filing 0 asset(s)",
no recorded failure and exit 0. Refusals other than duplicate now come
back from the client and are recorded against the photo and its wiki
pages. The album and tag stages also get separate error handling, so a
failed album write no longer skips tagging for the run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-14 10:20:42 +01:00
bobandClaude Fable 5.1 fbd77fc91b Remember why photos failed and report the pages without one
Each run now writes .failures.json in the backup directory: the last
reason every photo failed and the wiki pages that use it, dropping any
photo that has since arrived. A new --report mode reads the wiki index
and that file and lists every page whose photo is not on disk, with the
reason or "not yet attempted", calling neither flickr nor immich. That is
what tells a wiki editor which photos have gone from flickr and need
replacing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-13 13:45:09 +01:00
bobandClaude Fable 5.1 36c974e843 Slow the whole run down when flickr answers 429
Flickr's limit is an hourly window, so backing off one photo for a couple
of minutes and then hitting the next photo at the old rate just fails
again, which is how a full fetch gave up on photos after six attempts. A
429 on a paced request now doubles the pace for every later flickr call,
up to ten seconds, and the pace relaxes back to the configured value only
after twenty untroubled requests. The per-request backoff also starts at
fifteen seconds instead of five, caps at fifteen minutes, and gets eight
attempts, so a single photo can wait out a short window on its own.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 16:37:08 +01:00
bobandClaude Fable 5.1 4e0bafe497 Wire the phases into a command with a summary and exit status
Load only the credentials the requested phases need, run fetch then sync,
and exit 1 when any photo failed so cron mails. A quiet clean run prints
nothing; a quiet failing run prints the failure list at the end.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:46 +01:00
bobandClaude Fable 5.1 534d68aac0 Mirror the backup directory into an immich album
List what immich already holds by checksum, upload only what is missing,
then bring every matched asset up to date: the marked description block,
coordinates and capture date where absent, the RGL album, and licence and
photographer tags. Album membership and descriptions are read-compare-write;
uploaded assets are re-read from immich after the album and tag stage so a
duplicate answer or a late metadata job never sees a blank slate. Tag
assignments are re-sent each run and immich reports the duplicates.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:46 +01:00
bobandClaude Fable 5.1 a0a5d7c92b Add an immich client that can upload as well as annotate
Carry over immich-sync's client, which lists assets by checksum and drives
albums and tags, and add a hand-rolled multipart upload with the checksum
header so immich can answer duplicate without receiving the bytes twice,
plus a per-asset update for description, date and coordinates.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:45 +01:00
bobandClaude Fable 5.1 5549217db5 Fetch every wiki photo at its largest size into the backup directory
Walk the grouped index, ask flickr for each new photo, download the best
size that actually serves, and write the sidecar only once the file is
renamed into place. Photos already complete cost no flickr calls; a change
in which pages use one rewrites just the sidecar. Every failure is
recorded with the pages affected and the run carries on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:45 +01:00
bobandClaude Fable 5.1 2774267425 Build the immich description block and tags from a sidecar
Immich has no copyright or source fields, so the photographer, licence,
flickr page and every wiki page using the photo go into a marked block in
the description. The marker lets a later run find and replace only that
block, leaving anything written by hand alone. Tags mirror licence and
photographer for filtering.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:45 +01:00
bobandClaude Fable 5.1 f7884b943e Store each photo's metadata in a json sidecar beside it
The sidecar is what makes the directory a backup on its own and what the
immich phase reads, so it is written atomically and a photo only counts as
done when the sidecar, its file and no .part remain.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:44 +01:00
bobandClaude Fable 5.1 fc434a3d9b Ask flickr for each photo's details and its largest size
Two unsigned json calls per photo: getInfo for title, owner, dates and
licence, getSizes for the renditions. Sizes come back ordered best-first so
a missing original can fall through to the next. Not-found and permission
errors become PhotoGone so the run can name the wiki pages affected.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:44 +01:00
bobandClaude Fable 5.1 b68d477938 Read the RGL index and group nodes by photo
One json request to the wiki's index carries every node's image fields, so
no per-page scraping is needed. Nodes are grouped by flickr photo id, taken
from the thumbnail filename or the photo page, so a photo used on several
pages is fetched once and its description can list them all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:44 +01:00
bobandClaude Fable 5.1 f05837bd5e Add a retrying HTTP helper shared by every remote call
One place decides what is worth another attempt: 429, 5xx and network
errors, with jittered exponential backoff and Retry-After honoured. Other
4xx responses fail at once. Downloads stream to disk under the same policy,
refuse a body over the size cap, and only flickr calls and photo downloads
are paced; the api key is redacted from debug output.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:44 +01:00
bobandClaude Fable 5.1 b916165cab Read credentials and settings from config files
Reuse the flickr key flickrtouchr already holds and the immich url and key
immich-sync uses, so nothing secret is duplicated. Everything else comes
from a typed settings file with flag > environment > file > default
precedence, so a cron line can be the bare script.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:43 +01:00
bobandClaude Fable 5.1 a37e3b69d0 Scaffold rgl-photo-backup with output helpers and test harness
Start the script that will back up the Randomness Guide to London's photos
to disk and Immich. This commit holds the constants, error classes and
quiet-aware output helpers every later section relies on, plus the test
loader for an extensionless script.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 12:07:43 +01:00