"""代理 & 白名单配置路由""" import re import time from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from ..database import get_db from ..models import User, ProxyConfig as ProxyConfigModel, AuditLog from ..schemas import ProxyConfigOut, ProxyConfigUpdate, MessageResponse from ..deps import require_permission router = APIRouter(prefix="/api/proxy", tags=["代理与白名单"]) def _get_or_create(db: Session) -> ProxyConfigModel: cfg = db.query(ProxyConfigModel).first() if not cfg: cfg = ProxyConfigModel() db.add(cfg) db.commit() db.refresh(cfg) return cfg @router.get("", response_model=ProxyConfigOut) def get_proxy_config( db: Session = Depends(get_db), _: User = Depends(require_permission("proxy:manage")), ): return _get_or_create(db) @router.put("", response_model=ProxyConfigOut) def update_proxy_config( req: ProxyConfigUpdate, db: Session = Depends(get_db), current: User = Depends(require_permission("proxy:manage")), ): cfg = _get_or_create(db) cfg.enabled = req.enabled cfg.api_url = req.api_url cfg.http = req.http cfg.https = req.https cfg.whitelist_enabled = req.whitelist_enabled cfg.whitelist_uid = req.whitelist_uid cfg.whitelist_ukey = req.whitelist_ukey db.commit() db.refresh(cfg) db.add(AuditLog(user_id=current.id, username=current.username, action="proxy:update", target="proxy_config")) db.commit() return cfg @router.post("/test") def test_proxy( db: Session = Depends(get_db), current: User = Depends(require_permission("proxy:manage")), ): """测试代理连通性。""" import requests as req_lib cfg = _get_or_create(db) if not cfg.enabled: return {"success": False, "message": "代理未启用"} proxy_url = cfg.http or cfg.https if cfg.api_url and not proxy_url: try: resp = req_lib.get(cfg.api_url, timeout=10) match = re.search(r'(\d+\.\d+\.\d+\.\d+):(\d+)', resp.text) if match: proxy_url = f"http://{match.group(1)}:{match.group(2)}" except Exception as e: return {"success": False, "message": f"代理API请求失败: {e}"} if not proxy_url: return {"success": False, "message": "无可用代理地址"} try: resp = req_lib.get( "https://qifu-api.baidubce.com/ip/local/geo/v1/district", proxies={"http": proxy_url, "https": proxy_url}, timeout=(4, 6), headers={"User-Agent": "Mozilla/5.0"}, ) resp.raise_for_status() return {"success": True, "message": f"代理可用,响应: {resp.text[:100]}"} except Exception as e: return {"success": False, "message": f"代理验证失败: {e}"} @router.post("/whitelist/test") def test_whitelist( db: Session = Depends(get_db), current: User = Depends(require_permission("whitelist:test")), ): """测试白名单连接并自动同步出口IP。""" from core.douyu.whitelist import WhitelistManager, get_exit_ip_via_proxy import requests as req_lib cfg = _get_or_create(db) if not cfg.whitelist_enabled: return {"success": False, "message": "白名单未启用"} if not cfg.whitelist_uid or not cfg.whitelist_ukey: return {"success": False, "message": "未配置白名单UID/UKEY"} manager = WhitelistManager(cfg.whitelist_uid, cfg.whitelist_ukey) # 测试API连接 ok, msg = manager.test_connection() if not ok: return {"success": False, "message": msg} # 获取出口IP proxy_url = cfg.http or cfg.https if cfg.api_url and not proxy_url: try: resp = req_lib.get(cfg.api_url, timeout=10) match = re.search(r'(\d+\.\d+\.\d+\.\d+):(\d+)', resp.text) if match: proxy_url = f"http://{match.group(1)}:{match.group(2)}" except Exception: pass exit_ip = None if proxy_url: exit_ip = get_exit_ip_via_proxy(proxy_url) if not exit_ip: try: resp = req_lib.get("https://4.ipw.cn", timeout=6, headers={"User-Agent": "Mozilla/5.0"}) match = re.search(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', resp.text) if match: exit_ip = match.group(1) except Exception: pass if not exit_ip: return {"success": False, "message": "API连接正常但无法获取出口IP"} # 同步白名单 sync_ok, sync_msg = manager.sync_ip(exit_ip) if sync_ok: return {"success": True, "message": f"出口IP {exit_ip} 已同步: {sync_msg}"} return {"success": False, "message": f"同步失败: {sync_msg}"}