| 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 |