prcpy-erlc 0.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.
- prcpy_erlc-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
- prcpy_erlc-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- prcpy_erlc-0.1.0/.github/pull_request_template.md +12 -0
- prcpy_erlc-0.1.0/.github/workflows/ci.yml +33 -0
- prcpy_erlc-0.1.0/.gitignore +13 -0
- prcpy_erlc-0.1.0/CONTRIBUTING.md +144 -0
- prcpy_erlc-0.1.0/LICENSE +21 -0
- prcpy_erlc-0.1.0/PKG-INFO +248 -0
- prcpy_erlc-0.1.0/README.md +194 -0
- prcpy_erlc-0.1.0/SECURITY.md +64 -0
- prcpy_erlc-0.1.0/docs/api.md +57 -0
- prcpy_erlc-0.1.0/docs/design.md +23 -0
- prcpy_erlc-0.1.0/examples/async.py +13 -0
- prcpy_erlc-0.1.0/examples/basic.py +8 -0
- prcpy_erlc-0.1.0/poetry.lock +658 -0
- prcpy_erlc-0.1.0/pyproject.toml +53 -0
- prcpy_erlc-0.1.0/src/prcpy/__init__.py +51 -0
- prcpy_erlc-0.1.0/src/prcpy/client.py +360 -0
- prcpy_erlc-0.1.0/src/prcpy/errors.py +58 -0
- prcpy_erlc-0.1.0/src/prcpy/models.py +265 -0
- prcpy_erlc-0.1.0/src/prcpy/py.typed +0 -0
- prcpy_erlc-0.1.0/src/prcpy/rate_limits.py +31 -0
- prcpy_erlc-0.1.0/src/prcpy/webhooks.py +61 -0
- prcpy_erlc-0.1.0/tests/test_client.py +73 -0
- prcpy_erlc-0.1.0/tests/test_models.py +54 -0
- prcpy_erlc-0.1.0/tests/test_webhooks.py +23 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a reproducible problem
|
|
4
|
+
title: ""
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
## Reproduction
|
|
12
|
+
|
|
13
|
+
## Expected behavior
|
|
14
|
+
|
|
15
|
+
## Actual behavior
|
|
16
|
+
|
|
17
|
+
## Environment
|
|
18
|
+
|
|
19
|
+
- prcpy-erlc version:
|
|
20
|
+
- Python version:
|
|
21
|
+
- OS:
|
|
22
|
+
|
|
23
|
+
Do not include API keys or private server credentials.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v6
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
cache: pip
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
python -m pip install -e ".[dev]"
|
|
28
|
+
- name: Lint
|
|
29
|
+
run: python -m ruff check .
|
|
30
|
+
- name: Test
|
|
31
|
+
run: python -m pytest
|
|
32
|
+
- name: Build
|
|
33
|
+
run: python -m build
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for contributing to prcpy.
|
|
4
|
+
|
|
5
|
+
prcpy is a small, typed Python client for the ER:LC Private Server API. The project aims to keep its public API predictable, its dependencies small, and its implementation easy to maintain.
|
|
6
|
+
|
|
7
|
+
## Before you start
|
|
8
|
+
|
|
9
|
+
For a bug fix, documentation change, or small improvement, open an issue first when the change is likely to affect the public API or overall project direction. For straightforward fixes, you can open a pull request directly.
|
|
10
|
+
|
|
11
|
+
Please search existing issues and pull requests before opening a new one.
|
|
12
|
+
|
|
13
|
+
## Development setup
|
|
14
|
+
|
|
15
|
+
prcpy supports Python 3.10 and newer.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python -m venv .venv
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Windows:
|
|
22
|
+
```powershell
|
|
23
|
+
.venv\Scripts\Activate.ps1
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
macOS/Linux:
|
|
27
|
+
```bash
|
|
28
|
+
source .venv/bin/activate
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Install development dependencies:
|
|
32
|
+
```bash
|
|
33
|
+
python -m pip install -e ".[dev]"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Running checks
|
|
37
|
+
```bash
|
|
38
|
+
ruff check .
|
|
39
|
+
pytest
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run both commands before opening a pull request. Changes to webhook verification, HTTP behavior, models, error handling, or other public behavior should include tests.
|
|
43
|
+
|
|
44
|
+
## Project structure
|
|
45
|
+
```text
|
|
46
|
+
src/prcpy/ Package source
|
|
47
|
+
tests/ Test suite
|
|
48
|
+
examples/ Usage examples
|
|
49
|
+
docs/ API and design documentation
|
|
50
|
+
.github/ CI and repository templates
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Keep implementation code in `src/prcpy`. Avoid adding scripts or files without a clear maintenance or user-facing purpose.
|
|
54
|
+
|
|
55
|
+
## Code style
|
|
56
|
+
- Follow the existing project structure.
|
|
57
|
+
- Keep functions and classes focused.
|
|
58
|
+
- Prefer explicit, readable code over clever abstractions.
|
|
59
|
+
- Preserve type annotations.
|
|
60
|
+
- Keep the public API small and intentional.
|
|
61
|
+
- Use the standard library where it is sufficient.
|
|
62
|
+
- Avoid unnecessary dependencies.
|
|
63
|
+
- Keep error messages useful without exposing credentials or private data.
|
|
64
|
+
- Do not silently change existing public behavior.
|
|
65
|
+
- Do not add automatic retries to commands unless explicitly designed and documented; repeating a command can have side effects.
|
|
66
|
+
|
|
67
|
+
Ruff is the project's source of truth for linting.
|
|
68
|
+
|
|
69
|
+
## API changes
|
|
70
|
+
|
|
71
|
+
For public API changes:
|
|
72
|
+
1. Update the implementation.
|
|
73
|
+
2. Add or update tests.
|
|
74
|
+
3. Update documentation.
|
|
75
|
+
4. Update affected examples.
|
|
76
|
+
5. Consider backward compatibility.
|
|
77
|
+
6. Keep the change aligned with the official ER:LC API documentation.
|
|
78
|
+
|
|
79
|
+
If the ER:LC API itself changes, link the relevant official documentation in the pull request description. Do not invent undocumented API behavior when a documented alternative exists.
|
|
80
|
+
|
|
81
|
+
## Models
|
|
82
|
+
|
|
83
|
+
Keep API models typed and predictable. Match official API fields closely, handle missing optional data safely, preserve useful raw API data where the existing pattern does so, and add tests for new fields.
|
|
84
|
+
|
|
85
|
+
Avoid restrictive enums for API values unless the API guarantees those values are stable.
|
|
86
|
+
|
|
87
|
+
## HTTP behavior
|
|
88
|
+
|
|
89
|
+
Preserve useful HTTP status information, documented error details, authentication failures, and rate-limit information when changing request handling.
|
|
90
|
+
|
|
91
|
+
Be especially careful with retries: POST requests execute in-game commands and should not be automatically repeated without an explicit design.
|
|
92
|
+
|
|
93
|
+
Never log authenticated request headers.
|
|
94
|
+
|
|
95
|
+
## Webhooks
|
|
96
|
+
|
|
97
|
+
Webhook changes require tests for valid and invalid signatures.
|
|
98
|
+
|
|
99
|
+
Use synthetic keys and payloads in tests. Never use production webhook credentials.
|
|
100
|
+
|
|
101
|
+
Verify changes against the current ER:LC documentation before submitting them.
|
|
102
|
+
|
|
103
|
+
## Tests
|
|
104
|
+
|
|
105
|
+
Tests should be deterministic, fast, independent of a live ER:LC server, free of credentials, and focused on observable behavior.
|
|
106
|
+
|
|
107
|
+
Use mocked HTTP responses for API client tests. The normal test suite must not require a real ER:LC private server.
|
|
108
|
+
|
|
109
|
+
## Documentation
|
|
110
|
+
|
|
111
|
+
Document behavior users can actually rely on. Keep examples short and runnable. When a public API changes, update the README or the appropriate page under `docs/`.
|
|
112
|
+
|
|
113
|
+
## Commits
|
|
114
|
+
|
|
115
|
+
Use short, descriptive commit messages.
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
Add queue endpoint
|
|
119
|
+
Fix rate limit parsing
|
|
120
|
+
Update webhook docs
|
|
121
|
+
Test command errors
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Avoid commit messages that contain unnecessary detail or references to tools used to make the change.
|
|
125
|
+
|
|
126
|
+
## Pull requests
|
|
127
|
+
|
|
128
|
+
A good pull request should explain what changed, why it changed, any public API changes, how it was tested, and compatibility or migration considerations.
|
|
129
|
+
|
|
130
|
+
Keep pull requests focused.
|
|
131
|
+
|
|
132
|
+
Before opening a pull request:
|
|
133
|
+
- [ ] Tests pass.
|
|
134
|
+
- [ ] Ruff passes.
|
|
135
|
+
- [ ] Documentation is updated when needed.
|
|
136
|
+
- [ ] Examples still make sense when affected.
|
|
137
|
+
- [ ] No credentials or private server data are included.
|
|
138
|
+
- [ ] Public API changes are clearly described.
|
|
139
|
+
|
|
140
|
+
## Security
|
|
141
|
+
|
|
142
|
+
Never include ER:LC server keys, global API keys, webhook secrets, access tokens, or private server data in commits, issues, pull requests, examples, or tests.
|
|
143
|
+
|
|
144
|
+
See [SECURITY.md](SECURITY.md) for vulnerability reporting and security guidance.
|
prcpy_erlc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sidhak Singh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: prcpy-erlc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A typed Python client for the ER:LC Private Server API.
|
|
5
|
+
Project-URL: Documentation, https://apidocs.erlc.gg/
|
|
6
|
+
Project-URL: Repository, https://github.com/Metolix/erlcpy
|
|
7
|
+
Project-URL: Issues, https://github.com/Metolix/erlcpy/issues
|
|
8
|
+
Author: Sidhak Singh
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Sidhak Singh
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: api,erlc,private-server,python,roblox
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Typing :: Typed
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Requires-Dist: httpx<1,>=0.27
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
46
|
+
Requires-Dist: cryptography>=42; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
49
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
50
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
51
|
+
Provides-Extra: webhooks
|
|
52
|
+
Requires-Dist: cryptography>=42; extra == 'webhooks'
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
# prcpy
|
|
56
|
+
|
|
57
|
+
A typed Python client for the ER:LC Private Server API.
|
|
58
|
+
|
|
59
|
+
prcpy provides synchronous and asynchronous clients, typed response models, rate-limit metadata, structured exceptions, webhook helpers, and a low-level request interface for endpoints that are added to the API later.
|
|
60
|
+
|
|
61
|
+
> prcpy is an independent open-source project and is not affiliated with or endorsed by ER:LC or PRC.
|
|
62
|
+
|
|
63
|
+
## Requirements
|
|
64
|
+
|
|
65
|
+
- Python 3.10+
|
|
66
|
+
- An ER:LC private server with API access
|
|
67
|
+
- A server key from the server's API settings
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install prcpy-erlc
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For webhook signature verification:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "prcpy-erlc[webhooks]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quick start
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from prcpy import Client
|
|
85
|
+
|
|
86
|
+
with Client("your-server-key") as client:
|
|
87
|
+
server = client.get_server(players=True)
|
|
88
|
+
|
|
89
|
+
print(server.name)
|
|
90
|
+
print(f"{server.current_players}/{server.max_players}")
|
|
91
|
+
|
|
92
|
+
for player in server.players or []:
|
|
93
|
+
print(player.username, player.team)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Async
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from prcpy import AsyncClient
|
|
100
|
+
|
|
101
|
+
async with AsyncClient("your-server-key") as client:
|
|
102
|
+
server = await client.get_server(players=True)
|
|
103
|
+
print(server.name)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Available server data
|
|
107
|
+
|
|
108
|
+
The v2 server endpoint supports these optional resources:
|
|
109
|
+
|
|
110
|
+
- `players`
|
|
111
|
+
- `staff`
|
|
112
|
+
- `join_logs`
|
|
113
|
+
- `queue`
|
|
114
|
+
- `kill_logs`
|
|
115
|
+
- `command_logs`
|
|
116
|
+
- `mod_calls`
|
|
117
|
+
- `emergency_calls`
|
|
118
|
+
- `vehicles`
|
|
119
|
+
|
|
120
|
+
Only request the data an application needs.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
server = client.get_server(
|
|
124
|
+
players=True,
|
|
125
|
+
staff=True,
|
|
126
|
+
vehicles=True,
|
|
127
|
+
emergency_calls=True,
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Convenience methods
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
players = client.get_players()
|
|
135
|
+
staff = client.get_staff()
|
|
136
|
+
join_logs = client.get_join_logs()
|
|
137
|
+
queue = client.get_queue()
|
|
138
|
+
kill_logs = client.get_kill_logs()
|
|
139
|
+
command_logs = client.get_command_logs()
|
|
140
|
+
mod_calls = client.get_mod_calls()
|
|
141
|
+
vehicles = client.get_vehicles()
|
|
142
|
+
bans = client.get_bans()
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Commands
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
result = client.send_command(":h Hello from prcpy")
|
|
149
|
+
print(result.message)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The API documents a `commandId` on command failures. prcpy exposes it as `CommandError.command_id` or `ServerOfflineError.command_id` when supplied by the API.
|
|
153
|
+
|
|
154
|
+
## Authentication
|
|
155
|
+
|
|
156
|
+
All API requests use the `server-key` header.
|
|
157
|
+
|
|
158
|
+
Public applications may also provide a global API key:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
client = Client(
|
|
162
|
+
"server-key",
|
|
163
|
+
global_api_key="global-api-key",
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Environment variables are supported:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
ERLC_SERVER_KEY=...
|
|
171
|
+
ERLC_GLOBAL_API_KEY=...
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
client = Client.from_env()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Never commit keys to source control.
|
|
179
|
+
|
|
180
|
+
## Rate limits
|
|
181
|
+
|
|
182
|
+
The client reads the API's `X-RateLimit-Bucket`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` response headers.
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
client.get_server()
|
|
186
|
+
print(client.rate_limit)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
A 429 response raises `RateLimitError` with `retry_after` when the server provides a `Retry-After` header.
|
|
190
|
+
|
|
191
|
+
prcpy does not silently retry commands. This avoids accidentally executing an in-game command more than once.
|
|
192
|
+
|
|
193
|
+
## Raw API access
|
|
194
|
+
|
|
195
|
+
The typed methods cover the documented API, but the API can grow independently of this package.
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
data = client.request("GET", "/v2/server", params={"Players": "true"})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Webhooks
|
|
202
|
+
|
|
203
|
+
prcpy includes a small helper for Ed25519 webhook verification:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from prcpy.webhooks import verify_signature
|
|
207
|
+
|
|
208
|
+
verify_signature(
|
|
209
|
+
timestamp=request.headers["X-Signature-Timestamp"],
|
|
210
|
+
signature=request.headers["X-Signature-Ed25519"],
|
|
211
|
+
body=raw_request_body,
|
|
212
|
+
public_key="your-webhook-public-key",
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Always verify the raw request body before parsing JSON.
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
python -m pip install -e ".[dev]"
|
|
222
|
+
ruff check .
|
|
223
|
+
pytest
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Project structure
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
prcpy/
|
|
230
|
+
├── docs/
|
|
231
|
+
├── examples/
|
|
232
|
+
├── src/prcpy/
|
|
233
|
+
│ ├── client.py
|
|
234
|
+
│ ├── errors.py
|
|
235
|
+
│ ├── models.py
|
|
236
|
+
│ ├── rate_limits.py
|
|
237
|
+
│ └── webhooks.py
|
|
238
|
+
├── tests/
|
|
239
|
+
├── .github/workflows/
|
|
240
|
+
├── CONTRIBUTING.md
|
|
241
|
+
├── LICENSE
|
|
242
|
+
├── pyproject.toml
|
|
243
|
+
└── README.md
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# prcpy
|
|
2
|
+
|
|
3
|
+
A typed Python client for the ER:LC Private Server API.
|
|
4
|
+
|
|
5
|
+
prcpy provides synchronous and asynchronous clients, typed response models, rate-limit metadata, structured exceptions, webhook helpers, and a low-level request interface for endpoints that are added to the API later.
|
|
6
|
+
|
|
7
|
+
> prcpy is an independent open-source project and is not affiliated with or endorsed by ER:LC or PRC.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Python 3.10+
|
|
12
|
+
- An ER:LC private server with API access
|
|
13
|
+
- A server key from the server's API settings
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install prcpy-erlc
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For webhook signature verification:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install "prcpy-erlc[webhooks]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from prcpy import Client
|
|
31
|
+
|
|
32
|
+
with Client("your-server-key") as client:
|
|
33
|
+
server = client.get_server(players=True)
|
|
34
|
+
|
|
35
|
+
print(server.name)
|
|
36
|
+
print(f"{server.current_players}/{server.max_players}")
|
|
37
|
+
|
|
38
|
+
for player in server.players or []:
|
|
39
|
+
print(player.username, player.team)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Async
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from prcpy import AsyncClient
|
|
46
|
+
|
|
47
|
+
async with AsyncClient("your-server-key") as client:
|
|
48
|
+
server = await client.get_server(players=True)
|
|
49
|
+
print(server.name)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Available server data
|
|
53
|
+
|
|
54
|
+
The v2 server endpoint supports these optional resources:
|
|
55
|
+
|
|
56
|
+
- `players`
|
|
57
|
+
- `staff`
|
|
58
|
+
- `join_logs`
|
|
59
|
+
- `queue`
|
|
60
|
+
- `kill_logs`
|
|
61
|
+
- `command_logs`
|
|
62
|
+
- `mod_calls`
|
|
63
|
+
- `emergency_calls`
|
|
64
|
+
- `vehicles`
|
|
65
|
+
|
|
66
|
+
Only request the data an application needs.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
server = client.get_server(
|
|
70
|
+
players=True,
|
|
71
|
+
staff=True,
|
|
72
|
+
vehicles=True,
|
|
73
|
+
emergency_calls=True,
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Convenience methods
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
players = client.get_players()
|
|
81
|
+
staff = client.get_staff()
|
|
82
|
+
join_logs = client.get_join_logs()
|
|
83
|
+
queue = client.get_queue()
|
|
84
|
+
kill_logs = client.get_kill_logs()
|
|
85
|
+
command_logs = client.get_command_logs()
|
|
86
|
+
mod_calls = client.get_mod_calls()
|
|
87
|
+
vehicles = client.get_vehicles()
|
|
88
|
+
bans = client.get_bans()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Commands
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
result = client.send_command(":h Hello from prcpy")
|
|
95
|
+
print(result.message)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The API documents a `commandId` on command failures. prcpy exposes it as `CommandError.command_id` or `ServerOfflineError.command_id` when supplied by the API.
|
|
99
|
+
|
|
100
|
+
## Authentication
|
|
101
|
+
|
|
102
|
+
All API requests use the `server-key` header.
|
|
103
|
+
|
|
104
|
+
Public applications may also provide a global API key:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
client = Client(
|
|
108
|
+
"server-key",
|
|
109
|
+
global_api_key="global-api-key",
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Environment variables are supported:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
ERLC_SERVER_KEY=...
|
|
117
|
+
ERLC_GLOBAL_API_KEY=...
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
client = Client.from_env()
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Never commit keys to source control.
|
|
125
|
+
|
|
126
|
+
## Rate limits
|
|
127
|
+
|
|
128
|
+
The client reads the API's `X-RateLimit-Bucket`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` response headers.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
client.get_server()
|
|
132
|
+
print(client.rate_limit)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
A 429 response raises `RateLimitError` with `retry_after` when the server provides a `Retry-After` header.
|
|
136
|
+
|
|
137
|
+
prcpy does not silently retry commands. This avoids accidentally executing an in-game command more than once.
|
|
138
|
+
|
|
139
|
+
## Raw API access
|
|
140
|
+
|
|
141
|
+
The typed methods cover the documented API, but the API can grow independently of this package.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
data = client.request("GET", "/v2/server", params={"Players": "true"})
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Webhooks
|
|
148
|
+
|
|
149
|
+
prcpy includes a small helper for Ed25519 webhook verification:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from prcpy.webhooks import verify_signature
|
|
153
|
+
|
|
154
|
+
verify_signature(
|
|
155
|
+
timestamp=request.headers["X-Signature-Timestamp"],
|
|
156
|
+
signature=request.headers["X-Signature-Ed25519"],
|
|
157
|
+
body=raw_request_body,
|
|
158
|
+
public_key="your-webhook-public-key",
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Always verify the raw request body before parsing JSON.
|
|
163
|
+
|
|
164
|
+
## Development
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
python -m pip install -e ".[dev]"
|
|
168
|
+
ruff check .
|
|
169
|
+
pytest
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Project structure
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
prcpy/
|
|
176
|
+
├── docs/
|
|
177
|
+
├── examples/
|
|
178
|
+
├── src/prcpy/
|
|
179
|
+
│ ├── client.py
|
|
180
|
+
│ ├── errors.py
|
|
181
|
+
│ ├── models.py
|
|
182
|
+
│ ├── rate_limits.py
|
|
183
|
+
│ └── webhooks.py
|
|
184
|
+
├── tests/
|
|
185
|
+
├── .github/workflows/
|
|
186
|
+
├── CONTRIBUTING.md
|
|
187
|
+
├── LICENSE
|
|
188
|
+
├── pyproject.toml
|
|
189
|
+
└── README.md
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|