remnawave-client 2.0.8__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.
- remnawave_client-2.0.8/PKG-INFO +122 -0
- remnawave_client-2.0.8/README.md +112 -0
- remnawave_client-2.0.8/pyproject.toml +80 -0
- remnawave_client-2.0.8/src/remnawave/__init__.py +9 -0
- remnawave_client-2.0.8/src/remnawave/_generated/__init__.py +1 -0
- remnawave_client-2.0.8/src/remnawave/_generated/enums.py +68 -0
- remnawave_client-2.0.8/src/remnawave/_generated/groups.py +165 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/__init__.py +1 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/api_tokens_management.py +56 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/auth.py +101 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/bandwidth_stats.py +78 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/config_profiles.py +131 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/hosts.py +98 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/hosts_bulk_actions.py +89 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/hwid_user_devices.py +68 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/infra_billing.py +238 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/internal_squads.py +135 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/keygen.py +28 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/nodes.py +150 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/subscription.py +125 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/subscriptions.py +73 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/subscriptions_settings.py +46 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/subscriptions_template.py +51 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/system.py +84 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/users.py +287 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/users_bulk_actions.py +155 -0
- remnawave_client-2.0.8/src/remnawave/_generated/methods/users_stats.py +42 -0
- remnawave_client-2.0.8/src/remnawave/_generated/models.py +1030 -0
- remnawave_client-2.0.8/src/remnawave/_generated/renames.py +19 -0
- remnawave_client-2.0.8/src/remnawave/_generated/webhooks.py +11 -0
- remnawave_client-2.0.8/src/remnawave/client.py +118 -0
- remnawave_client-2.0.8/src/remnawave/exceptions.py +67 -0
- remnawave_client-2.0.8/src/remnawave/execution/__init__.py +22 -0
- remnawave_client-2.0.8/src/remnawave/execution/auth.py +5 -0
- remnawave_client-2.0.8/src/remnawave/execution/backoff.py +74 -0
- remnawave_client-2.0.8/src/remnawave/execution/bearer.py +15 -0
- remnawave_client-2.0.8/src/remnawave/execution/executor.py +220 -0
- remnawave_client-2.0.8/src/remnawave/execution/group.py +51 -0
- remnawave_client-2.0.8/src/remnawave/execution/retry.py +14 -0
- remnawave_client-2.0.8/src/remnawave/http/__init__.py +18 -0
- remnawave_client-2.0.8/src/remnawave/http/httpx.py +60 -0
- remnawave_client-2.0.8/src/remnawave/http/transport.py +30 -0
- remnawave_client-2.0.8/src/remnawave/operations/__init__.py +20 -0
- remnawave_client-2.0.8/src/remnawave/operations/builder.py +79 -0
- remnawave_client-2.0.8/src/remnawave/operations/operation.py +33 -0
- remnawave_client-2.0.8/src/remnawave/operations/pagination.py +52 -0
- remnawave_client-2.0.8/src/remnawave/operations/parser.py +104 -0
- remnawave_client-2.0.8/src/remnawave/py.typed +0 -0
- remnawave_client-2.0.8/src/remnawave/serialization/__init__.py +13 -0
- remnawave_client-2.0.8/src/remnawave/serialization/adaptix.py +66 -0
- remnawave_client-2.0.8/src/remnawave/serialization/serializer.py +8 -0
- remnawave_client-2.0.8/src/remnawave/types/__init__.py +374 -0
- remnawave_client-2.0.8/src/remnawave/webhooks.py +58 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: remnawave-client
|
|
3
|
+
Version: 2.0.8
|
|
4
|
+
Summary: Sync and async client for the Remnawave API
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Dist: httpx>=0.28.1
|
|
7
|
+
Requires-Dist: adaptix>=3.0.0b12
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# remnawave-client
|
|
12
|
+
|
|
13
|
+
Sync and async client for the [Remnawave](https://docs.rw) API, generated from
|
|
14
|
+
the panel's OpenAPI specification.
|
|
15
|
+
|
|
16
|
+
- Every endpoint typed end to end — `mypy --strict` clean, `py.typed` shipped
|
|
17
|
+
- The same surface synchronously and asynchronously
|
|
18
|
+
- Listings walked lazily through `iter_*`
|
|
19
|
+
- Webhook events parsed and their signatures verified
|
|
20
|
+
- Transport, serializer, auth and retry policy are all replaceable
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install remnawave-client
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requires Python 3.11 or newer.
|
|
27
|
+
|
|
28
|
+
## Versions
|
|
29
|
+
|
|
30
|
+
The library version equals the API version it was generated from. A tag exists
|
|
31
|
+
for every minor release of the panel from 2.0 onwards, so pin the one matching
|
|
32
|
+
your deployment:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install remnawave-client==3.0.0
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
2.0.8 2.1.19 2.2.6 2.3.2 2.4.4 2.5.7 2.6.4
|
|
40
|
+
2.7.4 2.8.1 3.0.0 3.1.0 3.2.3 3.3.2 3.4.3
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from remnawave import Remnawave
|
|
47
|
+
|
|
48
|
+
with Remnawave("https://panel.example.com", token) as rw:
|
|
49
|
+
user = rw.users.get_user_by_username("zen")
|
|
50
|
+
print(user.username, user.status, user.expire_at)
|
|
51
|
+
|
|
52
|
+
for u in rw.users.iter_users():
|
|
53
|
+
print(u.username)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The async client mirrors it:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import asyncio
|
|
60
|
+
|
|
61
|
+
from remnawave import AsyncRemnawave
|
|
62
|
+
|
|
63
|
+
async def main() -> None:
|
|
64
|
+
async with AsyncRemnawave("https://panel.example.com", token) as rw:
|
|
65
|
+
stats = rw.system.get_stats()
|
|
66
|
+
nodes = rw.nodes.get_nodes()
|
|
67
|
+
async for user in rw.users.iter_users():
|
|
68
|
+
print(user.username)
|
|
69
|
+
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
More in [`examples/`](examples/): pagination, partial updates, error handling,
|
|
74
|
+
webhooks and swapping out the client's parts.
|
|
75
|
+
|
|
76
|
+
## Errors
|
|
77
|
+
|
|
78
|
+
Everything the library raises inherits from `RemnawaveError`. Below it the
|
|
79
|
+
hierarchy splits by cause: `ApiError` for anything the panel answered with,
|
|
80
|
+
`TransportError` when the request never got a reply, `SerializationError` when
|
|
81
|
+
the payload did not match the schema.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from remnawave.exceptions import NotFoundError
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
rw.users.get_user_by_id(42)
|
|
88
|
+
except NotFoundError as error:
|
|
89
|
+
print(error.status, error.error_code) # 404 'A025'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`error_code` is the panel's own code and is more specific than the HTTP
|
|
93
|
+
status — branch on it when you need to tell cases apart.
|
|
94
|
+
|
|
95
|
+
## Webhooks
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from remnawave.webhooks import SIGNATURE_HEADER, WebhookReceiver
|
|
99
|
+
|
|
100
|
+
hooks = WebhookReceiver(secret=os.environ["WEBHOOK_SECRET_HEADER"])
|
|
101
|
+
event = hooks.receive(request.body, request.headers[SIGNATURE_HEADER])
|
|
102
|
+
|
|
103
|
+
if event.scope == "user":
|
|
104
|
+
print(event.event, event.data.username)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Pass the raw request body: the signature covers those exact bytes, so
|
|
108
|
+
re-serialising parsed JSON breaks verification.
|
|
109
|
+
|
|
110
|
+
## Regenerating
|
|
111
|
+
|
|
112
|
+
`src/remnawave/_generated/` is machine-written and must not be edited by hand.
|
|
113
|
+
To target another panel version, drop its specification into `specs/` and run:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
python -m tools.codegen 3.4.3
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Where the specification is wrong or awkward, `overlay.yaml` patches it before
|
|
120
|
+
generation: type names, forced field types, fields kept out of `repr`. Editing
|
|
121
|
+
the generated code directly would be lost on the next run; editing the vendored
|
|
122
|
+
specification would be lost on the next update.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# remnawave-client
|
|
2
|
+
|
|
3
|
+
Sync and async client for the [Remnawave](https://docs.rw) API, generated from
|
|
4
|
+
the panel's OpenAPI specification.
|
|
5
|
+
|
|
6
|
+
- Every endpoint typed end to end — `mypy --strict` clean, `py.typed` shipped
|
|
7
|
+
- The same surface synchronously and asynchronously
|
|
8
|
+
- Listings walked lazily through `iter_*`
|
|
9
|
+
- Webhook events parsed and their signatures verified
|
|
10
|
+
- Transport, serializer, auth and retry policy are all replaceable
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install remnawave-client
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires Python 3.11 or newer.
|
|
17
|
+
|
|
18
|
+
## Versions
|
|
19
|
+
|
|
20
|
+
The library version equals the API version it was generated from. A tag exists
|
|
21
|
+
for every minor release of the panel from 2.0 onwards, so pin the one matching
|
|
22
|
+
your deployment:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install remnawave-client==3.0.0
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
2.0.8 2.1.19 2.2.6 2.3.2 2.4.4 2.5.7 2.6.4
|
|
30
|
+
2.7.4 2.8.1 3.0.0 3.1.0 3.2.3 3.3.2 3.4.3
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from remnawave import Remnawave
|
|
37
|
+
|
|
38
|
+
with Remnawave("https://panel.example.com", token) as rw:
|
|
39
|
+
user = rw.users.get_user_by_username("zen")
|
|
40
|
+
print(user.username, user.status, user.expire_at)
|
|
41
|
+
|
|
42
|
+
for u in rw.users.iter_users():
|
|
43
|
+
print(u.username)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The async client mirrors it:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import asyncio
|
|
50
|
+
|
|
51
|
+
from remnawave import AsyncRemnawave
|
|
52
|
+
|
|
53
|
+
async def main() -> None:
|
|
54
|
+
async with AsyncRemnawave("https://panel.example.com", token) as rw:
|
|
55
|
+
stats = rw.system.get_stats()
|
|
56
|
+
nodes = rw.nodes.get_nodes()
|
|
57
|
+
async for user in rw.users.iter_users():
|
|
58
|
+
print(user.username)
|
|
59
|
+
|
|
60
|
+
asyncio.run(main())
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
More in [`examples/`](examples/): pagination, partial updates, error handling,
|
|
64
|
+
webhooks and swapping out the client's parts.
|
|
65
|
+
|
|
66
|
+
## Errors
|
|
67
|
+
|
|
68
|
+
Everything the library raises inherits from `RemnawaveError`. Below it the
|
|
69
|
+
hierarchy splits by cause: `ApiError` for anything the panel answered with,
|
|
70
|
+
`TransportError` when the request never got a reply, `SerializationError` when
|
|
71
|
+
the payload did not match the schema.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from remnawave.exceptions import NotFoundError
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
rw.users.get_user_by_id(42)
|
|
78
|
+
except NotFoundError as error:
|
|
79
|
+
print(error.status, error.error_code) # 404 'A025'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`error_code` is the panel's own code and is more specific than the HTTP
|
|
83
|
+
status — branch on it when you need to tell cases apart.
|
|
84
|
+
|
|
85
|
+
## Webhooks
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from remnawave.webhooks import SIGNATURE_HEADER, WebhookReceiver
|
|
89
|
+
|
|
90
|
+
hooks = WebhookReceiver(secret=os.environ["WEBHOOK_SECRET_HEADER"])
|
|
91
|
+
event = hooks.receive(request.body, request.headers[SIGNATURE_HEADER])
|
|
92
|
+
|
|
93
|
+
if event.scope == "user":
|
|
94
|
+
print(event.event, event.data.username)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Pass the raw request body: the signature covers those exact bytes, so
|
|
98
|
+
re-serialising parsed JSON breaks verification.
|
|
99
|
+
|
|
100
|
+
## Regenerating
|
|
101
|
+
|
|
102
|
+
`src/remnawave/_generated/` is machine-written and must not be edited by hand.
|
|
103
|
+
To target another panel version, drop its specification into `specs/` and run:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
python -m tools.codegen 3.4.3
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Where the specification is wrong or awkward, `overlay.yaml` patches it before
|
|
110
|
+
generation: type names, forced field types, fields kept out of `repr`. Editing
|
|
111
|
+
the generated code directly would be lost on the next run; editing the vendored
|
|
112
|
+
specification would be lost on the next update.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "remnawave-client"
|
|
3
|
+
version = "2.0.8"
|
|
4
|
+
description = "Sync and async client for the Remnawave API"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"httpx>=0.28.1",
|
|
10
|
+
"adaptix>=3.0.0b12",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[dependency-groups]
|
|
14
|
+
dev = [
|
|
15
|
+
"pytest>=9.1.1",
|
|
16
|
+
"pytest-asyncio>=1.4.0",
|
|
17
|
+
"mypy>=2.3.1",
|
|
18
|
+
"ruff>=0.16.4",
|
|
19
|
+
"jinja2>=3.1",
|
|
20
|
+
"pyyaml>=6.0",
|
|
21
|
+
"types-PyYAML>=6.0",
|
|
22
|
+
"pytest-cov>=6.0",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["uv_build>=0.9.21,<0.10.0"]
|
|
27
|
+
build-backend = "uv_build"
|
|
28
|
+
|
|
29
|
+
[tool.uv.build-backend]
|
|
30
|
+
# Пакет называется remnawave, а дистрибутив remnawave-client,
|
|
31
|
+
# поэтому имя модуля задаём явно.
|
|
32
|
+
module-name = "remnawave"
|
|
33
|
+
|
|
34
|
+
[tool.pytest.ini_options]
|
|
35
|
+
asyncio_mode = "auto"
|
|
36
|
+
addopts = "--cov --cov-report=term-missing --cov-fail-under=100"
|
|
37
|
+
|
|
38
|
+
[tool.coverage.run]
|
|
39
|
+
source = ["src/remnawave"]
|
|
40
|
+
omit = ["src/remnawave/_generated/*"]
|
|
41
|
+
|
|
42
|
+
[tool.coverage.report]
|
|
43
|
+
show_missing = true
|
|
44
|
+
exclude_lines = [
|
|
45
|
+
"pragma: no cover",
|
|
46
|
+
"if TYPE_CHECKING:",
|
|
47
|
+
': \.\.\.$', # Protocols/overloads
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 80
|
|
52
|
+
target-version = "py311"
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["ALL"]
|
|
56
|
+
ignore = [
|
|
57
|
+
"RUF001",
|
|
58
|
+
"RUF002",
|
|
59
|
+
"RUF003",
|
|
60
|
+
"CPY001",
|
|
61
|
+
"D",
|
|
62
|
+
"COM812",
|
|
63
|
+
"ASYNC109",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint.per-file-ignores]
|
|
67
|
+
"src/remnawave/_generated/**" = ["PLR0913", "ANN401", "S105"]
|
|
68
|
+
"examples/**" = ["T201", "INP001"]
|
|
69
|
+
"src/remnawave/types/**" = ["E501"]
|
|
70
|
+
"tests/**" = [
|
|
71
|
+
"S101",
|
|
72
|
+
"PLR2004",
|
|
73
|
+
"EM101",
|
|
74
|
+
"TRY003",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
[tool.mypy]
|
|
78
|
+
python_version = "3.11"
|
|
79
|
+
strict = true
|
|
80
|
+
files = ["src", "tests", "tools", "examples"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @generated by tools/codegen -- do not edit
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @generated by tools/codegen -- do not edit
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class OAuth2CallbackRequestProvider(StrEnum):
|
|
6
|
+
GITHUB = "github"
|
|
7
|
+
POCKETID = "pocketid"
|
|
8
|
+
YANDEX = "yandex"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UserStatus(StrEnum):
|
|
12
|
+
ACTIVE = "ACTIVE"
|
|
13
|
+
DISABLED = "DISABLED"
|
|
14
|
+
LIMITED = "LIMITED"
|
|
15
|
+
EXPIRED = "EXPIRED"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class UserTrafficLimitStrategy(StrEnum):
|
|
19
|
+
NO_RESET = "NO_RESET"
|
|
20
|
+
DAY = "DAY"
|
|
21
|
+
WEEK = "WEEK"
|
|
22
|
+
MONTH = "MONTH"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SubscriptionControllerGetSubscriptionByClientType(StrEnum):
|
|
26
|
+
STASH = "stash"
|
|
27
|
+
SINGBOX = "singbox"
|
|
28
|
+
SINGBOX_LEGACY = "singbox-legacy"
|
|
29
|
+
MIHOMO = "mihomo"
|
|
30
|
+
JSON = "json"
|
|
31
|
+
V2RAY_JSON = "v2ray-json"
|
|
32
|
+
CLASH = "clash"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TemplateTemplateType(StrEnum):
|
|
36
|
+
STASH = "STASH"
|
|
37
|
+
SINGBOX = "SINGBOX"
|
|
38
|
+
SINGBOX_LEGACY = "SINGBOX_LEGACY"
|
|
39
|
+
MIHOMO = "MIHOMO"
|
|
40
|
+
XRAY_JSON = "XRAY_JSON"
|
|
41
|
+
CLASH = "CLASH"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class HostSecurityLayer(StrEnum):
|
|
45
|
+
DEFAULT = "DEFAULT"
|
|
46
|
+
TLS = "TLS"
|
|
47
|
+
NONE = "NONE"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CreateHostRequestAlpn(StrEnum):
|
|
51
|
+
H3 = "h3"
|
|
52
|
+
H2 = "h2"
|
|
53
|
+
HTTP_1_1 = "http/1.1"
|
|
54
|
+
H2_HTTP_1_1 = "h2,http/1.1"
|
|
55
|
+
H3_H2_HTTP_1_1 = "h3,h2,http/1.1"
|
|
56
|
+
H3_H2 = "h3,h2"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class CreateHostRequestFingerprint(StrEnum):
|
|
60
|
+
CHROME = "chrome"
|
|
61
|
+
FIREFOX = "firefox"
|
|
62
|
+
SAFARI = "safari"
|
|
63
|
+
IOS = "ios"
|
|
64
|
+
ANDROID = "android"
|
|
65
|
+
EDGE = "edge"
|
|
66
|
+
QQ = "qq"
|
|
67
|
+
RANDOM = "random"
|
|
68
|
+
RANDOMIZED = "randomized"
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# @generated by tools/codegen -- do not edit
|
|
2
|
+
|
|
3
|
+
from remnawave._generated.methods.api_tokens_management import (
|
|
4
|
+
ApiTokensManagementApi,
|
|
5
|
+
AsyncApiTokensManagementApi,
|
|
6
|
+
)
|
|
7
|
+
from remnawave._generated.methods.auth import (
|
|
8
|
+
AsyncAuthApi,
|
|
9
|
+
AuthApi,
|
|
10
|
+
)
|
|
11
|
+
from remnawave._generated.methods.bandwidth_stats import (
|
|
12
|
+
AsyncBandwidthStatsApi,
|
|
13
|
+
BandwidthStatsApi,
|
|
14
|
+
)
|
|
15
|
+
from remnawave._generated.methods.config_profiles import (
|
|
16
|
+
AsyncConfigProfilesApi,
|
|
17
|
+
ConfigProfilesApi,
|
|
18
|
+
)
|
|
19
|
+
from remnawave._generated.methods.hosts import (
|
|
20
|
+
AsyncHostsApi,
|
|
21
|
+
HostsApi,
|
|
22
|
+
)
|
|
23
|
+
from remnawave._generated.methods.hosts_bulk_actions import (
|
|
24
|
+
AsyncHostsBulkActionsApi,
|
|
25
|
+
HostsBulkActionsApi,
|
|
26
|
+
)
|
|
27
|
+
from remnawave._generated.methods.hwid_user_devices import (
|
|
28
|
+
AsyncHwidUserDevicesApi,
|
|
29
|
+
HwidUserDevicesApi,
|
|
30
|
+
)
|
|
31
|
+
from remnawave._generated.methods.infra_billing import (
|
|
32
|
+
AsyncInfraBillingApi,
|
|
33
|
+
InfraBillingApi,
|
|
34
|
+
)
|
|
35
|
+
from remnawave._generated.methods.internal_squads import (
|
|
36
|
+
AsyncInternalSquadsApi,
|
|
37
|
+
InternalSquadsApi,
|
|
38
|
+
)
|
|
39
|
+
from remnawave._generated.methods.keygen import (
|
|
40
|
+
AsyncKeygenApi,
|
|
41
|
+
KeygenApi,
|
|
42
|
+
)
|
|
43
|
+
from remnawave._generated.methods.nodes import (
|
|
44
|
+
AsyncNodesApi,
|
|
45
|
+
NodesApi,
|
|
46
|
+
)
|
|
47
|
+
from remnawave._generated.methods.subscription import (
|
|
48
|
+
AsyncSubscriptionApi,
|
|
49
|
+
SubscriptionApi,
|
|
50
|
+
)
|
|
51
|
+
from remnawave._generated.methods.subscriptions import (
|
|
52
|
+
AsyncSubscriptionsApi,
|
|
53
|
+
SubscriptionsApi,
|
|
54
|
+
)
|
|
55
|
+
from remnawave._generated.methods.subscriptions_settings import (
|
|
56
|
+
AsyncSubscriptionsSettingsApi,
|
|
57
|
+
SubscriptionsSettingsApi,
|
|
58
|
+
)
|
|
59
|
+
from remnawave._generated.methods.subscriptions_template import (
|
|
60
|
+
AsyncSubscriptionsTemplateApi,
|
|
61
|
+
SubscriptionsTemplateApi,
|
|
62
|
+
)
|
|
63
|
+
from remnawave._generated.methods.system import (
|
|
64
|
+
AsyncSystemApi,
|
|
65
|
+
SystemApi,
|
|
66
|
+
)
|
|
67
|
+
from remnawave._generated.methods.users import (
|
|
68
|
+
AsyncUsersApi,
|
|
69
|
+
UsersApi,
|
|
70
|
+
)
|
|
71
|
+
from remnawave._generated.methods.users_bulk_actions import (
|
|
72
|
+
AsyncUsersBulkActionsApi,
|
|
73
|
+
UsersBulkActionsApi,
|
|
74
|
+
)
|
|
75
|
+
from remnawave._generated.methods.users_stats import (
|
|
76
|
+
AsyncUsersStatsApi,
|
|
77
|
+
UsersStatsApi,
|
|
78
|
+
)
|
|
79
|
+
from remnawave.execution import AsyncExecutor, SyncExecutor
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SyncGroups:
|
|
83
|
+
api_tokens_management: ApiTokensManagementApi
|
|
84
|
+
auth: AuthApi
|
|
85
|
+
bandwidth_stats: BandwidthStatsApi
|
|
86
|
+
config_profiles: ConfigProfilesApi
|
|
87
|
+
hosts: HostsApi
|
|
88
|
+
hosts_bulk_actions: HostsBulkActionsApi
|
|
89
|
+
hwid_user_devices: HwidUserDevicesApi
|
|
90
|
+
infra_billing: InfraBillingApi
|
|
91
|
+
internal_squads: InternalSquadsApi
|
|
92
|
+
keygen: KeygenApi
|
|
93
|
+
nodes: NodesApi
|
|
94
|
+
subscription: SubscriptionApi
|
|
95
|
+
subscriptions: SubscriptionsApi
|
|
96
|
+
subscriptions_settings: SubscriptionsSettingsApi
|
|
97
|
+
subscriptions_template: SubscriptionsTemplateApi
|
|
98
|
+
system: SystemApi
|
|
99
|
+
users: UsersApi
|
|
100
|
+
users_bulk_actions: UsersBulkActionsApi
|
|
101
|
+
users_stats: UsersStatsApi
|
|
102
|
+
|
|
103
|
+
def _attach(self, executor: SyncExecutor) -> None:
|
|
104
|
+
self.api_tokens_management = ApiTokensManagementApi(executor)
|
|
105
|
+
self.auth = AuthApi(executor)
|
|
106
|
+
self.bandwidth_stats = BandwidthStatsApi(executor)
|
|
107
|
+
self.config_profiles = ConfigProfilesApi(executor)
|
|
108
|
+
self.hosts = HostsApi(executor)
|
|
109
|
+
self.hosts_bulk_actions = HostsBulkActionsApi(executor)
|
|
110
|
+
self.hwid_user_devices = HwidUserDevicesApi(executor)
|
|
111
|
+
self.infra_billing = InfraBillingApi(executor)
|
|
112
|
+
self.internal_squads = InternalSquadsApi(executor)
|
|
113
|
+
self.keygen = KeygenApi(executor)
|
|
114
|
+
self.nodes = NodesApi(executor)
|
|
115
|
+
self.subscription = SubscriptionApi(executor)
|
|
116
|
+
self.subscriptions = SubscriptionsApi(executor)
|
|
117
|
+
self.subscriptions_settings = SubscriptionsSettingsApi(executor)
|
|
118
|
+
self.subscriptions_template = SubscriptionsTemplateApi(executor)
|
|
119
|
+
self.system = SystemApi(executor)
|
|
120
|
+
self.users = UsersApi(executor)
|
|
121
|
+
self.users_bulk_actions = UsersBulkActionsApi(executor)
|
|
122
|
+
self.users_stats = UsersStatsApi(executor)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class AsyncGroups:
|
|
126
|
+
api_tokens_management: AsyncApiTokensManagementApi
|
|
127
|
+
auth: AsyncAuthApi
|
|
128
|
+
bandwidth_stats: AsyncBandwidthStatsApi
|
|
129
|
+
config_profiles: AsyncConfigProfilesApi
|
|
130
|
+
hosts: AsyncHostsApi
|
|
131
|
+
hosts_bulk_actions: AsyncHostsBulkActionsApi
|
|
132
|
+
hwid_user_devices: AsyncHwidUserDevicesApi
|
|
133
|
+
infra_billing: AsyncInfraBillingApi
|
|
134
|
+
internal_squads: AsyncInternalSquadsApi
|
|
135
|
+
keygen: AsyncKeygenApi
|
|
136
|
+
nodes: AsyncNodesApi
|
|
137
|
+
subscription: AsyncSubscriptionApi
|
|
138
|
+
subscriptions: AsyncSubscriptionsApi
|
|
139
|
+
subscriptions_settings: AsyncSubscriptionsSettingsApi
|
|
140
|
+
subscriptions_template: AsyncSubscriptionsTemplateApi
|
|
141
|
+
system: AsyncSystemApi
|
|
142
|
+
users: AsyncUsersApi
|
|
143
|
+
users_bulk_actions: AsyncUsersBulkActionsApi
|
|
144
|
+
users_stats: AsyncUsersStatsApi
|
|
145
|
+
|
|
146
|
+
def _attach(self, executor: AsyncExecutor) -> None:
|
|
147
|
+
self.api_tokens_management = AsyncApiTokensManagementApi(executor)
|
|
148
|
+
self.auth = AsyncAuthApi(executor)
|
|
149
|
+
self.bandwidth_stats = AsyncBandwidthStatsApi(executor)
|
|
150
|
+
self.config_profiles = AsyncConfigProfilesApi(executor)
|
|
151
|
+
self.hosts = AsyncHostsApi(executor)
|
|
152
|
+
self.hosts_bulk_actions = AsyncHostsBulkActionsApi(executor)
|
|
153
|
+
self.hwid_user_devices = AsyncHwidUserDevicesApi(executor)
|
|
154
|
+
self.infra_billing = AsyncInfraBillingApi(executor)
|
|
155
|
+
self.internal_squads = AsyncInternalSquadsApi(executor)
|
|
156
|
+
self.keygen = AsyncKeygenApi(executor)
|
|
157
|
+
self.nodes = AsyncNodesApi(executor)
|
|
158
|
+
self.subscription = AsyncSubscriptionApi(executor)
|
|
159
|
+
self.subscriptions = AsyncSubscriptionsApi(executor)
|
|
160
|
+
self.subscriptions_settings = AsyncSubscriptionsSettingsApi(executor)
|
|
161
|
+
self.subscriptions_template = AsyncSubscriptionsTemplateApi(executor)
|
|
162
|
+
self.system = AsyncSystemApi(executor)
|
|
163
|
+
self.users = AsyncUsersApi(executor)
|
|
164
|
+
self.users_bulk_actions = AsyncUsersBulkActionsApi(executor)
|
|
165
|
+
self.users_stats = AsyncUsersStatsApi(executor)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @generated by tools/codegen -- do not edit
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @generated by tools/codegen -- do not edit
|
|
2
|
+
"""API Tokens Management."""
|
|
3
|
+
|
|
4
|
+
from remnawave._generated.models import (
|
|
5
|
+
ApiToken,
|
|
6
|
+
CreateApiTokenRequest,
|
|
7
|
+
FindAllApiTokens,
|
|
8
|
+
)
|
|
9
|
+
from remnawave.execution import AsyncGroup, SyncGroup
|
|
10
|
+
from remnawave.operations import (
|
|
11
|
+
Operation,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
CREATE: Operation[ApiToken] = Operation(
|
|
15
|
+
"POST",
|
|
16
|
+
"/api/tokens",
|
|
17
|
+
ApiToken,
|
|
18
|
+
)
|
|
19
|
+
FIND_ALL: Operation[FindAllApiTokens] = Operation(
|
|
20
|
+
"GET",
|
|
21
|
+
"/api/tokens",
|
|
22
|
+
FindAllApiTokens,
|
|
23
|
+
)
|
|
24
|
+
DELETE: Operation[bool] = Operation(
|
|
25
|
+
"DELETE",
|
|
26
|
+
"/api/tokens/{uuid}",
|
|
27
|
+
bool,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ApiTokensManagementApi(SyncGroup):
|
|
32
|
+
def create(self, body: CreateApiTokenRequest) -> ApiToken:
|
|
33
|
+
"""Create a new API token."""
|
|
34
|
+
return self._executor.execute(CREATE, body=body)
|
|
35
|
+
|
|
36
|
+
def find_all(self) -> FindAllApiTokens:
|
|
37
|
+
"""Get all API tokens."""
|
|
38
|
+
return self._executor.execute(FIND_ALL)
|
|
39
|
+
|
|
40
|
+
def delete(self, uuid: str) -> bool:
|
|
41
|
+
"""Delete an API token by UUID."""
|
|
42
|
+
return self._executor.execute(DELETE, path={"uuid": uuid})
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class AsyncApiTokensManagementApi(AsyncGroup):
|
|
46
|
+
async def create(self, body: CreateApiTokenRequest) -> ApiToken:
|
|
47
|
+
"""Create a new API token."""
|
|
48
|
+
return await self._executor.execute(CREATE, body=body)
|
|
49
|
+
|
|
50
|
+
async def find_all(self) -> FindAllApiTokens:
|
|
51
|
+
"""Get all API tokens."""
|
|
52
|
+
return await self._executor.execute(FIND_ALL)
|
|
53
|
+
|
|
54
|
+
async def delete(self, uuid: str) -> bool:
|
|
55
|
+
"""Delete an API token by UUID."""
|
|
56
|
+
return await self._executor.execute(DELETE, path={"uuid": uuid})
|