import atexit import time from logging.config import dictConfig from threading import Thread from flask import Flask, request, render_template from config import BOTS_LOOKUP, SLEEP_TIME from command_system import RollbotMessage, RollbotResponse, RollbotFailure from rollbot import Rollbot from util import post_message dictConfig({ "version": 1, "formatters": {"default": { "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s", }}, "handlers": {"wsgi": { "class": "logging.StreamHandler", "stream": "ext://flask.logging.wsgi_errors_stream", "formatter": "default" }}, "root": { "level": "INFO", "handlers": ["wsgi"] } }) app = Flask(__name__) rollbot = Rollbot(app.logger) rollbot.start_plugins() atexit.register(rollbot.shutdown_plugins) @app.route("/teamspeak", methods=["GET"]) def teamspeak(): response = rollbot.run_command(RollbotMessage.from_web("!teamspeak")) if response.is_success: response = response.txt else: response = response.failure_msg return render_template("teamspeak.html", r=response) @app.route("/services", methods=["GET", "POST"]) def services(): if request.method == "POST": msg = RollbotMessage.from_web(request.form["cmd"]) if msg.is_command: response = rollbot.run_command(msg) if response.is_success: txt = response.txt img = response.img else: txt = response.failure_msg img = None return render_template("services.html", r=response.respond, txt=txt, img=img) return render_template("services.html", r=None) @app.route("/rollbot", methods=["POST"]) def execute(): json = request.get_json() msg = RollbotMessage.from_groupme(json) if not msg.is_command: app.logger.debug("Received non-command message") return "", 204 if msg.group_id not in BOTS_LOOKUP: app.logger.warning(f"Received message from unknown group ID {msg.group_id}") return "Invalid group ID", 403 def run_command_and_respond(): app.logger.info(f"Entering command thread for {msg.message_id}") t = time.time() try: response = rollbot.run_command(msg) except Exception as e: app.logger.error(f"Exception during command execution {e}, for message {msg.message_id}") response = RollbotResponse(msg, failure=RollbotFailure.INTERNAL_ERROR) if not response.respond: app.logger.info(f"Skipping response to message {msg.message_id}") return app.logger.info(f"Responding to message {msg.message_id}") sleep = SLEEP_TIME - time.time() + t if sleep > 0: app.logger.info(f"Sleeping for {sleep:.3f}s before responding") time.sleep(sleep) bot_id = BOTS_LOOKUP[msg.group_id] if response.is_success: if response.txt is not None: post_message(response.txt, bot_id=bot_id) if response.img is not None: post_message(response.img, bot_id=bot_id) else: post_message(response.failure_msg, bot_id=bot_id) app.logger.warning(f"Failed command response: {response}") t = time.time() - t app.logger.info(f"Exiting command thread for {msg.message_id} after {t:.3f}s") t = Thread(target=run_command_and_respond) t.start() return "OK", 200 if __name__ == "__main__": # default deployment in debug mode app.run(host="0.0.0.0", port=6070)