Skip to content

Commit b249375

Browse files
committed
feat: more api impl
1 parent 35b9bdd commit b249375

5 files changed

Lines changed: 90 additions & 37 deletions

File tree

‎MEFrpLib/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .exceptions import APIError, AuthError, MEFrpError, NetworkError
1212
from .models import *
1313

14-
__version__ = "3.2.0"
14+
__version__ = "3.3.0"
1515
__all__ = [
1616
"MEFrpClient",
1717
"AsyncMEFrpClient",

‎MEFrpLib/client_async.py‎

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import dataclasses
23
from typing import Any, Dict, List, Optional
34

45
import aiohttp
@@ -104,7 +105,7 @@ async def get_statistics(self) -> Statistics:
104105
async def get_popup_notice(self) -> str:
105106
return await self._request("GET", "/auth/popupNotice")
106107

107-
async def get_notice(self) -> List[str]:
108+
async def get_notice(self) -> str:
108109
return await self._request("GET", "/auth/notice")
109110

110111
async def get_system_status(self) -> SystemStatus:
@@ -116,17 +117,17 @@ async def get_user_info(self) -> UserInfo:
116117
data = await self._request("GET", "/auth/user/info")
117118
return UserInfo(**data)
118119

120+
async def get_frp_token(self) -> str:
121+
data = await self._request("GET", "/auth/user/frpToken")
122+
return data.get("token") if isinstance(data, dict) else data
123+
119124
async def sign(self, captcha_token: str):
120125
return await self._request("POST", "/auth/user/sign", {"captchaToken": captcha_token})
121126

122127
async def get_user_groups(self) -> List[UserGroup]:
123128
data = await self._request("GET", "/auth/user/groups")
124129
return [UserGroup(**g) for g in data]
125130

126-
async def get_frp_token(self) -> str:
127-
data = await self._request("GET", "/auth/user/frpToken")
128-
return data.get("frpToken") if isinstance(data, dict) else data
129-
130131
async def reset_token(self, captcha_token: str):
131132
return await self._request("POST", "/auth/user/tokenReset", {"captchaToken": captcha_token})
132133

@@ -170,21 +171,21 @@ async def get_node_list(self) -> List[Node]:
170171
data = await self._request("GET", "/auth/node/list")
171172
return [Node(**n) for n in data]
172173

173-
async def get_node_status(self, node_id: int) -> NodeStatus:
174-
data = await self._request("GET", "/auth/node/status", params={"nodeId": node_id})
175-
return NodeStatus(**data)
176-
177174
async def get_node_name_list(self) -> List[NodeNameListItem]:
178175
data = await self._request("GET", "/auth/node/nameList")
179176
return [NodeNameListItem(**n) for n in data]
180177

178+
async def get_node_status(self) -> List[NodeStatus]:
179+
data = await self._request("GET", "/auth/node/status")
180+
return [NodeStatus(**n) for n in data]
181+
181182
async def get_node_token(self, node_id: int) -> str:
182183
data = await self._request("POST", "/auth/node/secret", {"nodeId": node_id})
183184
return data.get("token") if isinstance(data, dict) else data
184185

185-
async def get_free_port(self, node_id: int, proxy_type: str):
186+
async def get_free_port(self, node_id: int, protocol: str):
186187
return await self._request(
187-
"GET", "/auth/node/freePort", params={"nodeId": node_id, "proxyType": proxy_type}
188+
"POST", "/auth/node/freePort", {"nodeId": node_id, "protocol": protocol}
188189
)
189190

190191
# --- Ads API ---
@@ -240,7 +241,19 @@ async def get_operation_log_stats(self) -> OperationLogStats:
240241

241242
async def get_create_proxy_data(self) -> CreateProxyDataResponse:
242243
data = await self._request("GET", "/auth/createProxyData")
243-
return CreateProxyDataResponse(**data)
244+
nodes = []
245+
# 获取 Node 类定义的字段,用于过滤后端返回的冗余字段
246+
node_fields = {f.name for f in dataclasses.fields(Node)}
247+
for n in data["nodes"]:
248+
load_percent = n.pop("loadPercent", 0)
249+
# 过滤掉不在 Node 定义中的字段
250+
filtered_n = {k: v for k, v in n.items() if k in node_fields}
251+
node_base = Node(**filtered_n)
252+
nodes.append(NodeWithLoad(**node_base.__dict__, loadPercent=load_percent))
253+
groups = [UserGroup(**g) for g in data["groups"]]
254+
return CreateProxyDataResponse(
255+
nodes=nodes, groups=groups, currentGroup=data["currentGroup"]
256+
)
244257

245258
# --- CDK API ---
246259
async def redeem_cdk(self, code: str):

‎MEFrpLib/client_sync.py‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def get_statistics(self) -> Statistics:
7272
def get_popup_notice(self) -> str:
7373
return self._request("GET", "/auth/popupNotice")
7474

75-
def get_notice(self) -> List[str]:
75+
def get_notice(self) -> str:
7676
return self._request("GET", "/auth/notice")
7777

7878
def get_system_status(self) -> SystemStatus:
@@ -86,7 +86,7 @@ def get_user_info(self) -> UserInfo:
8686

8787
def get_frp_token(self) -> str:
8888
data = self._request("GET", "/auth/user/frpToken")
89-
return data.get("frpToken") if isinstance(data, dict) else data
89+
return data.get("token") if isinstance(data, dict) else data
9090

9191
def sign(self, captcha_token: str):
9292
return self._request("POST", "/auth/user/sign", {"captchaToken": captcha_token})
@@ -140,17 +140,17 @@ def get_node_name_list(self) -> List[NodeNameListItem]:
140140
data = self._request("GET", "/auth/node/nameList")
141141
return [NodeNameListItem(**n) for n in data]
142142

143-
def get_node_status(self, node_id: int) -> NodeStatus:
144-
data = self._request("GET", "/auth/node/status", params={"nodeId": node_id})
145-
return NodeStatus(**data)
143+
def get_node_status(self) -> List[NodeStatus]:
144+
data = self._request("GET", "/auth/node/status")
145+
return [NodeStatus(**n) for n in data]
146146

147147
def get_node_token(self, node_id: int) -> str:
148148
data = self._request("POST", "/auth/node/secret", {"nodeId": node_id})
149149
return data.get("token") if isinstance(data, dict) else data
150150

151-
def get_free_port(self, node_id: int, proxy_type: str):
151+
def get_free_port(self, node_id: int, protocol: str):
152152
return self._request(
153-
"GET", "/auth/node/freePort", params={"nodeId": node_id, "proxyType": proxy_type}
153+
"POST", "/auth/node/freePort", {"nodeId": node_id, "protocol": protocol}
154154
)
155155

156156
# --- Ads API ---
@@ -204,7 +204,20 @@ def get_operation_log_stats(self) -> OperationLogStats:
204204

205205
def get_create_proxy_data(self) -> CreateProxyDataResponse:
206206
data = self._request("GET", "/auth/createProxyData")
207-
return CreateProxyDataResponse(**data)
207+
nodes = []
208+
for n in data["nodes"]:
209+
# 移除 NodeWithLoad 中多余的字段,确保能正确解包到 Node 基类
210+
load_percent = n.pop("loadPercent", 0)
211+
# 过滤掉 Node 类不接受的字段
212+
import dataclasses
213+
node_fields = {f.name for f in dataclasses.fields(Node)}
214+
filtered_n = {k: v for k, v in n.items() if k in node_fields}
215+
node_base = Node(**filtered_n)
216+
nodes.append(NodeWithLoad(**node_base.__dict__, loadPercent=load_percent))
217+
groups = [UserGroup(**g) for g in data["groups"]]
218+
return CreateProxyDataResponse(
219+
nodes=nodes, groups=groups, currentGroup=data["currentGroup"]
220+
)
208221

209222
# --- CDK API ---
210223
def redeem_cdk(self, code: str):

‎MEFrpLib/models.py‎

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class UserInfo:
1818
inBound: int
1919
outBound: int
2020
todaySigned: bool
21+
banReason: Optional[str] = None
22+
realnameTimes: int = 0
2123
vipExpireTime: Optional[int] = None
2224

2325

@@ -59,7 +61,6 @@ class Proxy:
5961
httpUser: str
6062
httpPassword: str
6163
transportProtocol: str
62-
tags: str
6364

6465

6566
@dataclass
@@ -75,19 +76,6 @@ class ProxyListResponse:
7576
nodes: List[NodeConnection]
7677

7778

78-
@dataclass
79-
class CreateProxyDataResponse:
80-
nodes: List[Dict]
81-
groups: List["UserGroup"]
82-
currentGroup: str
83-
84-
85-
@dataclass
86-
class ProxyConfigResponse:
87-
config: str
88-
type: str
89-
90-
9179
@dataclass
9280
class Node:
9381
nodeId: int
@@ -109,6 +97,26 @@ class Node:
10997
totalTrafficOut: int
11098
upTime: int
11199
version: str
100+
donateId: int = 0
101+
donateUser: str = ""
102+
103+
104+
@dataclass
105+
class NodeWithLoad(Node):
106+
loadPercent: int = 0
107+
108+
109+
@dataclass
110+
class CreateProxyDataResponse:
111+
nodes: List[NodeWithLoad]
112+
groups: List["UserGroup"]
113+
currentGroup: str
114+
115+
116+
@dataclass
117+
class ProxyConfigResponse:
118+
config: str
119+
type: str
112120

113121

114122
@dataclass
@@ -305,3 +313,22 @@ class NodeNameListItem:
305313
nodeId: int
306314
name: str
307315
hostname: str
316+
317+
318+
@dataclass
319+
class Product:
320+
productId: str
321+
system: str
322+
arch: str
323+
name: str
324+
desc: str
325+
path: str
326+
version: str
327+
isPublic: bool
328+
329+
330+
@dataclass
331+
class DownloadSource:
332+
id: int
333+
path: str
334+
name: str

‎pyproject.toml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ Documentation = "https://github.com/MagicEdgeNet/ME-Frp-v5-PythonSdk#readme"
4141
Repository = "https://github.com/MagicEdgeNet/ME-Frp-v5-PythonSdk.git"
4242
Issues = "https://github.com/MagicEdgeNet/ME-Frp-v5-PythonSdk/issues"
4343

44-
[tool.setuptools.dynamic]
45-
version = { attr = "MEFrpLib.__version__" }
44+
[tool.hatch.version]
45+
path = "MEFrpLib/__init__.py"
4646

4747
[tool.hatch.build.targets.wheel]
4848
packages = ["MEFrpLib"]

0 commit comments

Comments
 (0)