Skip to content

Commit b8f3f71

Browse files
authored
Merge pull request #28 from surface-security/bot_messages
Import Bot/Requests messages
2 parents 5055e0e + 71321c3 commit b8f3f71

3 files changed

Lines changed: 133 additions & 26 deletions

File tree

slackbot/apps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
BOT_TOKEN=None,
99
APP_TOKEN=None,
1010
SLACK_CHANNELS={"test_channel": "1"},
11+
BOT_EXCLUSIONS={"dummy_bot": "111"},
1112
USER_MODEL="slackbot.User",
1213
)
1314

slackbot/management/commands/resync_slack_messages.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,37 @@ def handle(self, *args, **options) -> None:
3232
for message in response["messages"]:
3333
thread_response = None
3434
aware_thread_timestamp = None
35+
text = message["text"]
36+
message_from = message.get("user_profile", {}).get("display_name", "Unknown User")
3537
time_stamp = datetime.fromtimestamp(float(message["ts"]))
3638
aware_timestamp = timezone.make_aware(time_stamp, timezone.get_default_timezone())
3739
now_h = time_stamp.strftime("%Y-%m-%d %H")
3840
if last_h != now_h:
3941
last_h = now_h
4042

41-
if message.get("bot_id"):
42-
continue
43-
4443
if aware_timestamp < timezone.now() - timezone.timedelta(days=365):
4544
continue
4645

46+
try:
47+
if message.get("bot_id"):
48+
if message["bot_id"] in settings.SLACKBOT_BOT_EXCLUSIONS.values():
49+
continue
50+
51+
message_from_id = message["text"].split("<@")[1].split(">")[0]
52+
if user := User.objects.filter(ext_id=message_from_id).first():
53+
message_from = user.name
54+
else:
55+
message_from = "Unknown User"
56+
57+
text_list = str(message["text"]).split("*Description:*", 1)
58+
59+
if len(text_list) == 2:
60+
text = text_list[1]
61+
else:
62+
text = "-"
63+
except Exception as e:
64+
self.log_warning("Error processing bot %s", message["bot_id"], e)
65+
4766
replies = []
4867
if "thread_ts" in message:
4968
thread_response = client.conversations_replies(channel=channel_id, ts=message["thread_ts"])
@@ -92,11 +111,11 @@ def handle(self, *args, **options) -> None:
92111
"reply_users": reply_users,
93112
"reply_users_count": message.get("reply_users_count", 0),
94113
"team": message.get("team", ""),
95-
"text": message["text"],
114+
"text": text,
96115
"thread_timestamp": aware_thread_timestamp,
97116
"type": message["type"],
98117
"user": message["user"],
99-
"message_from": message.get("user_profile", {}).get("display_name", "Unknown User"),
118+
"message_from": message_from,
100119
"user_team": message.get("user_team", ""),
101120
"thread_message": replies,
102121
},
@@ -108,7 +127,7 @@ def handle(self, *args, **options) -> None:
108127
except SlackApiError as e:
109128
if e.response["error"] == "ratelimited":
110129
retry_after = int(e.response.headers["Retry-After"])
111-
self.log_exception("Rate limit hit. Retrying.... %s")
130+
self.log_warning("Rate limit hit. Retrying....")
112131
time.sleep(retry_after)
113132
else:
114133
self.log_exception("Error fetching history: %s", e.response["error"])

testapp/tests/test_resync_slack_messages.py

Lines changed: 107 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,94 @@
55

66
SLACK_RESPONSE = {
77
"ok": True,
8-
"oldest": "1738713600.000000",
98
"messages": [
109
{
11-
"user": "U02MB3L4YBV",
10+
"user": "XXXXX",
1211
"type": "message",
13-
"ts": "1738760392.589109",
14-
"client_msg_id": "56f29274-afc1-4d86-b8a7-464433e75b3a",
15-
"text": "Hello, can someone please review and merge this: <https://gitlab.app/cloudflare/-/merge_requests/0000> ? :women_thanks:",
16-
"team": "XXXXXXXXX",
17-
"user_team": "XXXXXXXXX",
18-
"source_team": "XXXXXXXXX",
12+
"ts": "1708081153.162449",
13+
"client_msg_id": "1",
14+
"text": "Good morning, please could I have access to this repo if this is the right place? <https://test.com> thank you",
15+
"team": "YYYYY",
16+
"user_team": "YYYYY",
17+
"source_team": "YYYYY",
1918
"user_profile": {
20-
"avatar_hash": "0fa9732db392",
21-
"image_72": "https://avatars.slack-edge.com/2024-01-10/xxxxxx.png",
19+
"avatar_hash": "zzzzz",
20+
"image_72": "https://avatars.slack-edge.com/zzzzz",
2221
"first_name": "Joe",
2322
"real_name": "Joe Doe",
2423
"display_name": "Joe Doe",
25-
"team": "XXXXXXXXX",
26-
"name": "00u1wwkokbuk29m05417",
24+
"team": "a",
25+
"name": "bo",
2726
"is_restricted": False,
2827
"is_ultra_restricted": False,
2928
},
29+
"thread_ts": "1708081153.162449",
30+
"reply_count": 11,
31+
"reply_users_count": 2,
32+
"latest_reply": "1708094262.712709",
33+
"reply_users": ["test1", "test2"],
34+
"is_locked": False,
35+
"subscribed": False,
3036
"blocks": [
3137
{
3238
"type": "rich_text",
33-
"block_id": "2SkH1",
39+
"block_id": "CDI6a",
3440
"elements": [
3541
{
3642
"type": "rich_text_section",
3743
"elements": [
3844
{
3945
"type": "text",
40-
"text": "Hello, can someone please review and merge this: ",
46+
"text": "Good morning, please could I have access to this repo if this is the right place?",
4147
},
4248
{
4349
"type": "link",
44-
"url": "https://gitlab.app/cloudflare/-/merge_requests/0000",
50+
"url": "https://github.com/x",
51+
},
52+
{"type": "text", "text": " thank you"},
53+
],
54+
}
55+
],
56+
}
57+
],
58+
"reactions": [{"name": "tick", "users": ["test1"], "count": 1}],
59+
},
60+
{
61+
"user": "s",
62+
"type": "message",
63+
"ts": "1708081225.366299",
64+
"client_msg_id": "2",
65+
"text": "hello <@s>, what is your github username?",
66+
"team": "b",
67+
"user_team": "b",
68+
"source_team": "b",
69+
"user_profile": {
70+
"avatar_hash": "1",
71+
"image_72": "https://avatars.slack-edge.com/1",
72+
"first_name": "Joe",
73+
"real_name": "Joe Doe",
74+
"display_name": "test",
75+
"team": "y",
76+
"name": "00",
77+
"is_restricted": False,
78+
"is_ultra_restricted": False,
79+
},
80+
"thread_ts": "1708081153.162449",
81+
"parent_user_id": "U04",
82+
"blocks": [
83+
{
84+
"type": "rich_text",
85+
"block_id": "OeaW8",
86+
"elements": [
87+
{
88+
"type": "rich_text_section",
89+
"elements": [
90+
{"type": "text", "text": "hello "},
91+
{"type": "user", "user_id": "U040"},
92+
{
93+
"type": "text",
94+
"text": ", what is your github username?",
4595
},
46-
{"type": "text", "text": " ? "},
47-
{"type": "emoji", "name": "women_thanks"},
4896
],
4997
}
5098
],
@@ -53,15 +101,37 @@
53101
},
54102
],
55103
"has_more": False,
56-
"pin_count": 3,
57-
"channel_actions_ts": 1664441977,
58-
"channel_actions_count": 0,
104+
}
105+
106+
107+
SLACK_RESPONSE_WITH_BOT = {
108+
"ok": True,
109+
"messages": [
110+
{
111+
"bot_id": "ABCD",
112+
"user": "U040",
113+
"type": "message",
114+
"ts": "1708081153.162449",
115+
"text": "<@BOTUSER> *Description:* This is a test message",
116+
"team": "TEAM",
117+
},
118+
{
119+
"bot_id": "EXCLUDED",
120+
"user": "U01B",
121+
"type": "message",
122+
"ts": "1708081225.366299",
123+
"text": "This should be skipped",
124+
"team": "TEAM",
125+
},
126+
],
127+
"has_more": False,
59128
}
60129

61130

62131
class TestResyncSlackMessages(TestCase):
63132
def setUp(self):
64133
models.SlackMessage.objects.all().delete()
134+
self.user = models.User.objects.create(ext_id="BOTUSER", name="Test User")
65135

66136
@mock.patch("slack_sdk.WebClient")
67137
def test_resync_command(self, wc_mock):
@@ -70,4 +140,21 @@ def test_resync_command(self, wc_mock):
70140
management.call_command("resync_slack_messages")
71141
wc_mock.assert_called_once()
72142
api_mock.conversations_history.assert_any_call(channel=mock.ANY, cursor=None, limit=20, oldest=mock.ANY)
143+
self.assertEqual(models.SlackMessage.objects.count(), 2)
144+
145+
@mock.patch("slackbot.management.commands.resync_slack_messages.WebClient")
146+
@mock.patch("django.conf.settings.SLACKBOT_BOT_EXCLUSIONS", {"Excluded Bot": "EXCLUDED"})
147+
def test_resync_command_with_bot_messages(self, wc_mock):
148+
api_mock = wc_mock.return_value
149+
api_mock.conversations_history.return_value = SLACK_RESPONSE_WITH_BOT
150+
151+
management.call_command("resync_slack_messages")
152+
153+
wc_mock.assert_called_once()
154+
api_mock.conversations_history.assert_any_call(channel=mock.ANY, cursor=None, limit=20, oldest=mock.ANY)
155+
73156
self.assertEqual(models.SlackMessage.objects.count(), 1)
157+
158+
slack_msg = models.SlackMessage.objects.first()
159+
self.assertEqual(slack_msg.message_from, "Test User")
160+
self.assertEqual(slack_msg.text, " This is a test message")

0 commit comments

Comments
 (0)