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.
Files changed (30) hide show
  1. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/PKG-INFO +1 -1
  2. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/__init__.py +5 -1
  3. pixelarraythirdparty-1.3.0/pixelarraythirdparty/custom_events/__init__.py +3 -0
  4. pixelarraythirdparty-1.3.0/pixelarraythirdparty/custom_events/custom_events.py +52 -0
  5. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/unified_login/unified_login.py +163 -41
  6. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/PKG-INFO +1 -1
  7. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/SOURCES.txt +2 -0
  8. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pyproject.toml +1 -1
  9. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/LICENSE +0 -0
  10. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/MANIFEST.in +0 -0
  11. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/client.py +0 -0
  12. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/cron/__init__.py +0 -0
  13. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/cron/cron.py +0 -0
  14. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/__init__.py +0 -0
  15. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/feedback/feedback.py +0 -0
  16. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/__init__.py +0 -0
  17. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/order/order.py +0 -0
  18. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/__init__.py +0 -0
  19. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/product/product.py +0 -0
  20. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/__init__.py +0 -0
  21. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/project/project.py +0 -0
  22. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/support_chat/__init__.py +0 -0
  23. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/support_chat/support_chat.py +0 -0
  24. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/unified_login/__init__.py +0 -0
  25. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/user/__init__.py +0 -0
  26. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty/user/user.py +0 -0
  27. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/dependency_links.txt +0 -0
  28. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/requires.txt +0 -0
  29. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/pixelarraythirdparty.egg-info/top_level.txt +0 -0
  30. {pixelarraythirdparty-1.2.8 → pixelarraythirdparty-1.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pixelarraythirdparty
3
- Version: 1.2.8
3
+ Version: 1.3.0
4
4
  Summary: PixelArray 第三方微服务客户端
5
5
  Author-email: Lu qi <qi.lu@pixelarrayai.com>
6
6
  License-Expression: MIT
@@ -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.2.8"
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,3 @@
1
+ from .custom_events import CustomEventsManagerAsync
2
+
3
+ __all__ = ["CustomEventsManagerAsync"]
@@ -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__(self, api_key: str, provider: str, login_type: Optional[str] = None):
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
- data, success = await self._request("POST", endpoint)
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(self) -> Tuple[Optional[Dict[str, str]], bool]:
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
- data, success = await self._request(
230
- "POST", "/api/unified-login/google/auth-url"
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
- data, success = await self._request("POST", endpoint)
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(self) -> Tuple[Optional[Dict[str, str]], bool]:
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
- data, success = await self._request(
439
- "POST", "/api/unified-login/github/auth-url"
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(self) -> Tuple[Optional[Dict[str, str]], bool]:
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
- data, success = await self._request(
518
- "POST", "/api/unified-login/douyin/auth-url"
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(self) -> Tuple[Optional[Dict[str, str]], bool]:
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
- data, success = await self._request(
597
- "POST", "/api/unified-login/tiktok/auth-url"
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(self) -> Tuple[Optional[Dict[str, str]], bool]:
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
- data, success = await self._request(
676
- "POST", "/api/unified-login/gitlab/auth-url"
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(self, phone: str, code: str) -> bool:
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={"phone": phone, "code": code},
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, phone: str, code: str, timeout: int = 180
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(self, email: str, code: str) -> bool:
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={"email": email, "code": code},
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, email: str, code: str, timeout: int = 180
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pixelarraythirdparty
3
- Version: 1.2.8
3
+ Version: 1.3.0
4
4
  Summary: PixelArray 第三方微服务客户端
5
5
  Author-email: Lu qi <qi.lu@pixelarrayai.com>
6
6
  License-Expression: MIT
@@ -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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pixelarraythirdparty"
7
- version = "1.2.8"
7
+ version = "1.3.0"
8
8
  authors = [
9
9
  {name = "Lu qi", email = "qi.lu@pixelarrayai.com"},
10
10
  ]