""" Slack models with self-parsing from Slack API responses. """ from pydantic import BaseModel from typing import Optional, List from datetime import datetime class User(BaseModel): id: str name: str real_name: Optional[str] = None display_name: Optional[str] = None is_bot: bool = False @classmethod def from_slack(cls, user: dict) -> "User": profile = user.get("profile", {}) return cls( id=user["id"], name=user.get("name", ""), real_name=profile.get("real_name") or user.get("real_name"), display_name=profile.get("display_name"), is_bot=user.get("is_bot", False), ) class Channel(BaseModel): id: str name: str is_private: bool = False is_archived: bool = False is_member: bool = False topic: Optional[str] = None purpose: Optional[str] = None num_members: Optional[int] = None @classmethod def from_slack(cls, channel: dict) -> "Channel": return cls( id=channel["id"], name=channel.get("name", ""), is_private=channel.get("is_private", False), is_archived=channel.get("is_archived", False), is_member=channel.get("is_member", False), topic=channel.get("topic", {}).get("value"), purpose=channel.get("purpose", {}).get("value"), num_members=channel.get("num_members"), ) class Message(BaseModel): ts: str # Slack timestamp (unique message ID) user: Optional[str] = None text: str thread_ts: Optional[str] = None reply_count: int = 0 reactions: List[dict] = [] timestamp: Optional[datetime] = None @classmethod def from_slack(cls, msg: dict) -> "Message": ts = msg.get("ts", "") return cls( ts=ts, user=msg.get("user"), text=msg.get("text", ""), thread_ts=msg.get("thread_ts"), reply_count=msg.get("reply_count", 0), reactions=msg.get("reactions", []), timestamp=cls._ts_to_datetime(ts), ) @staticmethod def _ts_to_datetime(ts: str) -> Optional[datetime]: if not ts: return None try: return datetime.fromtimestamp(float(ts)) except (ValueError, TypeError): return None class MessageList(BaseModel): messages: List[Message] channel_id: str has_more: bool = False class ChannelList(BaseModel): channels: List[Channel] total: int class UserList(BaseModel): users: List[User] total: int