max1949 commited on
Commit
1bd50ff
·
verified ·
1 Parent(s): 9933f70

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +14 -35
app.py CHANGED
@@ -17,7 +17,7 @@ import io
17
  import time
18
  import threading
19
  from PIL import Image, ImageDraw, ImageFont
20
- import gradio as gr # 替换 Flask 为 Gradio
21
 
22
  # ==============================================================================
23
  # 0. 机构级审计日志 (Institutional Logging)
@@ -35,7 +35,6 @@ logger = logging.getLogger("BK_GTA_ARCHITECT_GRADIO")
35
  def get_status():
36
  """
37
  提供给 UptimeRobot 的监控探针内容
38
- Gradio 会自动将其渲染为一个 API 端点,确保 HF 容器不休眠
39
  """
40
  now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
41
  latency = "N/A"
@@ -47,7 +46,7 @@ def get_status():
47
 
48
  return {
49
  "status": "BK-GTA-GRADIO-TITAN-ACTIVE",
50
- "version": "V62.9-Full-Stack",
51
  "bot_latency": latency,
52
  "server_time": now,
53
  "keys_loaded": len(KEY_POOL),
@@ -87,16 +86,16 @@ intents.message_content = True
87
  intents.members = True
88
  bot = commands.Bot(command_prefix='!', intents=intents)
89
 
90
- # 并发审计锁 (防止内存溢出)
91
  audit_lock = asyncio.Lock()
92
 
93
- # 数据库路径适配 (Gradio 模式也支持 /data 持久化)
94
  if os.path.exists('/data'):
95
  DB_PATH_CONFIG = '/data/bk_gta_v62_unified.json'
96
  logger.info(f"📂 [Storage] Using Persistent Storage: {DB_PATH_CONFIG}")
97
  else:
98
  DB_PATH_CONFIG = 'bk_gta_v62_unified.json'
99
- logger.warning(f"⚠️ [Storage] Using Ephemeral Storage (Data lost on restart).")
100
 
101
  # ==============================================================================
102
  # 3. 状态引擎 (BKEngine Core)
@@ -136,7 +135,6 @@ class BKEngine:
136
 
137
  def save_db(self):
138
  try:
139
- # 原子写入防止文件损坏
140
  temp = self.db_file + '.tmp'
141
  with open(temp, 'w', encoding='utf-8') as f:
142
  json.dump(self.data, f, ensure_ascii=False, indent=4)
@@ -215,9 +213,6 @@ def safe_extract_text(text, key_start, key_end=None):
215
  except: return "N/A"
216
 
217
  async def call_gemini_multiplex(prompt, attachment=None):
218
- """
219
- [Core Logic] 8 密钥自动轮询与故障转移
220
- """
221
  if not KEY_POOL: return "ERROR: NO_KEYS_CONFIGURED"
222
 
223
  image_data = None
@@ -254,7 +249,7 @@ async def call_gemini_multiplex(prompt, attachment=None):
254
  return "ERROR: ALL_KEYS_EXHAUSTED"
255
 
256
  # ==============================================================================
257
- # 5. 模块一:全网天梯 (Leaderboard)
258
  # ==============================================================================
259
  @bot.command()
260
  async def profile(ctx, member: discord.Member = None):
@@ -262,7 +257,6 @@ async def profile(ctx, member: discord.Member = None):
262
  u = bk_engine.get_user(target.id)
263
  elo = u['elo']
264
 
265
- # 完整段位逻辑
266
  if elo < 1300: rank, color = "Iron (学徒) 🗑️", 0x717d7e
267
  elif elo < 1500: rank, color = "Bronze (资深) 🥉", 0xcd7f32
268
  elif elo < 1800: rank, color = "Silver (精英) 🥈", 0xbdc3c7
@@ -301,7 +295,6 @@ async def leaderboard(ctx):
301
 
302
  emb = discord.Embed(title="🏆 Global Ranking (Institutional)", description=desc or "No data available.", color=0xf1c40f)
303
 
304
- # 阵营战况
305
  f_txt = ""
306
  for k, v in bk_engine.data["factions"].items():
307
  f_txt += f"{v['emoji']} {k}: {v['score']} pts | "
@@ -310,7 +303,7 @@ async def leaderboard(ctx):
310
  await ctx.send(embed=emb)
311
 
312
  # ==============================================================================
313
- # 6. 模块二:宏观情报 (Macro Intelligence)
314
  # ==============================================================================
315
  @bot.command()
316
  async def news(ctx):
@@ -336,16 +329,11 @@ async def news(ctx):
336
  await ctx.send(embed=emb)
337
 
338
  # ==============================================================================
339
- # 7. 模块三:量化审计 (Concurrent Safe Audit)
340
  # ==============================================================================
341
  @bot.command()
342
  async def evaluate(ctx):
343
- """
344
- 带有并发锁的审计功能,防止 HF 容器 OOM
345
- """
346
  if not ctx.message.attachments: return await ctx.send("❌ No image detected.")
347
-
348
- # [Lock Check] 检查是否忙碌
349
  if audit_lock.locked():
350
  return await ctx.send("⚠️ **[System Busy]** Another audit is processing. Please wait 10s.")
351
 
@@ -376,7 +364,6 @@ async def evaluate(ctx):
376
  status = "REJECTED (High Risk)"
377
  color = 0xe74c3c
378
  else:
379
- # 完整评分公式
380
  trades_adj = math.log10(max(trades, 1)) / 1.5
381
  s_final = s_base * min(max(trades_adj, 0.5), 1.2) * (sharpe/2.0 if sharpe>0 else 0.5)
382
  s_final = min(max(s_final, 0.0), 100.0)
@@ -395,7 +382,7 @@ async def evaluate(ctx):
395
  await ctx.send(embed=emb)
396
 
397
  # ==============================================================================
398
- # 8. 模块四:博弈盘口 (Betting System)
399
  # ==============================================================================
400
  @bot.command()
401
  @commands.has_permissions(administrator=True)
@@ -446,7 +433,7 @@ async def settle_bet(ctx, bid: str, winner: str):
446
  await ctx.send(f"🏁 Bet {bid} Settled. Winner: {winner}. Payouts Distributed.")
447
 
448
  # ==============================================================================
449
- # 9. 模块五:PVP 竞技场 (Arena)
450
  # ==============================================================================
451
  @bot.command()
452
  async def challenge(ctx, member: discord.Member):
@@ -493,13 +480,12 @@ async def duel_submit(ctx, did: str):
493
  await m.delete()
494
 
495
  # ==============================================================================
496
- # 10. 模块六:海报渲染 (Full Viral Poster)
497
  # ==============================================================================
498
  @bot.command()
499
  async def viral_audit(ctx):
500
  """
501
  [完整版] 提取审计数据并渲染具备社交传播属性的海报图片
502
- 包含完整的 PIL 绘图逻辑,无省略。
503
  """
504
  if not ctx.message.attachments:
505
  return await ctx.send("❌ 请上传审计截图。")
@@ -512,29 +498,23 @@ async def viral_audit(ctx):
512
 
513
  try:
514
  W, H = 600, 800
515
- # 创建暗黑科技风底色
516
  base = Image.new('RGB', (W, H), color=(18, 20, 30))
517
  draw = ImageDraw.Draw(base)
518
 
519
- # 1. 绘制装饰性雷达背景
520
  for i in range(0, W, 40): draw.line([(i, 0), (i, H)], fill=(30, 35, 45), width=1)
521
  for j in range(0, H, 40): draw.line([(0, j), (W, j)], fill=(30, 35, 45), width=1)
522
 
523
- # 2. 绘制外边框
524
  draw.rectangle([10, 10, 590, 790], outline=(46, 204, 113), width=2)
525
  draw.rectangle([20, 20, 580, 780], outline=(46, 204, 113), width=5)
526
 
527
- # 3. 填充文字数据 (默认字体降级)
528
  draw.text((40, 60), "BK-GTA QUANTITATIVE SYSTEM", fill=(255, 255, 255))
529
  draw.text((40, 150), f"TRADER ID: {ctx.author.name.upper()}", fill=(46, 204, 113))
530
  draw.text((40, 260), f"ALPHA RETURN: +{ret}%", fill=(255, 255, 255))
531
  draw.text((40, 360), f"SHARPE RATIO: {sharpe}", fill=(255, 255, 255))
532
  draw.text((40, 460), f"SESSION: {SESSION_ID}", fill=(120, 120, 130))
533
 
534
- # 加入验证水印
535
  draw.text((40, 720), "VERIFIED BY BK-GTA SENTINEL AI", fill=(46, 204, 113))
536
 
537
- # 内存缓冲交付
538
  fp = io.BytesIO()
539
  base.save(fp, 'PNG')
540
  fp.seek(0)
@@ -572,14 +552,13 @@ if __name__ == "__main__":
572
  # 1. 在后台线程启动 Discord 机器人 (非阻塞)
573
  threading.Thread(target=run_discord_bot).start()
574
 
575
- # 2. 在主线程启动 Gradio UI (这是 HF 要求的保活入口)
576
- # 这会生成一个网页,显示 JSON 状态,UptimeRobot 访问这个网页就能保活
577
  iface = gr.Interface(
578
  fn=get_status,
579
  inputs=None,
580
  outputs="json",
581
  title="BK-GTA Sentinel",
582
- description="Core logic is running in background thread.",
583
- every=5 # 自动刷新
584
  )
585
  iface.launch(server_name="0.0.0.0", server_port=7860)
 
17
  import time
18
  import threading
19
  from PIL import Image, ImageDraw, ImageFont
20
+ import gradio as gr
21
 
22
  # ==============================================================================
23
  # 0. 机构级审计日志 (Institutional Logging)
 
35
  def get_status():
36
  """
37
  提供给 UptimeRobot 的监控探针内容
 
38
  """
39
  now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
40
  latency = "N/A"
 
46
 
47
  return {
48
  "status": "BK-GTA-GRADIO-TITAN-ACTIVE",
49
+ "version": "V62.9-Stable",
50
  "bot_latency": latency,
51
  "server_time": now,
52
  "keys_loaded": len(KEY_POOL),
 
86
  intents.members = True
87
  bot = commands.Bot(command_prefix='!', intents=intents)
88
 
89
+ # 并发审计锁
90
  audit_lock = asyncio.Lock()
91
 
92
+ # 数据库路径适配
93
  if os.path.exists('/data'):
94
  DB_PATH_CONFIG = '/data/bk_gta_v62_unified.json'
95
  logger.info(f"📂 [Storage] Using Persistent Storage: {DB_PATH_CONFIG}")
96
  else:
97
  DB_PATH_CONFIG = 'bk_gta_v62_unified.json'
98
+ logger.warning(f"⚠️ [Storage] Using Ephemeral Storage.")
99
 
100
  # ==============================================================================
101
  # 3. 状态引擎 (BKEngine Core)
 
135
 
136
  def save_db(self):
137
  try:
 
138
  temp = self.db_file + '.tmp'
139
  with open(temp, 'w', encoding='utf-8') as f:
140
  json.dump(self.data, f, ensure_ascii=False, indent=4)
 
213
  except: return "N/A"
214
 
215
  async def call_gemini_multiplex(prompt, attachment=None):
 
 
 
216
  if not KEY_POOL: return "ERROR: NO_KEYS_CONFIGURED"
217
 
218
  image_data = None
 
249
  return "ERROR: ALL_KEYS_EXHAUSTED"
250
 
251
  # ==============================================================================
252
+ # 5. 模块一:全网天梯
253
  # ==============================================================================
254
  @bot.command()
255
  async def profile(ctx, member: discord.Member = None):
 
257
  u = bk_engine.get_user(target.id)
258
  elo = u['elo']
259
 
 
260
  if elo < 1300: rank, color = "Iron (学徒) 🗑️", 0x717d7e
261
  elif elo < 1500: rank, color = "Bronze (资深) 🥉", 0xcd7f32
262
  elif elo < 1800: rank, color = "Silver (精英) 🥈", 0xbdc3c7
 
295
 
296
  emb = discord.Embed(title="🏆 Global Ranking (Institutional)", description=desc or "No data available.", color=0xf1c40f)
297
 
 
298
  f_txt = ""
299
  for k, v in bk_engine.data["factions"].items():
300
  f_txt += f"{v['emoji']} {k}: {v['score']} pts | "
 
303
  await ctx.send(embed=emb)
304
 
305
  # ==============================================================================
306
+ # 6. 模块二:宏观情报
307
  # ==============================================================================
308
  @bot.command()
309
  async def news(ctx):
 
329
  await ctx.send(embed=emb)
330
 
331
  # ==============================================================================
332
+ # 7. 模块三:量化审计
333
  # ==============================================================================
334
  @bot.command()
335
  async def evaluate(ctx):
 
 
 
336
  if not ctx.message.attachments: return await ctx.send("❌ No image detected.")
 
 
337
  if audit_lock.locked():
338
  return await ctx.send("⚠️ **[System Busy]** Another audit is processing. Please wait 10s.")
339
 
 
364
  status = "REJECTED (High Risk)"
365
  color = 0xe74c3c
366
  else:
 
367
  trades_adj = math.log10(max(trades, 1)) / 1.5
368
  s_final = s_base * min(max(trades_adj, 0.5), 1.2) * (sharpe/2.0 if sharpe>0 else 0.5)
369
  s_final = min(max(s_final, 0.0), 100.0)
 
382
  await ctx.send(embed=emb)
383
 
384
  # ==============================================================================
385
+ # 8. 模块四:博弈盘口
386
  # ==============================================================================
387
  @bot.command()
388
  @commands.has_permissions(administrator=True)
 
433
  await ctx.send(f"🏁 Bet {bid} Settled. Winner: {winner}. Payouts Distributed.")
434
 
435
  # ==============================================================================
436
+ # 9. 模块五:PVP 竞技场
437
  # ==============================================================================
438
  @bot.command()
439
  async def challenge(ctx, member: discord.Member):
 
480
  await m.delete()
481
 
482
  # ==============================================================================
483
+ # 10. 模块六:海报渲染
484
  # ==============================================================================
485
  @bot.command()
486
  async def viral_audit(ctx):
487
  """
488
  [完整版] 提取审计数据并渲染具备社交传播属性的海报图片
 
489
  """
490
  if not ctx.message.attachments:
491
  return await ctx.send("❌ 请上传审计截图。")
 
498
 
499
  try:
500
  W, H = 600, 800
 
501
  base = Image.new('RGB', (W, H), color=(18, 20, 30))
502
  draw = ImageDraw.Draw(base)
503
 
 
504
  for i in range(0, W, 40): draw.line([(i, 0), (i, H)], fill=(30, 35, 45), width=1)
505
  for j in range(0, H, 40): draw.line([(0, j), (W, j)], fill=(30, 35, 45), width=1)
506
 
 
507
  draw.rectangle([10, 10, 590, 790], outline=(46, 204, 113), width=2)
508
  draw.rectangle([20, 20, 580, 780], outline=(46, 204, 113), width=5)
509
 
 
510
  draw.text((40, 60), "BK-GTA QUANTITATIVE SYSTEM", fill=(255, 255, 255))
511
  draw.text((40, 150), f"TRADER ID: {ctx.author.name.upper()}", fill=(46, 204, 113))
512
  draw.text((40, 260), f"ALPHA RETURN: +{ret}%", fill=(255, 255, 255))
513
  draw.text((40, 360), f"SHARPE RATIO: {sharpe}", fill=(255, 255, 255))
514
  draw.text((40, 460), f"SESSION: {SESSION_ID}", fill=(120, 120, 130))
515
 
 
516
  draw.text((40, 720), "VERIFIED BY BK-GTA SENTINEL AI", fill=(46, 204, 113))
517
 
 
518
  fp = io.BytesIO()
519
  base.save(fp, 'PNG')
520
  fp.seek(0)
 
552
  # 1. 在后台线程启动 Discord 机器人 (非阻塞)
553
  threading.Thread(target=run_discord_bot).start()
554
 
555
+ # 2. 在主线程启动 Gradio UI
556
+ # [FIX] 移除了 every=5 参数以修复 TypeError
557
  iface = gr.Interface(
558
  fn=get_status,
559
  inputs=None,
560
  outputs="json",
561
  title="BK-GTA Sentinel",
562
+ description="Core logic is running in background thread."
 
563
  )
564
  iface.launch(server_name="0.0.0.0", server_port=7860)