批量导入Token
(
request: ImportTokensRequest,
token: str = Depends(verify_admin_token)
)
| 1095 | |
| 1096 | @router.post("/api/tokens/import") |
| 1097 | async def import_tokens( |
| 1098 | request: ImportTokensRequest, |
| 1099 | token: str = Depends(verify_admin_token) |
| 1100 | ): |
| 1101 | """批量导入Token""" |
| 1102 | from datetime import datetime, timezone |
| 1103 | |
| 1104 | added = 0 |
| 1105 | updated = 0 |
| 1106 | errors = [] |
| 1107 | # 保持与历史逻辑一致:按 created_at DESC 的结果中,优先命中同邮箱“最新一条” |
| 1108 | existing_by_email = {} |
| 1109 | for existing_token in await token_manager.get_all_tokens(): |
| 1110 | if existing_token.email and existing_token.email not in existing_by_email: |
| 1111 | existing_by_email[existing_token.email] = existing_token |
| 1112 | |
| 1113 | for idx, item in enumerate(request.tokens): |
| 1114 | try: |
| 1115 | st = item.session_token |
| 1116 | |
| 1117 | if not st: |
| 1118 | errors.append(f"第{idx+1}项: 缺少 session_token") |
| 1119 | continue |
| 1120 | |
| 1121 | # 使用 ST 转 AT 获取用户信息 |
| 1122 | try: |
| 1123 | result = await token_manager.flow_client.st_to_at(st) |
| 1124 | at = result["access_token"] |
| 1125 | email = result.get("user", {}).get("email") |
| 1126 | expires = result.get("expires") |
| 1127 | |
| 1128 | if not email: |
| 1129 | errors.append(f"第{idx+1}项: 无法获取邮箱信息") |
| 1130 | continue |
| 1131 | |
| 1132 | # 解析过期时间 |
| 1133 | at_expires = None |
| 1134 | is_expired = False |
| 1135 | if expires: |
| 1136 | try: |
| 1137 | at_expires = datetime.fromisoformat(expires.replace('Z', '+00:00')) |
| 1138 | # 判断是否过期 |
| 1139 | now = datetime.now(timezone.utc) |
| 1140 | is_expired = at_expires <= now |
| 1141 | except: |
| 1142 | pass |
| 1143 | |
| 1144 | # 使用邮箱检查是否已存在 |
| 1145 | existing = existing_by_email.get(email) |
| 1146 | |
| 1147 | if existing: |
| 1148 | # 更新现有Token |
| 1149 | await token_manager.update_token( |
| 1150 | token_id=existing.id, |
| 1151 | st=st, |
| 1152 | at=at, |
| 1153 | at_expires=at_expires, |
| 1154 | captcha_proxy_url=item.captcha_proxy_url.strip() if item.captcha_proxy_url is not None else None, |
nothing calls this directly
no test coverage detected