TheSmallHanCat commited on
Commit
ea88387
·
1 Parent(s): 77eaf1d

fix: token导入

Browse files
Files changed (1) hide show
  1. src/api/admin.py +139 -0
src/api/admin.py CHANGED
@@ -90,6 +90,23 @@ class ST2ATRequest(BaseModel):
90
  st: str
91
 
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  # ========== Auth Middleware ==========
94
 
95
  async def verify_admin_token(authorization: str = Header(None)):
@@ -378,6 +395,98 @@ async def st_to_at(
378
  raise HTTPException(status_code=400, detail=str(e))
379
 
380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  # ========== Config Management ==========
382
 
383
  @router.get("/api/config/proxy")
@@ -722,3 +831,33 @@ async def update_cache_base_url(
722
  await db.reload_config_to_memory()
723
 
724
  return {"success": True, "message": "缓存Base URL更新成功"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  st: str
91
 
92
 
93
+ class ImportTokenItem(BaseModel):
94
+ """导入Token项"""
95
+ email: Optional[str] = None
96
+ access_token: Optional[str] = None
97
+ session_token: Optional[str] = None
98
+ is_active: bool = True
99
+ image_enabled: bool = True
100
+ video_enabled: bool = True
101
+ image_concurrency: int = -1
102
+ video_concurrency: int = -1
103
+
104
+
105
+ class ImportTokensRequest(BaseModel):
106
+ """导入Token请求"""
107
+ tokens: List[ImportTokenItem]
108
+
109
+
110
  # ========== Auth Middleware ==========
111
 
112
  async def verify_admin_token(authorization: str = Header(None)):
 
395
  raise HTTPException(status_code=400, detail=str(e))
396
 
397
 
398
+ @router.post("/api/tokens/import")
399
+ async def import_tokens(
400
+ request: ImportTokensRequest,
401
+ token: str = Depends(verify_admin_token)
402
+ ):
403
+ """批量导入Token"""
404
+ from datetime import datetime, timezone
405
+
406
+ added = 0
407
+ updated = 0
408
+ errors = []
409
+
410
+ for idx, item in enumerate(request.tokens):
411
+ try:
412
+ st = item.session_token
413
+
414
+ if not st:
415
+ errors.append(f"第{idx+1}项: 缺少 session_token")
416
+ continue
417
+
418
+ # 使用 ST 转 AT 获取用户信息
419
+ try:
420
+ result = await token_manager.flow_client.st_to_at(st)
421
+ at = result["access_token"]
422
+ email = result.get("user", {}).get("email")
423
+ expires = result.get("expires")
424
+
425
+ if not email:
426
+ errors.append(f"第{idx+1}项: 无法获取邮箱信息")
427
+ continue
428
+
429
+ # 解析过期时间
430
+ at_expires = None
431
+ is_expired = False
432
+ if expires:
433
+ try:
434
+ at_expires = datetime.fromisoformat(expires.replace('Z', '+00:00'))
435
+ # 判断是否过期
436
+ now = datetime.now(timezone.utc)
437
+ is_expired = at_expires <= now
438
+ except:
439
+ pass
440
+
441
+ # 使用邮箱检查是否已存在
442
+ existing_tokens = await token_manager.get_all_tokens()
443
+ existing = next((t for t in existing_tokens if t.email == email), None)
444
+
445
+ if existing:
446
+ # 更新现有Token
447
+ await token_manager.update_token(
448
+ token_id=existing.id,
449
+ st=st,
450
+ at=at,
451
+ at_expires=at_expires,
452
+ image_enabled=item.image_enabled,
453
+ video_enabled=item.video_enabled,
454
+ image_concurrency=item.image_concurrency,
455
+ video_concurrency=item.video_concurrency
456
+ )
457
+ # 如果过期则禁用
458
+ if is_expired:
459
+ await token_manager.disable_token(existing.id)
460
+ updated += 1
461
+ else:
462
+ # 添加新Token
463
+ new_token = await token_manager.add_token(
464
+ st=st,
465
+ image_enabled=item.image_enabled,
466
+ video_enabled=item.video_enabled,
467
+ image_concurrency=item.image_concurrency,
468
+ video_concurrency=item.video_concurrency
469
+ )
470
+ # 如果过期则禁用
471
+ if is_expired:
472
+ await token_manager.disable_token(new_token.id)
473
+ added += 1
474
+
475
+ except Exception as e:
476
+ errors.append(f"第{idx+1}项: {str(e)}")
477
+
478
+ except Exception as e:
479
+ errors.append(f"第{idx+1}项: {str(e)}")
480
+
481
+ return {
482
+ "success": True,
483
+ "added": added,
484
+ "updated": updated,
485
+ "errors": errors if errors else None,
486
+ "message": f"导入完成: 新增 {added} 个, 更新 {updated} 个" + (f", {len(errors)} 个失败" if errors else "")
487
+ }
488
+
489
+
490
  # ========== Config Management ==========
491
 
492
  @router.get("/api/config/proxy")
 
831
  await db.reload_config_to_memory()
832
 
833
  return {"success": True, "message": "缓存Base URL更新成功"}
834
+
835
+
836
+ @router.post("/api/captcha/config")
837
+ async def update_captcha_config(
838
+ request: dict,
839
+ token: str = Depends(verify_admin_token)
840
+ ):
841
+ """Update captcha configuration"""
842
+ yescaptcha_api_key = request.get("yescaptcha_api_key")
843
+ yescaptcha_base_url = request.get("yescaptcha_base_url")
844
+
845
+ await db.update_captcha_config(
846
+ yescaptcha_api_key=yescaptcha_api_key,
847
+ yescaptcha_base_url=yescaptcha_base_url
848
+ )
849
+
850
+ # 🔥 Hot reload: sync database config to memory
851
+ await db.reload_config_to_memory()
852
+
853
+ return {"success": True, "message": "验证码配置更新成功"}
854
+
855
+
856
+ @router.get("/api/captcha/config")
857
+ async def get_captcha_config(token: str = Depends(verify_admin_token)):
858
+ """Get captcha configuration"""
859
+ captcha_config = await db.get_captcha_config()
860
+ return {
861
+ "yescaptcha_api_key": captcha_config.yescaptcha_api_key,
862
+ "yescaptcha_base_url": captcha_config.yescaptcha_base_url
863
+ }