190 lines
5.4 KiB
Python
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)
|