aboutsummaryrefslogtreecommitdiffstats
path: root/slack
diff options
context:
space:
mode:
Diffstat (limited to 'slack')
-rw-r--r--slack/slack_api.py20
-rw-r--r--slack/slack_conversation.py54
-rw-r--r--slack/slack_message.py2
-rw-r--r--slack/slack_workspace.py56
4 files changed, 103 insertions, 29 deletions
diff --git a/slack/slack_api.py b/slack/slack_api.py
index eb04ce2..fd75277 100644
--- a/slack/slack_api.py
+++ b/slack/slack_api.py
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
from slack_api.slack_bots_info import SlackBotInfoResponse, SlackBotsInfoResponse
from slack_api.slack_conversations_history import SlackConversationsHistoryResponse
from slack_api.slack_conversations_info import SlackConversationsInfoResponse
+ from slack_api.slack_conversations_members import SlackConversationsMembersResponse
from slack_api.slack_rtm_connect import SlackRtmConnectResponse
from slack_api.slack_usergroups_info import SlackUsergroupsInfoResponse
from slack_api.slack_users_conversations import SlackUsersConversationsResponse
@@ -96,14 +97,29 @@ class SlackApi:
raise SlackApiError(self.workspace, method, response, params)
return response
- async def fetch_conversations_info(self, conversation: SlackConversation):
+ async def fetch_conversations_info(self, conversation_id: str):
method = "conversations.info"
- params = {"channel": conversation.id}
+ params = {"channel": conversation_id}
response: SlackConversationsInfoResponse = await self._fetch(method, params)
if response["ok"] is False:
raise SlackApiError(self.workspace, method, response, params)
return response
+ async def fetch_conversations_members(
+ self,
+ conversation: SlackConversation,
+ limit: int = 1000,
+ pages: int = -1,
+ ):
+ method = "conversations.members"
+ params = {"channel": conversation.id, "limit": limit}
+ response: SlackConversationsMembersResponse = await self._fetch_list(
+ method, "members", params, pages
+ )
+ if response["ok"] is False:
+ raise SlackApiError(self.workspace, method, response, params)
+ return response
+
async def fetch_users_conversations(
self,
types: str,
diff --git a/slack/slack_conversation.py b/slack/slack_conversation.py
index a23666e..fbf42bf 100644
--- a/slack/slack_conversation.py
+++ b/slack/slack_conversation.py
@@ -12,6 +12,7 @@ from slack.task import gather
from slack.util import get_callback_name
if TYPE_CHECKING:
+ from slack_api.slack_conversations_info import SlackConversationsInfo
from typing_extensions import Literal
from slack.slack_api import SlackApi
@@ -22,16 +23,21 @@ def get_conversation_from_buffer_pointer(
buffer_pointer: str,
) -> Optional[SlackConversation]:
for workspace in shared.workspaces.values():
- for conversation in workspace.conversations.values():
+ for conversation in workspace.open_conversations.values():
if conversation.buffer_pointer == buffer_pointer:
return conversation
return None
class SlackConversation:
- def __init__(self, workspace: SlackWorkspace, id: str):
+ def __init__(
+ self,
+ workspace: SlackWorkspace,
+ info: SlackConversationsInfo,
+ ):
self.workspace = workspace
- self.id = id
+ self._info = info
+ self._members: List[str]
# TODO: buffer_pointer may be accessed by buffer_switch before it's initialized
self.buffer_pointer: str = ""
self.name: str
@@ -48,10 +54,19 @@ class SlackConversation:
self.completion_values: List[str] = []
self.completion_index = 0
+ @classmethod
+ async def create(cls, workspace: SlackWorkspace, conversation_id: str):
+ info_response = await workspace.api.fetch_conversations_info(conversation_id)
+ return cls(workspace, info_response["channel"])
+
@property
def _api(self) -> SlackApi:
return self.workspace.api
+ @property
+ def id(self) -> str:
+ return self._info["id"]
+
@contextmanager
def loading(self):
self.is_loading = True
@@ -70,17 +85,28 @@ class SlackConversation:
finally:
self.completion_context = "ACTIVE_COMPLETION"
- async def init(self):
- with self.loading():
- info = await self._api.fetch_conversations_info(self)
+ async def open_if_open(self):
+ if "is_open" in self._info:
+ if self._info["is_open"]:
+ await self.open_buffer()
+ elif "is_member" in self._info and self._info["is_member"]:
+ await self.open_buffer()
- info_channel = info["channel"]
- if info_channel["is_im"] is True:
- self.name = "IM" # TODO
- elif info_channel["is_mpim"] is True:
- self.name = "MPIM" # TODO
- else:
- self.name = info_channel["name"]
+ async def open_buffer(self):
+ with self.loading():
+ if "is_im" in self._info and self._info["is_im"] is True:
+ im_user = await self.workspace.users[self._info["user"]]
+ self.name = im_user.nick()
+ elif self._info["is_mpim"] is True:
+ members_response = await self._api.fetch_conversations_members(self)
+ self._members = members_response["members"]
+ await self.workspace.users.initialize_items(self._members)
+ member_users = await gather(
+ *(self.workspace.users[user_id] for user_id in self._members)
+ )
+ self.name = ",".join([user.nick() for user in member_users])
+ else:
+ self.name = f"#{self._info['name']}"
full_name = f"{shared.SCRIPT_NAME}.{self.workspace.name}.{self.name}"
@@ -92,6 +118,8 @@ class SlackConversation:
self.buffer_pointer, "localvar_set_nick", self.workspace.my_user.nick()
)
+ self.workspace.open_conversations[self.id] = self
+
async def fill_history(self):
if self.history_filled or self.history_pending:
return
diff --git a/slack/slack_message.py b/slack/slack_message.py
index f79cdc2..07b03f4 100644
--- a/slack/slack_message.py
+++ b/slack/slack_message.py
@@ -55,7 +55,7 @@ class SlackMessage:
async def _lookup_item_id(self, item_id: str):
if item_id.startswith("#"):
- return self.workspace.conversations[removeprefix(item_id, "#")]
+ return await self.workspace.conversations[removeprefix(item_id, "#")]
elif item_id.startswith("@"):
return await self.workspace.users[removeprefix(item_id, "@")]
elif item_id.startswith("!subteam^"):
diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py
index c5c4732..176e031 100644
--- a/slack/slack_workspace.py
+++ b/slack/slack_workspace.py
@@ -15,21 +15,29 @@ from slack.shared import shared
from slack.slack_api import SlackApi
from slack.slack_conversation import SlackConversation
from slack.slack_user import SlackBot, SlackUser, SlackUsergroup
-from slack.task import Future, create_task
+from slack.task import Future, create_task, gather
from slack.util import get_callback_name
if TYPE_CHECKING:
from slack_api.slack_bots_info import SlackBotInfo
+ from slack_api.slack_conversations_info import SlackConversationsInfo
from slack_api.slack_usergroups_info import SlackUsergroupInfo
from slack_api.slack_users_info import SlackUserInfo
else:
SlackBotInfo = Any
+ SlackConversationsInfo = Any
SlackUsergroupInfo = Any
SlackUserInfo = Any
-SlackItemClass = TypeVar("SlackItemClass", SlackUser, SlackBot, SlackUsergroup)
+SlackItemClass = TypeVar(
+ "SlackItemClass", SlackConversation, SlackUser, SlackBot, SlackUsergroup
+)
SlackItemInfo = TypeVar(
- "SlackItemInfo", SlackUserInfo, SlackBotInfo, SlackUsergroupInfo
+ "SlackItemInfo",
+ SlackConversationsInfo,
+ SlackUserInfo,
+ SlackBotInfo,
+ SlackUsergroupInfo,
)
@@ -74,6 +82,29 @@ class SlackItem(
raise NotImplementedError()
+class SlackConversations(SlackItem[SlackConversation, SlackConversationsInfo]):
+ def __init__(self, workspace: SlackWorkspace):
+ super().__init__(workspace, SlackConversation)
+
+ async def _fetch_items_info(
+ self, item_ids: Iterable[str]
+ ) -> Dict[str, SlackConversationsInfo]:
+ responses = await gather(
+ *(
+ self.workspace.api.fetch_conversations_info(item_id)
+ for item_id in item_ids
+ )
+ )
+ return {
+ response["channel"]["id"]: response["channel"] for response in responses
+ }
+
+ def _create_item_from_info(
+ self, item_info: SlackConversationsInfo
+ ) -> SlackConversation:
+ return self._item_class(self.workspace, item_info)
+
+
class SlackUsers(SlackItem[SlackUser, SlackUserInfo]):
def __init__(self, workspace: SlackWorkspace):
super().__init__(workspace, SlackUser)
@@ -122,10 +153,11 @@ class SlackWorkspace:
self.config = shared.config.create_workspace_config(self.name)
self.api = SlackApi(self)
self._is_connected = False
+ self.conversations = SlackConversations(self)
+ self.open_conversations: Dict[str, SlackConversation] = {}
self.users = SlackUsers(self)
self.bots = SlackBots(self)
self.usergroups = SlackUsergroups(self)
- self.conversations: Dict[str, SlackConversation] = {}
def __repr__(self):
return f"{self.__class__.__name__}('{self.name}')"
@@ -147,16 +179,14 @@ class SlackWorkspace:
await self.connect_ws(rtm_connect["url"])
- # "types": "public_channel,private_channel,im",
- user_channels_response = await self.api.fetch_users_conversations(
- "public_channel"
+ users_conversations_response = await self.api.fetch_users_conversations(
+ "public_channel,private_channel,mpim,im"
)
- user_channels = user_channels_response["channels"]
-
- for channel in user_channels:
- conversation = SlackConversation(self, channel["id"])
- self.conversations[channel["id"]] = conversation
- create_task(conversation.init())
+ channels = users_conversations_response["channels"]
+ await self.conversations.initialize_items(channel["id"] for channel in channels)
+ for channel in channels:
+ conversation = await self.conversations[channel["id"]]
+ create_task(conversation.open_if_open())
self.is_connected = True