goopdl 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. goopdl-1.0.0/LICENSE +22 -0
  2. goopdl-1.0.0/PKG-INFO +381 -0
  3. goopdl-1.0.0/README.md +359 -0
  4. goopdl-1.0.0/goopdl/__init__.py +3 -0
  5. goopdl-1.0.0/goopdl/__main__.py +3 -0
  6. goopdl-1.0.0/goopdl/aastoken.py +133 -0
  7. goopdl-1.0.0/goopdl/api.py +925 -0
  8. goopdl-1.0.0/goopdl/auth.py +822 -0
  9. goopdl-1.0.0/goopdl/cli.py +980 -0
  10. goopdl-1.0.0/goopdl/download.py +203 -0
  11. goopdl-1.0.0/goopdl/profiles/1Z.properties +41 -0
  12. goopdl-1.0.0/goopdl/profiles/7M.properties +41 -0
  13. goopdl-1.0.0/goopdl/profiles/8r.properties +41 -0
  14. goopdl-1.0.0/goopdl/profiles/B1.properties +41 -0
  15. goopdl-1.0.0/goopdl/profiles/D2.properties +41 -0
  16. goopdl-1.0.0/goopdl/profiles/F-.properties +44 -0
  17. goopdl-1.0.0/goopdl/profiles/Fj.properties +41 -0
  18. goopdl-1.0.0/goopdl/profiles/Gb.properties +41 -0
  19. goopdl-1.0.0/goopdl/profiles/Gj.properties +41 -0
  20. goopdl-1.0.0/goopdl/profiles/HE.properties +41 -0
  21. goopdl-1.0.0/goopdl/profiles/Hb.properties +41 -0
  22. goopdl-1.0.0/goopdl/profiles/IV.properties +41 -0
  23. goopdl-1.0.0/goopdl/profiles/L8.properties +41 -0
  24. goopdl-1.0.0/goopdl/profiles/Pv.properties +41 -0
  25. goopdl-1.0.0/goopdl/profiles/VP.properties +41 -0
  26. goopdl-1.0.0/goopdl/profiles/XK.properties +41 -0
  27. goopdl-1.0.0/goopdl/profiles/Yc.properties +41 -0
  28. goopdl-1.0.0/goopdl/profiles/b2.properties +41 -0
  29. goopdl-1.0.0/goopdl/profiles/eV.properties +41 -0
  30. goopdl-1.0.0/goopdl/profiles/iq.properties +41 -0
  31. goopdl-1.0.0/goopdl/profiles/lv.properties +41 -0
  32. goopdl-1.0.0/goopdl/profiles/p6.properties +41 -0
  33. goopdl-1.0.0/goopdl/profiles/wD.properties +41 -0
  34. goopdl-1.0.0/goopdl/profiles.py +219 -0
  35. goopdl-1.0.0/goopdl/protobuf.py +175 -0
  36. goopdl-1.0.0/goopdl.egg-info/PKG-INFO +381 -0
  37. goopdl-1.0.0/goopdl.egg-info/SOURCES.txt +46 -0
  38. goopdl-1.0.0/goopdl.egg-info/dependency_links.txt +1 -0
  39. goopdl-1.0.0/goopdl.egg-info/entry_points.txt +2 -0
  40. goopdl-1.0.0/goopdl.egg-info/requires.txt +3 -0
  41. goopdl-1.0.0/goopdl.egg-info/top_level.txt +1 -0
  42. goopdl-1.0.0/pyproject.toml +35 -0
  43. goopdl-1.0.0/setup.cfg +4 -0
  44. goopdl-1.0.0/tests/test_aastoken.py +110 -0
  45. goopdl-1.0.0/tests/test_auth_redaction.py +44 -0
  46. goopdl-1.0.0/tests/test_cli_auth_exit.py +37 -0
  47. goopdl-1.0.0/tests/test_direct_auth.py +470 -0
  48. goopdl-1.0.0/tests/test_integrity.py +158 -0
goopdl-1.0.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Rehmat Alam
4
+ Copyright (c) 2025 Mikel Villota
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
goopdl-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,381 @@
1
+ Metadata-Version: 2.4
2
+ Name: goopdl
3
+ Version: 1.0.0
4
+ Summary: Download APKs from Google Play Store with anonymous authentication
5
+ Author-email: Mikel Villota <mikelvillotatic@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Villoh/goopdl
8
+ Project-URL: Repository, https://github.com/Villoh/goopdl
9
+ Project-URL: Issues, https://github.com/Villoh/goopdl/issues
10
+ Keywords: google-play,apk,downloader,android
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Utilities
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: typer>=0.9.0
19
+ Requires-Dist: rich>=13.0.0
20
+ Requires-Dist: httpx>=0.27.0
21
+ Dynamic: license-file
22
+
23
+ # goopdl
24
+
25
+ Download APKs from Google Play Store using anonymous authentication. Downloads base APKs, split APKs (App Bundles), OBB expansion files, and Play Asset Delivery packs — all by default.
26
+
27
+ > **Hard fork.** Independent project, hard-forked from [appknox/gplaydl](https://github.com/appknox/gplaydl), itself a fork of [rehmatworks/gplaydl](https://github.com/rehmatworks/gplaydl). MIT licensed, upstream copyright preserved.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pip install goopdl
33
+ ```
34
+
35
+ ## Features
36
+
37
+ - Anonymous authentication via Aurora Store's token dispenser (no Google account needed)
38
+ - Optional Google account AAS token retrieval without credential or token files
39
+ - Multiple device profiles with automatic rotation for reliable token acquisition
40
+ - Downloads base APK, split APKs, OBB files, and asset packs in one go
41
+ - Streaming gzip decompression for Play Asset Delivery packs
42
+ - Beautiful terminal UI with real-time download progress bars
43
+ - Architecture support: ARM64 (modern phones) and ARMv7 (older phones)
44
+ - Custom token dispenser URL support
45
+ - Search and browse app details from the command line
46
+ - Find the latest available version by sampling multiple fresh GSF IDs
47
+
48
+ ## Deployment / Integration
49
+
50
+ For servers, Docker images, or any environment that uses `pip` directly:
51
+
52
+ ```bash
53
+ pip install git+https://github.com/Villoh/goopdl.git
54
+ ```
55
+
56
+ In a **Dockerfile**:
57
+
58
+ ```dockerfile
59
+ RUN pip3 install git+https://github.com/Villoh/goopdl.git
60
+ ```
61
+
62
+ To pin to a specific release tag or commit (recommended for production):
63
+
64
+ ```dockerfile
65
+ RUN pip3 install git+https://github.com/Villoh/goopdl.git@v2.0.0
66
+ # or by commit SHA:
67
+ RUN pip3 install git+https://github.com/Villoh/goopdl.git@46d0b1f
68
+ ```
69
+
70
+ In a **`requirements.txt`**:
71
+
72
+ ```
73
+ git+https://github.com/Villoh/goopdl.git
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Installation
79
+
80
+ **Requirements:** Python 3.9+, [uv](https://github.com/astral-sh/uv)
81
+
82
+ Or install from source:
83
+
84
+ ```bash
85
+ git clone https://github.com/Villoh/goopdl.git
86
+ cd goopdl
87
+ uv sync
88
+ uv pip install .
89
+ ```
90
+
91
+ ## Quick Start
92
+
93
+ ```bash
94
+ # 1. Get an auth token (automatic, anonymous)
95
+ uv run goopdl auth
96
+
97
+ # 2. Download an app (base APK only)
98
+ uv run goopdl download com.whatsapp
99
+ ```
100
+
101
+ All commands below use `uv run goopdl ...`. If you activate the virtual environment (`source .venv/bin/activate`) you can drop the `uv run` prefix.
102
+
103
+ ## Commands
104
+
105
+ ### `auth` — Acquire an authentication token
106
+
107
+ ```bash
108
+ goopdl auth # Default (arm64)
109
+ goopdl auth --arch armv7 # Token for older ARM devices
110
+ goopdl auth -d https://my-server/api # Use a custom dispenser
111
+ goopdl auth --clear # Remove all cached tokens
112
+ goopdl auth --country IN # Register device with India MCC/MNC
113
+ goopdl auth --proxy socks5://host:1080 # Route dispenser call through proxy
114
+ goopdl auth --profile "Galaxy S25 Ultra" # Use a specific device profile
115
+ ```
116
+
117
+ | Flag | Short | Default | Description |
118
+ | ------ | ------- | --------- | ------------- |
119
+ | `--arch` | | `arm64` | Architecture: `arm64` or `armv7` |
120
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
121
+ | `--clear` | | `false` | Remove all cached tokens |
122
+ | `--country` | `-c` | — | 2-letter country code; registers device with that region's MCC/MNC |
123
+ | `--proxy` | `-p` | — | Proxy URL for dispenser calls (e.g. `socks5://host:port`) |
124
+ | `--profile` | | — | Device profile key or name substring (e.g. `Pv` or `Samsung`). Run `goopdl profiles` to list all |
125
+
126
+ Tokens are cached at `~/.config/goopdl/auth-{arch}.json` and reused automatically by other commands.
127
+
128
+ #### Direct Google account authentication
129
+
130
+ Set both environment variables to bypass Aurora's dispenser and authenticate directly with Google:
131
+
132
+ ```bash
133
+ export GOOPDL_ACCOUNT_EMAIL="account@example.com"
134
+ export GOOPDL_AAS_TOKEN="your-aas-token"
135
+ goopdl download com.whatsapp
136
+ ```
137
+
138
+ No CLI flags, config files, or secret files are used. The AAS token is a persistent sensitive credential; changing the Google account password invalidates it. Temporary Google Play bearer tokens are kept in memory and never cached. If only one variable is configured, goopdl fails without falling back to anonymous authentication.
139
+
140
+ ---
141
+
142
+ ### `aastoken` — Print a Google account AAS token
143
+
144
+ #### Password or app-password mode
145
+
146
+ ```bash
147
+ # Interactive: asks for email and hides password input
148
+ goopdl aastoken
149
+
150
+ # Arguments: convenient, but password remains in shell history
151
+ goopdl aastoken user@example.com password
152
+ ```
153
+
154
+ Google commonly rejects both account passwords and 16-character app passwords with `BadAuthentication`. Keep 2-Step Verification enabled and use OAuth mode instead.
155
+
156
+ #### OAuth mode (recommended)
157
+
158
+ ```bash
159
+ goopdl aastoken --oauth
160
+ ```
161
+
162
+ Get the required one-time `oauth_token`:
163
+
164
+ 1. Open [Google EmbeddedSetup](https://accounts.google.com/EmbeddedSetup).
165
+ 2. Sign in and select **I agree**.
166
+ 3. The page may remain frozen/loading forever. This is expected; the cookie is normally already available.
167
+ 4. Open browser developer tools (`F12`).
168
+ 5. In Chrome or Edge, open **Application → Cookies → `https://accounts.google.com`**.
169
+ 6. Copy the value of the `oauth_token` cookie. It starts with `oauth2_4/`.
170
+ 7. Run `goopdl aastoken --oauth`, enter the same email, then paste the token. Both inputs are handled interactively and the token is hidden.
171
+
172
+ The `oauth_token` is short-lived and single-use. The resulting AAS token is printed to the console. Credentials and tokens are used in memory only; no `credentials.txt` or `token.txt` files are created.
173
+
174
+ ---
175
+
176
+ ### `latest` — Find the latest available version
177
+
178
+ Probes multiple fresh GSF IDs (Google Services Framework IDs) from the token dispenser. Because Google stages rollouts by device cohort (tied to the GSF ID), sampling many IDs and taking the maximum version gives the most accurate latest version available.
179
+
180
+ ```bash
181
+ goopdl latest com.instagram.android
182
+ goopdl latest com.instagram.android --stable 5
183
+ goopdl latest com.instagram.android --profile "Galaxy S25 Ultra"
184
+ goopdl latest com.instagram.android --country IN
185
+ goopdl latest com.instagram.android --proxy socks5://host:1080
186
+ goopdl latest com.instagram.android -s 4 -c US -p socks5://host:1080
187
+ ```
188
+
189
+ | Flag | Short | Default | Description |
190
+ | ------ | ------- | --------- | ------------- |
191
+ | `--stable` | `-s` | `3` | Stop early when the highest version code is unchanged for this many consecutive probes |
192
+ | `--profile` | | top-ranked | Device profile for all probes (e.g. `Galaxy S25 Ultra`). Defaults to the highest SDK + Vending version profile |
193
+ | `--country` | `-c` | — | 2-letter country code sent with FDFE requests |
194
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
195
+ | `--proxy` | `-p` | — | Proxy URL for dispenser + FDFE calls (e.g. `socks5://host:port`) |
196
+ | `--arch` | | `arm64` | Architecture for token acquisition |
197
+
198
+ **How the pool works:** The tool maintains a regional pool of 5 GSF ID / token pairs on disk (`~/.config/goopdl/token-pool-{arch}-{country}.json`). Before every `latest` or `download` call, it checks how many valid (unexpired) tokens exist in that region's pool and fetches only the deficit from Aurora's dispenser — so if the pool is already full, zero dispenser calls are made. Tokens are valid for 50 minutes. If a token dies mid-request (HTTP 401), it is automatically replaced in the pool.
199
+
200
+ **How convergence works:** After each probe, if the best version code seen so far hasn't increased for `--stable` consecutive probes, the command stops early.
201
+
202
+ **Output:** A table with each probe's GSF ID prefix, version string, and version code. The highest version code is highlighted and printed as the final result with its version code.
203
+
204
+ ---
205
+
206
+ ### `download` — Download APKs
207
+
208
+ By default, `download` fetches the base APK, all split APKs, and any additional files (OBB expansion files, Play Asset Delivery packs).
209
+
210
+ ```bash
211
+ goopdl download com.whatsapp # Everything (base + splits + extras)
212
+ goopdl download com.whatsapp -o ./apks # Custom output directory
213
+ goopdl download com.whatsapp -a armv7 # ARMv7 build
214
+ goopdl download com.whatsapp -v 231205015 # Specific version code
215
+ goopdl download com.instagram.android -v 434.0.0.44.74 # Specific version string
216
+ goopdl download com.whatsapp --no-splits # Skip split APKs
217
+ goopdl download com.whatsapp --no-extras # Skip OBB / asset packs
218
+ goopdl download com.whatsapp -d https://... # Use custom dispenser
219
+ goopdl download com.whatsapp --country IN # Country header for regional variant
220
+ goopdl download com.whatsapp --proxy socks5://host:1080 # Route through proxy
221
+ goopdl download com.whatsapp --profile "Galaxy S25 Ultra" # Specific device profile
222
+ ```
223
+
224
+ | Flag | Short | Default | Description |
225
+ | ------ | ------- | --------- | ------------- |
226
+ | `--output` | `-o` | `.` (current dir) | Output directory |
227
+ | `--arch` | `-a` | `arm64` | Architecture: `arm64` or `armv7` |
228
+ | `--version` | `-v` | latest | Version code (e.g. `384009971`) **or** version string (e.g. `434.0.0.44.74`). When a version string is given, the tool probes fresh GSF IDs until it finds a cohort that sees that version |
229
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
230
+ | `--no-splits` | | `false` | Skip downloading split APKs |
231
+ | `--no-extras` | | `false` | Skip downloading OBB files and asset packs |
232
+ | `--country` | `-c` | — | 2-letter country code (e.g. `IN`, `US`). Combine with `--proxy` for true regional APK variants |
233
+ | `--proxy` | `-p` | — | Proxy URL for FDFE calls (e.g. `socks5://host:port` or `http://host:port`) |
234
+ | `--profile` | | — | Device profile key or name substring (e.g. `D2` or `Samsung`). Run `goopdl profiles` to list all |
235
+
236
+ **Output files:**
237
+
238
+ | Type | Naming | Example |
239
+ | ------ | -------- | --------- |
240
+ | Base APK | `{package}-{vc}.apk` | `com.whatsapp-231205015.apk` |
241
+ | Split APK | `{package}-{vc}-{split}.apk` | `com.whatsapp-231205015-config.arm64_v8a.apk` |
242
+ | OBB (main/patch) | `{type}.{vc}.{package}.obb` | `main.20925.com.tencent.ig.obb` |
243
+ | Asset pack | `{package}-{vc}-asset.apk` | `com.tencent.ig-20925-asset.apk` |
244
+
245
+ Split APKs can be installed to a device with:
246
+
247
+ ```bash
248
+ adb install-multiple *.apk
249
+ ```
250
+
251
+ ---
252
+
253
+ ### `info` — Show app details
254
+
255
+ ```bash
256
+ goopdl info com.whatsapp
257
+ goopdl info com.whatsapp --country IN
258
+ goopdl info com.whatsapp --proxy socks5://host:1080
259
+ goopdl info com.whatsapp --profile "Galaxy S25 Ultra"
260
+ ```
261
+
262
+ | Flag | Short | Default | Description |
263
+ | ------ | ------- | --------- | ------------- |
264
+ | `--arch` | | `arm64` | Architecture for token |
265
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
266
+ | `--country` | `-c` | — | 2-letter country code; sets `gl=` and locale headers |
267
+ | `--proxy` | `-p` | — | Proxy URL for FDFE calls |
268
+ | `--profile` | | — | Device profile key or name substring |
269
+
270
+ Displays app name, version, developer, rating, download count, and Play Store URL.
271
+
272
+ ---
273
+
274
+ ### `search` — Search for apps
275
+
276
+ ```bash
277
+ goopdl search "whatsapp"
278
+ goopdl search "file manager" --limit 5
279
+ goopdl search "whatsapp" --country IN
280
+ ```
281
+
282
+ | Flag | Short | Default | Description |
283
+ | ------ | ------- | --------- | ------------- |
284
+ | `--limit` | `-l` | `10` | Max results |
285
+ | `--arch` | | `arm64` | Architecture for token |
286
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
287
+ | `--country` | `-c` | — | 2-letter country code for regional results |
288
+ | `--proxy` | `-p` | — | Proxy URL for FDFE calls |
289
+ | `--profile` | | — | Device profile key or name substring |
290
+
291
+ ---
292
+
293
+ ### `list-splits` — List available split APKs
294
+
295
+ ```bash
296
+ goopdl list-splits com.whatsapp
297
+ ```
298
+
299
+ | Flag | Short | Default | Description |
300
+ |------|-------|---------|-------------|
301
+ | `--arch` | | `arm64` | Architecture for token |
302
+ | `--dispenser` | `-d` | Aurora Store | Custom token dispenser URL |
303
+
304
+ Shows all split APK names (config splits, language splits, etc.) without downloading.
305
+
306
+ ---
307
+
308
+ ### `profiles` — List device profiles
309
+
310
+ ```bash
311
+ goopdl profiles # All profiles
312
+ goopdl profiles --arch arm64 # ARM64 only
313
+ goopdl profiles --arch armv7 # ARMv7 only
314
+ ```
315
+
316
+ Use the **Key** column value with `--profile` in any command.
317
+
318
+ ## Running without installing globally
319
+
320
+ After `uv sync`, you can also invoke via the module directly:
321
+
322
+ ```bash
323
+ uv run python -m goopdl auth
324
+ uv run python -m goopdl download com.whatsapp
325
+ ```
326
+
327
+ ## How It Works
328
+
329
+ 1. **Authentication** — Gets an anonymous token from Aurora Store's dispenser, rotating through device profiles for reliability
330
+ 2. **Details** — Fetches app metadata (version, size, splits) via Google Play's protobuf API
331
+ 3. **Purchase** — "Purchases" the free app to get download authorization
332
+ 4. **Delivery** — Gets download URLs for the base APK, split APKs, OBB files, and asset packs
333
+ 5. **Download** — Streams all files in parallel from Google Play CDN with progress tracking
334
+
335
+ ## Finding the Latest Version
336
+
337
+ Google stages app rollouts by device cohort, which is determined by the GSF ID (Google Services Framework ID) — a device registration number assigned during token acquisition. Different GSF IDs may see different active versions (e.g. 434 vs 435 for the same app).
338
+
339
+ The `latest` command exploits this by sampling multiple fresh GSF IDs and reporting the highest version code seen:
340
+
341
+ ```bash
342
+ goopdl latest com.instagram.android --probes 10 --stable 3
343
+ ```
344
+
345
+ - Each probe fetches a fresh token → fresh GSF ID → queries Play Store for that cohort's version
346
+ - Probing stops early once the max version has been stable for `--stable` consecutive probes
347
+ - The device profile (`--profile`) affects which SDK level is presented; higher SDK profiles tend to receive new versions first
348
+
349
+ ## Token Dispenser
350
+
351
+ The tool uses [Aurora Store's](https://auroraoss.com/) public token dispenser by default (`https://auroraoss.com/api/auth`). This service provides anonymous Google Play authentication tokens — no personal Google account required.
352
+
353
+ You can point to a custom/self-hosted dispenser with the `--dispenser` / `-d` flag on any command:
354
+
355
+ ```bash
356
+ goopdl auth -d https://my-dispenser.example.com/api/auth
357
+ goopdl download com.whatsapp -d https://my-dispenser.example.com/api/auth
358
+ ```
359
+
360
+ ## Device Profiles
361
+
362
+ The tool includes multiple device profiles, used to authenticate with Google Play's token dispenser. Profiles are rotated automatically during token acquisition to maximise compatibility.
363
+
364
+ Run `goopdl profiles` to see all available profiles and their keys. Use `--profile` with any command to pin a specific device.
365
+
366
+ Profiles are stored as `.properties` files in the `goopdl/profiles/` directory.
367
+
368
+ ## Architecture Support
369
+
370
+ | Flag | ABI | Devices |
371
+ |------|-----|---------|
372
+ | `arm64` (default) | arm64-v8a | Modern phones (2017+) |
373
+ | `armv7` | armeabi-v7a | Older 32-bit phones |
374
+
375
+ ### Verified integrity manifest
376
+
377
+ `download --integrity-manifest PATH` fails unless every requested base/split APK has
378
+ Google delivery size and digest metadata. SHA-256 is preferred; SHA-1 is used only
379
+ when SHA-256 is absent. Files are verified before atomic publication, then manifest
380
+ is written atomically with relative filename, size, algorithm, and Base64url digest.
381
+ Manifest never contains download URLs, cookies, headers, or auth tokens.