| import random
|
| import re
|
| import os
|
| import logging
|
| from datetime import datetime, timedelta
|
| from apscheduler.schedulers.background import BackgroundScheduler
|
| from app.utils.logging import format_log_message
|
|
|
| logger = logging.getLogger("my_logger")
|
|
|
| class APIKeyManager:
|
| def __init__(self):
|
| self.api_keys = re.findall(
|
| r"AIzaSy[a-zA-Z0-9_-]{33}", os.environ.get('GEMINI_API_KEYS', ""))
|
| self.key_stack = []
|
| self._reset_key_stack()
|
|
|
|
|
| self.scheduler = BackgroundScheduler()
|
| self.scheduler.start()
|
| self.tried_keys_for_request = set()
|
|
|
| def _reset_key_stack(self):
|
| """创建并随机化密钥栈"""
|
| shuffled_keys = self.api_keys[:]
|
| random.shuffle(shuffled_keys)
|
| self.key_stack = shuffled_keys
|
|
|
|
|
| def get_available_key(self):
|
| """从栈顶获取密钥,栈空时重新生成 (修改后)"""
|
| while self.key_stack:
|
| key = self.key_stack.pop()
|
|
|
| if key not in self.tried_keys_for_request:
|
| self.tried_keys_for_request.add(key)
|
| return key
|
|
|
| if not self.api_keys:
|
| log_msg = format_log_message('ERROR', "没有配置任何 API 密钥!")
|
| logger.error(log_msg)
|
| return None
|
|
|
| self._reset_key_stack()
|
|
|
|
|
| while self.key_stack:
|
| key = self.key_stack.pop()
|
|
|
| if key not in self.tried_keys_for_request:
|
| self.tried_keys_for_request.add(key)
|
| return key
|
|
|
| return None
|
|
|
|
|
| def show_all_keys(self):
|
| log_msg = format_log_message('INFO', f"当前可用API key个数: {len(self.api_keys)} ")
|
| logger.info(log_msg)
|
| for i, api_key in enumerate(self.api_keys):
|
| log_msg = format_log_message('INFO', f"API Key{i}: {api_key[:8]}...{api_key[-3:]}")
|
| logger.info(log_msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| def reset_tried_keys_for_request(self):
|
| """在新的请求尝试时重置已尝试的 key 集合"""
|
| self.tried_keys_for_request = set()
|
|
|
| async def test_api_key(api_key: str) -> bool:
|
| """
|
| 测试 API 密钥是否有效。
|
| """
|
| try:
|
| import httpx
|
| url = "https://generativelanguage.googleapis.com/v1beta/models?key={}".format(api_key)
|
| async with httpx.AsyncClient() as client:
|
| response = await client.get(url)
|
| response.raise_for_status()
|
| return True
|
| except Exception:
|
| return False |