Эх сурвалжийг харах

First pass at GroupMe driver

Kirk Trombley 4 жил өмнө
parent
commit
5a2dece31a
1 өөрчлөгдсөн 144 нэмэгдсэн , 0 устгасан
  1. 144 0
      drivers/groupme.py

+ 144 - 0
drivers/groupme.py

@@ -0,0 +1,144 @@
+from datetime import datetime
+import json
+import traceback
+import asyncio
+
+import toml
+from fastapi import FastAPI, BackgroundTasks, Response
+from pydantic import BaseModel
+
+import rollbot
+from commands import config
+
+
+with open("secrets.toml", "r") as sfile:
+    secrets = toml.load(sfile)
+groupme_bots = secrets["groupme_bots"]
+groupme_token = secrets["groupme_token"]
+groupme_admins = secrets["admins"]["origin"]
+group_admins = secrets["admins"]["channel"]
+
+max_msg_len = 1000
+split_text = "\n..."
+msg_slice = max_msg_len - len(split_text)
+
+
+class GroupMeMessage(BaseModel):
+    sender_id: str
+    group_id: str
+    name: str
+    text: str
+    created_at: int
+    attachments: list[dict[str, str]]
+
+
+class GroupMeBot(rollbot.Rollbot[GroupMeMessage]):
+    def __init__(self):
+        super().__init__(
+            config.extend(rollbot.CommandConfiguration(bangs=("!",))), "/tmp/rollbot.db"
+        )
+
+    def read_config(self, key):
+        cfg = secrets
+        for part in key.split("."):
+            cfg = cfg.get(part, None)
+            if cfg is None:
+                return None
+        return cfg
+
+    def parse(self, msg: GroupMeMessage):
+        return rollbot.Message(
+            origin_id="GROUPME",
+            channel_id=msg.group_id,
+            sender_id=msg.sender_id,
+            timestamp=datetime.fromtimestamp(msg.created_at),
+            origin_admin=msg.sender_id in groupme_admins,
+            channel_admin=msg.sender_id in group_admins.get(msg.group_id, ()),
+            sender_name=msg.name,
+            text=msg.text,
+            attachments=[rollbot.Attachment(d["type"], json.dumps(d)) for d in msg.attachments],
+        )
+
+    async def respond(self, res: rollbot.Response):
+        if res.origin_id == "GROUPME":
+            bot_id = groupme_bots.get(res.channel_id, None)
+            if bot_id is None:
+                self.context.logger.error(f"Unable to respond to group {res.channel_id} in GroupMe")
+                return
+            message = ""
+            attachments = []
+            try:
+                for att in res.attachments:
+                    if att.name == "image":
+                        if isinstance(att.body, bytes):
+                            async with self.context.request.post(
+                                "https://image.groupme.com/pictures",
+                                headers={
+                                    "Content-Type": "image/png",
+                                    "X-Access-Token": groupme_token,
+                                },
+                                data=att.body,
+                            ) as upload:
+                                upload.raise_for_status()
+                                attachments.append(
+                                    {
+                                        "type": "image",
+                                        "url": (await upload.json())["payload"]["url"],
+                                    }
+                                )
+                        else:
+                            attachments.append({"type": "image", "url": att.body})
+            except:
+                self.context.debugging = "".join(traceback.format_exc())
+                message += "Failed to upload one or more attachments!\n"
+                self.context.logger.exception("Failed to upload attachment")
+
+            if res.text is not None:
+                message += res.text
+
+            msgs = []
+            while len(message) > max_msg_len:
+                msgs.append(message[:msg_slice] + split_text)
+                message = message[msg_slice:]
+            msgs.append(message)
+
+            await self.context.request.post(
+                "https://api.groupme.com/v3/bots/post",
+                json={
+                    "bot_id": bot_id,
+                    "text": msgs[0],
+                    "attachments": attachments,
+                },
+                timeout=10,
+            )
+
+            for m in msgs[1:]:
+                await asyncio.sleep(0.1)
+                await self.context.request.post(
+                    "https://api.groupme.com/v3/bots/post",
+                    json={
+                        "bot_id": bot_id,
+                        "text": m,
+                    },
+                    timeout=10,
+                )
+
+
+app = FastAPI()
+bot = GroupMeBot()
+
+
+@app.on_event("startup")
+async def startup():
+    await bot.on_startup()
+
+
+@app.on_event("shutdown")
+async def shutdown():
+    await bot.on_shutdown()
+
+
+@app.post("/", status_code=204)
+async def receive(message: GroupMeMessage, tasks: BackgroundTasks):
+    tasks.add_task(bot.on_message, message)
+    return Response(status_code=204)