Stylized member cards with static fields

This commit is contained in:
2025-11-27 02:44:52 -05:00
parent 317442b8ea
commit 7cf882959b
9 changed files with 435 additions and 165 deletions

117
main.py
View File

@@ -6,6 +6,8 @@ from cogs.commands import HitCommands
import asyncio
import uvicorn
import json
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
@@ -13,47 +15,97 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from services.torn_api import update_enemy_faction, update_friendly_faction
from services.torn_api import populate_friendly, populate_enemy, start_friendly_status_loop, start_enemy_status_loop
# ============================================================
# FastAPI Setup
# ============================================================
# -----------------------------
# FastAPI setup
# -----------------------------
app = FastAPI()
templates = Jinja2Templates(directory="templates")
app.mount("/static", StaticFiles(directory="static"), name="static")
# -----------------------------
# Dashboard page
# -----------------------------
# ============================================================
# Dashboard Webpage
# ============================================================
@app.get("/", response_class=HTMLResponse)
async def dashboard(request: Request):
print(">>> DASHBOARD ROUTE LOADED")
return templates.TemplateResponse("dashboard.html", {"request": request})
# -----------------------------
# Pydantic model for JSON payloads
# -----------------------------
# ============================================================
# Pydantic model for JSON POST input
# ============================================================
class FactionRequest(BaseModel):
faction_id: int
interval: int
# -----------------------------
# API Endpoints
# -----------------------------
@app.post("/api/update_enemy_faction")
async def api_enemy(data: FactionRequest):
await update_enemy_faction(data.faction_id, data.interval)
return {"status": "enemy loop running", "id": data.faction_id, "interval": data.interval}
@app.post("/api/update_friendly_faction")
async def api_friendly(data: FactionRequest):
await update_friendly_faction(data.faction_id, data.interval)
return {"status": "friendly loop running", "id": data.faction_id, "interval": data.interval}
# -----------------------------
# Discord bot setup
# Populate endpoints (populate JSON once)
# -----------------------------
@app.post("/api/populate_friendly")
async def api_populate_friendly(data: FactionRequest):
from services.torn_api import populate_friendly
await populate_friendly(data.faction_id)
return {"status": "friendly populated", "id": data.faction_id}
@app.post("/api/populate_enemy")
async def api_populate_enemy(data: FactionRequest):
from services.torn_api import populate_enemy
await populate_enemy(data.faction_id)
return {"status": "enemy populated", "id": data.faction_id}
# -----------------------------
# Start status refresh loops
# -----------------------------
@app.post("/api/start_friendly_status")
async def api_start_friendly_status(data: FactionRequest):
from services.torn_api import start_friendly_status_loop
await start_friendly_status_loop(data.faction_id, data.interval)
return {"status": "friendly status loop started", "id": data.faction_id, "interval": data.interval}
@app.post("/api/start_enemy_status")
async def api_start_enemy_status(data: FactionRequest):
from services.torn_api import start_enemy_status_loop
await start_enemy_status_loop(data.faction_id, data.interval)
return {"status": "enemy status loop started", "id": data.faction_id, "interval": data.interval}
# =============================
# Member JSON endpoints
# =============================
@app.get("/api/friendly_members")
async def get_friendly_members():
path = Path("data/friendly_faction.json")
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
@app.get("/api/enemy_members")
async def get_enemy_members():
path = Path("data/enemy_faction.json")
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
# ============================================================
# Discord Bot Setup
# ============================================================
intents = discord.Intents.default()
intents.message_content = True
@@ -62,9 +114,9 @@ enemy_queue = []
active_assignments = {}
round_robin_index = 0
class HitDispatchBot(commands.Bot):
async def setup_hook(self):
# Load cogs with injected state
await self.add_cog(
Assignments(
self,
@@ -72,9 +124,10 @@ class HitDispatchBot(commands.Bot):
active_assignments=active_assignments,
enrolled_attackers=enrolled_attackers,
hit_check=HIT_CHECK_INTERVAL,
reassign_delay=REASSIGN_DELAY
reassign_delay=REASSIGN_DELAY,
)
)
await self.add_cog(
HitCommands(
self,
@@ -86,25 +139,31 @@ class HitDispatchBot(commands.Bot):
async def cog_check(self, ctx):
return ctx.channel.id == ALLOWED_CHANNEL_ID
bot = HitDispatchBot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user.name}")
TOKEN = "YOUR_DISCORD_TOKEN"
async def start_bot():
await bot.start(TOKEN)
# -----------------------------
# Main entry
# -----------------------------
# ============================================================
# Main Entry Point
# ============================================================
if __name__ == "__main__":
loop = asyncio.get_event_loop()
# Start Discord bot in background
loop.create_task(start_bot())
# Run FastAPI (this will keep the loop alive)
# Run FastAPI app — keeps loop alive
uvicorn.run(app, host="127.0.0.1", port=8000)