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.
- {cocapi-4.0.0 → cocapi-4.1.0}/.github/FUNDING.yml +1 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/.github/workflows/ci.yml +5 -5
- cocapi-4.1.0/.github/workflows/docs.yml +33 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/.github/workflows/release.yml +5 -5
- cocapi-4.1.0/PKG-INFO +257 -0
- cocapi-4.1.0/README.md +218 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/__init__.py +46 -1
- cocapi-4.1.0/cocapi/army.py +89 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/async_client.py +41 -10
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/client.py +129 -6
- cocapi-4.1.0/cocapi/controls.py +66 -0
- cocapi-4.1.0/cocapi/errors.py +106 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_state.py +10 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_stream.py +10 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_watchers.py +56 -0
- cocapi-4.1.0/cocapi/game_time.py +68 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/schemas.py +91 -0
- cocapi-4.1.0/cocapi/static_data.py +125 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/utils.py +8 -0
- cocapi-4.1.0/docs/changelog.md +56 -0
- cocapi-4.1.0/docs/examples.md +123 -0
- cocapi-4.1.0/docs/getting-started/authentication.md +82 -0
- cocapi-4.1.0/docs/getting-started/installation.md +53 -0
- cocapi-4.1.0/docs/getting-started/quickstart.md +76 -0
- cocapi-4.1.0/docs/guides/async.md +112 -0
- cocapi-4.1.0/docs/guides/caching.md +74 -0
- cocapi-4.1.0/docs/guides/cli.md +94 -0
- cocapi-4.1.0/docs/guides/configuration.md +88 -0
- cocapi-4.1.0/docs/guides/error-handling.md +119 -0
- cocapi-4.1.0/docs/guides/events.md +152 -0
- cocapi-4.1.0/docs/guides/game-data.md +40 -0
- cocapi-4.1.0/docs/guides/metrics.md +54 -0
- cocapi-4.1.0/docs/guides/middleware.md +83 -0
- cocapi-4.1.0/docs/guides/pagination-batch.md +88 -0
- cocapi-4.1.0/docs/guides/pydantic-models.md +70 -0
- cocapi-4.1.0/docs/index.md +62 -0
- cocapi-4.1.0/mkdocs.yml +136 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/pyproject.toml +16 -1
- cocapi-4.1.0/uv.lock +1937 -0
- cocapi-4.0.0/PKG-INFO +0 -955
- cocapi-4.0.0/README.md +0 -924
- cocapi-4.0.0/_config.yml +0 -1
- cocapi-4.0.0/uv.lock +0 -668
- {cocapi-4.0.0 → cocapi-4.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/.gitignore +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/.pre-commit-config.yaml +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/CODE_OF_CONDUCT.md +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/LICENSE +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/SECURITY.md +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/api_methods.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cache.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cli.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/cocapi.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/config.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/__init__.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_diff.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_types.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/events/_war_fsm.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/key_manager.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/metrics.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/middleware.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/model_registry.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/models.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/cocapi/py.typed +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/mypy.ini +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/setup.py +0 -0
- {cocapi-4.0.0 → cocapi-4.1.0}/sonar-project.properties +0 -0
|
@@ -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/
|
|
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/
|
|
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.
|
|
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",
|