Skip to content

Commit 79b7a2a

Browse files
committed
slack bridge: Add legacy mode for Slack Bridge.
Slack Bridge now uses the Slack Webhook integration to get messages accross from Slack instead of the legacy RTM API based connection our Slack Bridge use. This commit adds a "--legacy" argument to the script, it acts as a toggle to run the RTM API based connection to get messages accross to Zulip. It is used to ensure backwards compitability for users who want to maintain any ongoing Slack mirror.
1 parent 2ba2a48 commit 79b7a2a

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

zulip/integrations/bridge_with_slack/bridge_with_slack_config.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
},
77
"slack": {
88
"username": "slack_username",
9-
"token": "xoxb-your-slack-token",
9+
"token": "xoxp-your-slack-token",
1010
},
1111
# Mapping between Slack channels and Zulip stream-topic's.
1212
# You can specify multiple pairs.
1313
"channel_mapping": {
1414
# Slack channel; must be channel ID
1515
"C5Z5N7R8A": {
16-
# Zulip stream
17-
"stream": "test here",
16+
# Zulip channel
17+
"channel": "test here",
1818
# Zulip topic
1919
"topic": "<- slack-bridge",
2020
},

zulip/integrations/bridge_with_slack/run-slack-bridge

+40-9
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import traceback
88
from typing import Any, Callable, Dict, Optional, Tuple
99

1010
import bridge_with_slack_config
11-
import slack_sdk
1211
from slack_sdk.rtm_v2 import RTMClient
12+
from slack_sdk.web.client import WebClient
1313

1414
import zulip
1515

@@ -41,6 +41,18 @@ def get_slack_channel_for_zulip_message(
4141
return zulip_to_slack_map[stream_topic]
4242

4343

44+
def check_token_access(token: str) -> None:
45+
if token.startswith("xoxp-"):
46+
print(
47+
"--- Warning! ---\n"
48+
"You entered a Slack user token, please copy the token under\n"
49+
"'Bot User OAuth Token' which starts with 'xoxb-...'."
50+
)
51+
sys.exit(1)
52+
elif token.startswith("xoxb-"):
53+
return
54+
55+
4456
class SlackBridge:
4557
def __init__(self, config: Dict[str, Any]) -> None:
4658
self.config = config
@@ -49,7 +61,7 @@ class SlackBridge:
4961

5062
self.slack_to_zulip_map: Dict[str, Dict[str, str]] = config["channel_mapping"]
5163
self.zulip_to_slack_map: Dict[StreamTopicT, str] = {
52-
(z["stream"], z["topic"]): s for s, z in config["channel_mapping"].items()
64+
(z["channel"], z["topic"]): s for s, z in config["channel_mapping"].items()
5365
}
5466

5567
# zulip-specific
@@ -69,7 +81,7 @@ class SlackBridge:
6981
self.slack_client = rtm
7082
# Spawn a non-websocket client for getting the users
7183
# list and for posting messages in Slack.
72-
self.slack_webclient = slack_sdk.WebClient(token=self.slack_config["token"])
84+
self.slack_webclient = WebClient(token=self.slack_config["token"])
7385

7486
def wrap_slack_mention_with_bracket(self, zulip_msg: Dict[str, Any]) -> None:
7587
words = zulip_msg["content"].split(" ")
@@ -123,7 +135,7 @@ class SlackBridge:
123135
zulip_endpoint = self.slack_to_zulip_map[event["channel"]]
124136
msg_data = dict(
125137
type="stream",
126-
to=zulip_endpoint["stream"],
138+
to=zulip_endpoint["channel"],
127139
subject=zulip_endpoint["topic"],
128140
content=content,
129141
)
@@ -141,6 +153,10 @@ if __name__ == "__main__":
141153

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

145161
config: Dict[str, Any] = bridge_with_slack_config.config
146162
if "channel_mapping" not in config:
@@ -150,10 +166,13 @@ if __name__ == "__main__":
150166
)
151167
sys.exit(1)
152168

169+
check_token_access(config["slack"]["token"])
170+
153171
print("Starting slack mirroring bot")
154172
print("MAKE SURE THE BOT IS SUBSCRIBED TO THE RELEVANT ZULIP STREAM(S) & SLACK CHANNEL(S)!")
155173

156174
# We have to define rtm outside of SlackBridge because the rtm variable is used as a method decorator.
175+
# the RTM API is a legacy Slack SDK, we keep using them only to provide backwards compitability.
157176
rtm = RTMClient(token=config["slack"]["token"])
158177

159178
backoff = zulip.RandomExponentialBackoff(timeout_success_equivalent=300)
@@ -164,14 +183,26 @@ if __name__ == "__main__":
164183
zp = threading.Thread(
165184
target=sb.zulip_client.call_on_each_message, args=(sb.zulip_to_slack(),)
166185
)
167-
sp = threading.Thread(target=sb.run_slack_listener, args=())
168186
print("Starting message handler on Zulip client")
169187
zp.start()
170-
print("Starting message handler on Slack client")
171-
sp.start()
172188

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

0 commit comments

Comments
 (0)