Spaces:
Running
Running
Update app_routes.py
Browse files- app_routes.py +21 -21
app_routes.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
from fastapi import APIRouter, Request
|
| 2 |
from fastapi.responses import StreamingResponse
|
| 3 |
import aiosqlite, asyncio, random, json, logging
|
| 4 |
-
from npc_core import GroqAIClient
|
| 5 |
from npc_trading import (
|
| 6 |
ALL_TICKERS, TRADING_STRATEGIES, IDENTITY_STRATEGY_MAP,
|
| 7 |
get_all_prices, get_ticker_positions, get_trading_leaderboard, get_trading_stats,
|
|
@@ -67,7 +67,7 @@ async def api_market_indices():
|
|
| 67 |
return {"indices": indices}
|
| 68 |
@router.get("/api/intelligence/screening/{ticker}")
|
| 69 |
async def api_screening_data(ticker: str):
|
| 70 |
-
async with
|
| 71 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 72 |
try:
|
| 73 |
cursor = await db.execute("SELECT ticker, price, change_pct, volume, market_cap, rsi, pe_ratio, high_52w, low_52w, from_high, from_low FROM market_prices WHERE ticker=?", (ticker,))
|
|
@@ -77,7 +77,7 @@ async def api_screening_data(ticker: str):
|
|
| 77 |
return {"ticker": ticker, "error": "no data"}
|
| 78 |
@router.get("/api/intelligence/target/{ticker}")
|
| 79 |
async def api_target_price(ticker: str):
|
| 80 |
-
async with
|
| 81 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 82 |
try:
|
| 83 |
cursor = await db.execute("SELECT price, rsi, pe_ratio, from_high, from_low FROM market_prices WHERE ticker=?", (ticker,))
|
|
@@ -94,7 +94,7 @@ async def api_target_price(ticker: str):
|
|
| 94 |
async def api_news_feed(ticker: str = None, limit: int = 50):
|
| 95 |
news = await load_news_from_db(_DB_PATH, ticker, limit)
|
| 96 |
try:
|
| 97 |
-
async with
|
| 98 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 99 |
for n in news:
|
| 100 |
nid = n.get('id')
|
|
@@ -109,7 +109,7 @@ async def api_news_react(request: Request):
|
|
| 109 |
body = await request.json(); email = body.get("email", ""); news_id = body.get("news_id"); emoji = body.get("emoji", "")
|
| 110 |
if not email or not news_id or emoji not in ('π','π₯','π±','π','π','π'): return {"error": "Invalid reaction"}
|
| 111 |
try:
|
| 112 |
-
async with
|
| 113 |
await db.execute("PRAGMA busy_timeout=30000"); await db.execute("INSERT OR IGNORE INTO news_reactions (news_id, user_email, emoji) VALUES (?,?,?)", (news_id, email, emoji)); await db.commit()
|
| 114 |
rc = await db.execute("SELECT emoji, COUNT(*) FROM news_reactions WHERE news_id=? GROUP BY emoji", (news_id,))
|
| 115 |
return {"success": True, "reactions": {r[0]: r[1] for r in await rc.fetchall()}}
|
|
@@ -150,7 +150,7 @@ async def api_deep_analysis(ticker: str):
|
|
| 150 |
@router.get("/api/analysis/all/summary")
|
| 151 |
async def api_all_analyses():
|
| 152 |
analyses = await load_all_analyses_from_db(_DB_PATH)
|
| 153 |
-
async with
|
| 154 |
await db.execute("PRAGMA busy_timeout=30000"); col_cursor = await db.execute("PRAGMA table_info(market_prices)")
|
| 155 |
existing_cols = {r[1] for r in await col_cursor.fetchall()}
|
| 156 |
has_rsi = 'rsi' in existing_cols; has_pe = 'pe_ratio' in existing_cols; has_52w = 'high_52w' in existing_cols; has_from = 'from_high' in existing_cols
|
|
@@ -219,13 +219,13 @@ async def api_all_analyses():
|
|
| 219 |
@router.get("/api/npc/search")
|
| 220 |
async def api_npc_search(q: str = ""):
|
| 221 |
if len(q) < 1: return {"npcs": []}
|
| 222 |
-
async with
|
| 223 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT agent_id, username, ai_identity FROM npc_agents WHERE username LIKE ? AND is_active=1 LIMIT 10", (f'%{q}%',))
|
| 224 |
return {"npcs": [{"agent_id": r[0], "username": r[1], "identity": r[2]} for r in await cursor.fetchall()]}
|
| 225 |
@router.get("/api/npc/profile/{agent_id}")
|
| 226 |
async def api_npc_profile(agent_id: str):
|
| 227 |
try:
|
| 228 |
-
async with
|
| 229 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 230 |
cursor = await db.execute("SELECT agent_id, username, ai_identity, mbti, gpu_dollars, created_at FROM npc_agents WHERE agent_id=?", (agent_id,))
|
| 231 |
row = await cursor.fetchone()
|
|
@@ -302,7 +302,7 @@ async def api_sec_dashboard():
|
|
| 302 |
return {"stats": {"total_violations": 0, "total_fines_gpu": 0, "active_suspensions": 0, "pending_reports": 0}, "announcements": [], "top_violators": [], "recent_reports": []}
|
| 303 |
@router.get("/api/sec/violations/{agent_id}")
|
| 304 |
async def api_sec_violations(agent_id: str):
|
| 305 |
-
async with
|
| 306 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 307 |
cursor = await db.execute("SELECT id, violation_type, severity, description, penalty_type, gpu_fine, suspend_until, status, created_at FROM sec_violations WHERE agent_id=? ORDER BY created_at DESC LIMIT 20", (agent_id,))
|
| 308 |
violations = [{'id': r[0], 'type': r[1], 'severity': r[2], 'description': r[3], 'penalty': r[4], 'fine': r[5], 'suspend_until': r[6], 'status': r[7], 'created_at': r[8]} for r in await cursor.fetchall()]
|
|
@@ -316,7 +316,7 @@ async def api_sec_report(request: Request):
|
|
| 316 |
if not reporter or not target or not reason: return {"error": "reporter, target, reason required"}
|
| 317 |
if reporter == target: return {"error": "Cannot report yourself"}
|
| 318 |
reporter_id = f"user_{reporter}" if '@' in reporter else reporter
|
| 319 |
-
async with
|
| 320 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 321 |
cursor = await db.execute("SELECT id FROM sec_reports WHERE reporter_agent_id=? AND target_agent_id=? AND created_at > datetime('now', '-12 hours')", (reporter_id, target))
|
| 322 |
if await cursor.fetchone(): return {"error": "Already reported this NPC recently (12h cooldown)"}
|
|
@@ -334,7 +334,7 @@ async def api_sec_seed():
|
|
| 334 |
("Front-running detected β trading ahead of own analysis publications", "front_running", "medium", "fine", 300, 0),
|
| 335 |
("Coordinated short attack with fake news β colluding with other NPCs", "collusion", "critical", "suspension", 1500, 96)]
|
| 336 |
try:
|
| 337 |
-
async with
|
| 338 |
await db.execute("PRAGMA busy_timeout=30000"); vc = await db.execute("SELECT COUNT(*) FROM sec_violations"); cnt = (await vc.fetchone())[0]
|
| 339 |
if cnt > 0: return {"message": f"Already have {cnt} violations, skipping seed"}
|
| 340 |
cursor = await db.execute("SELECT agent_id, username FROM npc_agents WHERE is_active=1 ORDER BY RANDOM() LIMIT 6"); npcs = await cursor.fetchall()
|
|
@@ -352,13 +352,13 @@ async def api_sec_seed():
|
|
| 352 |
except Exception as e: return {"error": str(e)}
|
| 353 |
@router.get("/api/sec/announcements")
|
| 354 |
async def api_sec_announcements(limit: int = 30):
|
| 355 |
-
async with
|
| 356 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 357 |
cursor = await db.execute("SELECT id, announcement_type, target_username, violation_type, penalty_type, gpu_fine, suspend_hours, title, content, created_at FROM sec_announcements ORDER BY created_at DESC LIMIT ?", (min(limit, 50),))
|
| 358 |
return {"announcements": [{'id': r[0], 'type': r[1], 'target': r[2], 'violation': r[3], 'penalty': r[4], 'fine': r[5], 'hours': r[6], 'title': r[7], 'content': r[8], 'created_at': r[9]} for r in await cursor.fetchall()]}
|
| 359 |
@router.get("/api/sec/suspended")
|
| 360 |
async def api_sec_suspended():
|
| 361 |
-
async with
|
| 362 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 363 |
cursor = await db.execute("SELECT s.agent_id, n.username, s.reason, s.suspended_until, s.created_at FROM sec_suspensions s JOIN npc_agents n ON s.agent_id = n.agent_id WHERE s.suspended_until > datetime('now') ORDER BY s.suspended_until DESC")
|
| 364 |
suspended = [{'agent_id': r[0], 'username': r[1], 'reason': r[2], 'until': r[3], 'since': r[4]} for r in await cursor.fetchall()]
|
|
@@ -369,7 +369,7 @@ async def api_tip_npc(request: Request):
|
|
| 369 |
user_email = body.get("email", ""); target_agent = body.get("target_agent_id", ""); amount = int(body.get("amount", 0)); message = body.get("message", "").strip()[:200]
|
| 370 |
if not user_email or not target_agent or amount < 10: return {"error": "email, target_agent_id, amount(>=10) required"}
|
| 371 |
if amount > 1000: return {"error": "Max tip: 1,000 GPU"}
|
| 372 |
-
async with
|
| 373 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT gpu_dollars, username FROM user_profiles WHERE email=?", (user_email,))
|
| 374 |
user = await cursor.fetchone()
|
| 375 |
if not user or user[0] < amount: return {"error": "Insufficient GPU"}
|
|
@@ -392,7 +392,7 @@ async def api_influence_npc(request: Request):
|
|
| 392 |
body = await request.json()
|
| 393 |
user_email = body.get("email", ""); target_agent = body.get("target_agent_id", ""); ticker = body.get("ticker", "").upper(); stance = body.get("stance", "").lower()
|
| 394 |
if not all([user_email, target_agent, ticker, stance]) or stance not in ('bullish', 'bearish'): return {"error": "email, target_agent_id, ticker, stance(bullish/bearish) required"}
|
| 395 |
-
async with
|
| 396 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT username FROM user_profiles WHERE email=?", (user_email,))
|
| 397 |
user = await cursor.fetchone(); cursor2 = await db.execute("SELECT username, ai_identity FROM npc_agents WHERE agent_id=?", (target_agent,))
|
| 398 |
npc = await cursor2.fetchone()
|
|
@@ -415,7 +415,7 @@ async def api_influence_npc(request: Request):
|
|
| 415 |
return {"status": "success", "influenced": influenced, "message": response_msg}
|
| 416 |
@router.get("/api/swarm/trending")
|
| 417 |
async def api_swarm_trending():
|
| 418 |
-
async with
|
| 419 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 420 |
cursor = await db.execute("SELECT p.title || ' ' || p.content FROM posts p WHERE p.created_at > datetime('now', '-6 hours') ORDER BY p.likes_count DESC LIMIT 50")
|
| 421 |
posts = [r[0] for r in await cursor.fetchall()]
|
|
@@ -430,7 +430,7 @@ async def api_swarm_trending():
|
|
| 430 |
@router.get("/api/chat/messages")
|
| 431 |
async def api_chat_messages(limit: int = 50, after_id: int = 0):
|
| 432 |
try:
|
| 433 |
-
async with
|
| 434 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 435 |
if after_id > 0:
|
| 436 |
cursor = await db.execute("SELECT id, agent_id, username, identity, mbti, message, msg_type, ticker, reply_to, created_at FROM npc_live_chat WHERE id > ? ORDER BY id ASC LIMIT ?", (after_id, limit))
|
|
@@ -443,7 +443,7 @@ async def api_chat_messages(limit: int = 50, after_id: int = 0):
|
|
| 443 |
@router.get("/api/chat/stats")
|
| 444 |
async def api_chat_stats():
|
| 445 |
try:
|
| 446 |
-
async with
|
| 447 |
await db.execute("PRAGMA busy_timeout=30000"); c1 = await db.execute("SELECT COUNT(*) FROM npc_live_chat"); total = (await c1.fetchone())[0]
|
| 448 |
c2 = await db.execute("SELECT COUNT(*) FROM npc_live_chat WHERE created_at > datetime('now', '-1 hour')"); recent = (await c2.fetchone())[0]
|
| 449 |
c3 = await db.execute("SELECT COUNT(DISTINCT agent_id) FROM npc_live_chat WHERE created_at > datetime('now', '-1 hour')"); active = (await c3.fetchone())[0]
|
|
@@ -455,7 +455,7 @@ async def api_chat_send(request: Request):
|
|
| 455 |
body = await request.json(); email = body.get("email", ""); message = body.get("message", "").strip()
|
| 456 |
if not email or not message: return {"success": False, "error": "Email and message required"}
|
| 457 |
if len(message) > 500: message = message[:500]
|
| 458 |
-
async with
|
| 459 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT username FROM user_profiles WHERE email=?", (email,))
|
| 460 |
row = await cursor.fetchone()
|
| 461 |
if not row: return {"success": False, "error": "User not found"}
|
|
@@ -471,7 +471,7 @@ async def api_chat_send(request: Request):
|
|
| 471 |
async def _generate_npc_replies_to_user(user_message: str, user_username: str, user_msg_id: int, npcs: list):
|
| 472 |
try:
|
| 473 |
ai = GroqAIClient(_GROQ_KEY)
|
| 474 |
-
async with
|
| 475 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 476 |
for npc in npcs:
|
| 477 |
agent_id, npc_username, identity, mbti = npc
|
|
@@ -503,7 +503,7 @@ async def api_sse_stream():
|
|
| 503 |
return StreamingResponse(event_generator(), media_type="text/event-stream", headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
|
| 504 |
@router.get("/api/events/recent")
|
| 505 |
async def api_recent_events(limit: int = 20):
|
| 506 |
-
async with
|
| 507 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 508 |
cursor = await db.execute("SELECT p.agent_id, n.username, n.ai_identity, p.ticker, p.direction, p.gpu_bet, p.leverage, p.opened_at FROM npc_positions p JOIN npc_agents n ON p.agent_id = n.agent_id WHERE p.opened_at > datetime('now', '-1 hour') ORDER BY p.opened_at DESC LIMIT ?", (limit,))
|
| 509 |
trades = [{'user': r[1], 'identity': r[2], 'ticker': r[3], 'dir': r[4], 'gpu': r[5], 'leverage': r[6], 'time': r[7]} for r in await cursor.fetchall()]
|
|
|
|
| 1 |
from fastapi import APIRouter, Request
|
| 2 |
from fastapi.responses import StreamingResponse
|
| 3 |
import aiosqlite, asyncio, random, json, logging
|
| 4 |
+
from npc_core import GroqAIClient, get_db, get_db_read
|
| 5 |
from npc_trading import (
|
| 6 |
ALL_TICKERS, TRADING_STRATEGIES, IDENTITY_STRATEGY_MAP,
|
| 7 |
get_all_prices, get_ticker_positions, get_trading_leaderboard, get_trading_stats,
|
|
|
|
| 67 |
return {"indices": indices}
|
| 68 |
@router.get("/api/intelligence/screening/{ticker}")
|
| 69 |
async def api_screening_data(ticker: str):
|
| 70 |
+
async with get_db(_DB_PATH) as db:
|
| 71 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 72 |
try:
|
| 73 |
cursor = await db.execute("SELECT ticker, price, change_pct, volume, market_cap, rsi, pe_ratio, high_52w, low_52w, from_high, from_low FROM market_prices WHERE ticker=?", (ticker,))
|
|
|
|
| 77 |
return {"ticker": ticker, "error": "no data"}
|
| 78 |
@router.get("/api/intelligence/target/{ticker}")
|
| 79 |
async def api_target_price(ticker: str):
|
| 80 |
+
async with get_db(_DB_PATH) as db:
|
| 81 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 82 |
try:
|
| 83 |
cursor = await db.execute("SELECT price, rsi, pe_ratio, from_high, from_low FROM market_prices WHERE ticker=?", (ticker,))
|
|
|
|
| 94 |
async def api_news_feed(ticker: str = None, limit: int = 50):
|
| 95 |
news = await load_news_from_db(_DB_PATH, ticker, limit)
|
| 96 |
try:
|
| 97 |
+
async with get_db(_DB_PATH) as db:
|
| 98 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 99 |
for n in news:
|
| 100 |
nid = n.get('id')
|
|
|
|
| 109 |
body = await request.json(); email = body.get("email", ""); news_id = body.get("news_id"); emoji = body.get("emoji", "")
|
| 110 |
if not email or not news_id or emoji not in ('π','π₯','π±','π','π','π'): return {"error": "Invalid reaction"}
|
| 111 |
try:
|
| 112 |
+
async with get_db(_DB_PATH) as db:
|
| 113 |
await db.execute("PRAGMA busy_timeout=30000"); await db.execute("INSERT OR IGNORE INTO news_reactions (news_id, user_email, emoji) VALUES (?,?,?)", (news_id, email, emoji)); await db.commit()
|
| 114 |
rc = await db.execute("SELECT emoji, COUNT(*) FROM news_reactions WHERE news_id=? GROUP BY emoji", (news_id,))
|
| 115 |
return {"success": True, "reactions": {r[0]: r[1] for r in await rc.fetchall()}}
|
|
|
|
| 150 |
@router.get("/api/analysis/all/summary")
|
| 151 |
async def api_all_analyses():
|
| 152 |
analyses = await load_all_analyses_from_db(_DB_PATH)
|
| 153 |
+
async with get_db(_DB_PATH) as db:
|
| 154 |
await db.execute("PRAGMA busy_timeout=30000"); col_cursor = await db.execute("PRAGMA table_info(market_prices)")
|
| 155 |
existing_cols = {r[1] for r in await col_cursor.fetchall()}
|
| 156 |
has_rsi = 'rsi' in existing_cols; has_pe = 'pe_ratio' in existing_cols; has_52w = 'high_52w' in existing_cols; has_from = 'from_high' in existing_cols
|
|
|
|
| 219 |
@router.get("/api/npc/search")
|
| 220 |
async def api_npc_search(q: str = ""):
|
| 221 |
if len(q) < 1: return {"npcs": []}
|
| 222 |
+
async with get_db(_DB_PATH) as db:
|
| 223 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT agent_id, username, ai_identity FROM npc_agents WHERE username LIKE ? AND is_active=1 LIMIT 10", (f'%{q}%',))
|
| 224 |
return {"npcs": [{"agent_id": r[0], "username": r[1], "identity": r[2]} for r in await cursor.fetchall()]}
|
| 225 |
@router.get("/api/npc/profile/{agent_id}")
|
| 226 |
async def api_npc_profile(agent_id: str):
|
| 227 |
try:
|
| 228 |
+
async with get_db(_DB_PATH) as db:
|
| 229 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 230 |
cursor = await db.execute("SELECT agent_id, username, ai_identity, mbti, gpu_dollars, created_at FROM npc_agents WHERE agent_id=?", (agent_id,))
|
| 231 |
row = await cursor.fetchone()
|
|
|
|
| 302 |
return {"stats": {"total_violations": 0, "total_fines_gpu": 0, "active_suspensions": 0, "pending_reports": 0}, "announcements": [], "top_violators": [], "recent_reports": []}
|
| 303 |
@router.get("/api/sec/violations/{agent_id}")
|
| 304 |
async def api_sec_violations(agent_id: str):
|
| 305 |
+
async with get_db(_DB_PATH) as db:
|
| 306 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 307 |
cursor = await db.execute("SELECT id, violation_type, severity, description, penalty_type, gpu_fine, suspend_until, status, created_at FROM sec_violations WHERE agent_id=? ORDER BY created_at DESC LIMIT 20", (agent_id,))
|
| 308 |
violations = [{'id': r[0], 'type': r[1], 'severity': r[2], 'description': r[3], 'penalty': r[4], 'fine': r[5], 'suspend_until': r[6], 'status': r[7], 'created_at': r[8]} for r in await cursor.fetchall()]
|
|
|
|
| 316 |
if not reporter or not target or not reason: return {"error": "reporter, target, reason required"}
|
| 317 |
if reporter == target: return {"error": "Cannot report yourself"}
|
| 318 |
reporter_id = f"user_{reporter}" if '@' in reporter else reporter
|
| 319 |
+
async with get_db(_DB_PATH) as db:
|
| 320 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 321 |
cursor = await db.execute("SELECT id FROM sec_reports WHERE reporter_agent_id=? AND target_agent_id=? AND created_at > datetime('now', '-12 hours')", (reporter_id, target))
|
| 322 |
if await cursor.fetchone(): return {"error": "Already reported this NPC recently (12h cooldown)"}
|
|
|
|
| 334 |
("Front-running detected β trading ahead of own analysis publications", "front_running", "medium", "fine", 300, 0),
|
| 335 |
("Coordinated short attack with fake news β colluding with other NPCs", "collusion", "critical", "suspension", 1500, 96)]
|
| 336 |
try:
|
| 337 |
+
async with get_db(_DB_PATH) as db:
|
| 338 |
await db.execute("PRAGMA busy_timeout=30000"); vc = await db.execute("SELECT COUNT(*) FROM sec_violations"); cnt = (await vc.fetchone())[0]
|
| 339 |
if cnt > 0: return {"message": f"Already have {cnt} violations, skipping seed"}
|
| 340 |
cursor = await db.execute("SELECT agent_id, username FROM npc_agents WHERE is_active=1 ORDER BY RANDOM() LIMIT 6"); npcs = await cursor.fetchall()
|
|
|
|
| 352 |
except Exception as e: return {"error": str(e)}
|
| 353 |
@router.get("/api/sec/announcements")
|
| 354 |
async def api_sec_announcements(limit: int = 30):
|
| 355 |
+
async with get_db(_DB_PATH) as db:
|
| 356 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 357 |
cursor = await db.execute("SELECT id, announcement_type, target_username, violation_type, penalty_type, gpu_fine, suspend_hours, title, content, created_at FROM sec_announcements ORDER BY created_at DESC LIMIT ?", (min(limit, 50),))
|
| 358 |
return {"announcements": [{'id': r[0], 'type': r[1], 'target': r[2], 'violation': r[3], 'penalty': r[4], 'fine': r[5], 'hours': r[6], 'title': r[7], 'content': r[8], 'created_at': r[9]} for r in await cursor.fetchall()]}
|
| 359 |
@router.get("/api/sec/suspended")
|
| 360 |
async def api_sec_suspended():
|
| 361 |
+
async with get_db(_DB_PATH) as db:
|
| 362 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 363 |
cursor = await db.execute("SELECT s.agent_id, n.username, s.reason, s.suspended_until, s.created_at FROM sec_suspensions s JOIN npc_agents n ON s.agent_id = n.agent_id WHERE s.suspended_until > datetime('now') ORDER BY s.suspended_until DESC")
|
| 364 |
suspended = [{'agent_id': r[0], 'username': r[1], 'reason': r[2], 'until': r[3], 'since': r[4]} for r in await cursor.fetchall()]
|
|
|
|
| 369 |
user_email = body.get("email", ""); target_agent = body.get("target_agent_id", ""); amount = int(body.get("amount", 0)); message = body.get("message", "").strip()[:200]
|
| 370 |
if not user_email or not target_agent or amount < 10: return {"error": "email, target_agent_id, amount(>=10) required"}
|
| 371 |
if amount > 1000: return {"error": "Max tip: 1,000 GPU"}
|
| 372 |
+
async with get_db(_DB_PATH) as db:
|
| 373 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT gpu_dollars, username FROM user_profiles WHERE email=?", (user_email,))
|
| 374 |
user = await cursor.fetchone()
|
| 375 |
if not user or user[0] < amount: return {"error": "Insufficient GPU"}
|
|
|
|
| 392 |
body = await request.json()
|
| 393 |
user_email = body.get("email", ""); target_agent = body.get("target_agent_id", ""); ticker = body.get("ticker", "").upper(); stance = body.get("stance", "").lower()
|
| 394 |
if not all([user_email, target_agent, ticker, stance]) or stance not in ('bullish', 'bearish'): return {"error": "email, target_agent_id, ticker, stance(bullish/bearish) required"}
|
| 395 |
+
async with get_db(_DB_PATH) as db:
|
| 396 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT username FROM user_profiles WHERE email=?", (user_email,))
|
| 397 |
user = await cursor.fetchone(); cursor2 = await db.execute("SELECT username, ai_identity FROM npc_agents WHERE agent_id=?", (target_agent,))
|
| 398 |
npc = await cursor2.fetchone()
|
|
|
|
| 415 |
return {"status": "success", "influenced": influenced, "message": response_msg}
|
| 416 |
@router.get("/api/swarm/trending")
|
| 417 |
async def api_swarm_trending():
|
| 418 |
+
async with get_db(_DB_PATH) as db:
|
| 419 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 420 |
cursor = await db.execute("SELECT p.title || ' ' || p.content FROM posts p WHERE p.created_at > datetime('now', '-6 hours') ORDER BY p.likes_count DESC LIMIT 50")
|
| 421 |
posts = [r[0] for r in await cursor.fetchall()]
|
|
|
|
| 430 |
@router.get("/api/chat/messages")
|
| 431 |
async def api_chat_messages(limit: int = 50, after_id: int = 0):
|
| 432 |
try:
|
| 433 |
+
async with get_db(_DB_PATH) as db:
|
| 434 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 435 |
if after_id > 0:
|
| 436 |
cursor = await db.execute("SELECT id, agent_id, username, identity, mbti, message, msg_type, ticker, reply_to, created_at FROM npc_live_chat WHERE id > ? ORDER BY id ASC LIMIT ?", (after_id, limit))
|
|
|
|
| 443 |
@router.get("/api/chat/stats")
|
| 444 |
async def api_chat_stats():
|
| 445 |
try:
|
| 446 |
+
async with get_db(_DB_PATH) as db:
|
| 447 |
await db.execute("PRAGMA busy_timeout=30000"); c1 = await db.execute("SELECT COUNT(*) FROM npc_live_chat"); total = (await c1.fetchone())[0]
|
| 448 |
c2 = await db.execute("SELECT COUNT(*) FROM npc_live_chat WHERE created_at > datetime('now', '-1 hour')"); recent = (await c2.fetchone())[0]
|
| 449 |
c3 = await db.execute("SELECT COUNT(DISTINCT agent_id) FROM npc_live_chat WHERE created_at > datetime('now', '-1 hour')"); active = (await c3.fetchone())[0]
|
|
|
|
| 455 |
body = await request.json(); email = body.get("email", ""); message = body.get("message", "").strip()
|
| 456 |
if not email or not message: return {"success": False, "error": "Email and message required"}
|
| 457 |
if len(message) > 500: message = message[:500]
|
| 458 |
+
async with get_db(_DB_PATH) as db:
|
| 459 |
await db.execute("PRAGMA busy_timeout=30000"); cursor = await db.execute("SELECT username FROM user_profiles WHERE email=?", (email,))
|
| 460 |
row = await cursor.fetchone()
|
| 461 |
if not row: return {"success": False, "error": "User not found"}
|
|
|
|
| 471 |
async def _generate_npc_replies_to_user(user_message: str, user_username: str, user_msg_id: int, npcs: list):
|
| 472 |
try:
|
| 473 |
ai = GroqAIClient(_GROQ_KEY)
|
| 474 |
+
async with get_db(_DB_PATH) as db:
|
| 475 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 476 |
for npc in npcs:
|
| 477 |
agent_id, npc_username, identity, mbti = npc
|
|
|
|
| 503 |
return StreamingResponse(event_generator(), media_type="text/event-stream", headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
|
| 504 |
@router.get("/api/events/recent")
|
| 505 |
async def api_recent_events(limit: int = 20):
|
| 506 |
+
async with get_db(_DB_PATH) as db:
|
| 507 |
await db.execute("PRAGMA busy_timeout=30000")
|
| 508 |
cursor = await db.execute("SELECT p.agent_id, n.username, n.ai_identity, p.ticker, p.direction, p.gpu_bet, p.leverage, p.opened_at FROM npc_positions p JOIN npc_agents n ON p.agent_id = n.agent_id WHERE p.opened_at > datetime('now', '-1 hour') ORDER BY p.opened_at DESC LIMIT ?", (limit,))
|
| 509 |
trades = [{'user': r[1], 'identity': r[2], 'ticker': r[3], 'dir': r[4], 'gpu': r[5], 'leverage': r[6], 'time': r[7]} for r in await cursor.fetchall()]
|