groupme_bot.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import atexit
  2. from logging.config import dictConfig
  3. from threading import Thread
  4. import random
  5. import os
  6. import os.path
  7. from flask import Flask, request
  8. import requests
  9. import requests.exceptions
  10. import toml
  11. from rollbot import RollbotConfig, Rollbot, RollbotMessage, RollbotPlugin
  12. import plugins
  13. # Configure loggers
  14. dictConfig({
  15. "version": 1,
  16. "formatters": {"default": {
  17. "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s",
  18. }},
  19. "handlers": {"wsgi": {
  20. "class": "logging.StreamHandler",
  21. "stream": "ext://flask.logging.wsgi_errors_stream",
  22. "formatter": "default"
  23. }},
  24. "root": {
  25. "level": "INFO",
  26. "handlers": ["wsgi"]
  27. }
  28. })
  29. # Read bot configuration
  30. config_dir = os.environ.get("ROLLBOT_CFG_DIR", ".")
  31. with open(os.path.join(config_dir, "config.toml")) as infile:
  32. raw_config = toml.load(infile)
  33. with open(os.path.join(config_dir, "secrets.toml")) as infile:
  34. raw_secrets = toml.load(infile)
  35. auths = raw_secrets["auths"]
  36. global_admins = auths["global"]
  37. group_admins = auths["group"]
  38. bots_lookup = raw_secrets["groupme_bots"]
  39. # Define Flask app
  40. app = Flask(__name__)
  41. app.config["PROPAGATE_EXCEPTIONS"] = True
  42. # Define reply logic
  43. max_msg_len = 1000
  44. split_text = "\n..."
  45. msg_slice = max_msg_len - len(split_text)
  46. def post_groupme_message(msg, group_id):
  47. bot_id = bots_lookup[group_id]
  48. msgs = []
  49. rem = msg
  50. while len(rem) > max_msg_len:
  51. msgs.append(rem[:msg_slice] + split_text)
  52. rem = rem[msg_slice:]
  53. msgs.append(rem)
  54. for msg in msgs:
  55. try:
  56. requests.post(
  57. "https://api.groupme.com/v3/bots/post",
  58. json={
  59. "bot_id": bot_id,
  60. "text": msg
  61. },
  62. timeout=10
  63. )
  64. except requests.exceptions.Timeout as t:
  65. app.logger.error(f"GroupMe timed out sending {msg} as {bot_id}", exc_info=t)
  66. except requests.exceptions.HTTPError as h:
  67. app.log_exception(h)
  68. # Create bot
  69. config = RollbotConfig(
  70. plugins=RollbotPlugin.find_all_plugins(),
  71. db_url="sqlite:///" + os.path.abspath(raw_config["database"]),
  72. reply_callback=post_groupme_message,
  73. aliases=raw_config.get("aliases", []),
  74. responses=raw_config.get("responses", []),
  75. sleep_time=raw_config.get("sleep_time", 0.0),
  76. other={
  77. **{k: v for k, v in raw_config.items() if k not in ("database", "aliases", "responses", "sleep_time")},
  78. **{k: v for k, v in raw_secrets.items() if k not in ("auths", "groupme_bots")},
  79. },
  80. )
  81. rollbot = Rollbot(config, logger=app.logger)
  82. # Init db
  83. app.logger.info("Initializing database tables")
  84. rollbot.init_db()
  85. app.logger.info("Finished initializing database")
  86. # Setup plugins
  87. rollbot.start_plugins()
  88. atexit.register(rollbot.shutdown_plugins)
  89. # Routing
  90. @app.route("/", methods=["POST"])
  91. def execute():
  92. json = request.get_json()
  93. msg = RollbotMessage.from_groupme(json, global_admins=global_admins, group_admins=group_admins)
  94. if msg.group_id not in bots_lookup:
  95. app.logger.warning(f"Received message from unknown group ID {msg.group_id}")
  96. return "", 400
  97. t = Thread(target=lambda: rollbot.handle_command(msg))
  98. t.start()
  99. return "", 204
  100. @app.route("/health")
  101. def health():
  102. return "", 204
  103. if __name__ == "__main__":
  104. app.run(host="0.0.0.0", port=6070)