mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 06:23:38 +00:00
slack: Handle integration bots with missing data.
We encountered the following two new cases with integration bots in Slack imports: 1. Bots without the image_72 field in their data. Such bots should fall back to gravatar. 2. Bots whose bot_id is the sender of certain messages, but querying the bots.info endpoint returns bot_not_found error. We should create dummy accounts in place of such bots.
This commit is contained in:
committed by
Tim Abbott
parent
c3a138cfa8
commit
a52bc4d71b
@@ -471,7 +471,7 @@ def build_avatar_url(slack_user_id: str, user: ZerverFieldsT) -> tuple[str, str]
|
|||||||
avatar_hash = user["profile"]["avatar_hash"]
|
avatar_hash = user["profile"]["avatar_hash"]
|
||||||
avatar_url = f"https://ca.slack-edge.com/{team_id}-{slack_user_id}-{avatar_hash}"
|
avatar_url = f"https://ca.slack-edge.com/{team_id}-{slack_user_id}-{avatar_hash}"
|
||||||
avatar_source = UserProfile.AVATAR_FROM_USER
|
avatar_source = UserProfile.AVATAR_FROM_USER
|
||||||
elif user.get("is_integration_bot"):
|
elif user.get("is_integration_bot") and "image_72" in user["profile"]:
|
||||||
# Unlike other Slack user types, Slacks integration bot avatar URL ends with
|
# Unlike other Slack user types, Slacks integration bot avatar URL ends with
|
||||||
# a file type extension (.png, in this case).
|
# a file type extension (.png, in this case).
|
||||||
# e.g https://avatars.slack-edge.com/2024-05-01/7218497908_deb94eac4c_512.png
|
# e.g https://avatars.slack-edge.com/2024-05-01/7218497908_deb94eac4c_512.png
|
||||||
@@ -1316,11 +1316,32 @@ def convert_bot_info_to_slack_user(bot_info: dict[str, Any]) -> ZerverFieldsT:
|
|||||||
"real_name": bot_info["name"],
|
"real_name": bot_info["name"],
|
||||||
"is_integration_bot": True,
|
"is_integration_bot": True,
|
||||||
"profile": {
|
"profile": {
|
||||||
"image_72": bot_info["icons"]["image_72"],
|
|
||||||
"bot_id": bot_info["id"],
|
"bot_id": bot_info["id"],
|
||||||
"first_name": bot_info["name"],
|
"first_name": bot_info["name"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if "image_72" in bot_info["icons"]:
|
||||||
|
# Otherwise, gravatar will be used.
|
||||||
|
bot_user["profile"]["image_72"] = bot_info["icons"]["image_72"]
|
||||||
|
|
||||||
|
return bot_user
|
||||||
|
|
||||||
|
|
||||||
|
def make_deleted_placeholder(bot_id: str) -> ZerverFieldsT:
|
||||||
|
name = f"Deleted Slack Bot {bot_id}"
|
||||||
|
bot_user = {
|
||||||
|
"id": bot_id,
|
||||||
|
"name": name,
|
||||||
|
"deleted": True,
|
||||||
|
"is_mirror_dummy": False,
|
||||||
|
"real_name": name,
|
||||||
|
"is_integration_bot": True,
|
||||||
|
"profile": {
|
||||||
|
# Intentionally skip image_72. Gravatar should be used.
|
||||||
|
"bot_id": bot_id,
|
||||||
|
"first_name": name,
|
||||||
|
},
|
||||||
|
}
|
||||||
return bot_user
|
return bot_user
|
||||||
|
|
||||||
|
|
||||||
@@ -1366,9 +1387,14 @@ def fetch_shared_channel_users(
|
|||||||
bot_id = message["bot_id"]
|
bot_id = message["bot_id"]
|
||||||
if bot_id in integration_bot_users:
|
if bot_id in integration_bot_users:
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
bot_info = get_slack_api_data(
|
bot_info = get_slack_api_data(
|
||||||
"https://slack.com/api/bots.info", "bot", token=token, bot=bot_id
|
"https://slack.com/api/bots.info", "bot", token=token, bot=bot_id
|
||||||
)
|
)
|
||||||
|
except SlackBotNotFoundError:
|
||||||
|
logging.info("Bot %s not found, creating a deleted placeholder", bot_id)
|
||||||
|
bot_user = make_deleted_placeholder(bot_id)
|
||||||
|
else:
|
||||||
bot_user = convert_bot_info_to_slack_user(bot_info)
|
bot_user = convert_bot_info_to_slack_user(bot_info)
|
||||||
|
|
||||||
user_list.append(bot_user)
|
user_list.append(bot_user)
|
||||||
@@ -1688,6 +1714,9 @@ def get_slack_api_data(
|
|||||||
|
|
||||||
result = response.json()
|
result = response.json()
|
||||||
if not result["ok"]:
|
if not result["ok"]:
|
||||||
|
if result["error"] == "bot_not_found":
|
||||||
|
raise SlackBotNotFoundError
|
||||||
|
|
||||||
raise Exception("Error accessing Slack API: {}".format(result["error"]))
|
raise Exception("Error accessing Slack API: {}".format(result["error"]))
|
||||||
|
|
||||||
result_data = result[get_param]
|
result_data = result[get_param]
|
||||||
@@ -1704,3 +1733,7 @@ def get_slack_api_data(
|
|||||||
cursor = result["response_metadata"]["next_cursor"]
|
cursor = result["response_metadata"]["next_cursor"]
|
||||||
|
|
||||||
return accumulated_result
|
return accumulated_result
|
||||||
|
|
||||||
|
|
||||||
|
class SlackBotNotFoundError(Exception):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from zerver.data_import.slack import (
|
|||||||
AddedMPIMsT,
|
AddedMPIMsT,
|
||||||
DMMembersT,
|
DMMembersT,
|
||||||
SlackBotEmail,
|
SlackBotEmail,
|
||||||
|
SlackBotNotFoundError,
|
||||||
channel_message_to_zerver_message,
|
channel_message_to_zerver_message,
|
||||||
channels_to_zerver_stream,
|
channels_to_zerver_stream,
|
||||||
check_token_access,
|
check_token_access,
|
||||||
@@ -264,9 +265,8 @@ class SlackImporter(ZulipTestCase):
|
|||||||
# Bot info
|
# Bot info
|
||||||
slack_bots_info_url = "https://slack.com/api/bots.info"
|
slack_bots_info_url = "https://slack.com/api/bots.info"
|
||||||
responses.add_callback(responses.GET, slack_bots_info_url, callback=request_callback)
|
responses.add_callback(responses.GET, slack_bots_info_url, callback=request_callback)
|
||||||
with self.assertRaises(Exception) as invalid:
|
with self.assertRaises(SlackBotNotFoundError):
|
||||||
get_slack_api_data(slack_bots_info_url, "XXXYYYZZZ", token=token)
|
get_slack_api_data(slack_bots_info_url, "XXXYYYZZZ", token=token)
|
||||||
self.assertEqual(invalid.exception.args, ("Error accessing Slack API: bot_not_found",))
|
|
||||||
|
|
||||||
# Api test
|
# Api test
|
||||||
api_test_info_url = "https://slack.com/api/api.test"
|
api_test_info_url = "https://slack.com/api/api.test"
|
||||||
|
|||||||
Reference in New Issue
Block a user