1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# AGENTS.md
Guidance for AI coding agents working in this repository.
## What this is
`coomer_dl`: single-file Python script that downloads Coomer creators, single
posts and single files. Runtime dependency: `requests` only. Keep it a single
file and do not add dependencies. Sibling project: `../bunkr_dl`, same
structure and `download_file`.
## Download chain
The site sits behind DDoS-Guard. When the script finds nothing, re-inspect the
API with `curl --compressed -H 'Accept: text/css'` before changing code.
1. `GET /api/v1/<service>/user/<id>/posts?o=N` returns a JSON list of up to 50
posts. Pagination stops on a short or empty page.
2. `GET /api/v1/<service>/user/<id>/post/<post id>` returns
`{"post": {...}, ...}`.
3. `GET /api/v1/<service>/user/<id>/profile` gives the creator `name`, used as
the folder name.
4. Each post has `file` (may be `{}`) and `attachments`, each `{name, path}`.
The main file often repeats as an attachment, `post_files` dedupes by path.
5. `GET /data<path>` 302-redirects to `nN.<domain>/data<path>`.
All API calls need `Accept: text/css`, otherwise 403.
## Conventions
- New options go in the `argparse` setup in `main()` and in the README usage
table.
- `download_file` resumes with a per-request `Range` header. Never mutate the
global `headers` dict. 206 appends, 200 overwrites, 416 means already complete.
- Creator folders are reused across runs (not suffixed like bunkr_dl) so a
re-run resumes and only fetches new posts.
- Use placeholder URLs (`https://coomer.st/onlyfans/user/NAME`) in docs,
comments and commit messages, never real creator names or post ids.
## Testing
No test suite. Verify the API side without downloading by stubbing
`download_file`:
python - <<'PY'
import importlib.util, importlib.machinery
l = importlib.machinery.SourceFileLoader('c', 'coomer_dl')
c = importlib.util.module_from_spec(importlib.util.spec_from_loader('c', l)); l.exec_module(c)
got = []; c.download_file = lambda *a: got.append(a)
c.process_creator('https://coomer.st', 'onlyfans', 'NAME', '/tmp/x')
print(len(got), got[0])
PY
The "Found N posts" total should match `post_count` from the profile endpoint.
For a full run use `-o` pointing at a temp dir.
## Repo facts
- License: GPLv2 only (`LICENSE`, header in `coomer_dl`).
|