pixelarraythirdparty 1.2.8__tar.gz → 1.3.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.
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/PKG-INFO +1 -1
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/__init__.py +5 -1
- pixelarraythirdparty-1.3.0/pixelarraythirdparty/custom_events/__init__.py +3 -0
- pixelarraythirdparty-1.3.0/pixelarraythirdparty/custom_events/custom_events.py +52 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/unified_login/unified_login.py +163 -41
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/PKG-INFO +1 -1
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/SOURCES.txt +2 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pyproject.toml +1 -1
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/LICENSE +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/MANIFEST.in +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/client.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/cron/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/cron/cron.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/feedback.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/order.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/product.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/project.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/support_chat/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/support_chat/support_chat.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/unified_login/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/user/__init__.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/user/user.py +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/dependency_links.txt +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/requires.txt +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/top_level.txt +0 -0
- {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/setup.cfg +0 -0
|
@@ -12,11 +12,13 @@ PixelArray 第三方微服务客户端
|
|
|
12
12
|
- feedback: 客户反馈模块
|
|
13
13
|
- project: 项目管理模块
|
|
14
14
|
- support_chat: 在线客服(临时会话链接)
|
|
15
|
+
- custom_events: 自定义事件上报(需在 Portal 配置事件定义)
|
|
15
16
|
"""
|
|
16
17
|
|
|
17
18
|
from .support_chat.support_chat import SupportChatManagerAsync
|
|
19
|
+
from .custom_events.custom_events import CustomEventsManagerAsync
|
|
18
20
|
|
|
19
|
-
__version__ = "1.
|
|
21
|
+
__version__ = "1.3.0"
|
|
20
22
|
__author__ = "Lu qi"
|
|
21
23
|
__email__ = "qi.lu@pixelarrayai.com"
|
|
22
24
|
|
|
@@ -29,5 +31,7 @@ __all__ = [
|
|
|
29
31
|
"feedback",
|
|
30
32
|
"project",
|
|
31
33
|
"support_chat",
|
|
34
|
+
"custom_events",
|
|
32
35
|
"SupportChatManagerAsync",
|
|
36
|
+
"CustomEventsManagerAsync",
|
|
33
37
|
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from pixelarraythirdparty.client import AsyncClient
|
|
2
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CustomEventsManagerAsync(AsyncClient):
|
|
6
|
+
"""自定义事件上报(需先在 Portal 配置事件定义与字段 schema)。"""
|
|
7
|
+
|
|
8
|
+
async def report_custom_event(
|
|
9
|
+
self,
|
|
10
|
+
project_id: int,
|
|
11
|
+
event_key: str,
|
|
12
|
+
payload: Dict[str, Any],
|
|
13
|
+
client_occurred_at: Optional[str] = None,
|
|
14
|
+
) -> Tuple[Dict[str, Any], bool]:
|
|
15
|
+
"""
|
|
16
|
+
description:
|
|
17
|
+
上报单条自定义事件日志(JSON 载荷须符合 Portal 中配置的 field_schema)
|
|
18
|
+
parameters:
|
|
19
|
+
project_id(int): 项目 ID
|
|
20
|
+
event_key(str): 事件键
|
|
21
|
+
payload(dict): JSON 对象,键与类型须与定义一致
|
|
22
|
+
client_occurred_at(str, optional): 客户端事件发生时间,ISO8601 字符串
|
|
23
|
+
return:
|
|
24
|
+
data(dict): 成功时为日志记录;失败时含 message 等
|
|
25
|
+
success(bool): 是否成功
|
|
26
|
+
"""
|
|
27
|
+
data: Dict[str, Any] = {
|
|
28
|
+
"project_id": project_id,
|
|
29
|
+
"event_key": event_key,
|
|
30
|
+
"payload": payload,
|
|
31
|
+
}
|
|
32
|
+
if client_occurred_at is not None:
|
|
33
|
+
data["client_occurred_at"] = client_occurred_at
|
|
34
|
+
return await self._request("POST", "/api/custom-events/report", json=data)
|
|
35
|
+
|
|
36
|
+
async def report_custom_events_batch(
|
|
37
|
+
self,
|
|
38
|
+
project_id: int,
|
|
39
|
+
items: List[Dict[str, Any]],
|
|
40
|
+
) -> Tuple[Dict[str, Any], bool]:
|
|
41
|
+
"""
|
|
42
|
+
description:
|
|
43
|
+
批量上报自定义事件(同一 project_id;任一条校验失败则整批失败)
|
|
44
|
+
parameters:
|
|
45
|
+
project_id(int): 项目 ID
|
|
46
|
+
items(list): 每项为 dict,须含 event_key、payload;可选 client_occurred_at(字符串)
|
|
47
|
+
return:
|
|
48
|
+
data(dict): 成功时为日志列表;失败时含 message
|
|
49
|
+
success(bool): 是否成功
|
|
50
|
+
"""
|
|
51
|
+
body = {"project_id": project_id, "items": items}
|
|
52
|
+
return await self._request("POST", "/api/custom-events/report/batch", json=body)
|
|
@@ -6,6 +6,20 @@ from typing import Any, Dict, Optional, Tuple
|
|
|
6
6
|
from pixelarraythirdparty.client import AsyncClient
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _normalized_project_name(project_name: Optional[str]) -> Optional[str]:
|
|
10
|
+
if project_name is None:
|
|
11
|
+
return None
|
|
12
|
+
s = str(project_name).strip()
|
|
13
|
+
return s or None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _auth_url_json(project_name: Optional[str]) -> Optional[Dict[str, Any]]:
|
|
17
|
+
s = _normalized_project_name(project_name)
|
|
18
|
+
if s is None:
|
|
19
|
+
return None
|
|
20
|
+
return {"project_name": s}
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
class OAuth2Login(AsyncClient):
|
|
10
24
|
"""
|
|
11
25
|
统一的 OAuth2 登录客户端基类
|
|
@@ -66,7 +80,13 @@ class OAuth2Login(AsyncClient):
|
|
|
66
80
|
},
|
|
67
81
|
}
|
|
68
82
|
|
|
69
|
-
def __init__(
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
api_key: str,
|
|
86
|
+
provider: str,
|
|
87
|
+
login_type: Optional[str] = None,
|
|
88
|
+
project_name: Optional[str] = None,
|
|
89
|
+
):
|
|
70
90
|
"""
|
|
71
91
|
description:
|
|
72
92
|
初始化OAuth2登录客户端
|
|
@@ -74,10 +94,12 @@ class OAuth2Login(AsyncClient):
|
|
|
74
94
|
api_key(str): API密钥
|
|
75
95
|
provider(str): 提供商名称,可选值:google, wechat, github, gitlab, douyin, tiktok
|
|
76
96
|
login_type(str, optional): 登录类型,仅对微信有效,可选值:desktop(PC端扫码), mobile(手机端)
|
|
97
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
77
98
|
"""
|
|
78
99
|
super().__init__(api_key)
|
|
79
100
|
self.provider = provider.lower()
|
|
80
101
|
self.login_type = login_type
|
|
102
|
+
self._project_name = project_name
|
|
81
103
|
|
|
82
104
|
# 验证提供商是否支持
|
|
83
105
|
if self.provider not in self.PROVIDER_ENDPOINTS:
|
|
@@ -118,7 +140,11 @@ class OAuth2Login(AsyncClient):
|
|
|
118
140
|
success(bool): 是否成功
|
|
119
141
|
"""
|
|
120
142
|
endpoint = self._get_endpoint("auth_url")
|
|
121
|
-
|
|
143
|
+
payload = _auth_url_json(self._project_name)
|
|
144
|
+
if payload:
|
|
145
|
+
data, success = await self._request("POST", endpoint, json=payload)
|
|
146
|
+
else:
|
|
147
|
+
data, success = await self._request("POST", endpoint)
|
|
122
148
|
if not success:
|
|
123
149
|
return data, False
|
|
124
150
|
auth_url = data.get("auth_url")
|
|
@@ -215,20 +241,30 @@ class GoogleLogin(AsyncClient):
|
|
|
215
241
|
def __init__(self, api_key: str):
|
|
216
242
|
super().__init__(api_key)
|
|
217
243
|
|
|
218
|
-
async def get_auth_url(
|
|
244
|
+
async def get_auth_url(
|
|
245
|
+
self, project_name: Optional[str] = None
|
|
246
|
+
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
219
247
|
"""
|
|
220
248
|
description:
|
|
221
249
|
获取Google OAuth授权URL(公共方法,供服务端调用)
|
|
222
250
|
|
|
223
251
|
服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
|
|
224
252
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
253
|
+
parameters:
|
|
254
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
225
255
|
return:
|
|
226
256
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
227
257
|
success(bool): 是否成功
|
|
228
258
|
"""
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
259
|
+
payload = _auth_url_json(project_name)
|
|
260
|
+
if payload:
|
|
261
|
+
data, success = await self._request(
|
|
262
|
+
"POST", "/api/unified-login/google/auth-url", json=payload
|
|
263
|
+
)
|
|
264
|
+
else:
|
|
265
|
+
data, success = await self._request(
|
|
266
|
+
"POST", "/api/unified-login/google/auth-url"
|
|
267
|
+
)
|
|
232
268
|
if not success:
|
|
233
269
|
return data, False
|
|
234
270
|
auth_url = data.get("auth_url")
|
|
@@ -328,7 +364,7 @@ class WechatLogin(AsyncClient):
|
|
|
328
364
|
super().__init__(api_key)
|
|
329
365
|
|
|
330
366
|
async def get_auth_url(
|
|
331
|
-
self, login_type: str = "desktop"
|
|
367
|
+
self, login_type: str = "desktop", project_name: Optional[str] = None
|
|
332
368
|
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
333
369
|
"""
|
|
334
370
|
description:
|
|
@@ -338,6 +374,7 @@ class WechatLogin(AsyncClient):
|
|
|
338
374
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
339
375
|
parameters:
|
|
340
376
|
login_type(str, optional): 登录类型,desktop表示PC端扫码登录,mobile表示微信公众号登录,默认为desktop
|
|
377
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
341
378
|
return:
|
|
342
379
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
343
380
|
success(bool): 是否成功
|
|
@@ -349,7 +386,11 @@ class WechatLogin(AsyncClient):
|
|
|
349
386
|
# PC端扫码登录
|
|
350
387
|
endpoint = "/api/unified-login/wechat/auth-url"
|
|
351
388
|
|
|
352
|
-
|
|
389
|
+
payload = _auth_url_json(project_name)
|
|
390
|
+
if payload:
|
|
391
|
+
data, success = await self._request("POST", endpoint, json=payload)
|
|
392
|
+
else:
|
|
393
|
+
data, success = await self._request("POST", endpoint)
|
|
353
394
|
if not success:
|
|
354
395
|
return data, False
|
|
355
396
|
auth_url = data.get("auth_url")
|
|
@@ -424,20 +465,30 @@ class GitHubLogin(AsyncClient):
|
|
|
424
465
|
def __init__(self, api_key: str):
|
|
425
466
|
super().__init__(api_key)
|
|
426
467
|
|
|
427
|
-
async def get_auth_url(
|
|
468
|
+
async def get_auth_url(
|
|
469
|
+
self, project_name: Optional[str] = None
|
|
470
|
+
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
428
471
|
"""
|
|
429
472
|
description:
|
|
430
473
|
获取GitHub OAuth授权URL(公共方法,供服务端调用)
|
|
431
474
|
|
|
432
475
|
服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
|
|
433
476
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
477
|
+
parameters:
|
|
478
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
434
479
|
return:
|
|
435
480
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
436
481
|
success(bool): 是否成功
|
|
437
482
|
"""
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
483
|
+
payload = _auth_url_json(project_name)
|
|
484
|
+
if payload:
|
|
485
|
+
data, success = await self._request(
|
|
486
|
+
"POST", "/api/unified-login/github/auth-url", json=payload
|
|
487
|
+
)
|
|
488
|
+
else:
|
|
489
|
+
data, success = await self._request(
|
|
490
|
+
"POST", "/api/unified-login/github/auth-url"
|
|
491
|
+
)
|
|
441
492
|
if not success:
|
|
442
493
|
return data, False
|
|
443
494
|
auth_url = data.get("auth_url")
|
|
@@ -503,20 +554,30 @@ class DouyinLogin(AsyncClient):
|
|
|
503
554
|
def __init__(self, api_key: str):
|
|
504
555
|
super().__init__(api_key)
|
|
505
556
|
|
|
506
|
-
async def get_auth_url(
|
|
557
|
+
async def get_auth_url(
|
|
558
|
+
self, project_name: Optional[str] = None
|
|
559
|
+
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
507
560
|
"""
|
|
508
561
|
description:
|
|
509
562
|
获取抖音OAuth授权URL(公共方法,供服务端调用)
|
|
510
563
|
|
|
511
564
|
服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
|
|
512
565
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
566
|
+
parameters:
|
|
567
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
513
568
|
return:
|
|
514
569
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
515
570
|
success(bool): 是否成功
|
|
516
571
|
"""
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
572
|
+
payload = _auth_url_json(project_name)
|
|
573
|
+
if payload:
|
|
574
|
+
data, success = await self._request(
|
|
575
|
+
"POST", "/api/unified-login/douyin/auth-url", json=payload
|
|
576
|
+
)
|
|
577
|
+
else:
|
|
578
|
+
data, success = await self._request(
|
|
579
|
+
"POST", "/api/unified-login/douyin/auth-url"
|
|
580
|
+
)
|
|
520
581
|
if not success:
|
|
521
582
|
return data, False
|
|
522
583
|
auth_url = data.get("auth_url")
|
|
@@ -582,20 +643,30 @@ class TiktokLogin(AsyncClient):
|
|
|
582
643
|
def __init__(self, api_key: str):
|
|
583
644
|
super().__init__(api_key)
|
|
584
645
|
|
|
585
|
-
async def get_auth_url(
|
|
646
|
+
async def get_auth_url(
|
|
647
|
+
self, project_name: Optional[str] = None
|
|
648
|
+
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
586
649
|
"""
|
|
587
650
|
description:
|
|
588
651
|
获取TikTok OAuth授权URL(公共方法,供服务端调用)
|
|
589
652
|
|
|
590
653
|
服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
|
|
591
654
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
655
|
+
parameters:
|
|
656
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
592
657
|
return:
|
|
593
658
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
594
659
|
success(bool): 是否成功
|
|
595
660
|
"""
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
661
|
+
payload = _auth_url_json(project_name)
|
|
662
|
+
if payload:
|
|
663
|
+
data, success = await self._request(
|
|
664
|
+
"POST", "/api/unified-login/tiktok/auth-url", json=payload
|
|
665
|
+
)
|
|
666
|
+
else:
|
|
667
|
+
data, success = await self._request(
|
|
668
|
+
"POST", "/api/unified-login/tiktok/auth-url"
|
|
669
|
+
)
|
|
599
670
|
if not success:
|
|
600
671
|
return data, False
|
|
601
672
|
auth_url = data.get("auth_url")
|
|
@@ -661,20 +732,30 @@ class GitLabLogin(AsyncClient):
|
|
|
661
732
|
def __init__(self, api_key: str):
|
|
662
733
|
super().__init__(api_key)
|
|
663
734
|
|
|
664
|
-
async def get_auth_url(
|
|
735
|
+
async def get_auth_url(
|
|
736
|
+
self, project_name: Optional[str] = None
|
|
737
|
+
) -> Tuple[Optional[Dict[str, str]], bool]:
|
|
665
738
|
"""
|
|
666
739
|
description:
|
|
667
740
|
获取GitLab OAuth授权URL(公共方法,供服务端调用)
|
|
668
741
|
|
|
669
742
|
服务端应该调用此方法获取授权URL,然后将URL返回给前端让用户点击授权。
|
|
670
743
|
获取到state后,使用wait_for_login方法等待登录结果。
|
|
744
|
+
parameters:
|
|
745
|
+
project_name(str, optional): 绑定项目名;不传或空字符串则匿名登录
|
|
671
746
|
return:
|
|
672
747
|
auth_data(dict, optional): 授权数据字典,包含auth_url和state
|
|
673
748
|
success(bool): 是否成功
|
|
674
749
|
"""
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
750
|
+
payload = _auth_url_json(project_name)
|
|
751
|
+
if payload:
|
|
752
|
+
data, success = await self._request(
|
|
753
|
+
"POST", "/api/unified-login/gitlab/auth-url", json=payload
|
|
754
|
+
)
|
|
755
|
+
else:
|
|
756
|
+
data, success = await self._request(
|
|
757
|
+
"POST", "/api/unified-login/gitlab/auth-url"
|
|
758
|
+
)
|
|
678
759
|
if not success:
|
|
679
760
|
return data, False
|
|
680
761
|
auth_url = data.get("auth_url")
|
|
@@ -769,18 +850,25 @@ class SMSLogin(AsyncClient):
|
|
|
769
850
|
)
|
|
770
851
|
return bool(success)
|
|
771
852
|
|
|
772
|
-
async def verify_code(
|
|
853
|
+
async def verify_code(
|
|
854
|
+
self, phone: str, code: str, project_name: Optional[str] = None
|
|
855
|
+
) -> bool:
|
|
773
856
|
"""
|
|
774
857
|
验证短信验证码
|
|
775
858
|
|
|
776
859
|
:param phone: 手机号码
|
|
777
860
|
:param code: 验证码
|
|
861
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
778
862
|
:return: success 是否成功
|
|
779
863
|
"""
|
|
864
|
+
payload: Dict[str, Any] = {"phone": phone, "code": code}
|
|
865
|
+
pn = _normalized_project_name(project_name)
|
|
866
|
+
if pn is not None:
|
|
867
|
+
payload["project_name"] = pn
|
|
780
868
|
_, success = await self._request(
|
|
781
869
|
"POST",
|
|
782
870
|
"/api/unified-login/sms/verify-code",
|
|
783
|
-
json=
|
|
871
|
+
json=payload,
|
|
784
872
|
)
|
|
785
873
|
return bool(success)
|
|
786
874
|
|
|
@@ -812,7 +900,11 @@ class SMSLogin(AsyncClient):
|
|
|
812
900
|
return {"message": "登录超时或未完成授权"}, False
|
|
813
901
|
|
|
814
902
|
async def login(
|
|
815
|
-
self,
|
|
903
|
+
self,
|
|
904
|
+
phone: str,
|
|
905
|
+
code: str,
|
|
906
|
+
timeout: int = 180,
|
|
907
|
+
project_name: Optional[str] = None,
|
|
816
908
|
) -> Tuple[Dict, bool]:
|
|
817
909
|
"""
|
|
818
910
|
验证验证码并等待登录结果
|
|
@@ -820,9 +912,10 @@ class SMSLogin(AsyncClient):
|
|
|
820
912
|
:param phone: 手机号码
|
|
821
913
|
:param code: 验证码
|
|
822
914
|
:param timeout: 等待登录结果的超时时间(秒)
|
|
915
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
823
916
|
:return: (用户信息, 是否成功)
|
|
824
917
|
"""
|
|
825
|
-
success = await self.verify_code(phone, code)
|
|
918
|
+
success = await self.verify_code(phone, code, project_name=project_name)
|
|
826
919
|
if not success:
|
|
827
920
|
return {"message": "验证码校验失败"}, False
|
|
828
921
|
|
|
@@ -859,18 +952,25 @@ class EmailLogin(AsyncClient):
|
|
|
859
952
|
)
|
|
860
953
|
return bool(success)
|
|
861
954
|
|
|
862
|
-
async def verify_code(
|
|
955
|
+
async def verify_code(
|
|
956
|
+
self, email: str, code: str, project_name: Optional[str] = None
|
|
957
|
+
) -> bool:
|
|
863
958
|
"""
|
|
864
959
|
验证邮箱验证码
|
|
865
960
|
|
|
866
961
|
:param email: 邮箱地址
|
|
867
962
|
:param code: 验证码
|
|
963
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
868
964
|
:return: success 是否成功
|
|
869
965
|
"""
|
|
966
|
+
payload: Dict[str, Any] = {"email": email, "code": code}
|
|
967
|
+
pn = _normalized_project_name(project_name)
|
|
968
|
+
if pn is not None:
|
|
969
|
+
payload["project_name"] = pn
|
|
870
970
|
_, success = await self._request(
|
|
871
971
|
"POST",
|
|
872
972
|
"/api/unified-login/email/verify-code",
|
|
873
|
-
json=
|
|
973
|
+
json=payload,
|
|
874
974
|
)
|
|
875
975
|
return bool(success)
|
|
876
976
|
|
|
@@ -902,7 +1002,11 @@ class EmailLogin(AsyncClient):
|
|
|
902
1002
|
return {"message": "登录超时或未完成授权"}, False
|
|
903
1003
|
|
|
904
1004
|
async def login(
|
|
905
|
-
self,
|
|
1005
|
+
self,
|
|
1006
|
+
email: str,
|
|
1007
|
+
code: str,
|
|
1008
|
+
timeout: int = 180,
|
|
1009
|
+
project_name: Optional[str] = None,
|
|
906
1010
|
) -> Tuple[Dict, bool]:
|
|
907
1011
|
"""
|
|
908
1012
|
验证验证码并等待登录结果
|
|
@@ -910,9 +1014,10 @@ class EmailLogin(AsyncClient):
|
|
|
910
1014
|
:param email: 邮箱地址
|
|
911
1015
|
:param code: 验证码
|
|
912
1016
|
:param timeout: 等待登录结果的超时时间(秒)
|
|
1017
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
913
1018
|
:return: (用户信息, 是否成功)
|
|
914
1019
|
"""
|
|
915
|
-
success = await self.verify_code(email, code)
|
|
1020
|
+
success = await self.verify_code(email, code, project_name=project_name)
|
|
916
1021
|
if not success:
|
|
917
1022
|
return {"message": "验证码校验失败"}, False
|
|
918
1023
|
|
|
@@ -955,6 +1060,7 @@ class PasswordLogin(AsyncClient):
|
|
|
955
1060
|
user_identifier: str,
|
|
956
1061
|
password: str,
|
|
957
1062
|
display_name: Optional[str] = None,
|
|
1063
|
+
project_name: Optional[str] = None,
|
|
958
1064
|
) -> bool:
|
|
959
1065
|
"""
|
|
960
1066
|
注册/设置密码:将密码哈希后写入外部用户表(login_method=password)。
|
|
@@ -963,6 +1069,7 @@ class PasswordLogin(AsyncClient):
|
|
|
963
1069
|
:param user_identifier: 用户标识(邮箱)
|
|
964
1070
|
:param password: 密码(6~100 位)
|
|
965
1071
|
:param display_name: 展示名称,可选
|
|
1072
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
966
1073
|
:return: 是否成功
|
|
967
1074
|
"""
|
|
968
1075
|
payload: Dict[str, Any] = {
|
|
@@ -971,6 +1078,9 @@ class PasswordLogin(AsyncClient):
|
|
|
971
1078
|
}
|
|
972
1079
|
if display_name is not None:
|
|
973
1080
|
payload["display_name"] = display_name
|
|
1081
|
+
pn = _normalized_project_name(project_name)
|
|
1082
|
+
if pn is not None:
|
|
1083
|
+
payload["project_name"] = pn
|
|
974
1084
|
_, success = await self._request(
|
|
975
1085
|
"POST",
|
|
976
1086
|
"/api/unified-login/password/register",
|
|
@@ -982,21 +1092,27 @@ class PasswordLogin(AsyncClient):
|
|
|
982
1092
|
self,
|
|
983
1093
|
user_identifier: str,
|
|
984
1094
|
password: str,
|
|
1095
|
+
project_name: Optional[str] = None,
|
|
985
1096
|
) -> Tuple[Dict, bool]:
|
|
986
1097
|
"""
|
|
987
1098
|
密码登录:校验邮箱与密码,成功则返回用户信息(与其它统一登录方式格式一致)。
|
|
988
1099
|
|
|
989
1100
|
:param user_identifier: 用户标识(邮箱)
|
|
990
1101
|
:param password: 密码
|
|
1102
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
991
1103
|
:return: (用户信息字典, 是否成功)
|
|
992
1104
|
"""
|
|
1105
|
+
body: Dict[str, Any] = {
|
|
1106
|
+
"user_identifier": user_identifier,
|
|
1107
|
+
"password": password,
|
|
1108
|
+
}
|
|
1109
|
+
pn = _normalized_project_name(project_name)
|
|
1110
|
+
if pn is not None:
|
|
1111
|
+
body["project_name"] = pn
|
|
993
1112
|
data, success = await self._request(
|
|
994
1113
|
"POST",
|
|
995
1114
|
"/api/unified-login/password/login",
|
|
996
|
-
json=
|
|
997
|
-
"user_identifier": user_identifier,
|
|
998
|
-
"password": password,
|
|
999
|
-
},
|
|
1115
|
+
json=body,
|
|
1000
1116
|
)
|
|
1001
1117
|
if not success:
|
|
1002
1118
|
return data if isinstance(data, dict) else {"message": data}, False
|
|
@@ -1007,6 +1123,7 @@ class PasswordLogin(AsyncClient):
|
|
|
1007
1123
|
user_identifier: str,
|
|
1008
1124
|
old_password: str,
|
|
1009
1125
|
new_password: str,
|
|
1126
|
+
project_name: Optional[str] = None,
|
|
1010
1127
|
) -> bool:
|
|
1011
1128
|
"""
|
|
1012
1129
|
修改密码:校验原密码后更新为新密码。
|
|
@@ -1014,15 +1131,20 @@ class PasswordLogin(AsyncClient):
|
|
|
1014
1131
|
:param user_identifier: 用户标识(邮箱)
|
|
1015
1132
|
:param old_password: 当前密码
|
|
1016
1133
|
:param new_password: 新密码(6~100 位)
|
|
1134
|
+
:param project_name: 绑定项目名;不传或空字符串则匿名登录
|
|
1017
1135
|
:return: 是否成功
|
|
1018
1136
|
"""
|
|
1137
|
+
body: Dict[str, Any] = {
|
|
1138
|
+
"user_identifier": user_identifier,
|
|
1139
|
+
"old_password": old_password,
|
|
1140
|
+
"new_password": new_password,
|
|
1141
|
+
}
|
|
1142
|
+
pn = _normalized_project_name(project_name)
|
|
1143
|
+
if pn is not None:
|
|
1144
|
+
body["project_name"] = pn
|
|
1019
1145
|
_, success = await self._request(
|
|
1020
1146
|
"POST",
|
|
1021
1147
|
"/api/unified-login/password/change",
|
|
1022
|
-
json=
|
|
1023
|
-
"user_identifier": user_identifier,
|
|
1024
|
-
"old_password": old_password,
|
|
1025
|
-
"new_password": new_password,
|
|
1026
|
-
},
|
|
1148
|
+
json=body,
|
|
1027
1149
|
)
|
|
1028
1150
|
return bool(success)
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/SOURCES.txt
RENAMED
|
@@ -10,6 +10,8 @@ pixelarraythirdparty.egg-info/requires.txt
|
|
|
10
10
|
pixelarraythirdparty.egg-info/top_level.txt
|
|
11
11
|
pixelarraythirdparty/cron/__init__.py
|
|
12
12
|
pixelarraythirdparty/cron/cron.py
|
|
13
|
+
pixelarraythirdparty/custom_events/__init__.py
|
|
14
|
+
pixelarraythirdparty/custom_events/custom_events.py
|
|
13
15
|
pixelarraythirdparty/feedback/__init__.py
|
|
14
16
|
pixelarraythirdparty/feedback/feedback.py
|
|
15
17
|
pixelarraythirdparty/order/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/cron/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/__init__.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/feedback.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/__init__.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/order.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/__init__.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/product.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/__init__.py
RENAMED
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/project.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/user/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|