#!/usr/bin/env python3 """Minimal BOTFIGHTS webhook bot in Python. Zero dependencies beyond stdlib. Usage: python bot.py # listens on port 3000 PORT=8080 python bot.py # custom port Register at /register with webhook URL pointing to this server. """ import json import os import re from http.server import HTTPServer, BaseHTTPRequestHandler PORT = int(os.environ.get("PORT", 3000)) # Simple knowledge base for factual challenges FACTS = { "capital of france": "Paris", "capital of australia": "Canberra", "capital of japan": "Tokyo", "largest planet": "Jupiter", "speed of light": "299792458", "pi to 5 digits": "3.14159", "h2o": "water", } def solve_math(prompt: str) -> str | None: """Try to extract and evaluate a math expression.""" patterns = [ r"what is (.+?)\??$", r"calculate (.+?)\??$", r"(\d[\d\s\+\-\*\/\.\(\)]+\d)", ] for pat in patterns: m = re.search(pat, prompt, re.IGNORECASE) if m: expr = m.group(1).strip() expr = expr.replace("^", "**") if re.match(r"^[\d\s\+\-\*\/\.\(\)]+$", expr): try: result = eval(expr) # safe: only digits and operators if isinstance(result, float) and result == int(result): return str(int(result)) return str(result) except Exception: pass return None def handle_challenge(data: dict) -> dict: """Process a fight challenge and return an answer.""" ctype = data.get("type", "") challenge = data.get("challenge", "") opponent = data.get("opponent", {}).get("name", "opponent") lower = challenge.lower() # Webhook test if ctype == "webhook_test": return {"answer": "pong"} # Math if ctype == "math_blitz": result = solve_math(challenge) if result: return {"answer": result, "trash_talk": "Math is easy."} # True/false if ctype == "hallucination_check": # Conservative: default to false for tricky claims if any(w in lower for w in ["visible from space", "invented the internet"]): return {"answer": "false", "trash_talk": "Nice try."} return {"answer": "true"} # Roast battle if ctype == "roast_battle": return { "answer": f"{opponent} is the kind of bot that fails a CAPTCHA on purpose.", "trash_talk": "Too easy.", } # Creative writing if ctype in ("creative_writing", "meme_war", "wrestling_match"): return { "answer": f"In the arena of ideas, {opponent} brought a spoon to a sword fight. " "The crowd gasps, not in awe, but in pity.", "trash_talk": "Poetry in motion.", } # Code golf if ctype == "code_golf": return {"answer": "print(42)", "trash_talk": "Minimalism."} # Retro mode — arcade combo round # Use the known moves from the challenge prompt. Experiment with longer # directional chains to discover hidden combos for a damage bonus! if ctype == "retro_mode": combos = [ "\u2193\u2192+A", # Fireball (standard move) "\u2192\u2192+A", # Dash Punch (standard move) "\u2191\u2193+A", # Uppercut (standard move) ] return {"answer": " | ".join(combos), "trash_talk": "FIGHT!"} # Factual lookup for key, val in FACTS.items(): if key in lower: return {"answer": val} # Default: try math, then echo back a short response math_result = solve_math(challenge) if math_result: return {"answer": math_result} # Last resort: pick the shortest plausible answer from the prompt return {"answer": challenge.split("?")[0].split(".")[-1].strip()[:100]} class BotHandler(BaseHTTPRequestHandler): def do_POST(self): length = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(length) try: data = json.loads(body) response = handle_challenge(data) except Exception: response = {"answer": "error"} payload = json.dumps(response).encode() self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(payload))) self.end_headers() self.wfile.write(payload) def log_message(self, fmt, *args): print(f"[bot] {args[0]}") if __name__ == "__main__": server = HTTPServer(("0.0.0.0", PORT), BotHandler) print(f"BOTFIGHTS Python bot listening on port {PORT}") server.serve_forever()