from typing import Dict, Any, Optional class SlackEvent(dict): @staticmethod def from_payload(payload: Dict[str, Any]) -> Optional["SlackEvent"]: try: event = SlackEvent(payload) return event except KeyError: return None @property def text(self) -> str: if self.get("event", {}).get("channel_type") == "im": blocks = self.get("event", {}).get("blocks", []) if not blocks: return "" elements = blocks[0].get("elements", []) if not elements: return "" elements = elements[0].get("elements", []) text = "" for el in elements: if el.get("type") == "text": text += el.get("text", "") elif el.get("type") == "link": text += el.get("url", "") return text if self.get("event",{}).get("channel_type") == 'channel': message_text = "" for block in self.get("event", {}).get("blocks", []): if block.get("type") == "rich_text": for element in block.get("elements", []): if element.get("type") == "rich_text_section": parts = [] for el in element.get("elements", []): if el.get("type") == "text": parts.append(el["text"]) elif el.get("type") == "link": parts.append(el["url"]) message_text = "".join(parts) return message_text @property def user_id(self) -> Optional[str]: return self.get("event", {}).get("user","") @property def channel_id(self) -> Optional[str]: return self.get("event", {}).get("channel","") @property def type(self) -> str: """ message对应私聊,app_mention对应频道at """ return self.get("event", {}).get("channel_type", "") @property def message_id(self) -> str: return self.get("event_id","") @property def pic_url(self) -> str: """提取 Slack 事件中的图片 URL""" files = self.get("event", {}).get("files", []) if files: return files[0].get("url_private", "") return None @property def sender_name(self) -> str: return self.get("event", {}).get("user","") def __getattr__(self, key: str) -> Optional[Any]: return self.get(key) def __setattr__(self, key: str, value: Any) -> None: self[key] = value def __repr__(self) -> str: return f""