pixelarraythirdparty 1.1.7__py3-none-any.whl → 1.1.9__py3-none-any.whl

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.
@@ -13,7 +13,7 @@ PixelArray 第三方微服务客户端
13
13
  - project: 项目管理模块
14
14
  """
15
15
 
16
- __version__ = "1.1.7"
16
+ __version__ = "1.1.9"
17
17
  __author__ = "Lu qi"
18
18
  __email__ = "qi.lu@pixelarrayai.com"
19
19
 
@@ -1,4 +1,20 @@
1
- from .unified_login import GoogleLogin, WechatLogin, GitHubLogin
1
+ from .unified_login import (
2
+ GoogleLogin,
3
+ WechatLogin,
4
+ GitHubLogin,
5
+ DouyinLogin,
6
+ GitLabLogin,
7
+ SMSLogin,
8
+ EmailLogin,
9
+ )
2
10
 
3
- __all__ = ["GoogleLogin", "WechatLogin", "GitHubLogin"]
11
+ __all__ = [
12
+ "GoogleLogin",
13
+ "WechatLogin",
14
+ "GitHubLogin",
15
+ "DouyinLogin",
16
+ "GitLabLogin",
17
+ "SMSLogin",
18
+ "EmailLogin",
19
+ ]
4
20
 
@@ -14,6 +14,15 @@ class GoogleLogin(AsyncClient):
14
14
  ```
15
15
  google = GoogleLogin(api_key="your_api_key")
16
16
  user_info, success = await google.login()
17
+ if success:
18
+ access_token = user_info.get("access_token")
19
+ refresh_token = user_info.get("refresh_token")
20
+
21
+ # 使用refresh_token刷新access_token
22
+ if refresh_token:
23
+ token_data, success = await google.refresh_access_token(refresh_token)
24
+ if success:
25
+ new_access_token = token_data.get("access_token")
17
26
  ```
18
27
  """
19
28
 
@@ -88,6 +97,31 @@ class GoogleLogin(AsyncClient):
88
97
 
89
98
  return {}, False
90
99
 
100
+ async def refresh_access_token(self, refresh_token: str) -> Tuple[Dict, bool]:
101
+ """
102
+ 使用refresh_token刷新access_token
103
+
104
+ :param refresh_token: Google OAuth refresh_token
105
+ :return: 包含新的access_token和可能的refresh_token的字典,以及是否成功的布尔值
106
+
107
+ 使用示例:
108
+ ```
109
+ google = GoogleLogin(api_key="your_api_key")
110
+ token_data, success = await google.refresh_access_token(refresh_token="your_refresh_token")
111
+ if success:
112
+ new_access_token = token_data.get("access_token")
113
+ new_refresh_token = token_data.get("refresh_token") # 可能为None
114
+ ```
115
+ """
116
+ data, success = await self._request(
117
+ "POST",
118
+ "/api/unified-login/google/refresh-token",
119
+ json={"refresh_token": refresh_token},
120
+ )
121
+ if not success:
122
+ return {}, False
123
+ return data, True
124
+
91
125
 
92
126
  class WechatLogin(AsyncClient):
93
127
  """
@@ -459,3 +493,207 @@ class GitLabLogin(AsyncClient):
459
493
  await asyncio.sleep(interval)
460
494
 
461
495
  return {}, False
496
+
497
+
498
+ class SMSLogin(AsyncClient):
499
+ """
500
+ 短信验证码登录客户端
501
+
502
+ 使用示例:
503
+ ```
504
+ sms = SMSLogin(api_key="your_api_key")
505
+ # 发送验证码
506
+ state, success = await sms.send_code(phone="13800138000")
507
+ if success:
508
+ # 验证验证码并登录
509
+ user_info, success = await sms.login(state=state, code="123456")
510
+ ```
511
+ """
512
+
513
+ def __init__(self, api_key: str):
514
+ super().__init__(api_key)
515
+
516
+ async def send_code(self, phone: str) -> Tuple[Optional[str], bool]:
517
+ """
518
+ 发送短信验证码
519
+
520
+ :param phone: 手机号码
521
+ :return: (state, success) state用于后续验证验证码
522
+ """
523
+ data, success = await self._request(
524
+ "POST", "/api/unified-login/sms/send-code", json={"phone": phone}
525
+ )
526
+ if not success:
527
+ return None, False
528
+ state = data.get("state")
529
+ if not state:
530
+ return None, False
531
+ return state, True
532
+
533
+ async def verify_code(self, state: str, code: str) -> Tuple[Optional[str], bool]:
534
+ """
535
+ 验证短信验证码
536
+
537
+ :param state: 发送验证码时返回的state
538
+ :param code: 验证码
539
+ :return: (state, success) state用于后续等待登录结果
540
+ """
541
+ data, success = await self._request(
542
+ "POST",
543
+ "/api/unified-login/sms/verify-code",
544
+ json={"state": state, "code": code},
545
+ )
546
+ if not success:
547
+ return None, False
548
+ new_state = data.get("state")
549
+ if not new_state:
550
+ return None, False
551
+ return new_state, True
552
+
553
+ async def _wait_for_login(
554
+ self, state: str, timeout: int
555
+ ) -> Tuple[Dict, bool]:
556
+ """
557
+ 等待短信登录结果
558
+
559
+ :param state: 验证验证码时返回的state
560
+ :param timeout: 超时时间(秒)
561
+ """
562
+ interval = 2
563
+ total_checks = max(1, timeout // interval) if timeout > 0 else 1
564
+
565
+ for _ in range(total_checks):
566
+ status, response = await self._request_raw(
567
+ "POST",
568
+ "/api/unified-login/sms/wait-sms-login",
569
+ json={"state": state},
570
+ )
571
+
572
+ if status == 200 and response.get("success") is True:
573
+ return response.get("data", {}), True
574
+
575
+ if status in (400, 408):
576
+ break
577
+
578
+ await asyncio.sleep(interval)
579
+
580
+ return {}, False
581
+
582
+ async def login(
583
+ self, state: str, code: str, timeout: int = 180
584
+ ) -> Tuple[Dict, bool]:
585
+ """
586
+ 验证验证码并等待登录结果
587
+
588
+ :param state: 发送验证码时返回的state
589
+ :param code: 验证码
590
+ :param timeout: 等待登录结果的超时时间(秒)
591
+ :return: (用户信息, 是否成功)
592
+ """
593
+ new_state, success = await self.verify_code(state, code)
594
+ if not success or not new_state:
595
+ return {}, False
596
+
597
+ return await self._wait_for_login(new_state, timeout)
598
+
599
+
600
+ class EmailLogin(AsyncClient):
601
+ """
602
+ 邮箱验证码登录客户端
603
+
604
+ 使用示例:
605
+ ```
606
+ email = EmailLogin(api_key="your_api_key")
607
+ # 发送验证码
608
+ state, success = await email.send_code(email="user@example.com")
609
+ if success:
610
+ # 验证验证码并登录
611
+ user_info, success = await email.login(state=state, code="123456")
612
+ ```
613
+ """
614
+
615
+ def __init__(self, api_key: str):
616
+ super().__init__(api_key)
617
+
618
+ async def send_code(self, email: str) -> Tuple[Optional[str], bool]:
619
+ """
620
+ 发送邮箱验证码
621
+
622
+ :param email: 邮箱地址
623
+ :return: (state, success) state用于后续验证验证码
624
+ """
625
+ data, success = await self._request(
626
+ "POST", "/api/unified-login/email/send-code", json={"email": email}
627
+ )
628
+ if not success:
629
+ return None, False
630
+ state = data.get("state")
631
+ if not state:
632
+ return None, False
633
+ return state, True
634
+
635
+ async def verify_code(self, state: str, code: str) -> Tuple[Optional[str], bool]:
636
+ """
637
+ 验证邮箱验证码
638
+
639
+ :param state: 发送验证码时返回的state
640
+ :param code: 验证码
641
+ :return: (state, success) state用于后续等待登录结果
642
+ """
643
+ data, success = await self._request(
644
+ "POST",
645
+ "/api/unified-login/email/verify-code",
646
+ json={"state": state, "code": code},
647
+ )
648
+ if not success:
649
+ return None, False
650
+ new_state = data.get("state")
651
+ if not new_state:
652
+ return None, False
653
+ return new_state, True
654
+
655
+ async def _wait_for_login(
656
+ self, state: str, timeout: int
657
+ ) -> Tuple[Dict, bool]:
658
+ """
659
+ 等待邮箱登录结果
660
+
661
+ :param state: 验证验证码时返回的state
662
+ :param timeout: 超时时间(秒)
663
+ """
664
+ interval = 2
665
+ total_checks = max(1, timeout // interval) if timeout > 0 else 1
666
+
667
+ for _ in range(total_checks):
668
+ status, response = await self._request_raw(
669
+ "POST",
670
+ "/api/unified-login/email/wait-email-login",
671
+ json={"state": state},
672
+ )
673
+
674
+ if status == 200 and response.get("success") is True:
675
+ return response.get("data", {}), True
676
+
677
+ if status in (400, 408):
678
+ break
679
+
680
+ await asyncio.sleep(interval)
681
+
682
+ return {}, False
683
+
684
+ async def login(
685
+ self, state: str, code: str, timeout: int = 180
686
+ ) -> Tuple[Dict, bool]:
687
+ """
688
+ 验证验证码并等待登录结果
689
+
690
+ :param state: 发送验证码时返回的state
691
+ :param code: 验证码
692
+ :param timeout: 等待登录结果的超时时间(秒)
693
+ :return: (用户信息, 是否成功)
694
+ """
695
+ new_state, success = await self.verify_code(state, code)
696
+ if not success or not new_state:
697
+ return {}, False
698
+
699
+ return await self._wait_for_login(new_state, timeout)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pixelarraythirdparty
3
- Version: 1.1.7
3
+ Version: 1.1.9
4
4
  Summary: PixelArray 第三方微服务客户端
5
5
  Author-email: Lu qi <qi.lu@pixelarrayai.com>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- pixelarraythirdparty/__init__.py,sha256=DJD0HApoVd_9RhJ6bMGjlWfs3eBJm3jHrWNJ5KPdYjE,582
1
+ pixelarraythirdparty/__init__.py,sha256=QoYi4YotAITkKgOLFe4a1RtY7dP_SXaSz2ArxGuGC-g,582
2
2
  pixelarraythirdparty/client.py,sha256=DY8w2DYsoGQ6cZYqT-FfoovmVd3Ry-aJbJls2Cxat8M,2006
3
3
  pixelarraythirdparty/cron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  pixelarraythirdparty/cron/cron.py,sha256=nv4e2hX_UkEJ-kbEARbInU2J6aREyYZ61dZ-4b9UWJI,3146
@@ -10,12 +10,12 @@ pixelarraythirdparty/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
10
10
  pixelarraythirdparty/product/product.py,sha256=5fgv2Ck860epYXxipY83vePziubCIlocFu43mGt_bhM,7497
11
11
  pixelarraythirdparty/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  pixelarraythirdparty/project/project.py,sha256=a8swjckyn4y3NlIx0-tMbcRwDY9woOijGi7lb1wN7Ok,2455
13
- pixelarraythirdparty/unified_login/__init__.py,sha256=2ejSpO0gp-J-XkT5p19V45FlYOW7-NO_aCExukfUTIo,123
14
- pixelarraythirdparty/unified_login/unified_login.py,sha256=bbbUvYlcR_G5zdfXaDHRZkg9gGjKniVD6cUaKOxhfPQ,14134
13
+ pixelarraythirdparty/unified_login/__init__.py,sha256=_PeHBsyrPLfcNjbdcsBgQ_75fr1CoRZCNu7S33fsh_Y,291
14
+ pixelarraythirdparty/unified_login/unified_login.py,sha256=Rh0EVxvQkTKOGZN9092JxVeGbD2OQ7L2Zvy4M4BlgXI,21559
15
15
  pixelarraythirdparty/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  pixelarraythirdparty/user/user.py,sha256=v018iisB5AQNs7AtrHIGfu8YIorX0vflDClsKrt3ZMU,5898
17
- pixelarraythirdparty-1.1.7.dist-info/licenses/LICENSE,sha256=O-g1dUr0U50rSIvmWE9toiVkSgFpVt72_MHITbWvAqA,1067
18
- pixelarraythirdparty-1.1.7.dist-info/METADATA,sha256=V4Dj8eyc9jYwDZWYPDn_Wi5WGyFGC9JRqOyB5alOf5I,993
19
- pixelarraythirdparty-1.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- pixelarraythirdparty-1.1.7.dist-info/top_level.txt,sha256=dzG2Ut8j7noUqj_0ZQjcIDAeHYCh_9WtlxjAxtoyufo,21
21
- pixelarraythirdparty-1.1.7.dist-info/RECORD,,
17
+ pixelarraythirdparty-1.1.9.dist-info/licenses/LICENSE,sha256=O-g1dUr0U50rSIvmWE9toiVkSgFpVt72_MHITbWvAqA,1067
18
+ pixelarraythirdparty-1.1.9.dist-info/METADATA,sha256=6nk6d65Q13hI39JUzL-MCOS_AyPOSnho1zngzOqY1Lk,993
19
+ pixelarraythirdparty-1.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ pixelarraythirdparty-1.1.9.dist-info/top_level.txt,sha256=dzG2Ut8j7noUqj_0ZQjcIDAeHYCh_9WtlxjAxtoyufo,21
21
+ pixelarraythirdparty-1.1.9.dist-info/RECORD,,