marzban 0.1.8__tar.gz → 0.1.10__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.
- {marzban-0.1.8 → marzban-0.1.10}/PKG-INFO +1 -1
- {marzban-0.1.8 → marzban-0.1.10}/marzban/__init__.py +1 -1
- {marzban-0.1.8 → marzban-0.1.10}/marzban/api.py +50 -79
- {marzban-0.1.8 → marzban-0.1.10}/marzban/models.py +5 -5
- {marzban-0.1.8 → marzban-0.1.10}/marzban.egg-info/PKG-INFO +1 -1
- {marzban-0.1.8 → marzban-0.1.10}/setup.py +1 -1
- {marzban-0.1.8 → marzban-0.1.10}/LICENSE +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/README.md +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/marzban.egg-info/SOURCES.txt +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/marzban.egg-info/dependency_links.txt +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/marzban.egg-info/requires.txt +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/marzban.egg-info/top_level.txt +0 -0
- {marzban-0.1.8 → marzban-0.1.10}/setup.cfg +0 -0
@@ -1,5 +1,6 @@
|
|
1
1
|
import httpx
|
2
2
|
from typing import Any, Dict, Optional, List
|
3
|
+
from pydantic import BaseModel
|
3
4
|
from .models import *
|
4
5
|
|
5
6
|
class MarzbanAPI:
|
@@ -10,6 +11,14 @@ class MarzbanAPI:
|
|
10
11
|
def _get_headers(self, token: str) -> Dict[str, str]:
|
11
12
|
return {"Authorization": f"Bearer {token}"}
|
12
13
|
|
14
|
+
async def _request(self, method: str, url: str, token: Optional[str] = None, data: Optional[BaseModel] = None, params: Optional[Dict[str, Any]] = None) -> httpx.Response:
|
15
|
+
headers = self._get_headers(token) if token else {}
|
16
|
+
json_data = data.model_dump(exclude_none=True) if data else None
|
17
|
+
|
18
|
+
response = await self.client.request(method, url, headers=headers, json=json_data, params=params)
|
19
|
+
response.raise_for_status()
|
20
|
+
return response
|
21
|
+
|
13
22
|
async def get_token(self, username: str, password: str) -> Token:
|
14
23
|
url = "/api/admin/token"
|
15
24
|
payload = {
|
@@ -26,231 +35,193 @@ class MarzbanAPI:
|
|
26
35
|
|
27
36
|
async def get_current_admin(self, token: str) -> Admin:
|
28
37
|
url = "/api/admin"
|
29
|
-
response = await self.
|
30
|
-
response.raise_for_status()
|
38
|
+
response = await self._request("GET", url, token)
|
31
39
|
return Admin(**response.json())
|
32
40
|
|
33
41
|
async def create_admin(self, admin: AdminCreate, token: str) -> Admin:
|
34
42
|
url = "/api/admin"
|
35
|
-
response = await self.
|
36
|
-
response.raise_for_status()
|
43
|
+
response = await self._request("POST", url, token, data=admin)
|
37
44
|
return Admin(**response.json())
|
38
45
|
|
39
46
|
async def modify_admin(self, username: str, admin: AdminModify, token: str) -> Admin:
|
40
47
|
url = f"/api/admin/{username}"
|
41
|
-
response = await self.
|
42
|
-
response.raise_for_status()
|
48
|
+
response = await self._request("PUT", url, token, data=admin)
|
43
49
|
return Admin(**response.json())
|
44
50
|
|
45
51
|
async def remove_admin(self, username: str, token: str) -> None:
|
46
52
|
url = f"/api/admin/{username}"
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
await self._request("DELETE", url, token)
|
54
|
+
|
50
55
|
async def get_admins(self, token: str, offset: Optional[int] = None, limit: Optional[int] = None, username: Optional[str] = None) -> List[Admin]:
|
51
56
|
url = "/api/admins"
|
52
57
|
params = {"offset": offset, "limit": limit, "username": username}
|
53
|
-
response = await self.
|
54
|
-
response.raise_for_status()
|
58
|
+
response = await self._request("GET", url, token, params=params)
|
55
59
|
return [Admin(**admin) for admin in response.json()]
|
56
60
|
|
57
61
|
async def get_system_stats(self, token: str) -> SystemStats:
|
58
62
|
url = "/api/system"
|
59
|
-
response = await self.
|
60
|
-
response.raise_for_status()
|
63
|
+
response = await self._request("GET", url, token)
|
61
64
|
return SystemStats(**response.json())
|
62
65
|
|
63
66
|
async def get_inbounds(self, token: str) -> Dict[str, List[ProxyInbound]]:
|
64
67
|
url = "/api/inbounds"
|
65
|
-
response = await self.
|
66
|
-
response.raise_for_status()
|
68
|
+
response = await self._request("GET", url, token)
|
67
69
|
return response.json()
|
68
70
|
|
69
|
-
async def get_hosts(self, token: str) -> Dict
|
71
|
+
async def get_hosts(self, token: str) -> Dict[str, List[ProxyHost]]:
|
70
72
|
url = "/api/hosts"
|
71
|
-
response = await self.
|
72
|
-
response.raise_for_status()
|
73
|
+
response = await self._request("GET", url, token)
|
73
74
|
return response.json()
|
74
75
|
|
75
76
|
async def modify_hosts(self, hosts: Dict[str, List[ProxyHost]], token: str) -> Dict[str, List[ProxyHost]]:
|
76
77
|
url = "/api/hosts"
|
77
|
-
response = await self.
|
78
|
-
response.raise_for_status()
|
78
|
+
response = await self._request("PUT", url, token, data=hosts)
|
79
79
|
return response.json()
|
80
80
|
|
81
81
|
async def get_core_stats(self, token: str) -> CoreStats:
|
82
82
|
url = "/api/core"
|
83
|
-
response = await self.
|
84
|
-
response.raise_for_status()
|
83
|
+
response = await self._request("GET", url, token)
|
85
84
|
return CoreStats(**response.json())
|
86
85
|
|
87
86
|
async def restart_core(self, token: str) -> None:
|
88
87
|
url = "/api/core/restart"
|
89
|
-
|
90
|
-
response.raise_for_status()
|
88
|
+
await self._request("POST", url, token)
|
91
89
|
|
92
90
|
async def get_core_config(self, token: str) -> Dict[str, Any]:
|
93
91
|
url = "/api/core/config"
|
94
|
-
response = await self.
|
95
|
-
response.raise_for_status()
|
92
|
+
response = await self._request("GET", url, token)
|
96
93
|
return response.json()
|
97
94
|
|
98
95
|
async def modify_core_config(self, config: Dict[str, Any], token: str) -> Dict[str, Any]:
|
99
96
|
url = "/api/core/config"
|
100
|
-
response = await self.
|
101
|
-
response.raise_for_status()
|
97
|
+
response = await self._request("PUT", url, token, data=config)
|
102
98
|
return response.json()
|
103
99
|
|
104
100
|
async def add_user(self, user: UserCreate, token: str) -> UserResponse:
|
105
101
|
url = "/api/user"
|
106
|
-
response = await self.
|
107
|
-
response.raise_for_status()
|
102
|
+
response = await self._request("POST", url, token, data=user)
|
108
103
|
return UserResponse(**response.json())
|
109
104
|
|
110
105
|
async def get_user(self, username: str, token: str) -> UserResponse:
|
111
106
|
url = f"/api/user/{username}"
|
112
|
-
response = await self.
|
113
|
-
response.raise_for_status()
|
107
|
+
response = await self._request("GET", url, token)
|
114
108
|
return UserResponse(**response.json())
|
115
109
|
|
116
110
|
async def modify_user(self, username: str, user: UserModify, token: str) -> UserResponse:
|
117
111
|
url = f"/api/user/{username}"
|
118
|
-
response = await self.
|
119
|
-
response.raise_for_status()
|
112
|
+
response = await self._request("PUT", url, token, data=user)
|
120
113
|
return UserResponse(**response.json())
|
121
114
|
|
122
115
|
async def remove_user(self, username: str, token: str) -> None:
|
123
116
|
url = f"/api/user/{username}"
|
124
|
-
|
125
|
-
response.raise_for_status()
|
117
|
+
await self._request("DELETE", url, token)
|
126
118
|
|
127
119
|
async def reset_user_data_usage(self, username: str, token: str) -> UserResponse:
|
128
120
|
url = f"/api/user/{username}/reset"
|
129
|
-
response = await self.
|
130
|
-
response.raise_for_status()
|
121
|
+
response = await self._request("POST", url, token)
|
131
122
|
return UserResponse(**response.json())
|
132
123
|
|
133
124
|
async def revoke_user_subscription(self, username: str, token: str) -> UserResponse:
|
134
125
|
url = f"/api/user/{username}/revoke_sub"
|
135
|
-
response = await self.
|
136
|
-
response.raise_for_status()
|
126
|
+
response = await self._request("POST", url, token)
|
137
127
|
return UserResponse(**response.json())
|
138
128
|
|
139
129
|
async def get_users(self, token: str, offset: Optional[int] = None, limit: Optional[int] = None, username: Optional[List[str]] = None, status: Optional[str] = None, sort: Optional[str] = None) -> UsersResponse:
|
140
130
|
url = "/api/users"
|
141
131
|
params = {"offset": offset, "limit": limit, "username": username, "status": status, "sort": sort}
|
142
|
-
response = await self.
|
143
|
-
response.raise_for_status()
|
132
|
+
response = await self._request("GET", url, token, params=params)
|
144
133
|
return UsersResponse(**response.json())
|
145
134
|
|
146
135
|
async def reset_users_data_usage(self, token: str) -> None:
|
147
136
|
url = "/api/users/reset"
|
148
|
-
|
149
|
-
response.raise_for_status()
|
137
|
+
await self._request("POST", url, token)
|
150
138
|
|
151
139
|
async def get_user_usage(self, username: str, token: str, start: Optional[str] = None, end: Optional[str] = None) -> UserUsagesResponse:
|
152
140
|
url = f"/api/user/{username}/usage"
|
153
141
|
params = {"start": start, "end": end}
|
154
|
-
response = await self.
|
155
|
-
response.raise_for_status()
|
142
|
+
response = await self._request("GET", url, token, params=params)
|
156
143
|
return UserUsagesResponse(**response.json())
|
157
144
|
|
158
145
|
async def set_owner(self, username: str, admin_username: str, token: str) -> UserResponse:
|
159
146
|
url = f"/api/user/{username}/set-owner"
|
160
147
|
params = {"admin_username": admin_username}
|
161
|
-
response = await self.
|
162
|
-
response.raise_for_status()
|
148
|
+
response = await self._request("PUT", url, token, params=params)
|
163
149
|
return UserResponse(**response.json())
|
164
150
|
|
165
151
|
async def get_expired_users(self, token: str, expired_before: Optional[str] = None, expired_after: Optional[str] = None) -> List[str]:
|
166
152
|
url = "/api/users/expired"
|
167
153
|
params = {"expired_before": expired_before, "expired_after": expired_after}
|
168
|
-
response = await self.
|
169
|
-
response.raise_for_status()
|
154
|
+
response = await self._request("GET", url, token, params=params)
|
170
155
|
return response.json()
|
171
156
|
|
172
157
|
async def delete_expired_users(self, token: str, expired_before: Optional[str] = None, expired_after: Optional[str] = None) -> List[str]:
|
173
158
|
url = "/api/users/expired"
|
174
159
|
params = {"expired_before": expired_before, "expired_after": expired_after}
|
175
|
-
response = await self.
|
176
|
-
response.raise_for_status()
|
160
|
+
response = await self._request("DELETE", url, token, params=params)
|
177
161
|
return response.json()
|
178
162
|
|
179
163
|
async def get_user_templates(self, token: str, offset: Optional[int] = None, limit: Optional[int] = None) -> List[UserTemplateResponse]:
|
180
164
|
url = "/api/user_template"
|
181
165
|
params = {"offset": offset, "limit": limit}
|
182
|
-
response = await self.
|
183
|
-
response.raise_for_status()
|
166
|
+
response = await self._request("GET", url, token, params=params)
|
184
167
|
return [UserTemplateResponse(**template) for template in response.json()]
|
185
168
|
|
186
169
|
async def add_user_template(self, template: UserTemplateCreate, token: str) -> UserTemplateResponse:
|
187
170
|
url = "/api/user_template"
|
188
|
-
response = await self.
|
189
|
-
response.raise_for_status()
|
171
|
+
response = await self._request("POST", url, token, data=template)
|
190
172
|
return UserTemplateResponse(**response.json())
|
191
173
|
|
192
174
|
async def get_user_template(self, template_id: int, token: str) -> UserTemplateResponse:
|
193
175
|
url = f"/api/user_template/{template_id}"
|
194
|
-
response = await self.
|
195
|
-
response.raise_for_status()
|
176
|
+
response = await self._request("GET", url, token)
|
196
177
|
return UserTemplateResponse(**response.json())
|
197
178
|
|
198
179
|
async def modify_user_template(self, template_id: int, template: UserTemplateModify, token: str) -> UserTemplateResponse:
|
199
180
|
url = f"/api/user_template/{template_id}"
|
200
|
-
response = await self.
|
201
|
-
response.raise_for_status()
|
181
|
+
response = await self._request("PUT", url, token, data=template)
|
202
182
|
return UserTemplateResponse(**response.json())
|
203
|
-
|
183
|
+
|
204
184
|
async def remove_user_template(self, template_id: int, token: str) -> None:
|
205
185
|
url = f"/api/user_template/{template_id}"
|
206
|
-
|
207
|
-
response.raise_for_status()
|
186
|
+
await self._request("DELETE", url, token)
|
208
187
|
|
209
188
|
async def get_node_settings(self, token: str) -> Dict[str, Any]:
|
210
189
|
url = "/api/node/settings"
|
211
|
-
response = await self.
|
212
|
-
response.raise_for_status()
|
190
|
+
response = await self._request("GET", url, token)
|
213
191
|
return response.json()
|
214
192
|
|
215
193
|
async def add_node(self, node: NodeCreate, token: str) -> NodeResponse:
|
216
194
|
url = "/api/node"
|
217
|
-
response = await self.
|
218
|
-
response.raise_for_status()
|
195
|
+
response = await self._request("POST", url, token, data=node)
|
219
196
|
return NodeResponse(**response.json())
|
220
197
|
|
221
198
|
async def get_node(self, node_id: int, token: str) -> NodeResponse:
|
222
199
|
url = f"/api/node/{node_id}"
|
223
|
-
response = await self.
|
224
|
-
response.raise_for_status()
|
200
|
+
response = await self._request("GET", url, token)
|
225
201
|
return NodeResponse(**response.json())
|
226
202
|
|
227
203
|
async def modify_node(self, node_id: int, node: NodeModify, token: str) -> NodeResponse:
|
228
204
|
url = f"/api/node/{node_id}"
|
229
|
-
response = await self.
|
230
|
-
response.raise_for_status()
|
205
|
+
response = await self._request("PUT", url, token, data=node)
|
231
206
|
return NodeResponse(**response.json())
|
232
207
|
|
233
208
|
async def remove_node(self, node_id: int, token: str) -> None:
|
234
209
|
url = f"/api/node/{node_id}"
|
235
|
-
|
236
|
-
response.raise_for_status()
|
210
|
+
await self._request("DELETE", url, token)
|
237
211
|
|
238
212
|
async def reconnect_node(self, node_id: int, token: str) -> None:
|
239
213
|
url = f"/api/node/{node_id}/reconnect"
|
240
|
-
|
241
|
-
response.raise_for_status()
|
214
|
+
await self._request("POST", url, token)
|
242
215
|
|
243
216
|
async def get_nodes(self, token: str) -> List[NodeResponse]:
|
244
217
|
url = "/api/nodes"
|
245
|
-
response = await self.
|
246
|
-
response.raise_for_status()
|
218
|
+
response = await self._request("GET", url, token)
|
247
219
|
return [NodeResponse(**node) for node in response.json()]
|
248
220
|
|
249
221
|
async def get_usage(self, token: str, start: Optional[str] = None, end: Optional[str] = None) -> NodesUsageResponse:
|
250
222
|
url = "/api/nodes/usage"
|
251
223
|
params = {"start": start, "end": end}
|
252
|
-
response = await self.
|
253
|
-
response.raise_for_status()
|
224
|
+
response = await self._request("GET", url, token, params=params)
|
254
225
|
return NodesUsageResponse(**response.json())
|
255
226
|
|
256
227
|
async def close(self):
|
@@ -139,17 +139,17 @@ class CoreStats(BaseModel):
|
|
139
139
|
|
140
140
|
class UserModify(BaseModel):
|
141
141
|
proxies: Optional[Dict[str, ProxySettings]] = {}
|
142
|
-
expire: Optional[int] =
|
143
|
-
data_limit: Optional[int] =
|
144
|
-
data_limit_reset_strategy: Optional[str] =
|
142
|
+
expire: Optional[int] = None
|
143
|
+
data_limit: Optional[int] = None
|
144
|
+
data_limit_reset_strategy: Optional[str] = None
|
145
145
|
inbounds: Optional[Dict[str, List[str]]] = {}
|
146
146
|
note: Optional[str] = None
|
147
147
|
sub_updated_at: Optional[str] = None
|
148
148
|
sub_last_user_agent: Optional[str] = None
|
149
149
|
online_at: Optional[str] = None
|
150
|
-
on_hold_expire_duration: Optional[int] =
|
150
|
+
on_hold_expire_duration: Optional[int] = None
|
151
151
|
on_hold_timeout: Optional[str] = None
|
152
|
-
status: Optional[str] =
|
152
|
+
status: Optional[str] = None
|
153
153
|
|
154
154
|
class UserTemplateCreate(BaseModel):
|
155
155
|
name: Optional[str]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|