[2026-09-21] eagle: personal/how-to/old-ipad-ios935-ipa-sources.md personal/how-to/scripts/fetch-ios935-ipas.sh personal/tech/archive-org-collection-harvest.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-21 18:46:30 +06:00
1 parent cbc5019a10
commit 177da1e681
3 files changed
+305

No files matched your search

@@ -0,0 +1,70 @@
# archive-org-collection-harvest
**Type:** Hermes skill (`~/.hermes/hermes-whale/skills/research/archive-org-collection-harvest/SKILL.md`)
**Created:** 2026-09-21
**Origin:** Old iPad iOS 9.3.5 IPA hunt — archive.org was unreachable, this pattern was
worked out to get around it.
---
## What it does
Enumerate and bulk-download files from any archive.org collection when
**archive.org does not resolve** on the current network (home router blocks the DNS name).
Covers the metadata API, the "filenames are the index" filtering technique, and the
**double `--resolve`** needed because downloads 302 to a second host.
## The two things that make it non-obvious
### 1. Filenames carry the metadata
Archive.org item filenames often embed app ID + bundle ID + version + min OS:
```
iOS 4/jp.co.korg.iMS-20/iMS-20-(jp.co.korg.iMS-20)-1.5.2-(iOS_4.2)-b907eac….ipa
```
So one `curl` of `/metadata/<id>` + `jq -r '.files[].name'` + `grep -iE '<terms>'` gives you
full search, version targeting, and curation. No per-file API calls, no page scraping.
### 2. Downloads need the redirect host pinned separately
`archive.org/download/...` returns **302** to `https://dn####.ca.archive.org/...`.
Pinning only `archive.org` yields `http=302 size=0` — looks like a broken file, is actually
an unpinned redirect. You must read the `Location` header, resolve that host (`dig @1.1.1.1`),
and add a second `--resolve`:
```bash
ORIGIN_IP=$(dig +short archive.org @1.1.1.1 | tail -1)
DN=$(curl -sI --resolve archive.org:443:"$ORIGIN_IP" "$url" \
| grep -i '^location' | tr -d '\r' | sed 's/^[Ll]ocation: //')
HOST=$(printf '%s' "$DN" | sed -E 's#https://([^/]+)/.*#\1#')
IP=$(dig +short "$HOST" @1.1.1.1 | tail -1)
curl -sL --resolve archive.org:443:"$ORIGIN_IP" --resolve "$HOST:443:$IP" -o out.bin "$url"
```
## Other pitfalls recorded
- Spaces in filenames are **literal** → must `sed 's/ /%20/g'`. `+` is not accepted.
- `web_extract` on `archive.org/details/...` returns
`Blocked: URL targets a private or internal network address` — the extractor's own guard.
`web_search` on the same topic can also return empty. Fall back to `curl --resolve` fast
instead of retrying the web tools.
- Big metadata items (17k files) truncate in tool output and break `json.loads`.
**Always** `curl -o file.json` then `jq`, never parse the response inline.
- `HOST`/`IP` change per download host — re-derive, never hardcode `dn####`.
- Cheap probe before a big fetch: `curl -r 0-4095 -w 'http=%{http_code} size=%{size_download}'`
→ expect `HTTP 206` + non-zero bytes.
- Verify with `file` — an empty file or `HTML document` means the resolve failed.
- Write harvests as a **script file** run with `bash file.sh`; inline multi-line
`curl | jq` chains are fragile and each inline call may need approval.
## Verification checklist
- [ ] Control site returns 200 (network up, only archive.org DNS blocked)
- [ ] `/metadata/<id>` returns JSON with plausible `.files` count
- [ ] Filename list non-empty, filtered hits match expectations
- [ ] `-r 0-4095` probe → HTTP 206, non-zero size
- [ ] `file` on probe reports expected archive/binary type
## Applied in
- `personal/how-to/old-ipad-ios935-ipa-sources.md` — iOSObscura collection (17,652 IPAs),
curated iOS 9.3.5 music/MIDI + utility shortlist
- `personal/how-to/scripts/fetch-ios935-ipas.sh` — working downloader built on this pattern