from flask import Flask, request, jsonify import os import logging from waitress import serve from nacl.signing import VerifyKey from nacl.exceptions import BadSignatureError import threading import requests import time # Logging konfigurieren logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # Konfiguration PUBLIC_KEY = os.getenv('Public_Key', '').strip() APPLICATION_ID = os.getenv('Application_ID', '').strip() PORT = int(os.getenv('PORT', 7860)) # Hugging Face nutzt standardmäßig Port 7860 app = Flask(__name__) try: verify_key = VerifyKey(bytes.fromhex(PUBLIC_KEY)) if PUBLIC_KEY else None logger.info("Successfully initialized verify_key") except Exception as e: logger.error(f"Error initializing verify_key: {str(e)}") verify_key = None def verify_discord_request(): try: signature = request.headers.get('X-Signature-Ed25519') timestamp = request.headers.get('X-Signature-Timestamp') if not signature or not timestamp: return False body = request.data.decode('utf-8') verify_key.verify(f"{timestamp}{body}".encode(), bytes.fromhex(signature)) return True except Exception as e: logger.error(f"Verification error: {str(e)}") return False @app.route("/", methods=["GET"]) def health_check(): """Hugging Face nutzt diesen Endpoint um zu prüfen ob der Space läuft""" return jsonify({ "status": "running", "message": "Discord bot is running!", "public_key_present": bool(PUBLIC_KEY), "verify_key_initialized": verify_key is not None }) @app.route("/interactions", methods=["POST"]) def interactions(): if not verify_key: logger.error("verify_key not initialized") return "Configuration error", 500 if not verify_discord_request(): return "Invalid request signature", 401 try: data = request.json # Discord Ping Verification if data.get("type") == 1: logger.info("Responding to ping verification") return jsonify({"type": 1}) # Slash Commands if data.get("type") == 2: command = data.get("data", {}).get("name") logger.info(f"Received command: {command}") if command == "settings": return jsonify({ "type": 4, "data": { "content": "✅ Bot ist aktiv und verifiziert!" } }) return jsonify({"type": 1}) except Exception as e: logger.error(f"Error processing request: {str(e)}") return "Internal server error", 500 def health_check_worker(): """Background worker der regelmäßig den Health-Check Endpoint aufruft""" while True: try: response = requests.get(f"http://localhost:{PORT}/") logger.info(f"Health check status: {response.status_code}") except Exception as e: logger.error(f"Health check failed: {str(e)}") time.sleep(30) if __name__ == "__main__": logger.info(f"Starting Discord bot on port {PORT}...") # Starte Health-Check Worker in separatem Thread health_thread = threading.Thread(target=health_check_worker, daemon=True) health_thread.start() # Starte Server serve(app, host="0.0.0.0", port=PORT)