Skip to content

Commit e0f20f6

Browse files
committed
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.
1 parent 8b7417c commit e0f20f6

File tree

2 files changed

+6
-100
lines changed

2 files changed

+6
-100
lines changed

zulip/integrations/bridge_with_slack/README.md

-34
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,3 @@ This is a bridge between Slack and Zulip.
4444
### Running the bridge
4545

4646
Run Slack Bridge: `python3 run-slack-bridge`
47-
48-
<details>
49-
<summary>Legacy: If you're still using classic Slack app, follow this instruction instead!</summary>
50-
51-
### 1. Zulip endpoint
52-
1. Create a generic Zulip bot, with a full name like `Slack Bot`.
53-
2. (Important) Subscribe the bot user to the Zulip stream you'd like to bridge your Slack
54-
channel into.
55-
3. In the `zulip` section of the configuration file, enter the bot's `zuliprc`
56-
details (`email`, `api_key`, and `site`).
57-
4. In the same section, also enter the Zulip `stream` and `topic`.
58-
59-
### 2. Slack endpoint
60-
1. Make sure Websocket isn't blocked in the computer where you run this bridge.
61-
Test it at https://www.websocket.org/echo.html.
62-
2. Go to https://api.slack.com/apps?new_classic_app=1 and create a new classic
63-
app (note: must be a classic app). Choose a bot name that will be put into
64-
bridge_with_slack_config.py, e.g. "zulip_mirror". In the process of doing
65-
this, you need to add oauth token scope. Simply choose `bot`. Slack will say
66-
that this is a legacy scope, but we still need to use it anyway. The reason
67-
why we need the legacy scope is because otherwise the RTM API wouldn't work.
68-
We might remove the RTM API usage in newer version of this bot. Make sure to
69-
install the app to the workspace. When successful, you should see a token
70-
that starts with "xoxb-...". There is also a token that starts with
71-
"xoxp-...", we need the "xoxb-..." one.
72-
3. Go to "App Home", click the button "Add Legacy Bot User".
73-
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.
74-
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).
75-
76-
### Running the bridge
77-
78-
Run Legacy Slack Bridge: `python3 run-slack-bridge --legacy`
79-
80-
</details>

zulip/integrations/bridge_with_slack/run-slack-bridge

+6-66
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ import traceback
88
from typing import Any, Callable, Dict, Optional, Tuple
99

1010
import bridge_with_slack_config
11-
from slack_sdk.rtm_v2 import RTMClient
1211
from slack_sdk.web.client import WebClient
1312

1413
import zulip
1514

1615
# change these templates to change the format of displayed message
17-
ZULIP_MESSAGE_TEMPLATE = "**{username}**: {message}"
1816
SLACK_MESSAGE_TEMPLATE = "<{username}> {message}"
1917

2018
StreamTopicT = Tuple[str, str]
@@ -59,7 +57,6 @@ class SlackBridge:
5957
self.zulip_config = config["zulip"]
6058
self.slack_config = config["slack"]
6159

62-
self.slack_to_zulip_map: Dict[str, Dict[str, str]] = config["channel_mapping"]
6360
self.zulip_to_slack_map: Dict[StreamTopicT, str] = {
6461
(z["channel"], z["topic"]): s for s, z in config["channel_mapping"].items()
6562
}
@@ -77,8 +74,6 @@ class SlackBridge:
7774
# https://github.com/zulip/python-zulip-api/issues/761 is fixed.
7875
self.zulip_client_constructor = zulip_client_constructor
7976

80-
# slack-specific
81-
self.slack_client = rtm
8277
# Spawn a non-websocket client for getting the users
8378
# list and for posting messages in Slack.
8479
self.slack_webclient = WebClient(token=self.slack_config["token"])
@@ -89,13 +84,6 @@ class SlackBridge:
8984
if w.startswith("@"):
9085
zulip_msg["content"] = zulip_msg["content"].replace(w, "<" + w + ">")
9186

92-
def replace_slack_id_with_name(self, msg: Dict[str, Any]) -> None:
93-
words = msg["text"].split(" ")
94-
for w in words:
95-
if w.startswith("<@") and w.endswith(">"):
96-
_id = w[2:-1]
97-
msg["text"] = msg["text"].replace(_id, self.slack_id_to_name[_id])
98-
9987
def zulip_to_slack(self) -> Callable[[Dict[str, Any]], None]:
10088
def _zulip_to_slack(msg: Dict[str, Any]) -> None:
10189
slack_channel = get_slack_channel_for_zulip_message(
@@ -114,36 +102,6 @@ class SlackBridge:
114102

115103
return _zulip_to_slack
116104

117-
def run_slack_listener(self) -> None:
118-
members = self.slack_webclient.users_list()["members"]
119-
# See also https://api.slack.com/changelog/2017-09-the-one-about-usernames
120-
self.slack_id_to_name: Dict[str, str] = {
121-
u["id"]: u["profile"].get("display_name", u["profile"]["real_name"]) for u in members
122-
}
123-
self.slack_name_to_id = {v: k for k, v in self.slack_id_to_name.items()}
124-
125-
@rtm.on("message")
126-
def slack_to_zulip(client: RTMClient, event: Dict[str, Any]) -> None:
127-
if event["channel"] not in self.slack_to_zulip_map:
128-
return
129-
user_id = event["user"]
130-
user = self.slack_id_to_name[user_id]
131-
from_bot = user == self.slack_config["username"]
132-
if from_bot:
133-
return
134-
self.replace_slack_id_with_name(event)
135-
content = ZULIP_MESSAGE_TEMPLATE.format(username=user, message=event["text"])
136-
zulip_endpoint = self.slack_to_zulip_map[event["channel"]]
137-
msg_data = dict(
138-
type="stream",
139-
to=zulip_endpoint["channel"],
140-
subject=zulip_endpoint["topic"],
141-
content=content,
142-
)
143-
self.zulip_client_constructor().send_message(msg_data)
144-
145-
self.slack_client.start()
146-
147105

148106
if __name__ == "__main__":
149107
usage = """run-slack-bridge
@@ -154,9 +112,7 @@ if __name__ == "__main__":
154112

155113
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
156114
parser = argparse.ArgumentParser(usage=usage)
157-
parser.add_argument(
158-
"--legacy", action="store_true", help="Run the bridge using the legacy Slack RTM API"
159-
)
115+
160116
args = parser.parse_args()
161117

162118
config: Dict[str, Any] = bridge_with_slack_config.config
@@ -172,10 +128,6 @@ if __name__ == "__main__":
172128
print("Starting slack mirroring bot")
173129
print("MAKE SURE THE BOT IS SUBSCRIBED TO THE RELEVANT ZULIP STREAM(S) & SLACK CHANNEL(S)!")
174130

175-
# We have to define rtm outside of SlackBridge because the rtm variable is used as a method decorator.
176-
# the RTM API is a legacy Slack SDK, we keep using them only to provide backwards compitability.
177-
rtm = RTMClient(token=config["slack"]["token"])
178-
179131
backoff = zulip.RandomExponentialBackoff(timeout_success_equivalent=300)
180132
while backoff.keep_going():
181133
try:
@@ -187,23 +139,11 @@ if __name__ == "__main__":
187139
print("Starting message handler on Zulip client")
188140
zp.start()
189141

190-
if args.legacy:
191-
sp = threading.Thread(target=sb.run_slack_listener, args=())
192-
print(
193-
"Warning! Running on legacy Slack SDK\n"
194-
"Starting message handler on Slack client"
195-
)
196-
sp.start()
197-
sp.join()
198-
zp.join()
199-
else:
200-
print(
201-
"Warning! if you haven't moved to the new Slack app,\n"
202-
"please run the script with the --legacy argument.\n"
203-
"Make sure your Slack Webhook integration is running\n"
204-
"to receive messages from Slack."
205-
)
206-
zp.join()
142+
print(
143+
"Make sure your Slack Webhook integration is running\n"
144+
"to receive messages from Slack."
145+
)
146+
zp.join()
207147
except Exception:
208148
traceback.print_exc()
209149
backoff.fail()

0 commit comments

Comments
 (0)