From d8e6f714a4d874e2e0e76741363eca86ef2a3981 Mon Sep 17 00:00:00 2001 From: PieterCK Date: Sat, 29 Jun 2024 14:50:41 +0700 Subject: [PATCH] slack bridge: Remove support for the legacy RTM API. This is an optional commit that drops support running the Slack Bridge using the legacy RTM API. The reasoning for removing backwards compitability is because the user can just use the older version of pyton-zulip-api. --- .../integrations/bridge_with_slack/README.md | 34 --------- .../bridge_with_slack/run-slack-bridge | 72 ++----------------- 2 files changed, 6 insertions(+), 100 deletions(-) diff --git a/zulip/integrations/bridge_with_slack/README.md b/zulip/integrations/bridge_with_slack/README.md index d0a6bda20..e499a82e9 100644 --- a/zulip/integrations/bridge_with_slack/README.md +++ b/zulip/integrations/bridge_with_slack/README.md @@ -44,37 +44,3 @@ This is a bridge between Slack and Zulip. ### Running the bridge Run Slack Bridge: `python3 run-slack-bridge` - -
-Legacy: If you're still using classic Slack app, follow this instruction instead! - -### 1. Zulip endpoint -1. Create a generic Zulip bot, with a full name like `Slack Bot`. -2. (Important) Subscribe the bot user to the Zulip stream you'd like to bridge your Slack - channel into. -3. In the `zulip` section of the configuration file, enter the bot's `zuliprc` - details (`email`, `api_key`, and `site`). -4. In the same section, also enter the Zulip `stream` and `topic`. - -### 2. Slack endpoint -1. Make sure Websocket isn't blocked in the computer where you run this bridge. - Test it at https://www.websocket.org/echo.html. -2. Go to https://api.slack.com/apps?new_classic_app=1 and create a new classic - app (note: must be a classic app). Choose a bot name that will be put into - bridge_with_slack_config.py, e.g. "zulip_mirror". In the process of doing - this, you need to add oauth token scope. Simply choose `bot`. Slack will say - that this is a legacy scope, but we still need to use it anyway. The reason - why we need the legacy scope is because otherwise the RTM API wouldn't work. - We might remove the RTM API usage in newer version of this bot. Make sure to - install the app to the workspace. When successful, you should see a token - that starts with "xoxb-...". There is also a token that starts with - "xoxp-...", we need the "xoxb-..." one. -3. Go to "App Home", click the button "Add Legacy Bot User". -4. (Important) Make sure the bot is subscribed to the channel. You can do this by typing e.g. `/invite @zulip_mirror` in the relevant channel. -5. In the `slack` section of the Zulip-Slack bridge configuration file, enter the bot name (e.g. "zulip_mirror") and token, and the channel ID (note: must be ID, not name). - -### Running the bridge - -Run Legacy Slack Bridge: `python3 run-slack-bridge --legacy` - -
diff --git a/zulip/integrations/bridge_with_slack/run-slack-bridge b/zulip/integrations/bridge_with_slack/run-slack-bridge index 11aee0242..afe4bad6f 100755 --- a/zulip/integrations/bridge_with_slack/run-slack-bridge +++ b/zulip/integrations/bridge_with_slack/run-slack-bridge @@ -8,13 +8,11 @@ import traceback from typing import Any, Callable, Dict, Optional, Tuple import bridge_with_slack_config -from slack_sdk.rtm_v2 import RTMClient from slack_sdk.web.client import WebClient import zulip # change these templates to change the format of displayed message -ZULIP_MESSAGE_TEMPLATE = "**{username}**: {message}" SLACK_MESSAGE_TEMPLATE = "<{username}> {message}" StreamTopicT = Tuple[str, str] @@ -47,7 +45,6 @@ class SlackBridge: self.zulip_config = config["zulip"] self.slack_config = config["slack"] - self.slack_to_zulip_map: Dict[str, Dict[str, str]] = config["channel_mapping"] self.zulip_to_slack_map: Dict[StreamTopicT, str] = { (z["channel"], z["topic"]): s for s, z in config["channel_mapping"].items() } @@ -65,8 +62,6 @@ class SlackBridge: # https://github.com/zulip/python-zulip-api/issues/761 is fixed. self.zulip_client_constructor = zulip_client_constructor - # slack-specific - self.slack_client = rtm # Spawn a non-websocket client for getting the users # list and for posting messages in Slack. self.slack_webclient = WebClient(token=self.slack_config["token"]) @@ -77,13 +72,6 @@ class SlackBridge: if w.startswith("@"): zulip_msg["content"] = zulip_msg["content"].replace(w, "<" + w + ">") - def replace_slack_id_with_name(self, msg: Dict[str, Any]) -> None: - words = msg["text"].split(" ") - for w in words: - if w.startswith("<@") and w.endswith(">"): - _id = w[2:-1] - msg["text"] = msg["text"].replace(_id, self.slack_id_to_name[_id]) - def zulip_to_slack(self) -> Callable[[Dict[str, Any]], None]: def _zulip_to_slack(msg: Dict[str, Any]) -> None: slack_channel = get_slack_channel_for_zulip_message( @@ -102,36 +90,6 @@ class SlackBridge: return _zulip_to_slack - def run_slack_listener(self) -> None: - members = self.slack_webclient.users_list()["members"] - # See also https://api.slack.com/changelog/2017-09-the-one-about-usernames - self.slack_id_to_name: Dict[str, str] = { - u["id"]: u["profile"].get("display_name", u["profile"]["real_name"]) for u in members - } - self.slack_name_to_id = {v: k for k, v in self.slack_id_to_name.items()} - - @rtm.on("message") - def slack_to_zulip(client: RTMClient, event: Dict[str, Any]) -> None: - if event["channel"] not in self.slack_to_zulip_map: - return - user_id = event["user"] - user = self.slack_id_to_name[user_id] - from_bot = user == self.slack_config["username"] - if from_bot: - return - self.replace_slack_id_with_name(event) - content = ZULIP_MESSAGE_TEMPLATE.format(username=user, message=event["text"]) - zulip_endpoint = self.slack_to_zulip_map[event["channel"]] - msg_data = dict( - type="stream", - to=zulip_endpoint["channel"], - subject=zulip_endpoint["topic"], - content=content, - ) - self.zulip_client_constructor().send_message(msg_data) - - self.slack_client.start() - if __name__ == "__main__": usage = """run-slack-bridge @@ -142,9 +100,7 @@ if __name__ == "__main__": sys.path.append(os.path.join(os.path.dirname(__file__), "..")) parser = argparse.ArgumentParser(usage=usage) - parser.add_argument( - "--legacy", action="store_true", help="Run the bridge using the legacy Slack RTM API" - ) + args = parser.parse_args() config: Dict[str, Any] = bridge_with_slack_config.config @@ -158,10 +114,6 @@ if __name__ == "__main__": print("Starting slack mirroring bot") print("MAKE SURE THE BOT IS SUBSCRIBED TO THE RELEVANT ZULIP STREAM(S) & SLACK CHANNEL(S)!") - # We have to define rtm outside of SlackBridge because the rtm variable is used as a method decorator. - # the RTM API is a legacy Slack SDK, we keep using them only to provide backwards compitability. - rtm = RTMClient(token=config["slack"]["token"]) - backoff = zulip.RandomExponentialBackoff(timeout_success_equivalent=300) while backoff.keep_going(): try: @@ -173,23 +125,11 @@ if __name__ == "__main__": print("Starting message handler on Zulip client") zp.start() - if args.legacy: - sp = threading.Thread(target=sb.run_slack_listener, args=()) - print( - "Warning! Running on legacy Slack SDK\n" - "Starting message handler on Slack client" - ) - sp.start() - sp.join() - zp.join() - else: - print( - "Warning! if you haven't moved to the new Slack app,\n" - "please run the script with the --legacy argument.\n" - "Make sure your Slack Webhook integration is running\n" - "to receive messages from Slack." - ) - zp.join() + print( + "Make sure your Slack Webhook integration is running\n" + "to receive messages from Slack." + ) + zp.join() except Exception: traceback.print_exc() backoff.fail()