8000 Support Teams message edit, message soft delete, message undelete act… · microsoft/botbuilder-python@a74532b · GitHub
[go: up one dir, main page]

Skip to content

Commit a74532b

Browse files
Support Teams message edit, message soft delete, message undelete activities (#2183)
Co-authored-by: tracyboehrer <tracyboehrer@users.noreply.github.com>
1 parent 3e76e54 commit a74532b

File tree

4 files changed

+275
-0
lines changed

4 files changed

+275
-0
lines changed

libraries/botbuilder-core/botbuilder/core/activity_handler.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ async def on_turn(
6868

6969
if turn_context.activity.type == ActivityTypes.message:
7070
await self.on_message_activity(turn_context)
71+
elif turn_context.activity.type == ActivityTypes.message_update:
72+
await self.on_message_update_activity(turn_context)
73+
elif turn_context.activity.type == ActivityTypes.message_delete:
74+
await self.on_message_delete_activity(turn_context)
7175
elif turn_context.activity.type == ActivityTypes.conversation_update:
7276
await self.on_conversation_update_activity(turn_context)
7377
elif turn_context.activity.type == ActivityTypes.message_reaction:
@@ -107,6 +111,34 @@ async def on_message_activity( # pylint: disable=unused-argument
107111
"""
108112
return
109113

114+
async def on_message_update_activity( # pylint: disable=unused-argument
115+
self, turn_context: TurnContext
116+
):
117+
"""
118+
Override this method in a derived class to provide logic specific to activities,
119+
such as the conversational logic.
120+
121+
:param turn_context: The context object for this turn
122+
:type turn_context: :class:`botbuilder.core.TurnContext`
123+
124+
:returns: A task that represents the work queued to execute
125+
"""
126+
return
127+
128+
async def on_message_delete_activity( # pylint: disable=unused-argument
129+
self, turn_context: TurnContext
130+
):
131+
"""
132+
Override this method in a derived class to provide logic specific to activities,
133+
such as the conversational logic.
134+
135+
:param turn_context: The context object for this turn
136+
:type turn_context: :class:`botbuilder.core.TurnContext`
137+
138+
:returns: A task that represents the work queued to execute
139+
"""
140+
return
141+
110142
async def on_conversation_update_activity(self, turn_context: TurnContext):
111143
"""
112144
Invoked when a conversation update activity is received from the channel when the base behavior of

libraries/botbuilder-core/botbuilder/core/teams/teams_activity_handler.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,3 +1042,73 @@ async def on_teams_meeting_participants_leave_event(
10421042
:returns: A task that represents the work queued to execute.
10431043
"""
10441044
return
1045+
1046+
async def on_message_update_activity(self, turn_context: TurnContext):
1047+
"""
1048+
Invoked when a message update activity is received, such as a message edit or undelete.
1049+
1050+
:param turn_context: A context object for this turn.
1051+
1052+
:returns: A task that represents the work queued to execute.
1053+
"""
1054+
if turn_context.activity.channel_id == Channels.ms_teams:
1055+
channel_data = TeamsChannelData().deserialize(
1056+
turn_context.activity.channel_data
1057+
)
1058+
1059+
if channel_data:
1060+
if channel_data.event_type == "editMessage":
1061+
return await self.on_teams_message_edit(turn_context)
1062+
if channel_data.event_type == "undeleteMessage":
1063+
return await self.on_teams_message_undelete(turn_context)
1064+
1065+
return await super().on_message_update_activity(turn_context)
1066+
1067+
async def on_message_delete_activity(self, turn_context: TurnContext):
1068+
"""
1069+
Invoked when a message delete activity is received, such as a soft delete message.
1070+
1071+
:param turn_context: A context object for this turn.
1072+
1073+
:returns: A task that represents the work queued to execute.
1074+
"""
1075+
if turn_context.activity.channel_id == Channels.ms_teams:
1076+
channel_data = TeamsChannelData().deserialize(
1077+
turn_context.activity.channel_data
1078+
)
1079+
1080+
if channel_data:
1081+
if channel_data.event_type == "softDeleteMessage":
1082+
return await self.on_teams_message_soft_delete(turn_context)
1083+
1084+
return await super().on_message_delete_activity(turn_context)
1085+
1086+
async def on_teams_message_edit(self, turn_context: TurnContext):
1087+
"""
1088+
Invoked when a Teams edit message event activity is received.
1089+
1090+
:param turn_context: A context object for this turn.
1091+
1092+
:returns: A task that represents the work queued to execute.
1093+
"""
1094+
return
1095+
1096+
async def on_teams_message_undelete(self, turn_context: TurnContext):
1097+
"""
1098+
Invoked when a Teams undo soft delete message event activity is received.
1099+
1100+
:param turn_context: A context object for this turn.
1101+
1102+
:returns: A task that represents the work queued to execute.
1103+
"""
1104+
return
1105+
1106+
async def on_teams_message_soft_delete(self, turn_context: TurnContext):
1107+
"""
1108+
Invoked when a Teams soft delete message event activity is received.
1109+
1110+
:param turn_context: A context object for this turn.
1111+
1112+
:returns: A task that represents the work queued to execute.
1113+
"""
1114+
return

libraries/botbuilder-core/tests/teams/test_teams_activity_handler.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
TabContext,
3535
MeetingParticipantsEventDetails,
3636
ReadReceiptInfo,
37+
TeamsChannelData,
3738
)
3839
from botframework.connector import Channels
3940
from simple_adapter import SimpleAdapter
@@ -351,6 +352,26 @@ async def on_teams_meeting_end_event(
351352
turn_context.activity.value, turn_context
352353
)
353354

355+
async def on_message_update_activity(self, turn_context: TurnContext):
356+
self.record.append("on_message_update_activity")
357+
return await super().on_message_update_activity(turn_context)
358+
359+
async def on_teams_message_edit(self, turn_context: TurnContext):
360+
self.record.append("on_teams_message_edit")
361+
return await super().on_teams_message_edit(turn_context)
362+
363+
async def on_teams_message_undelete(self, turn_context: TurnContext):
364+
self.record.append("on_teams_message_undelete")
365+
return await super().on_teams_message_undelete(turn_context)
366+
367+
async def on_message_delete_activity(self, turn_context: TurnContext):
368+
self.record.append("on_message_delete_activity")
369+
return await super().on_message_delete_activity(turn_context)
370+
371+
async def on_teams_message_soft_delete(self, turn_context: TurnContext):
372+
self.record.append("on_teams_message_soft_delete")
373+
return await super().on_teams_message_soft_delete(turn_context)
374+
354375
async def on_teams_meeting_participants_join_event(
355376
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
356377
):
@@ -1254,6 +1275,124 @@ async def test_on_teams_meeting_end_event(self):
12541275
assert bot.record[0] == "on_event_activity"
12551276
assert bot.record[1] == "on_teams_meeting_end_event"
12561277

1278+
async def test_message_update_activity_teams_message_edit(self):
1279+
# Arrange
1280+
activity = Activity(
1281+
type=ActivityTypes.message_update,
1282+
channel_data=TeamsChannelData(event_type="editMessage"),
1283+
channel_id=Channels.ms_teams,
1284+
)
1285+
turn_context = TurnContext(SimpleAdapter(), activity)
1286+
1287+
# Act
1288+
bot = TestingTeamsActivityHandler()
1289+
await bot.on_turn(turn_context)
1290+
1291+
# Assert
1292+
self.assertEqual(2, len(bot.record))
1293+
self.assertEqual("on_message_update_activity", bot.record[0])
1294+
self.assertEqual("on_teams_message_edit", bot.record[1])
1295+
1296+
async def test_message_update_activity_teams_message_undelete(self):
1297+
# Arrange
1298+
activity = Activity(
1299+
type=ActivityTypes.message_update,
1300+
channel_data=TeamsChannelData(event_type="undeleteMessage"),
1301+
channel_id=Channels.ms_teams,
1302+
)
1303+
turn_context = TurnContext(SimpleAdapter(), activity)
1304+
1305+
# Act
1306+
bot = TestingTeamsActivityHandler()
1307+
await bot.on_turn(turn_context)
1308+
1309+
# Assert
1310+
self.assertEqual(2, len(bot.record))
1311+
self.assertEqual("on_message_update_activity", bot.record[0])
1312+
self.assertEqual("on_teams_message_undelete", bot.record[1])
1313+
1314+
async def test_message_update_activity_teams_message_undelete_no_msteams(self):
1315+
# Arrange
1316+
activity = Activity(
1317+
type=ActivityTypes.message_update,
1318+
channel_data=TeamsChannelData(event_type="undeleteMessage"),
1319+
)
1320+
turn_context = TurnContext(SimpleAdapter(), activity)
1321+
1322+
# Act
1323+
bot = TestingTeamsActivityHandler()
1324+
await bot.on_turn(turn_context)
1325+
1326+
# Assert
1327+
self.assertEqual(1, len(bot.record))
1328+
self.assertEqual("on_message_update_activity", bot.record[0])
1329+
1330+
async def test_message_update_activity_teams_no_channel_data(self):
1331+
# Arrange
1332+
activity = Activity(
1333+
type=ActivityTypes.message_update,
1334+
channel_id=Channels.ms_teams,
1335+
)
1336+
turn_context = TurnContext(SimpleAdapter(), activity)
1337+
1338+
# Act
1339+
bot = TestingTeamsActivityHandler()
1340+
await bot.on_turn(turn_context)
1341+
1342+
# Assert
1343+
self.assertEqual(1, len(bot.record))
1344+
self.assertEqual("on_message_update_activity", bot.record[0])
1345+
1346+
async def test_message_delete_activity_teams_message_soft_delete(self):
1347+
# Arrange
1348+
activity = Activity(
1349+
type=ActivityTypes.message_delete,
1350+
channel_data=TeamsChannelData(event_type="softDeleteMessage"),
1351+
channel_id=Channels.ms_teams,
1352+
)
1353+
turn_context = TurnContext(SimpleAdapter(), activity)
1354+
1355+
# Act
1356+
bot = TestingTeamsActivityHandler()
1357+
await bot.on_turn(turn_context)
1358+
1359+
# Assert
1360+
self.assertEqual(2, len(bot.record))
1361+
self.assertEqual("on_message_delete_activity", bot.record[0])
1362+
self.assertEqual("on_teams_message_soft_delete", bot.record[1])
1363+
1364+
async def test_message_delete_activity_teams_message_soft_delete_no_msteams(self):
1365+
# Arrange
1366+
activity = Activity(
1367+
type=ActivityTypes.message_delete,
1368+
channel_data=TeamsChannelData(event_type="softDeleteMessage"),
1369+
)
1370+
turn_context = TurnContext(SimpleAdapter(), activity)
1371+
1372+
# Act
1373+
bot = TestingTeamsActivityHandler()
1374+
await bot.on_turn(turn_context)
1375+
1376+
# Assert
1377+
self.assertEqual(1, len(bot.record))
1378+
self.assertEqual("on_message_delete_activity", bot.record[0])
1379+
1380+
async def test_message_delete_activity_teams_no_channel_data(self):
1381+
# Arrange
1382+
activity = Activity(
1383+
type=ActivityTypes.message_delete,
1384+
channel_id=Channels.ms_teams,
1385+
)
1386+
turn_context = TurnContext(SimpleAdapter(), activity)
1387+
1388+
# Act
1389+
bot = TestingTeamsActivityHandler()
1390+
await bot.on_turn(turn_context)
1391+
1392+
# Assert
1393+
self.assertEqual(1, len(bot.record))
1394+
self.assertEqual("on_message_delete_activity", bot.record[0])
1395+
12571396
async def test_on_teams_meeting_participants_join_event(self):
12581397
# arrange
12591398
activity = Activity(

libraries/botbuilder-core/tests/test_activity_handler.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ async def on_message_activity(self, turn_context: TurnContext):
2626
self.record.append("on_message_activity")
2727
return await super().on_message_activity(turn_context)
2828

29+
async def on_message_update_activity(self, turn_context: TurnContext):
30+
self.record.append("on_message_update_activity")
31+
return await super().on_message_update_activity(turn_context)
32+
33+
async def on_message_delete_activity(self, turn_context: TurnContext):
34+
self.record.append("on_message_delete_activity")
35+
return await super().on_message_delete_activity(turn_context)
36+
2937
async def on_members_added_activity(
3038
self, members_added: ChannelAccount, turn_context: TurnContext
3139
):
@@ -208,6 +216,32 @@ async def test_invoke_should_not_match(self):
208216
assert bot.record[0] == "on_invoke_activity"
209217
assert adapter.activity.value.status == int(HTTPStatus.NOT_IMPLEMENTED)
210218

219+
async def test_on_message_update_activity(self):
220+
activity = Activity(type=ActivityTypes.message_update)
221+
222+
adapter = TestInvokeAdapter()
223+
turn_context = TurnContext(adapter, activity)
224+
225+
# Act
226+
bot = TestingActivityHandler()
227+
await bot.on_turn(turn_context)
228+
229+
assert len(bot.record) == 1
230+
assert bot.record[0] == "on_message_update_activity"
231+
232+
async def test_on_message_delete_activity(self):
233+
activity = Activity(type=ActivityTypes.message_delete)
234+
235+
adapter = TestInvokeAdapter()
236+
turn_context = TurnContext(adapter, activity)
237+
238+
# Act
239+
bot = TestingActivityHandler()
240+
await bot.on_turn(turn_context)
241+
242+
assert len(bot.record) == 1
243+
assert bot.record[0] == "on_message_delete_activity"
244+
211245
async def test_on_end_of_conversation_activity(self):
212246
activity = Activity(type=ActivityTypes.end_of_conversation)
213247

0 commit comments

Comments
 (0)
0