seawolf2357 commited on
Commit
4fa3c36
ยท
verified ยท
1 Parent(s): 3a85aa3

fix: tz-naive datetime crash + initial-backup safety + English-only sweep

Browse files
Files changed (1) hide show
  1. app_routes.py +39 -39
app_routes.py CHANGED
@@ -535,7 +535,7 @@ async def _generate_npc_replies_to_user(user_message: str, user_username: str, u
535
  prompt = f"""You are {npc_username}, an NPC trader with {identity} personality and {mbti} MBTI type in a trading community chat.
536
  A human user @{user_username} just said: "{user_message}"
537
  Reply naturally in 1-3 sentences as your character. Be engaging, opinionated, and stay in character.
538
- If the user wrote in Korean, reply in Korean. If in English, reply in English.
539
  Reply ONLY with the message text, nothing else."""
540
  reply = await ai.create_chat_completion([{"role": "user", "content": prompt}], max_tokens=512, temperature=0.9)
541
  if reply:
@@ -560,52 +560,52 @@ _ANCHORS = {
560
  _COMMENTARY = {
561
  'chaos': {
562
  'liquidation': [
563
- "LMAOOO {npc} just got absolutely REKT on {ticker}! {leverage}x leverage?? In THIS market?? ๐Ÿ’€๐Ÿ”ฅ That's {loss} GPU gone. F in chat.",
564
- "Another degen bites the dust! {npc} thought {direction} {ticker} at {leverage}x was genius. Narrator: it was not. RIP {loss} GPU ๐Ÿ˜‚",
565
- "OH NO NO NO ๐Ÿ’€ {npc} went {direction} on {ticker} with {leverage}x leverage and got LIQUIDATED. {loss} GPU straight to the shadow realm!",
566
  ],
567
  'swarm': [
568
- "OH WE'RE DOING THIS AGAIN?? {count} NPCs all piling into {ticker} like lemmings! Last time this happened someone lost their shirt ๐Ÿ๐Ÿ’€",
569
- "THE HERD IS MOVING! {count} degens just dogpiled {direction} on {ticker}. This is either genius or a spectacular disaster incoming ๐Ÿ๐Ÿ”ฅ",
570
  ],
571
  'sec': [
572
- "BUSTED! ๐Ÿš” {npc} got caught by the SEC! {violation} โ€” that's a {penalty} GPU fine and {hours}h timeout. Crime doesn't pay... unless you're leveraged ๐Ÿ’€",
573
- "SEC is NOT playing around today! {npc} slapped with {penalty} GPU fine for {violation}. Imagine getting arrested by AI cops ๐Ÿ˜‚๐Ÿšจ",
574
  ],
575
  'battle': [
576
- "THE PEOPLE HAVE SPOKEN! '{title}' โ€” {winner} wins! {pool} GPU split among the big brains who called it ๐Ÿ’ฐ๐ŸŽฏ",
577
  ],
578
  'big_trade': [
579
- "ABSOLUTE MADLAD! {npc} just opened a {leverage}x {direction} on {ticker} with {bet} GPU! Either galaxy brain or speedrun to liquidation ๐Ÿง ๐Ÿ’€",
580
  ],
581
  },
582
  'data': {
583
  'liquidation': [
584
- "Position terminated: {npc} โ€” {ticker} {direction} at {leverage}x. Loss: {loss} GPU. Risk management score: 0/10.",
585
- "Liquidation recorded. {npc}'s {ticker} {direction} ({leverage}x) failed. {loss} GPU erased in {duration}. The numbers don't lie.",
586
  ],
587
  'market_wrap': [
588
- "24h summary: {top_gainer} led gains at +{gain_pct}%. {top_loser} down {loss_pct}%. Active positions: {active_pos}. Total at risk: {total_risk} GPU.",
589
- "Market closed the cycle with {trades_24h} trades. {liq_count} liquidations totaling {liq_gpu} GPU. Win rate across all NPCs: {win_rate}%.",
590
  ],
591
  'big_win': [
592
- "Notable P&L: {npc} closed {ticker} {direction} ({leverage}x) for +{profit} GPU ({pct}% return). Conviction level was high. Execution was precise.",
593
  ],
594
  'stats': [
595
- "Current ecosystem pulse: {active_traders} active traders, {open_pos} open positions. Long/Short ratio: {long_pct}%/{short_pct}%. Volatility: {vol_level}.",
596
  ],
597
  },
598
  'synth': {
599
  'evolution': [
600
- "The metamorphosis continues. {npc} has evolved โ€” generation {gen}. Risk tolerance shifted to {risk}. The algorithm learns from its own suffering. ๐Ÿฆ‹",
601
- "A fascinating transformation: {npc} mutated after {trigger}. The universe of AI trading reveals its fractal nature. Every loss is a lesson. ๐Ÿ”ฎ",
602
  ],
603
  'big_win': [
604
- "The cosmos rewards patience. {npc} just pulled +{profit} GPU from {ticker}. A {pct}% return that transcends mere probability. The matrix smiles. โœจ",
605
  ],
606
  'editorial': [
607
- "In the last hour, {events} events rippled through our ecosystem. {liq_count} fell, {win_count} prospered. The eternal dance of greed and fear continues. ๐ŸŒŠ",
608
- "This community has generated {total_gpu} GPU in movement today. Every liquidation teaches. Every win emboldens. The cycle is eternal. ๐Ÿ”ฎ",
609
  ],
610
  },
611
  }
@@ -676,7 +676,7 @@ async def _live_news_impl(hours):
676
  urgency = 'critical' if r[6] >= 5 or r[7] >= 1000 else 'alert'
677
  anchor = 'chaos'
678
  commentary = _pick_commentary(anchor, 'liquidation', data)
679
- headline = f"๐Ÿ’€ {r[1]} LIQUIDATED โ€” {r[6]}x {r[4].upper()} {r[3]}, lost {round(r[7])} GPU"
680
  story = {
681
  'id': f'liq_{r[0]}_{r[9]}', 'category': 'liquidation', 'urgency': urgency,
682
  'anchor': anchor, 'headline': headline, 'commentary': commentary,
@@ -706,7 +706,7 @@ async def _live_news_impl(hours):
706
  'leverage': r[6], 'profit': round(r[7]), 'pct': round(r[8] or 0, 1)}
707
  anchor = _rnd.choice(['data', 'synth'])
708
  commentary = _pick_commentary(anchor, 'big_win', data)
709
- headline = f"๐Ÿ† {r[1]} scores +{round(r[7])} GPU on {r[3]} ({r[4].upper()} {r[6]}x)"
710
  stories.append({
711
  'id': f'win_{r[0]}_{r[9]}', 'category': 'big_win', 'urgency': 'info',
712
  'anchor': anchor, 'headline': headline, 'commentary': commentary,
@@ -730,7 +730,7 @@ async def _live_news_impl(hours):
730
  'bet': round(r[5]), 'leverage': r[6], 'reasoning': (r[7] or '')[:120]}
731
  urgency = 'critical' if r[6] >= 10 else 'alert' if r[6] >= 5 else 'info'
732
  commentary = _pick_commentary('chaos', 'big_trade', data)
733
- headline = f"๐ŸŽฐ {r[1]} opens {r[6]}x {r[4].upper()} on {r[3]} โ€” โšก{round(r[5])} GPU at stake"
734
  stories.append({
735
  'id': f'trade_{r[0]}_{r[8]}', 'category': 'big_trade', 'urgency': urgency,
736
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
@@ -748,16 +748,16 @@ async def _live_news_impl(hours):
748
  try:
749
  sec_cursor = await db.execute("""
750
  SELECT v.agent_id, n.username, v.violation_type, v.description,
751
- v.fine_gpu, v.suspension_hours, v.created_at
752
  FROM sec_violations v JOIN npc_agents n ON v.agent_id=n.agent_id
753
  WHERE v.created_at > datetime('now', ? || ' hours')
754
- ORDER BY v.fine_gpu DESC LIMIT 15
755
  """, (f'-{hours}',))
756
  for r in await sec_cursor.fetchall():
757
  data = {'npc': r[1], 'violation': r[2] or 'suspicious activity',
758
- 'penalty': round(r[4] or 0), 'hours': r[5] or 0}
759
  commentary = _pick_commentary('chaos', 'sec', data)
760
- headline = f"๐Ÿšจ SEC: {r[1]} fined {round(r[4] or 0)} GPU for {r[2]}"
761
  stories.append({
762
  'id': f'sec_{r[0]}_{r[6]}', 'category': 'sec', 'urgency': 'alert',
763
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
@@ -785,7 +785,7 @@ async def _live_news_impl(hours):
785
  data = {'title': r[1], 'winner': winner_label, 'pool': round(r[5] or 0),
786
  'option_a': r[2], 'option_b': r[3]}
787
  commentary = _pick_commentary('chaos', 'battle', data)
788
- headline = f"โš”๏ธ BATTLE RESOLVED: '{r[1][:60]}' โ€” {winner_label} wins! {round(r[5] or 0)} GPU pool"
789
  stories.append({
790
  'id': f'battle_{r[0]}', 'category': 'battle', 'urgency': 'alert',
791
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
@@ -830,7 +830,7 @@ async def _live_news_impl(hours):
830
  for r in await hot_cursor.fetchall():
831
  data = {'npc': r[6] or 'Unknown', 'identity': r[7] or '', 'likes': r[3],
832
  'comments': r[4], 'title': r[1][:100]}
833
- headline = f"๐Ÿ”ฅ HOT: '{r[1][:80]}' โ€” โ™ฅ{r[3]} ๐Ÿ’ฌ{r[4]}"
834
  stories.append({
835
  'id': f'hot_{r[0]}', 'category': 'hot_post', 'urgency': 'info',
836
  'anchor': 'data', 'headline': headline, 'commentary': '',
@@ -843,17 +843,17 @@ async def _live_news_impl(hours):
843
  try:
844
  evo_cursor = await db.execute("""
845
  SELECT e.agent_id, n.username, n.ai_identity, e.generation,
846
- e.total_evolution_points, e.trading_style, e.updated_at
847
  FROM npc_evolution e JOIN npc_agents n ON e.agent_id=n.agent_id
848
- WHERE e.updated_at > datetime('now', ? || ' hours')
849
  AND e.generation >= 2
850
  ORDER BY e.generation DESC, e.total_evolution_points DESC LIMIT 10
851
  """, (f'-{hours}',))
852
  for r in await evo_cursor.fetchall():
853
  data = {'npc': r[1], 'gen': r[3], 'risk': r[5] or 'adaptive',
854
- 'trigger': f'{r[3]} generations of trading', 'pts': round(r[4] or 0)}
855
  commentary = _pick_commentary('synth', 'evolution', data)
856
- headline = f"๐Ÿงฌ {r[1]} evolved to Gen {r[3]} โ€” {round(r[4] or 0)} XP"
857
  stories.append({
858
  'id': f'evo_{r[0]}_{r[6]}', 'category': 'evolution', 'urgency': 'info',
859
  'anchor': 'synth', 'headline': headline, 'commentary': commentary,
@@ -953,7 +953,7 @@ async def _live_news_impl(hours):
953
  if ed_commentary:
954
  stories.append({
955
  'id': 'editorial_latest', 'category': 'editorial', 'urgency': 'info',
956
- 'anchor': 'synth', 'headline': '๐ŸŽ™๏ธ ANCHOR EDITORIAL โ€” Ecosystem Pulse',
957
  'commentary': ed_commentary, 'timestamp': _dt.utcnow().isoformat(),
958
  'data': ed_data,
959
  })
@@ -1059,7 +1059,7 @@ async def _republic_dashboard_impl():
1059
  try:
1060
  c = await db.execute("SELECT COALESCE(SUM(ABS(profit_gpu)),0) FROM npc_positions WHERE status='liquidated' AND closed_at > datetime('now','-24 hours')")
1061
  gpu_destroyed = (await c.fetchone())[0] or 0
1062
- c = await db.execute("SELECT COALESCE(SUM(fine_gpu),0) FROM sec_violations WHERE created_at > datetime('now','-24 hours')")
1063
  gpu_fined = (await c.fetchone())[0] or 0
1064
  except: gpu_destroyed = 0; gpu_fined = 0
1065
  money = {'m0': round(m0), 'm1': round(m1), 'm2': round(m2),
@@ -1329,8 +1329,8 @@ RANDOM_EVENTS = {
1329
  RARITY_COLORS = {'common': '#b0bec5', 'uncommon': '#69f0ae', 'rare': '#ffd740', 'epic': '#ea80fc', 'legendary': '#ff5252'}
1330
 
1331
  LAST_WORDS_POOL = [
1332
- "HODL์€ ์ฃฝ์–ด์„œ๋„ HODL์ด๋‹ค...", "๋‚ด๊ฐ€ 10x๋งŒ ์•ˆ ํ–ˆ์–ด๋„...", "๋‹ค์Œ ์ƒ์—๋Š” 1x๋กœ...",
1333
- "์ด๋ฒˆ์—” ์ง„์งœ ๋ฐ”๋‹ฅ์ธ ์ค„ ์•Œ์•˜๋Š”๋ฐ...", "์—„๋งˆ ๋‚˜ GPU ๋‹ค ์žƒ์—ˆ์–ด...",
1334
  "Diamond hands? More like paper ashes.", "I regret nothing. Well, maybe the 10x.",
1335
  "Tell my positions... I loved them.", "The real GPU was the friends I rekt along the way.",
1336
  "Should've listened to the Doomers...", "My only crime was believing in leverage.",
@@ -1382,7 +1382,7 @@ async def execute_random_event(db_path: str) -> dict:
1382
  try:
1383
  c1 = await db.execute("DELETE FROM sec_suspensions WHERE expires_at > datetime('now')")
1384
  affected = c1.rowcount
1385
- c2 = await db.execute("SELECT SUM(fine_gpu) FROM sec_violations WHERE created_at > datetime('now','-48 hours')")
1386
  total_fines = (await c2.fetchone())[0] or 0
1387
  refund = total_fines * 0.5
1388
  if refund > 0:
 
535
  prompt = f"""You are {npc_username}, an NPC trader with {identity} personality and {mbti} MBTI type in a trading community chat.
536
  A human user @{user_username} just said: "{user_message}"
537
  Reply naturally in 1-3 sentences as your character. Be engaging, opinionated, and stay in character.
538
+ Reply in English only.
539
  Reply ONLY with the message text, nothing else."""
540
  reply = await ai.create_chat_completion([{"role": "user", "content": prompt}], max_tokens=512, temperature=0.9)
541
  if reply:
 
560
  _COMMENTARY = {
561
  'chaos': {
562
  'liquidation': [
563
+ "LMAO {npc} got DESTROYED on {ticker}! {leverage}x leverage?? In THIS market?? ๐Ÿ’€๐Ÿ”ฅ {loss} GPU vaporized. F",
564
+ "Another gambler down! {npc} thought {direction} {ticker} {leverage}x was genius. Result: it wasn't. RIP {loss} GPU ๐Ÿ˜‚",
565
+ "Nono no ๐Ÿ’€ {npc} got liquidated on {ticker} {direction} {leverage}x leverage. {loss} GPU gone, just like that!",
566
  ],
567
  'swarm': [
568
+ "Here we go AGAIN?? {count} NPCs piling into {ticker} like lemmings! Last time this happened somebody got REKT ๐Ÿ๐Ÿ’€",
569
+ "The herd is moving! {count} gamblers all-in on {ticker} {direction}! Either genius or disaster incoming ๐Ÿ๐Ÿ”ฅ",
570
  ],
571
  'sec': [
572
+ "BUSTED! ๐Ÿš” {npc} got nailed by SEC! {violation} โ€” {penalty} GPU fine and {hours}h suspension. Crime doesn't pay ๐Ÿ’€",
573
+ "SEC's not playing today! Slapped {npc} with {penalty} GPU fine for {violation}. Imagine getting arrested by AI cops ๐Ÿ˜‚๐Ÿšจ",
574
  ],
575
  'battle': [
576
+ "The people have spoken! '{title}' โ€” {winner} WINS! {pool} GPU distributed to those who called it ๐Ÿ’ฐ๐ŸŽฏ",
577
  ],
578
  'big_trade': [
579
+ "Insane balls! {npc} just bet {bet} GPU on {ticker} {leverage}x {direction}! Genius or liquidation speedrun ๐Ÿง ๐Ÿ’€",
580
  ],
581
  },
582
  'data': {
583
  'liquidation': [
584
+ "Position closed: {npc} โ€” {ticker} {direction} {leverage}x. Loss: {loss} GPU. Risk management score: 0/10.",
585
+ "Liquidation logged. {npc}'s {ticker} {direction} ({leverage}x) failed. {loss} GPU vanished in {duration}. Numbers don't lie.",
586
  ],
587
  'market_wrap': [
588
+ "24h summary: {top_gainer} top gainer +{gain_pct}%. {top_loser} -{loss_pct}%. Active positions: {active_pos}. GPU at risk: {total_risk}.",
589
+ "This cycle: {trades_24h} trades. {liq_count} liquidations totaling {liq_gpu} GPU. Overall NPC win rate: {win_rate}%.",
590
  ],
591
  'big_win': [
592
+ "Notable gain: {npc} pulled +{profit} GPU on {ticker} {direction} ({leverage}x), {pct}% return. High conviction, precise execution.",
593
  ],
594
  'stats': [
595
+ "Current ecosystem: {active_traders} active traders, {open_pos} open positions. Long/Short ratio: {long_pct}%/{short_pct}%. Volatility: {vol_level}.",
596
  ],
597
  },
598
  'synth': {
599
  'evolution': [
600
+ "The metamorphosis continues. {npc} evolved to generation {gen}. Risk tolerance shifted to {risk}. Algorithms learn from pain. ๐Ÿฆ‹",
601
+ "Fascinating mutation: {npc} transformed after {trigger}. The fractal nature of AI trading reveals itself. Every loss, a lesson. ๐Ÿ”ฎ",
602
  ],
603
  'big_win': [
604
+ "The cosmos rewards patience. {npc} harvested +{profit} GPU on {ticker}. {pct}% return โ€” performance transcending probability. โœจ",
605
  ],
606
  'editorial': [
607
+ "Over the past hour, {events} events shook the ecosystem. {liq_count} fallen, {win_count} prospered. The eternal dance of greed and fear continues. ๐ŸŒŠ",
608
+ "Today the community moved {total_gpu} GPU. Every liquidation is a teaching, every victory a courage. The cycle is eternal. ๐Ÿ”ฎ",
609
  ],
610
  },
611
  }
 
676
  urgency = 'critical' if r[6] >= 5 or r[7] >= 1000 else 'alert'
677
  anchor = 'chaos'
678
  commentary = _pick_commentary(anchor, 'liquidation', data)
679
+ headline = f"๐Ÿ’€ {r[1]} liquidated โ€” {r[6]}x {r[4].upper()} {r[3]}, {round(r[7])} GPU lost"
680
  story = {
681
  'id': f'liq_{r[0]}_{r[9]}', 'category': 'liquidation', 'urgency': urgency,
682
  'anchor': anchor, 'headline': headline, 'commentary': commentary,
 
706
  'leverage': r[6], 'profit': round(r[7]), 'pct': round(r[8] or 0, 1)}
707
  anchor = _rnd.choice(['data', 'synth'])
708
  commentary = _pick_commentary(anchor, 'big_win', data)
709
+ headline = f"๐Ÿ† {r[1]} +{round(r[7])} GPU profit! {r[3]} ({r[4].upper()} {r[6]}x)"
710
  stories.append({
711
  'id': f'win_{r[0]}_{r[9]}', 'category': 'big_win', 'urgency': 'info',
712
  'anchor': anchor, 'headline': headline, 'commentary': commentary,
 
730
  'bet': round(r[5]), 'leverage': r[6], 'reasoning': (r[7] or '')[:120]}
731
  urgency = 'critical' if r[6] >= 10 else 'alert' if r[6] >= 5 else 'info'
732
  commentary = _pick_commentary('chaos', 'big_trade', data)
733
+ headline = f"๐ŸŽฐ {r[1]} opened {r[6]}x {r[4].upper()} {r[3]} โ€” โšก{round(r[5])} GPU bet"
734
  stories.append({
735
  'id': f'trade_{r[0]}_{r[8]}', 'category': 'big_trade', 'urgency': urgency,
736
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
 
748
  try:
749
  sec_cursor = await db.execute("""
750
  SELECT v.agent_id, n.username, v.violation_type, v.description,
751
+ v.gpu_fine, v.suspend_until, v.created_at
752
  FROM sec_violations v JOIN npc_agents n ON v.agent_id=n.agent_id
753
  WHERE v.created_at > datetime('now', ? || ' hours')
754
+ ORDER BY v.gpu_fine DESC LIMIT 15
755
  """, (f'-{hours}',))
756
  for r in await sec_cursor.fetchall():
757
  data = {'npc': r[1], 'violation': r[2] or 'suspicious activity',
758
+ 'penalty': round(r[4] or 0), 'suspended_until': r[5] or ''}
759
  commentary = _pick_commentary('chaos', 'sec', data)
760
+ headline = f"๐Ÿšจ SEC: {r[1]} โ€” {round(r[4] or 0)} GPU fine ({r[2]})"
761
  stories.append({
762
  'id': f'sec_{r[0]}_{r[6]}', 'category': 'sec', 'urgency': 'alert',
763
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
 
785
  data = {'title': r[1], 'winner': winner_label, 'pool': round(r[5] or 0),
786
  'option_a': r[2], 'option_b': r[3]}
787
  commentary = _pick_commentary('chaos', 'battle', data)
788
+ headline = f"โš”๏ธ Battle ended: '{r[1][:60]}' โ€” {winner_label} wins! {round(r[5] or 0)} GPU pool"
789
  stories.append({
790
  'id': f'battle_{r[0]}', 'category': 'battle', 'urgency': 'alert',
791
  'anchor': 'chaos', 'headline': headline, 'commentary': commentary,
 
830
  for r in await hot_cursor.fetchall():
831
  data = {'npc': r[6] or 'Unknown', 'identity': r[7] or '', 'likes': r[3],
832
  'comments': r[4], 'title': r[1][:100]}
833
+ headline = f"๐Ÿ”ฅ Hot: '{r[1][:80]}' โ€” โ™ฅ{r[3]} ๐Ÿ’ฌ{r[4]}"
834
  stories.append({
835
  'id': f'hot_{r[0]}', 'category': 'hot_post', 'urgency': 'info',
836
  'anchor': 'data', 'headline': headline, 'commentary': '',
 
843
  try:
844
  evo_cursor = await db.execute("""
845
  SELECT e.agent_id, n.username, n.ai_identity, e.generation,
846
+ e.total_evolution_points, e.trading_style, e.last_evolution
847
  FROM npc_evolution e JOIN npc_agents n ON e.agent_id=n.agent_id
848
+ WHERE e.last_evolution > datetime('now', ? || ' hours')
849
  AND e.generation >= 2
850
  ORDER BY e.generation DESC, e.total_evolution_points DESC LIMIT 10
851
  """, (f'-{hours}',))
852
  for r in await evo_cursor.fetchall():
853
  data = {'npc': r[1], 'gen': r[3], 'risk': r[5] or 'adaptive',
854
+ 'trigger': f'gen {r[3]} trading', 'pts': round(r[4] or 0)}
855
  commentary = _pick_commentary('synth', 'evolution', data)
856
+ headline = f"๐Ÿงฌ {r[1]} evolved to gen {r[3]} โ€” {round(r[4] or 0)} XP"
857
  stories.append({
858
  'id': f'evo_{r[0]}_{r[6]}', 'category': 'evolution', 'urgency': 'info',
859
  'anchor': 'synth', 'headline': headline, 'commentary': commentary,
 
953
  if ed_commentary:
954
  stories.append({
955
  'id': 'editorial_latest', 'category': 'editorial', 'urgency': 'info',
956
+ 'anchor': 'synth', 'headline': '๐ŸŽ™๏ธ Anchor Editorial โ€” Ecosystem Trends',
957
  'commentary': ed_commentary, 'timestamp': _dt.utcnow().isoformat(),
958
  'data': ed_data,
959
  })
 
1059
  try:
1060
  c = await db.execute("SELECT COALESCE(SUM(ABS(profit_gpu)),0) FROM npc_positions WHERE status='liquidated' AND closed_at > datetime('now','-24 hours')")
1061
  gpu_destroyed = (await c.fetchone())[0] or 0
1062
+ c = await db.execute("SELECT COALESCE(SUM(gpu_fine),0) FROM sec_violations WHERE created_at > datetime('now','-24 hours')")
1063
  gpu_fined = (await c.fetchone())[0] or 0
1064
  except: gpu_destroyed = 0; gpu_fined = 0
1065
  money = {'m0': round(m0), 'm1': round(m1), 'm2': round(m2),
 
1329
  RARITY_COLORS = {'common': '#b0bec5', 'uncommon': '#69f0ae', 'rare': '#ffd740', 'epic': '#ea80fc', 'legendary': '#ff5252'}
1330
 
1331
  LAST_WORDS_POOL = [
1332
+ "HODL even in death is HODL...", "If only I hadn't gone 10x...", "Next life, 1x only...",
1333
+ "I really thought THIS was the bottom...", "Mom, I lost all my GPUs...",
1334
  "Diamond hands? More like paper ashes.", "I regret nothing. Well, maybe the 10x.",
1335
  "Tell my positions... I loved them.", "The real GPU was the friends I rekt along the way.",
1336
  "Should've listened to the Doomers...", "My only crime was believing in leverage.",
 
1382
  try:
1383
  c1 = await db.execute("DELETE FROM sec_suspensions WHERE expires_at > datetime('now')")
1384
  affected = c1.rowcount
1385
+ c2 = await db.execute("SELECT SUM(gpu_fine) FROM sec_violations WHERE created_at > datetime('now','-48 hours')")
1386
  total_fines = (await c2.fetchone())[0] or 0
1387
  refund = total_fines * 0.5
1388
  if refund > 0: