aboutsummaryrefslogtreecommitdiffstats
path: root/slack
diff options
context:
space:
mode:
Diffstat (limited to 'slack')
-rw-r--r--slack/api.py111
-rw-r--r--slack/commands.py19
-rw-r--r--slack/init.py44
-rw-r--r--slack/task.py7
4 files changed, 148 insertions, 33 deletions
diff --git a/slack/api.py b/slack/api.py
index 52479ae..3b7feb9 100644
--- a/slack/api.py
+++ b/slack/api.py
@@ -1,14 +1,21 @@
from __future__ import annotations
import json
-from typing import TYPE_CHECKING, Dict, Union
+from typing import TYPE_CHECKING, Dict, Optional, Union
from urllib.parse import urlencode
+import weechat
+
from slack.http import http_request
from slack.shared import shared
+from slack.task import await_all_concurrent, create_task
if TYPE_CHECKING:
- from slack_api import SlackConversation, SlackConversationIm, SlackConversationNotIm
+ from slack_api import (
+ SlackConversationIm,
+ SlackConversationInfo,
+ SlackConversationNotIm,
+ )
class SlackApi:
@@ -55,27 +62,99 @@ class SlackWorkspace:
self.api = SlackApi(self)
self.connected = False
self.nick = "TODO"
+ # Maybe make private, so you have to use get_user? Maybe make get_user a getter, though don't know if that's a problem since it's async
+ self.users: Dict[str, SlackUser] = {}
+ self.conversations: Dict[str, SlackConversation] = {}
+
+ async def connect(self):
+ # rtm_connect = await self.api.fetch("rtm.connect")
+ user_channels_response = await self.api.fetch_list(
+ "users.conversations",
+ "channels",
+ {
+ "exclude_archived": True,
+ # "types": "public_channel,private_channel,im",
+ "types": "public_channel",
+ "limit": 1000,
+ },
+ -1,
+ )
+ 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())
+
+ # print(rtm_connect)
+ # print([c["name"] for c in user_channels])
+
+ async def get_user(self, id: str) -> SlackUser:
+ if id in self.users:
+ return self.users[id]
+ user = SlackUser(self, id)
+ await user.init()
+ self.users[id] = user
+ return user
+
+ def get_conversation_from_buffer_pointer(
+ self, buffer_pointer: str
+ ) -> Optional[SlackConversation]:
+ for conversation in self.conversations.values():
+ if conversation.buffer_pointer == buffer_pointer:
+ return conversation
+
+
+class SlackUser:
+ def __init__(self, workspace: SlackWorkspace, id: str):
+ self.workspace = workspace
+ self.api = workspace.api
+ self.id = id
+ self.name: str
+ async def init(self):
+ info = await self.api.fetch("users.info", {"user": self.id})
+ self.name = info["user"]["name"]
-class SlackChannelCommonNew:
- def __init__(self, workspace: SlackWorkspace, slack_info: SlackConversation):
+
+class SlackConversation:
+ def __init__(self, workspace: SlackWorkspace, id: str):
self.workspace = workspace
self.api = workspace.api
- self.id = slack_info["id"]
- # self.fetch_info()
+ self.id = id
+ self.buffer_pointer: str
+ self.name: str
+ self.history_filled = False
+ self.history_pending = False
+
+ async def init(self):
+ info = await self.fetch_info()
+ self.name = info["channel"]["name"]
+ self.buffer_pointer = weechat.buffer_new(self.name, "", "", "", "")
async def fetch_info(self):
- response = await self.api.fetch("conversations.info", {"channel": self.id})
- print(len(response))
+ return await self.api.fetch("conversations.info", {"channel": self.id})
+ async def fill_history(self):
+ if self.history_filled or self.history_pending:
+ return
+ self.history_pending = True
-class SlackChannelNew(SlackChannelCommonNew):
- def __init__(self, workspace: SlackWorkspace, slack_info: SlackConversationNotIm):
- super().__init__(workspace, slack_info)
- self.name = slack_info["name"]
+ history = await self.api.fetch("conversations.history", {"channel": self.id})
+
+ messages = history["messages"]
+ user_ids = [message["user"] for message in messages if "user" in message]
+ await await_all_concurrent(
+ [self.workspace.get_user(user_id) for user_id in user_ids]
+ )
+ for message in reversed(messages):
+ if "user" in message:
+ user = await self.workspace.get_user(message["user"])
+ username = user.name
+ else:
+ username = "bot"
+ weechat.prnt(self.buffer_pointer, f'{username}\t{message["text"]}')
-class SlackIm(SlackChannelCommonNew):
- def __init__(self, workspace: SlackWorkspace, slack_info: SlackConversationIm):
- super().__init__(workspace, slack_info)
- self.user = slack_info["user"]
+ self.history_filled = True
+ self.history_pending = False
diff --git a/slack/commands.py b/slack/commands.py
index bf48dda..1acf545 100644
--- a/slack/commands.py
+++ b/slack/commands.py
@@ -11,6 +11,7 @@ from slack.api import SlackWorkspace
from slack.config import WeeChatOption
from slack.log import print_error
from slack.shared import shared
+from slack.task import create_task
from slack.util import get_callback_name, with_color
commands: Dict[str, Command] = {}
@@ -99,6 +100,24 @@ def command_slack(buffer: str, args: List[str], options: Dict[str, Optional[str]
print("ran slack")
+@weechat_command("%(slack_workspaces)")
+def command_slack_connect(
+ buffer: str, args: List[str], options: Dict[str, Optional[str]]
+):
+ async def connect():
+ if args and args[0]:
+ workspace = shared.workspaces.get(args[0])
+ if workspace:
+ await workspace.connect()
+ else:
+ print_error(f'workspace "{args[0]}" not found')
+ else:
+ for workspace in shared.workspaces.values():
+ await workspace.connect()
+
+ create_task(connect(), final=True)
+
+
@weechat_command()
def command_slack_workspace(
buffer: str, args: List[str], options: Dict[str, Optional[str]]
diff --git a/slack/init.py b/slack/init.py
index ff95f57..3964a51 100644
--- a/slack/init.py
+++ b/slack/init.py
@@ -1,9 +1,9 @@
import weechat
from slack.commands import register_commands
-from slack.config import SlackConfig, SlackWorkspace
+from slack.config import SlackConfig
from slack.shared import shared
-from slack.task import create_task
+from slack.task import create_task, sleep
from slack.util import get_callback_name
SCRIPT_AUTHOR = "Trygve Aaberge <trygveaa@gmail.com>"
@@ -17,21 +17,25 @@ def shutdown_cb():
return weechat.WEECHAT_RC_OK
+def signal_buffer_switch_cb(data: str, signal: str, signal_data: str) -> int:
+ current_conversation = None
+ for workspace in shared.workspaces.values():
+ conversation = workspace.get_conversation_from_buffer_pointer(signal_data)
+ if conversation:
+ current_conversation = conversation
+
+ if current_conversation:
+ create_task(current_conversation.fill_history())
+ return weechat.WEECHAT_RC_OK
+
+
async def init():
- pass
- # print(shared.workspaces)
- # if "wee-slack-test" not in shared.workspaces:
- # shared.workspaces["wee-slack-test"] = SlackWorkspace("wee-slack-test")
- # shared.workspaces[
- # "wee-slack-test"
- # ].config.api_token.value = weechat.config_get_plugin("api_token")
- # shared.workspaces[
- # "wee-slack-test"
- # ].config.api_cookies.value = weechat.config_get_plugin("api_cookie")
- # workspace = shared.workspaces["wee-slack-test"]
- # print(workspace)
- # print(workspace.config.slack_timeout.value)
- # print(shared.config.color.reaction_suffix.value)
+ auto_connect = weechat.info_get("auto_connect", "") == "1"
+ if auto_connect:
+ await sleep(1) # Defer auto connect to ensure the logger plugin is loaded
+ for workspace in shared.workspaces.values():
+ if workspace.config.autoconnect.value:
+ await workspace.connect()
def main():
@@ -49,4 +53,12 @@ def main():
shared.config = SlackConfig()
shared.config.config_read()
register_commands()
+
+ weechat.hook_signal(
+ "buffer_switch", get_callback_name(signal_buffer_switch_cb), ""
+ )
+ weechat.hook_signal(
+ "window_switch", get_callback_name(signal_buffer_switch_cb), ""
+ )
+
create_task(init(), final=True)
diff --git a/slack/task.py b/slack/task.py
index 2caf264..27abd48 100644
--- a/slack/task.py
+++ b/slack/task.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from typing import Any, Awaitable, Coroutine, Generator, Tuple, TypeVar
+from typing import Any, Awaitable, Coroutine, Generator, List, Tuple, TypeVar
from uuid import uuid4
import weechat
@@ -75,6 +75,11 @@ def create_task(
return task
+async def await_all_concurrent(requests: List[Coroutine[Any, Any, T]]) -> List[T]:
+ tasks = [create_task(request) for request in requests]
+ return [await task for task in tasks]
+
+
async def sleep(milliseconds: int):
future = FutureTimer()
weechat.hook_timer(