marzban 0.1.8__tar.gz → 0.1.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: marzban
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: Асинхронная библиотека Python для взаимодействия с MarzbanAPI
5
5
  Home-page: https://github.com/sm1ky/marzban_api
6
6
  Author: Artem
@@ -1,4 +1,4 @@
1
1
  from .api import MarzbanAPI
2
2
  from .models import *
3
3
 
4
- __version__ = "0.1.8"
4
+ __version__ = "0.1.9"
@@ -1,6 +1,7 @@
1
1
  import httpx
2
2
  from typing import Any, Dict, Optional, List
3
- from .models import *
3
+ from pydantic import BaseModel
4
+ from models import *
4
5
 
5
6
  class MarzbanAPI:
6
7
  def __init__(self, base_url: str):
@@ -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.client.get(url, headers=self._get_headers(token))
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.client.post(url, json=admin.dict(), headers=self._get_headers(token))
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.client.put(url, json=admin.dict(), headers=self._get_headers(token))
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
- response = await self.client.delete(url, headers=self._get_headers(token))
48
- response.raise_for_status()
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.client.get(url, headers=self._get_headers(token), params=params)
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.client.get(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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 [str, List[ProxyHost]]:
71
+ async def get_hosts(self, token: str) -> Dict[str, List[ProxyHost]]:
70
72
  url = "/api/hosts"
71
- response = await self.client.get(url, headers=self._get_headers(token))
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.client.put(url, json=hosts, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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
- response = await self.client.post(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.put(url, json=config, headers=self._get_headers(token))
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.client.post(url, json=user.dict(), headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.put(url, json=user.dict(), headers=self._get_headers(token))
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
- response = await self.client.delete(url, headers=self._get_headers(token))
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.client.post(url, headers=self._get_headers(token))
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.client.post(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token), params=params)
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
- response = await self.client.post(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token), params=params)
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.client.put(url, headers=self._get_headers(token), params=params)
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.client.get(url, headers=self._get_headers(token), params=params)
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.client.delete(url, headers=self._get_headers(token), params=params)
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.client.get(url, headers=self._get_headers(token), params=params)
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.client.post(url, json=template.dict(), headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.put(url, json=template.dict(), headers=self._get_headers(token))
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
- response = await self.client.delete(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.post(url, json=node.dict(), headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.put(url, json=node.dict(), headers=self._get_headers(token))
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
- response = await self.client.delete(url, headers=self._get_headers(token))
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
- response = await self.client.post(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token))
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.client.get(url, headers=self._get_headers(token), params=params)
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] = 0
143
- data_limit: Optional[int] = 0
144
- data_limit_reset_strategy: Optional[str] = "no_reset"
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] = 0
150
+ on_hold_expire_duration: Optional[int] = None
151
151
  on_hold_timeout: Optional[str] = None
152
- status: Optional[str] = "active"
152
+ status: Optional[str] = None
153
153
 
154
154
  class UserTemplateCreate(BaseModel):
155
155
  name: Optional[str]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: marzban
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: Асинхронная библиотека Python для взаимодействия с MarzbanAPI
5
5
  Home-page: https://github.com/sm1ky/marzban_api
6
6
  Author: Artem
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="marzban",
8
- version="0.1.8",
8
+ version="0.1.9",
9
9
  packages=find_packages(),
10
10
  install_requires=[
11
11
  "httpx>=0.23.0",
File without changes
File without changes
File without changes