clash-linux commited on
Commit
3cdbb76
·
verified ·
1 Parent(s): 8fea9ab

Upload 55 files

Browse files
app/api/dashboard.py CHANGED
@@ -95,7 +95,7 @@ async def get_dashboard_data():
95
  api_key_stats.sort(key=lambda x: x['usage_percent'], reverse=True)
96
 
97
  # 获取最近的日志
98
- recent_logs = log_manager.get_recent_logs(50) # 获取最近50条日志
99
 
100
  # 返回JSON格式的数据
101
  return {
 
95
  api_key_stats.sort(key=lambda x: x['usage_percent'], reverse=True)
96
 
97
  # 获取最近的日志
98
+ recent_logs = log_manager.get_recent_logs(500) # 获取最近50条日志
99
 
100
  # 返回JSON格式的数据
101
  return {
app/config/settings.py CHANGED
@@ -8,12 +8,13 @@ BASE_DIR = pathlib.Path(__file__).parent.parent
8
 
9
  # 流式响应配置
10
  FAKE_STREAMING = os.environ.get("FAKE_STREAMING", "true").lower() in ["true", "1", "yes"]
 
 
11
 
12
  #随机字符串
13
  RANDOM_STRING = os.environ.get("RANDOM_STRING", "true").lower() in ["true", "1", "yes"]
14
- RANDOM_STRING_LENGTH = int(os.environ.get("RANDOM_STRING_LENGTH", "25"))
15
- # 假流式请求的空内容返回间隔(秒)
16
- FAKE_STREAMING_INTERVAL = float(os.environ.get("FAKE_STREAMING_INTERVAL", "1"))
17
 
18
  # 日志配置
19
  logging.getLogger("uvicorn").disabled = True
@@ -39,10 +40,12 @@ REMOVE_CACHE_AFTER_USE = os.environ.get("REMOVE_CACHE_AFTER_USE", "true").lower(
39
  REQUEST_HISTORY_EXPIRY_TIME = int(os.environ.get("REQUEST_HISTORY_EXPIRY_TIME", "600")) # 默认10分钟
40
  ENABLE_RECONNECT_DETECTION = os.environ.get("ENABLE_RECONNECT_DETECTION", "true").lower() in ["true", "1", "yes"]
41
 
42
- # 版本信息
43
- local_version = "0.0.4"
44
- remote_version = "0.0.4"
45
- has_update = False
 
 
46
 
47
  # API调用统计
48
  api_call_stats = {
@@ -71,4 +74,4 @@ DEFAULT_BLOCKED_MODELS = []
71
  # 环境变量格式应为逗号分隔的模型名称字符串
72
  BLOCKED_MODELS = os.environ.get("BLOCKED_MODELS", ",".join(DEFAULT_BLOCKED_MODELS))
73
  # 将字符串转换为列表
74
- BLOCKED_MODELS = [model.strip() for model in BLOCKED_MODELS.split(",") if model.strip()]
 
8
 
9
  # 流式响应配置
10
  FAKE_STREAMING = os.environ.get("FAKE_STREAMING", "true").lower() in ["true", "1", "yes"]
11
+ # 假流式请求的空内容返回间隔(秒)
12
+ FAKE_STREAMING_INTERVAL = float(os.environ.get("FAKE_STREAMING_INTERVAL", "1"))
13
 
14
  #随机字符串
15
  RANDOM_STRING = os.environ.get("RANDOM_STRING", "true").lower() in ["true", "1", "yes"]
16
+ RANDOM_STRING_LENGTH = int(os.environ.get("RANDOM_STRING_LENGTH", "20"))
17
+
 
18
 
19
  # 日志配置
20
  logging.getLogger("uvicorn").disabled = True
 
40
  REQUEST_HISTORY_EXPIRY_TIME = int(os.environ.get("REQUEST_HISTORY_EXPIRY_TIME", "600")) # 默认10分钟
41
  ENABLE_RECONNECT_DETECTION = os.environ.get("ENABLE_RECONNECT_DETECTION", "true").lower() in ["true", "1", "yes"]
42
 
43
+
44
+ version={
45
+ "local_version":"0.0.0",
46
+ "remote_version":"0.0.0",
47
+ "has_update":False
48
+ }
49
 
50
  # API调用统计
51
  api_call_stats = {
 
74
  # 环境变量格式应为逗号分隔的模型名称字符串
75
  BLOCKED_MODELS = os.environ.get("BLOCKED_MODELS", ",".join(DEFAULT_BLOCKED_MODELS))
76
  # 将字符串转换为列表
77
+ BLOCKED_MODELS = [model.strip() for model in BLOCKED_MODELS.split(",") if model.strip()]
app/main.py CHANGED
@@ -22,6 +22,8 @@ from app.api import router, init_router, dashboard_router, init_dashboard_router
22
  from app.config.settings import (
23
  FAKE_STREAMING,
24
  FAKE_STREAMING_INTERVAL,
 
 
25
  PASSWORD,
26
  MAX_REQUESTS_PER_MINUTE,
27
  MAX_REQUESTS_PER_DAY_PER_IP,
@@ -34,9 +36,7 @@ from app.config.settings import (
34
  ENABLE_RECONNECT_DETECTION,
35
  api_call_stats,
36
  client_request_history,
37
- local_version,
38
- remote_version,
39
- has_update,
40
  API_KEY_DAILY_LIMIT
41
  )
42
  from app.config.safety import SAFETY_SETTINGS, SAFETY_SETTINGS_G2
@@ -115,7 +115,6 @@ async def startup_event():
115
 
116
  # 检查版本
117
  await check_version()
118
-
119
  available_keys = await check_keys()
120
  if available_keys:
121
  key_manager.api_keys = available_keys
@@ -202,7 +201,7 @@ async def root(request: Request):
202
  continue
203
 
204
  # 获取最近的日志
205
- recent_logs = log_manager.get_recent_logs(50) # 获取最近50条日志
206
 
207
  # 获取缓存统计
208
  total_cache = len(response_cache_manager.cache)
@@ -267,9 +266,15 @@ async def root(request: Request):
267
  "current_time": datetime.now().strftime('%H:%M:%S'),
268
  "logs": recent_logs,
269
  # 添加版本信息
270
- "local_version": local_version,
271
- "remote_version": remote_version,
272
- "has_update": has_update,
 
 
 
 
 
 
273
  # 添加缓存信息
274
  "cache_entries": total_cache,
275
  "valid_cache": valid_cache,
 
22
  from app.config.settings import (
23
  FAKE_STREAMING,
24
  FAKE_STREAMING_INTERVAL,
25
+ RANDOM_STRING,
26
+ RANDOM_STRING_LENGTH,
27
  PASSWORD,
28
  MAX_REQUESTS_PER_MINUTE,
29
  MAX_REQUESTS_PER_DAY_PER_IP,
 
36
  ENABLE_RECONNECT_DETECTION,
37
  api_call_stats,
38
  client_request_history,
39
+ version,
 
 
40
  API_KEY_DAILY_LIMIT
41
  )
42
  from app.config.safety import SAFETY_SETTINGS, SAFETY_SETTINGS_G2
 
115
 
116
  # 检查版本
117
  await check_version()
 
118
  available_keys = await check_keys()
119
  if available_keys:
120
  key_manager.api_keys = available_keys
 
201
  continue
202
 
203
  # 获取最近的日志
204
+ recent_logs = log_manager.get_recent_logs(500) # 获取最近50条日志
205
 
206
  # 获取缓存统计
207
  total_cache = len(response_cache_manager.cache)
 
266
  "current_time": datetime.now().strftime('%H:%M:%S'),
267
  "logs": recent_logs,
268
  # 添加版本信息
269
+ "local_version": version["local_version"],
270
+ "remote_version": version["remote_version"],
271
+ "has_update": version["has_update"],
272
+ # 添加流式响应配置
273
+ "fake_streaming": FAKE_STREAMING,
274
+ "fake_streaming_interval": FAKE_STREAMING_INTERVAL,
275
+ # 添加随机字符串配置
276
+ "random_string": RANDOM_STRING,
277
+ "random_string_length": RANDOM_STRING_LENGTH,
278
  # 添加缓存信息
279
  "cache_entries": total_cache,
280
  "valid_cache": valid_cache,
app/templates/index.html CHANGED
@@ -240,6 +240,15 @@
240
  .progress-bar.high {
241
  background-color: #dc3545; /* 红色 - 高使用率 */
242
  }
 
 
 
 
 
 
 
 
 
243
  </style>
244
  </head>
245
  <body>
@@ -294,6 +303,9 @@
294
 
295
  <div class="info-box">
296
  <h2 class="section-title">⚙️ 环境配置</h2>
 
 
 
297
  <div class="stats-grid">
298
  <div class="stat-card">
299
  <div class="stat-value">{{ max_requests_per_minute }}</div>
@@ -308,30 +320,41 @@
308
  <div class="stat-label">当前服务器时间</div>
309
  </div>
310
  </div>
311
- </div>
312
-
313
- <div class="info-box">
314
- <h2 class="section-title">📦 版本信息</h2>
315
- <div class="version-info" style="text-align: center; margin-bottom: 15px;">
316
- <div style="font-size: 18px; margin-bottom: 10px;">
317
- 当前版本: <span style="font-weight: bold; color: #007bff;">{{ local_version }}</span>
318
  </div>
319
- {% if has_update %}
320
- <div style="display: flex; align-items: center; justify-content: center; margin-top: 15px;">
321
- <div style="background-color: #fef6e0; border: 1px solid #ffeeba; border-radius: 4px; padding: 10px 15px; display: inline-flex; align-items: center;">
322
- <span style="color: #ff9800; margin-right: 10px;">
323
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
324
- <circle cx="12" cy="12" r="10"></circle>
325
- <line x1="12" y1="8" x2="12" y2="12"></line>
326
- <line x1="12" y1="16" x2="12.01" y2="16"></line>
327
- </svg>
328
- </span>
329
- <span>
330
- <strong>发现新版本!</strong> 最新版本: <span style="font-weight: bold; color: #28a745;">{{ remote_version }}</span>
331
- </span>
 
 
 
 
 
 
 
 
 
 
 
332
  </div>
 
333
  </div>
334
- {% endif %}
335
  </div>
336
  </div>
337
 
 
240
  .progress-bar.high {
241
  background-color: #dc3545; /* 红色 - 高使用率 */
242
  }
243
+
244
+ /* 版本更新状态样式 */
245
+ .update-needed {
246
+ color: #dc3545; /* 红色 - 需要更新 */
247
+ }
248
+
249
+ .up-to-date {
250
+ color: #28a745; /* 绿色 - 已是最新 */
251
+ }
252
  </style>
253
  </head>
254
  <body>
 
303
 
304
  <div class="info-box">
305
  <h2 class="section-title">⚙️ 环境配置</h2>
306
+
307
+ <!-- 基本配置 -->
308
+ <h3 class="section-title">基本配置</h3>
309
  <div class="stats-grid">
310
  <div class="stat-card">
311
  <div class="stat-value">{{ max_requests_per_minute }}</div>
 
320
  <div class="stat-label">当前服务器时间</div>
321
  </div>
322
  </div>
323
+
324
+ <!-- 功能配置 -->
325
+ <h3 class="section-title">功能配置</h3>
326
+ <div class="stats-grid">
327
+ <div class="stat-card">
328
+ <div class="stat-value">{{ "启用" if fake_streaming else "禁用" }}</div>
329
+ <div class="stat-label">假流式响应</div>
330
  </div>
331
+ <div class="stat-card">
332
+ <div class="stat-value">{{ fake_streaming_interval }}秒</div>
333
+ <div class="stat-label">假流式间隔</div>
334
+ </div>
335
+ <div class="stat-card">
336
+ <div class="stat-value">{{ "启用" if random_string else "禁用" }}</div>
337
+ <div class="stat-label">伪装信息</div>
338
+ </div>
339
+ </div>
340
+
341
+ <!-- 版本信息 -->
342
+ <h3 class="section-title">版本信息</h3>
343
+ <div class="stats-grid">
344
+ <div class="stat-card">
345
+ <div class="stat-value">{{ local_version }}</div>
346
+ <div class="stat-label">当前版本</div>
347
+ </div>
348
+ <div class="stat-card">
349
+ <div class="stat-value">{{ remote_version }}</div>
350
+ <div class="stat-label">最新版本</div>
351
+ </div>
352
+ <div class="stat-card">
353
+ <div class="stat-value {% if has_update %}update-needed{% else %}up-to-date{% endif %}">
354
+ {{ "需要更新" if has_update else "已是最新" }}
355
  </div>
356
+ <div class="stat-label">更新状态</div>
357
  </div>
 
358
  </div>
359
  </div>
360
 
app/utils/maintenance.py CHANGED
@@ -1,9 +1,12 @@
1
- import sys
2
- from apscheduler.schedulers.background import BackgroundScheduler
 
3
  from app.utils.logging import log
4
  from app.utils.stats import clean_expired_stats
5
  from app.config import api_call_stats
6
  from app.utils import check_version
 
 
7
  def handle_exception(exc_type, exc_value, exc_traceback):
8
  """
9
  全局异常处理函数
@@ -16,7 +19,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
16
  from app.utils.error_handling import translate_error
17
  error_message = translate_error(str(exc_value))
18
  log('error', f"未捕获的异常: {error_message}", status_code=500, error_message=error_message)
19
-
20
  def schedule_cache_cleanup(response_cache_manager, active_requests_manager):
21
  """
22
  设置定期清理缓存和活跃请求的定时任务
@@ -30,7 +33,45 @@ def schedule_cache_cleanup(response_cache_manager, active_requests_manager):
30
  scheduler.add_job(active_requests_manager.clean_completed, 'interval', seconds=30) # 每30秒清理已完成的活跃请求
31
  scheduler.add_job(active_requests_manager.clean_long_running, 'interval', minutes=5, args=[300]) # 每5分钟清理运行超过5分钟的任务
32
  scheduler.add_job(clean_expired_stats, 'interval', minutes=5,args=[api_call_stats]) # 每5分钟清理过期的统计数据
33
- scheduler.add_job(check_version, 'interval', minutes=240) # 每4小时检查更新
34
  scheduler.start()
35
 
36
- return scheduler
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys,asyncio
2
+ #from apscheduler.schedulers.background import BackgroundScheduler
3
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler # 替换为异步调度器
4
  from app.utils.logging import log
5
  from app.utils.stats import clean_expired_stats
6
  from app.config import api_call_stats
7
  from app.utils import check_version
8
+ from zoneinfo import ZoneInfo
9
+ from app.config import settings
10
  def handle_exception(exc_type, exc_value, exc_traceback):
11
  """
12
  全局异常处理函数
 
19
  from app.utils.error_handling import translate_error
20
  error_message = translate_error(str(exc_value))
21
  log('error', f"未捕获的异常: {error_message}", status_code=500, error_message=error_message)
22
+ '''
23
  def schedule_cache_cleanup(response_cache_manager, active_requests_manager):
24
  """
25
  设置定期清理缓存和活跃请求的定时任务
 
33
  scheduler.add_job(active_requests_manager.clean_completed, 'interval', seconds=30) # 每30秒清理已完成的活跃请求
34
  scheduler.add_job(active_requests_manager.clean_long_running, 'interval', minutes=5, args=[300]) # 每5分钟清理运行超过5分钟的任务
35
  scheduler.add_job(clean_expired_stats, 'interval', minutes=5,args=[api_call_stats]) # 每5分钟清理过期的统计数据
36
+ scheduler.add_job(check_version, 'interval', minutes=1) # 每4小时检查更新
37
  scheduler.start()
38
 
39
+ return scheduler
40
+
41
+ '''
42
+ def schedule_cache_cleanup(response_cache_manager, active_requests_manager):
43
+ """
44
+ 设置定期清理缓存和活跃请求的定时任务
45
+ 顺便定时检查更新
46
+ Args:
47
+ response_cache_manager: 响应缓存管理器实例
48
+ active_requests_manager: 活跃请求管理器实例
49
+ """
50
+ beijing_tz = ZoneInfo("Asia/Shanghai")
51
+ scheduler = AsyncIOScheduler(timezone=beijing_tz) # 使用 AsyncIOScheduler 替代 BackgroundScheduler
52
+
53
+ # 添加任务时直接传递异步函数(无需额外包装)
54
+ scheduler.add_job(response_cache_manager.clean_expired, 'interval', minutes=1)
55
+ scheduler.add_job(active_requests_manager.clean_completed, 'interval', seconds=30)
56
+ scheduler.add_job(active_requests_manager.clean_long_running, 'interval', minutes=5, args=[300])
57
+ scheduler.add_job(clean_expired_stats, 'interval', minutes=5, args=[api_call_stats])
58
+ scheduler.add_job(check_version, 'interval', hours=4)
59
+ scheduler.add_job(api_call_stats_clean, 'cron', hour=16,minute=0)
60
+ scheduler.start()
61
+ return scheduler
62
+
63
+ def api_call_stats_clean():
64
+ settings.api_call_stats = {
65
+ 'last_24h': {
66
+ 'total': {},
67
+ 'by_endpoint': {}
68
+ },
69
+ 'hourly': {
70
+ 'total': {},
71
+ 'by_endpoint': {}
72
+ },
73
+ 'minute': {
74
+ 'total': {},
75
+ 'by_endpoint': {}
76
+ }
77
+ }
app/utils/version.py CHANGED
@@ -13,18 +13,17 @@ async def check_version():
13
  # 读取本地版本
14
  with open("./version.txt", "r") as f:
15
  version_line = f.read().strip()
16
- settings.local_version = version_line.split("=")[1] if "=" in version_line else "0.0.0"
17
 
18
  # 获取远程版本
19
  github_url = "https://raw.githubusercontent.com/wyeeeee/hajimi/refs/heads/main/version.txt"
20
  response = requests.get(github_url, timeout=5)
21
  if response.status_code == 200:
22
  version_line = response.text.strip()
23
- settings.remote_version = version_line.split("=")[1] if "=" in version_line else "0.0.0"
24
-
25
  # 比较版本号
26
- local_parts = [int(x) for x in settings.local_version.split(".")]
27
- remote_parts = [int(x) for x in settings.remote_version.split(".")]
28
 
29
  # 确保两个列表长度相同
30
  while len(local_parts) < len(remote_parts):
@@ -33,18 +32,18 @@ async def check_version():
33
  remote_parts.append(0)
34
 
35
  # 比较版本号
36
- settings.has_update = False
37
  for i in range(len(local_parts)):
38
  if remote_parts[i] > local_parts[i]:
39
- settings.has_update = True
40
  break
41
  elif remote_parts[i] < local_parts[i]:
42
  break
43
 
44
- log('info', f"版本检查: 本地版本 {settings.local_version}, 远程版本 {settings.remote_version}, 有更新: {settings.has_update}")
45
  else:
46
  log('warning', f"无法获取远程版本信息,HTTP状态码: {response.status_code}")
47
  except Exception as e:
48
  log('error', f"版本检查失败: {str(e)}")
49
 
50
- return settings.local_version, settings.remote_version, settings.has_update
 
13
  # 读取本地版本
14
  with open("./version.txt", "r") as f:
15
  version_line = f.read().strip()
16
+ settings.version['local_version'] = version_line.split("=")[1] if "=" in version_line else "0.0.0"
17
 
18
  # 获取远程版本
19
  github_url = "https://raw.githubusercontent.com/wyeeeee/hajimi/refs/heads/main/version.txt"
20
  response = requests.get(github_url, timeout=5)
21
  if response.status_code == 200:
22
  version_line = response.text.strip()
23
+ settings.version['remote_version']= version_line.split("=")[1] if "=" in version_line else "0.0.0"
 
24
  # 比较版本号
25
+ local_parts = [int(x) for x in settings.version['local_version'].split(".")]
26
+ remote_parts = [int(x) for x in settings.version['remote_version'].split(".")]
27
 
28
  # 确保两个列表长度相同
29
  while len(local_parts) < len(remote_parts):
 
32
  remote_parts.append(0)
33
 
34
  # 比较版本号
35
+ settings.version['has_update'] = False
36
  for i in range(len(local_parts)):
37
  if remote_parts[i] > local_parts[i]:
38
+ settings.version['has_update'] = True
39
  break
40
  elif remote_parts[i] < local_parts[i]:
41
  break
42
 
43
+ log('info', f"版本检查: 本地版本 {settings.version['local_version']}, 远程版本 {settings.version['remote_version']}, 有更新: {settings.version['has_update']}")
44
  else:
45
  log('warning', f"无法获取远程版本信息,HTTP状态码: {response.status_code}")
46
  except Exception as e:
47
  log('error', f"版本检查失败: {str(e)}")
48
 
49
+ return settings.version['has_update']