Files
faction_war_dispatch_bot/main.py

190 lines
5.4 KiB
Python

import discord
from discord.ext import commands
from config import ALLOWED_CHANNEL_ID, HIT_CHECK_INTERVAL, REASSIGN_DELAY
from cogs.assignments import Assignments
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
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from services.torn_api import populate_friendly, populate_enemy, start_friendly_status_loop, start_enemy_status_loop
# ============================================================
# FastAPI Setup
# ============================================================
app = FastAPI()
templates = Jinja2Templates(directory="templates")
app.mount("/static", StaticFiles(directory="static"), name="static")
# ============================================================
# 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 POST input
# ============================================================
class FactionRequest(BaseModel):
faction_id: int
interval: int = 30
# -----------------------------
# 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)
# =============================
# Status JSON endpoints
# =============================
@app.get("/api/friendly_status")
async def api_friendly_status():
path = Path("data/friendly_status.json")
if not path.exists():
return {}
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
@app.get("/api/enemy_status")
async def api_enemy_status():
path = Path("data/enemy_status.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
enrolled_attackers = []
enemy_queue = []
active_assignments = {}
round_robin_index = 0
class HitDispatchBot(commands.Bot):
async def setup_hook(self):
await self.add_cog(
Assignments(
self,
enemy_queue=enemy_queue,
active_assignments=active_assignments,
enrolled_attackers=enrolled_attackers,
hit_check=HIT_CHECK_INTERVAL,
reassign_delay=REASSIGN_DELAY,
)
)
await self.add_cog(
HitCommands(
self,
enrolled_attackers=enrolled_attackers,
enemy_queue=enemy_queue
)
)
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 Point
# ============================================================
if __name__ == "__main__":
loop = asyncio.get_event_loop()
# Start Discord bot in background
loop.create_task(start_bot())
# Run FastAPI app — keeps loop alive
uvicorn.run(app, host="127.0.0.1", port=8000)