cocapi 4.0.0__tar.gz → 4.1.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 (68) hide show
  1. {cocapi-4.0.0 → cocapi-4.1.0}/.github/FUNDING.yml +1 -0
  2. {cocapi-4.0.0 → cocapi-4.1.0}/.github/workflows/ci.yml +5 -5
  3. cocapi-4.1.0/.github/workflows/docs.yml +33 -0
  4. {cocapi-4.0.0 → cocapi-4.1.0}/.github/workflows/release.yml +5 -5
  5. cocapi-4.1.0/PKG-INFO +257 -0
  6. cocapi-4.1.0/README.md +218 -0
  7. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/__init__.py +46 -1
  8. cocapi-4.1.0/cocapi/army.py +89 -0
  9. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/async_client.py +41 -10
  10. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/client.py +129 -6
  11. cocapi-4.1.0/cocapi/controls.py +66 -0
  12. cocapi-4.1.0/cocapi/errors.py +106 -0
  13. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_state.py +10 -0
  14. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_stream.py +10 -0
  15. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_watchers.py +56 -0
  16. cocapi-4.1.0/cocapi/game_time.py +68 -0
  17. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/schemas.py +91 -0
  18. cocapi-4.1.0/cocapi/static_data.py +125 -0
  19. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/utils.py +8 -0
  20. cocapi-4.1.0/docs/changelog.md +56 -0
  21. cocapi-4.1.0/docs/examples.md +123 -0
  22. cocapi-4.1.0/docs/getting-started/authentication.md +82 -0
  23. cocapi-4.1.0/docs/getting-started/installation.md +53 -0
  24. cocapi-4.1.0/docs/getting-started/quickstart.md +76 -0
  25. cocapi-4.1.0/docs/guides/async.md +112 -0
  26. cocapi-4.1.0/docs/guides/caching.md +74 -0
  27. cocapi-4.1.0/docs/guides/cli.md +94 -0
  28. cocapi-4.1.0/docs/guides/configuration.md +88 -0
  29. cocapi-4.1.0/docs/guides/error-handling.md +119 -0
  30. cocapi-4.1.0/docs/guides/events.md +152 -0
  31. cocapi-4.1.0/docs/guides/game-data.md +40 -0
  32. cocapi-4.1.0/docs/guides/metrics.md +54 -0
  33. cocapi-4.1.0/docs/guides/middleware.md +83 -0
  34. cocapi-4.1.0/docs/guides/pagination-batch.md +88 -0
  35. cocapi-4.1.0/docs/guides/pydantic-models.md +70 -0
  36. cocapi-4.1.0/docs/index.md +62 -0
  37. cocapi-4.1.0/mkdocs.yml +136 -0
  38. {cocapi-4.0.0 → cocapi-4.1.0}/pyproject.toml +16 -1
  39. cocapi-4.1.0/uv.lock +1937 -0
  40. cocapi-4.0.0/PKG-INFO +0 -955
  41. cocapi-4.0.0/README.md +0 -924
  42. cocapi-4.0.0/_config.yml +0 -1
  43. cocapi-4.0.0/uv.lock +0 -668
  44. {cocapi-4.0.0 → cocapi-4.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  45. {cocapi-4.0.0 → cocapi-4.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  46. {cocapi-4.0.0 → cocapi-4.1.0}/.gitignore +0 -0
  47. {cocapi-4.0.0 → cocapi-4.1.0}/.pre-commit-config.yaml +0 -0
  48. {cocapi-4.0.0 → cocapi-4.1.0}/CODE_OF_CONDUCT.md +0 -0
  49. {cocapi-4.0.0 → cocapi-4.1.0}/LICENSE +0 -0
  50. {cocapi-4.0.0 → cocapi-4.1.0}/SECURITY.md +0 -0
  51. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/api_methods.py +0 -0
  52. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cache.py +0 -0
  53. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cli.py +0 -0
  54. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cocapi.py +0 -0
  55. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/config.py +0 -0
  56. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/__init__.py +0 -0
  57. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_diff.py +0 -0
  58. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_types.py +0 -0
  59. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_war_fsm.py +0 -0
  60. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/key_manager.py +0 -0
  61. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/metrics.py +0 -0
  62. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/middleware.py +0 -0
  63. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/model_registry.py +0 -0
  64. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/models.py +0 -0
  65. {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/py.typed +0 -0
  66. {cocapi-4.0.0 → cocapi-4.1.0}/mypy.ini +0 -0
  67. {cocapi-4.0.0 → cocapi-4.1.0}/setup.py +0 -0
  68. {cocapi-4.0.0 → cocapi-4.1.0}/sonar-project.properties +0 -0
@@ -2,3 +2,4 @@
2
2
 
3
3
  github: tonybenoy
4
4
  patreon: tonybenoy
5
+ buy_me_a_coffee: tonybenoy
@@ -23,16 +23,16 @@ jobs:
23
23
  uses: astral-sh/setup-uv@v3
24
24
 
25
25
  - name: Install dependencies
26
- run: uv sync --dev --extra pydantic
26
+ run: uv sync --locked --no-build --dev --extra pydantic --extra cli
27
27
 
28
28
  - name: Run ruff linting
29
- run: uv run ruff check cocapi
29
+ run: uv run --locked --no-build ruff check cocapi
30
30
 
31
31
  - name: Run ruff formatting check
32
- run: uv run ruff format --check cocapi
32
+ run: uv run --locked --no-build ruff format --check cocapi
33
33
 
34
34
  - name: Run mypy type checking
35
- run: uv run mypy cocapi
35
+ run: uv run --locked --no-build mypy cocapi
36
36
 
37
37
  - name: Run tests
38
- run: uv run pytest tests/test_cocapi.py -v --tb=short
38
+ run: uv run --locked --no-build pytest tests/ -v --tb=short
@@ -0,0 +1,33 @@
1
+ name: Deploy Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ concurrency:
12
+ group: deploy-docs
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ deploy:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.12"
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v3
28
+
29
+ - name: Install dependencies
30
+ run: uv sync --dev --extra pydantic --extra docs
31
+
32
+ - name: Build and deploy docs
33
+ run: uv run mkdocs gh-deploy --force
@@ -22,19 +22,19 @@ jobs:
22
22
  uses: astral-sh/setup-uv@v3
23
23
 
24
24
  - name: Install dependencies
25
- run: uv sync --dev --extra pydantic
25
+ run: uv sync --locked --no-build --dev --extra pydantic --extra cli
26
26
 
27
27
  - name: Run ruff linting
28
- run: uv run ruff check cocapi
28
+ run: uv run --locked --no-build ruff check cocapi
29
29
 
30
30
  - name: Run ruff formatting check
31
- run: uv run ruff format --check cocapi
31
+ run: uv run --locked --no-build ruff format --check cocapi
32
32
 
33
33
  - name: Run mypy type checking
34
- run: uv run mypy cocapi
34
+ run: uv run --locked --no-build mypy cocapi
35
35
 
36
36
  - name: Run tests
37
- run: uv run pytest tests/test_cocapi.py -v --tb=short
37
+ run: uv run --locked --no-build pytest tests/ -v --tb=short
38
38
 
39
39
  check-version:
40
40
  needs: ci
cocapi-4.1.0/PKG-INFO ADDED
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.5
2
+ Name: cocapi
3
+ Version: 4.1.0
4
+ Summary: Async & sync Python wrapper for the Clash of Clans API with auto key management
5
+ Project-URL: Homepage, https://github.com/tonybenoy/cocapi
6
+ Project-URL: Documentation, https://tonybenoy.github.io/cocapi/
7
+ Project-URL: Repository, https://github.com/tonybenoy/cocapi
8
+ Project-URL: Issues, https://github.com/tonybenoy/cocapi/issues
9
+ Author-email: Tony Benoy <me@tonybenoy.com>
10
+ License: GPL-3.0
11
+ License-File: LICENSE
12
+ Keywords: api-wrapper,async,clans,clash,clash-of-clans,coc,coc-api,game-api,supercell
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Framework :: AsyncIO
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Games/Entertainment :: Real Time Strategy
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: httpx>=0.23.0
27
+ Provides-Extra: cli
28
+ Requires-Dist: typer>=0.9.0; extra == 'cli'
29
+ Provides-Extra: docs
30
+ Requires-Dist: mkdocs-gen-files>=0.5.0; extra == 'docs'
31
+ Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == 'docs'
32
+ Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
33
+ Requires-Dist: mkdocs-section-index>=0.3.9; extra == 'docs'
34
+ Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
35
+ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == 'docs'
36
+ Provides-Extra: pydantic
37
+ Requires-Dist: pydantic>=2.0.0; extra == 'pydantic'
38
+ Description-Content-Type: text/markdown
39
+
40
+ <p>
41
+ <a href="https://github.com/tonybenoy/cocapi/actions">
42
+ <img src="https://github.com/tonybenoy/cocapi/workflows/CI/badge.svg" alt="CI Status" height="20">
43
+ </a>
44
+ <a href="https://pypi.org/project/cocapi/"><img src="https://img.shields.io/pypi/v/cocapi" alt="Pypi version" height="21"></a>
45
+ <a href="https://pypi.org/project/cocapi/"><img src="https://img.shields.io/pypi/dm/cocapi" alt="PyPI Downloads" height="21"></a>
46
+ <a href="https://tonybenoy.github.io/cocapi/"><img src="https://img.shields.io/badge/docs-mkdocs-blue.svg" alt="Documentation" height="21"></a>
47
+ </p>
48
+ <p>
49
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python version" height="17"></a>
50
+ <a href="https://github.com/tonybenoy/cocapi/blob/main/LICENSE"><img src="https://img.shields.io/github/license/tonybenoy/cocapi" alt="License" height="17"></a>
51
+ <a href="https://github.com/astral-sh/ruff">
52
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" height="17">
53
+ </a>
54
+ </p>
55
+
56
+ # cocapi
57
+
58
+ A Python wrapper for the official [Clash of Clans API](https://developer.clashofclans.com/) with full async support, automatic key management, caching, retries, and optional Pydantic models.
59
+
60
+ **[Full Documentation](https://tonybenoy.github.io/cocapi/)**
61
+
62
+ ## Features
63
+
64
+ - **Sync & async** — same methods, same names, both modes
65
+ - **Automatic key management** — login with email/password, keys are created, reused, and rotated automatically
66
+ - **Caching** — TTL-based response caching with stats
67
+ - **Retries** — exponential backoff for rate limits and server errors
68
+ - **Pagination & batch** — `paginate()` auto-follows cursors, `batch()` fetches many resources at once
69
+ - **Event polling** — real-time monitoring of clans, wars, and players with `async for` or callbacks
70
+ - **Game data helpers** — static game data lookups, army link parsing, CWL-aware current war, typed errors, per-call cache control
71
+ - **Pydantic models** — optional typed response objects with IDE autocompletion
72
+ - **Middleware** — plug in custom request/response processing
73
+ - **CLI** — `cocapi clan "#2PP"` from the terminal
74
+ - **Maintenance detection** — automatic detection of API maintenance windows
75
+
76
+ ## Install
77
+
78
+ ```bash
79
+ pip install cocapi
80
+
81
+ # With Pydantic model support
82
+ pip install 'cocapi[pydantic]'
83
+
84
+ # With CLI
85
+ pip install 'cocapi[cli]'
86
+ ```
87
+
88
+ Requires Python 3.10+.
89
+
90
+ ## Quick Start
91
+
92
+ ### With an API Token
93
+
94
+ Get a token from [developer.clashofclans.com](https://developer.clashofclans.com/):
95
+
96
+ ```python
97
+ from cocapi import CocApi
98
+
99
+ api = CocApi("your_api_token")
100
+
101
+ clan = api.clan_tag("#2PP")
102
+ print(clan["name"])
103
+
104
+ player = api.players("#900PUCPV")
105
+ print(player["trophies"])
106
+ ```
107
+
108
+ ### With Email/Password (Automatic Key Management)
109
+
110
+ Skip manual key creation entirely. cocapi logs into the developer portal, detects your IP, and manages keys for you:
111
+
112
+ ```python
113
+ from cocapi import CocApi
114
+
115
+ api = CocApi.from_credentials("you@example.com", "your_password")
116
+ clan = api.clan_tag("#2PP")
117
+ ```
118
+
119
+ Keys are created automatically, reused when valid, and rotated when your IP changes. See the [Authentication guide](https://tonybenoy.github.io/cocapi/getting-started/authentication/) for details.
120
+
121
+ ### Async
122
+
123
+ ```python
124
+ import asyncio
125
+ from cocapi import CocApi
126
+
127
+ async def main():
128
+ async with CocApi("your_token") as api:
129
+ clan = await api.clan_tag("#2PP")
130
+ player = await api.players("#900PUCPV")
131
+ print(clan["name"], player["trophies"])
132
+
133
+ asyncio.run(main())
134
+ ```
135
+
136
+ See the [Async guide](https://tonybenoy.github.io/cocapi/guides/async/) for more patterns.
137
+
138
+ ## Configuration
139
+
140
+ All options are set through `ApiConfig`:
141
+
142
+ ```python
143
+ from cocapi import CocApi, ApiConfig
144
+
145
+ config = ApiConfig(
146
+ timeout=30,
147
+ max_retries=3,
148
+ enable_caching=True,
149
+ cache_ttl=600,
150
+ enable_rate_limiting=True, # async only
151
+ requests_per_second=10.0,
152
+ enable_metrics=True,
153
+ use_pydantic_models=True, # requires cocapi[pydantic]
154
+ )
155
+
156
+ api = CocApi("your_token", config=config)
157
+ ```
158
+
159
+ See the [Configuration guide](https://tonybenoy.github.io/cocapi/guides/configuration/) for all options.
160
+
161
+ ## Pagination & Batch
162
+
163
+ ```python
164
+ # Auto-paginate through all clan members
165
+ for member in api.paginate(api.clan_members, "#CLAN_TAG"):
166
+ print(member["name"])
167
+
168
+ # Fetch multiple players at once
169
+ results = api.batch(api.players, ["#TAG1", "#TAG2", "#TAG3"])
170
+ ```
171
+
172
+ Both work in sync and async. See the [Pagination & Batch guide](https://tonybenoy.github.io/cocapi/guides/pagination-batch/).
173
+
174
+ ## Event Polling
175
+
176
+ Monitor clans, wars, and players in real time. Async only.
177
+
178
+ ```python
179
+ from cocapi.events import EventStream, EventType
180
+
181
+ async with CocApi("token") as api:
182
+ stream = EventStream(api)
183
+ stream.watch_clans(["#2PP"], interval=60)
184
+ stream.watch_wars(["#2PP"], interval=30)
185
+ stream.watch_players(["#900PUCPV"], interval=120)
186
+
187
+ async with stream:
188
+ async for event in stream:
189
+ print(event.event_type, event.tag)
190
+ for change in event.changes:
191
+ print(f" {change.field}: {change.old_value} -> {change.new_value}")
192
+ ```
193
+
194
+ Supports 20+ event types including member join/leave, war state transitions, troop/hero upgrades, maintenance detection, and more. See the [Event Polling guide](https://tonybenoy.github.io/cocapi/guides/events/).
195
+
196
+ ## CLI
197
+
198
+ ```bash
199
+ pip install 'cocapi[cli]'
200
+
201
+ # Login once (key is persisted)
202
+ cocapi login --email you@example.com --password yourpass
203
+
204
+ # Use without --token
205
+ cocapi clan "#2PP"
206
+ cocapi player "#900PUCPV"
207
+ cocapi war "#2PP"
208
+ cocapi search "clash" --limit 5
209
+ cocapi goldpass
210
+ ```
211
+
212
+ See the [CLI guide](https://tonybenoy.github.io/cocapi/guides/cli/) for all commands.
213
+
214
+ ## Error Handling
215
+
216
+ All endpoints return a dict (or Pydantic model). Errors never raise exceptions:
217
+
218
+ ```python
219
+ result = api.clan_tag("#INVALID")
220
+ if result.get("result") == "error":
221
+ print(result["message"]) # Human-readable message
222
+ print(result["error_type"]) # "timeout", "connection", "http", "json", etc.
223
+ print(result.get("status_code"))
224
+ ```
225
+
226
+ See the [Error Handling guide](https://tonybenoy.github.io/cocapi/guides/error-handling/).
227
+
228
+ ## Examples
229
+
230
+ Runnable scripts in the [`examples/`](examples/) folder:
231
+
232
+ | Script | What it covers |
233
+ |---|---|
234
+ | [`basic_usage.py`](examples/basic_usage.py) | Sync: clan info, player info, search, error handling |
235
+ | [`async_usage.py`](examples/async_usage.py) | Async with context manager, concurrent requests |
236
+ | [`credential_auth.py`](examples/credential_auth.py) | Email/password login, key persistence, auto-refresh |
237
+ | [`pagination_batch.py`](examples/pagination_batch.py) | `paginate()` and `batch()` in sync and async |
238
+ | [`event_polling.py`](examples/event_polling.py) | `EventStream` with `async for` — real-time monitoring |
239
+ | [`event_callbacks.py`](examples/event_callbacks.py) | `@stream.on()` decorators and `stream.run()` |
240
+ | [`configuration.py`](examples/configuration.py) | ApiConfig, caching, metrics, middleware |
241
+
242
+ ## API Reference
243
+
244
+ Full API reference with all endpoints, parameters, and response schemas is available in the [documentation](https://tonybenoy.github.io/cocapi/reference/).
245
+
246
+ Key classes:
247
+ - [`CocApi`](https://tonybenoy.github.io/cocapi/reference/client/) — main entry point (sync/async)
248
+ - [`ApiConfig`](https://tonybenoy.github.io/cocapi/reference/config/) — configuration options
249
+ - [`EventStream`](https://tonybenoy.github.io/cocapi/reference/events/) — real-time event polling
250
+ - [Pydantic Schemas](https://tonybenoy.github.io/cocapi/reference/schemas/) — typed response models
251
+ - [All Endpoints](https://tonybenoy.github.io/cocapi/reference/api_methods/) — every API method
252
+
253
+ ## Credits
254
+
255
+ - [All Contributors](../../contributors)
256
+
257
+ *cocapi is not affiliated with SuperCell.*
cocapi-4.1.0/README.md ADDED
@@ -0,0 +1,218 @@
1
+ <p>
2
+ <a href="https://github.com/tonybenoy/cocapi/actions">
3
+ <img src="https://github.com/tonybenoy/cocapi/workflows/CI/badge.svg" alt="CI Status" height="20">
4
+ </a>
5
+ <a href="https://pypi.org/project/cocapi/"><img src="https://img.shields.io/pypi/v/cocapi" alt="Pypi version" height="21"></a>
6
+ <a href="https://pypi.org/project/cocapi/"><img src="https://img.shields.io/pypi/dm/cocapi" alt="PyPI Downloads" height="21"></a>
7
+ <a href="https://tonybenoy.github.io/cocapi/"><img src="https://img.shields.io/badge/docs-mkdocs-blue.svg" alt="Documentation" height="21"></a>
8
+ </p>
9
+ <p>
10
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python version" height="17"></a>
11
+ <a href="https://github.com/tonybenoy/cocapi/blob/main/LICENSE"><img src="https://img.shields.io/github/license/tonybenoy/cocapi" alt="License" height="17"></a>
12
+ <a href="https://github.com/astral-sh/ruff">
13
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" height="17">
14
+ </a>
15
+ </p>
16
+
17
+ # cocapi
18
+
19
+ A Python wrapper for the official [Clash of Clans API](https://developer.clashofclans.com/) with full async support, automatic key management, caching, retries, and optional Pydantic models.
20
+
21
+ **[Full Documentation](https://tonybenoy.github.io/cocapi/)**
22
+
23
+ ## Features
24
+
25
+ - **Sync & async** — same methods, same names, both modes
26
+ - **Automatic key management** — login with email/password, keys are created, reused, and rotated automatically
27
+ - **Caching** — TTL-based response caching with stats
28
+ - **Retries** — exponential backoff for rate limits and server errors
29
+ - **Pagination & batch** — `paginate()` auto-follows cursors, `batch()` fetches many resources at once
30
+ - **Event polling** — real-time monitoring of clans, wars, and players with `async for` or callbacks
31
+ - **Game data helpers** — static game data lookups, army link parsing, CWL-aware current war, typed errors, per-call cache control
32
+ - **Pydantic models** — optional typed response objects with IDE autocompletion
33
+ - **Middleware** — plug in custom request/response processing
34
+ - **CLI** — `cocapi clan "#2PP"` from the terminal
35
+ - **Maintenance detection** — automatic detection of API maintenance windows
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install cocapi
41
+
42
+ # With Pydantic model support
43
+ pip install 'cocapi[pydantic]'
44
+
45
+ # With CLI
46
+ pip install 'cocapi[cli]'
47
+ ```
48
+
49
+ Requires Python 3.10+.
50
+
51
+ ## Quick Start
52
+
53
+ ### With an API Token
54
+
55
+ Get a token from [developer.clashofclans.com](https://developer.clashofclans.com/):
56
+
57
+ ```python
58
+ from cocapi import CocApi
59
+
60
+ api = CocApi("your_api_token")
61
+
62
+ clan = api.clan_tag("#2PP")
63
+ print(clan["name"])
64
+
65
+ player = api.players("#900PUCPV")
66
+ print(player["trophies"])
67
+ ```
68
+
69
+ ### With Email/Password (Automatic Key Management)
70
+
71
+ Skip manual key creation entirely. cocapi logs into the developer portal, detects your IP, and manages keys for you:
72
+
73
+ ```python
74
+ from cocapi import CocApi
75
+
76
+ api = CocApi.from_credentials("you@example.com", "your_password")
77
+ clan = api.clan_tag("#2PP")
78
+ ```
79
+
80
+ Keys are created automatically, reused when valid, and rotated when your IP changes. See the [Authentication guide](https://tonybenoy.github.io/cocapi/getting-started/authentication/) for details.
81
+
82
+ ### Async
83
+
84
+ ```python
85
+ import asyncio
86
+ from cocapi import CocApi
87
+
88
+ async def main():
89
+ async with CocApi("your_token") as api:
90
+ clan = await api.clan_tag("#2PP")
91
+ player = await api.players("#900PUCPV")
92
+ print(clan["name"], player["trophies"])
93
+
94
+ asyncio.run(main())
95
+ ```
96
+
97
+ See the [Async guide](https://tonybenoy.github.io/cocapi/guides/async/) for more patterns.
98
+
99
+ ## Configuration
100
+
101
+ All options are set through `ApiConfig`:
102
+
103
+ ```python
104
+ from cocapi import CocApi, ApiConfig
105
+
106
+ config = ApiConfig(
107
+ timeout=30,
108
+ max_retries=3,
109
+ enable_caching=True,
110
+ cache_ttl=600,
111
+ enable_rate_limiting=True, # async only
112
+ requests_per_second=10.0,
113
+ enable_metrics=True,
114
+ use_pydantic_models=True, # requires cocapi[pydantic]
115
+ )
116
+
117
+ api = CocApi("your_token", config=config)
118
+ ```
119
+
120
+ See the [Configuration guide](https://tonybenoy.github.io/cocapi/guides/configuration/) for all options.
121
+
122
+ ## Pagination & Batch
123
+
124
+ ```python
125
+ # Auto-paginate through all clan members
126
+ for member in api.paginate(api.clan_members, "#CLAN_TAG"):
127
+ print(member["name"])
128
+
129
+ # Fetch multiple players at once
130
+ results = api.batch(api.players, ["#TAG1", "#TAG2", "#TAG3"])
131
+ ```
132
+
133
+ Both work in sync and async. See the [Pagination & Batch guide](https://tonybenoy.github.io/cocapi/guides/pagination-batch/).
134
+
135
+ ## Event Polling
136
+
137
+ Monitor clans, wars, and players in real time. Async only.
138
+
139
+ ```python
140
+ from cocapi.events import EventStream, EventType
141
+
142
+ async with CocApi("token") as api:
143
+ stream = EventStream(api)
144
+ stream.watch_clans(["#2PP"], interval=60)
145
+ stream.watch_wars(["#2PP"], interval=30)
146
+ stream.watch_players(["#900PUCPV"], interval=120)
147
+
148
+ async with stream:
149
+ async for event in stream:
150
+ print(event.event_type, event.tag)
151
+ for change in event.changes:
152
+ print(f" {change.field}: {change.old_value} -> {change.new_value}")
153
+ ```
154
+
155
+ Supports 20+ event types including member join/leave, war state transitions, troop/hero upgrades, maintenance detection, and more. See the [Event Polling guide](https://tonybenoy.github.io/cocapi/guides/events/).
156
+
157
+ ## CLI
158
+
159
+ ```bash
160
+ pip install 'cocapi[cli]'
161
+
162
+ # Login once (key is persisted)
163
+ cocapi login --email you@example.com --password yourpass
164
+
165
+ # Use without --token
166
+ cocapi clan "#2PP"
167
+ cocapi player "#900PUCPV"
168
+ cocapi war "#2PP"
169
+ cocapi search "clash" --limit 5
170
+ cocapi goldpass
171
+ ```
172
+
173
+ See the [CLI guide](https://tonybenoy.github.io/cocapi/guides/cli/) for all commands.
174
+
175
+ ## Error Handling
176
+
177
+ All endpoints return a dict (or Pydantic model). Errors never raise exceptions:
178
+
179
+ ```python
180
+ result = api.clan_tag("#INVALID")
181
+ if result.get("result") == "error":
182
+ print(result["message"]) # Human-readable message
183
+ print(result["error_type"]) # "timeout", "connection", "http", "json", etc.
184
+ print(result.get("status_code"))
185
+ ```
186
+
187
+ See the [Error Handling guide](https://tonybenoy.github.io/cocapi/guides/error-handling/).
188
+
189
+ ## Examples
190
+
191
+ Runnable scripts in the [`examples/`](examples/) folder:
192
+
193
+ | Script | What it covers |
194
+ |---|---|
195
+ | [`basic_usage.py`](examples/basic_usage.py) | Sync: clan info, player info, search, error handling |
196
+ | [`async_usage.py`](examples/async_usage.py) | Async with context manager, concurrent requests |
197
+ | [`credential_auth.py`](examples/credential_auth.py) | Email/password login, key persistence, auto-refresh |
198
+ | [`pagination_batch.py`](examples/pagination_batch.py) | `paginate()` and `batch()` in sync and async |
199
+ | [`event_polling.py`](examples/event_polling.py) | `EventStream` with `async for` — real-time monitoring |
200
+ | [`event_callbacks.py`](examples/event_callbacks.py) | `@stream.on()` decorators and `stream.run()` |
201
+ | [`configuration.py`](examples/configuration.py) | ApiConfig, caching, metrics, middleware |
202
+
203
+ ## API Reference
204
+
205
+ Full API reference with all endpoints, parameters, and response schemas is available in the [documentation](https://tonybenoy.github.io/cocapi/reference/).
206
+
207
+ Key classes:
208
+ - [`CocApi`](https://tonybenoy.github.io/cocapi/reference/client/) — main entry point (sync/async)
209
+ - [`ApiConfig`](https://tonybenoy.github.io/cocapi/reference/config/) — configuration options
210
+ - [`EventStream`](https://tonybenoy.github.io/cocapi/reference/events/) — real-time event polling
211
+ - [Pydantic Schemas](https://tonybenoy.github.io/cocapi/reference/schemas/) — typed response models
212
+ - [All Endpoints](https://tonybenoy.github.io/cocapi/reference/api_methods/) — every API method
213
+
214
+ ## Credits
215
+
216
+ - [All Contributors](../../contributors)
217
+
218
+ *cocapi is not affiliated with SuperCell.*
@@ -40,6 +40,8 @@ Async Usage:
40
40
  """
41
41
 
42
42
  # Main API class - primary interface
43
+ # Army links, static data, event windows, error handling, per-call controls
44
+ from .army import Army, ArmyUnit, build_army_link, parse_army_link
43
45
  from .async_client import AsyncCocApiCore, AsyncRateLimiter
44
46
 
45
47
  # Advanced components for power users
@@ -48,6 +50,25 @@ from .client import CocApi
48
50
 
49
51
  # Configuration classes
50
52
  from .config import ApiConfig, CacheEntry, RequestMetric
53
+ from .controls import cache_control, without_rate_limit
54
+ from .errors import (
55
+ AccessDeniedError,
56
+ BadRequestError,
57
+ CocApiError,
58
+ MaintenanceError,
59
+ NotFoundError,
60
+ PrivateWarLogError,
61
+ RateLimitedError,
62
+ ServerError,
63
+ raise_for_error,
64
+ )
65
+ from .game_time import (
66
+ clan_games_window,
67
+ is_clan_games,
68
+ is_raid_weekend,
69
+ legend_day_window,
70
+ raid_weekend_window,
71
+ )
51
72
 
52
73
  # Key management (credential-based auth)
53
74
  from .key_manager import (
@@ -70,6 +91,7 @@ from .middleware import (
70
91
 
71
92
  # Utility functions
72
93
  from .models import create_dynamic_model, get_pydantic_info, validate_pydantic_available
94
+ from .static_data import StaticData
73
95
  from .utils import build_url, clean_tag, validate_params
74
96
 
75
97
  # Pydantic response models (optional - only available when pydantic is installed)
@@ -123,7 +145,7 @@ except (ImportError, SyntaxError):
123
145
  _SCHEMAS_AVAILABLE = False
124
146
 
125
147
  # Version info
126
- __version__ = "4.0.0"
148
+ __version__ = "4.1.0"
127
149
  __author__ = "Tony Benoy"
128
150
  __email__ = "me@tonybenoy.com"
129
151
 
@@ -144,6 +166,29 @@ __all__ = [
144
166
  "AsyncKeyManager",
145
167
  "KeyManagerError",
146
168
  "InvalidCredentials",
169
+ # Army links / static data / event windows
170
+ "Army",
171
+ "ArmyUnit",
172
+ "parse_army_link",
173
+ "build_army_link",
174
+ "StaticData",
175
+ "clan_games_window",
176
+ "raid_weekend_window",
177
+ "legend_day_window",
178
+ "is_clan_games",
179
+ "is_raid_weekend",
180
+ # Errors and per-call controls
181
+ "CocApiError",
182
+ "AccessDeniedError",
183
+ "BadRequestError",
184
+ "MaintenanceError",
185
+ "NotFoundError",
186
+ "PrivateWarLogError",
187
+ "RateLimitedError",
188
+ "ServerError",
189
+ "raise_for_error",
190
+ "cache_control",
191
+ "without_rate_limit",
147
192
  # Data structures
148
193
  "CacheEntry",
149
194
  "RequestMetric",