diff --git a/__pycache__/config.cpython-311.pyc b/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000..4411a3c Binary files /dev/null and b/__pycache__/config.cpython-311.pyc differ diff --git a/__pycache__/main.cpython-311.pyc b/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000..583d2c2 Binary files /dev/null and b/__pycache__/main.cpython-311.pyc differ diff --git a/cogs/__pycache__/assignments.cpython-311.pyc b/cogs/__pycache__/assignments.cpython-311.pyc new file mode 100644 index 0000000..5daaedd Binary files /dev/null and b/cogs/__pycache__/assignments.cpython-311.pyc differ diff --git a/cogs/__pycache__/commands.cpython-311.pyc b/cogs/__pycache__/commands.cpython-311.pyc new file mode 100644 index 0000000..256618d Binary files /dev/null and b/cogs/__pycache__/commands.cpython-311.pyc differ diff --git a/main.py b/main.py index 6b504f4..1d3e4fc 100644 --- a/main.py +++ b/main.py @@ -4,10 +4,54 @@ 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 + +from fastapi import FastAPI, Request, Form +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +from services.torn_api import update_enemy_faction, update_friendly_faction + + + +app = FastAPI() + +templates = Jinja2Templates(directory="templates") +app.mount("/static", StaticFiles(directory="static"), name="static") + + +# ----------------------------- +# Dashboard page +# ----------------------------- +@app.get("/", response_class=HTMLResponse) +async def dashboard(request: Request): + print(">>> DASHBOARD ROUTE LOADED") + return templates.TemplateResponse("dashboard.html", {"request": request}) + + + +# ----------------------------- +# API Endpoints +# ----------------------------- +@app.post("/api/enemy") +async def api_enemy(faction_id: int, interval: int): + await update_enemy_faction(faction_id, interval) + return {"status": "enemy loop running", "id": faction_id, "interval": interval} + + +@app.post("/api/friendly") +async def api_friendly(faction_id: int, interval: int): + await update_friendly_faction(faction_id, interval) + return {"status": "friendly loop running", "id": faction_id, "interval": interval} + + +# Discord intents = discord.Intents.default() intents.message_content = True -# Global state + enrolled_attackers = [] enemy_queue = [] active_assignments = {} @@ -43,4 +87,16 @@ bot = HitDispatchBot(command_prefix="!", intents=intents) async def on_ready(): print(f"Logged in as {bot.user.name}") -bot.run("MTQ0Mjg3NjU3NTUzMDg3NzAxMQ.GNuHPr.UreuYD1B7YYjfsbfRcEbhFyjyqvhQDepRCN4kk") +TOKEN = "YOUR_DISCORD_TOKEN" + +async def start_bot(): + await bot.start(TOKEN) + +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) + uvicorn.run(app, host="127.0.0.1", port=8000) diff --git a/routes/faction.py b/routes/faction.py new file mode 100644 index 0000000..25268f8 --- /dev/null +++ b/routes/faction.py @@ -0,0 +1,31 @@ +from fastapi import APIRouter +from pydantic import BaseModel +import asyncio + +router = APIRouter() + +class FactionRequest(BaseModel): + faction_id: int + refresh_interval: int + +async def update_friendly_faction_loop(faction_id: int, interval: int): + while True: + print(f"Refreshing friendly faction {faction_id}") + # call your update_friendly_faction() here + await asyncio.sleep(interval) + +async def update_enemy_faction_loop(faction_id: int, interval: int): + while True: + print(f"Refreshing enemy faction {faction_id}") + # call your update_enemy_faction() here + await asyncio.sleep(interval) + +@router.post("/refresh/friendly") +async def refresh_friendly(data: FactionRequest): + asyncio.create_task(update_friendly_faction_loop(data.faction_id, data.refresh_interval)) + return {"status": "friendly loop started"} + +@router.post("/refresh/enemy") +async def refresh_enemy(data: FactionRequest): + asyncio.create_task(update_enemy_faction_loop(data.faction_id, data.refresh_interval)) + return {"status": "enemy loop started"} diff --git a/services/__pycache__/ffscouter.cpython-311.pyc b/services/__pycache__/ffscouter.cpython-311.pyc new file mode 100644 index 0000000..02e0f28 Binary files /dev/null and b/services/__pycache__/ffscouter.cpython-311.pyc differ diff --git a/services/__pycache__/torn_api.cpython-311.pyc b/services/__pycache__/torn_api.cpython-311.pyc new file mode 100644 index 0000000..29c497b Binary files /dev/null and b/services/__pycache__/torn_api.cpython-311.pyc differ diff --git a/services/torn_api.py b/services/torn_api.py index cfbbd0e..e38fd8c 100644 --- a/services/torn_api.py +++ b/services/torn_api.py @@ -1,6 +1,7 @@ # services/torn_api.py import aiohttp import json +import asyncio from pathlib import Path from config import TORN_API_KEY, ENEMY_FACTION_ID, YOUR_FACTION_ID from .ffscouter import fetch_batch_stats @@ -8,6 +9,13 @@ from .ffscouter import fetch_batch_stats ENEMY_FILE = Path("data/enemy_faction.json") FRIENDLY_FILE = Path("data/friendly_faction.json") +# Track running tasks + current faction IDs +enemy_task = None +friendly_task = None + +current_enemy_id = None +current_friendly_id = None + async def fetch_and_save_faction(faction_id: int, file_path: Path) -> bool: """ @@ -59,10 +67,59 @@ async def fetch_and_save_faction(faction_id: int, file_path: Path) -> bool: return True -# Wrappers for clarity -async def update_enemy_faction() -> bool: - return await fetch_and_save_faction(ENEMY_FACTION_ID, ENEMY_FILE) -async def update_friendly_faction() -> bool: - return await fetch_and_save_faction(YOUR_FACTION_ID, FRIENDLY_FILE) +#Loop for the constant update of members and the stop function + +async def stop_task_if_running(task: asyncio.Task | None): + """Cancel an existing running task safely.""" + if task and not task.done(): + task.cancel() + try: + await task + except asyncio.CancelledError: + pass + +async def faction_loop(faction_id: int, file_path: Path, interval: int): + """ + Runs fetch_and_save_faction() in a loop forever, waiting `interval` + seconds between iterations. + """ + while True: + try: + await fetch_and_save_faction(faction_id, file_path) + except Exception as e: + print(f"Error during faction loop for {faction_id}: {e}") + + await asyncio.sleep(interval) + + + +#Functions to call the loop, maybe add one to just call once? +async def update_enemy_faction(new_faction_id: int, interval: int): + global enemy_task, current_enemy_id + + # If faction ID changes → stop old loop + if new_faction_id != current_enemy_id: + print(f"[ENEMY] Changing faction from {current_enemy_id} → {new_faction_id}") + await stop_task_if_running(enemy_task) + current_enemy_id = new_faction_id + + # Start new loop + enemy_task = asyncio.create_task( + faction_loop(new_faction_id, ENEMY_FILE, interval) + ) + + +async def update_friendly_faction(new_faction_id: int, interval: int): + global friendly_task, current_friendly_id + + if new_faction_id != current_friendly_id: + print(f"[FRIENDLY] Changing faction from {current_friendly_id} → {new_faction_id}") + await stop_task_if_running(friendly_task) + current_friendly_id = new_faction_id + + friendly_task = asyncio.create_task( + faction_loop(new_faction_id, FRIENDLY_FILE, interval) + ) + diff --git a/static/dashboard.js b/static/dashboard.js new file mode 100644 index 0000000..e69de29 diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 0000000..667d65a --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,24 @@ + + +
+