microsoft-agents-hosting-teams 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- microsoft/agents/hosting/teams/__init__.py +4 -0
- microsoft/agents/hosting/teams/teams_activity_handler.py +910 -0
- microsoft/agents/hosting/teams/teams_cloud_adapter.py +0 -0
- microsoft/agents/hosting/teams/teams_info.py +653 -0
- microsoft_agents_hosting_teams-0.0.0.dist-info/METADATA +13 -0
- microsoft_agents_hosting_teams-0.0.0.dist-info/RECORD +8 -0
- microsoft_agents_hosting_teams-0.0.0.dist-info/WHEEL +5 -0
- microsoft_agents_hosting_teams-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,910 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
Licensed under the MIT License.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from http import HTTPStatus
|
|
7
|
+
from typing import Any, List
|
|
8
|
+
|
|
9
|
+
from microsoft.agents.hosting.core import ActivityHandler, TurnContext
|
|
10
|
+
from microsoft.agents.activity import (
|
|
11
|
+
InvokeResponse,
|
|
12
|
+
ChannelAccount,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from microsoft.agents.activity.teams import (
|
|
16
|
+
AppBasedLinkQuery,
|
|
17
|
+
TeamInfo,
|
|
18
|
+
ChannelInfo,
|
|
19
|
+
ConfigResponse,
|
|
20
|
+
FileConsentCardResponse,
|
|
21
|
+
MeetingEndEventDetails,
|
|
22
|
+
MeetingParticipantsEventDetails,
|
|
23
|
+
MeetingStartEventDetails,
|
|
24
|
+
MessagingExtensionAction,
|
|
25
|
+
MessagingExtensionActionResponse,
|
|
26
|
+
MessagingExtensionQuery,
|
|
27
|
+
MessagingExtensionResponse,
|
|
28
|
+
O365ConnectorCardActionQuery,
|
|
29
|
+
ReadReceiptInfo,
|
|
30
|
+
SigninStateVerificationQuery,
|
|
31
|
+
TabRequest,
|
|
32
|
+
TabResponse,
|
|
33
|
+
TabSubmit,
|
|
34
|
+
TaskModuleRequest,
|
|
35
|
+
TaskModuleResponse,
|
|
36
|
+
TeamsChannelAccount,
|
|
37
|
+
TeamsChannelData,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from .teams_info import TeamsInfo
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TeamsActivityHandler(ActivityHandler):
|
|
44
|
+
"""
|
|
45
|
+
The TeamsActivityHandler is derived from the ActivityHandler class and adds support for
|
|
46
|
+
Microsoft Teams-specific functionality.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
async def on_invoke_activity(self, turn_context: TurnContext) -> InvokeResponse:
|
|
50
|
+
"""
|
|
51
|
+
Handles invoke activities.
|
|
52
|
+
|
|
53
|
+
:param turn_context: The context object for the turn.
|
|
54
|
+
:return: An InvokeResponse.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
if (
|
|
59
|
+
not turn_context.activity.name
|
|
60
|
+
and turn_context.activity.channel_id == "msteams"
|
|
61
|
+
):
|
|
62
|
+
return await self.on_teams_card_action_invoke(turn_context)
|
|
63
|
+
else:
|
|
64
|
+
name = turn_context.activity.name
|
|
65
|
+
value = turn_context.activity.value
|
|
66
|
+
|
|
67
|
+
if name == "config/fetch":
|
|
68
|
+
return self._create_invoke_response(
|
|
69
|
+
await self.on_teams_config_fetch(turn_context, value)
|
|
70
|
+
)
|
|
71
|
+
elif name == "config/submit":
|
|
72
|
+
return self._create_invoke_response(
|
|
73
|
+
await self.on_teams_config_submit(turn_context, value)
|
|
74
|
+
)
|
|
75
|
+
elif name == "fileConsent/invoke":
|
|
76
|
+
return self._create_invoke_response(
|
|
77
|
+
await self.on_teams_file_consent(turn_context, value)
|
|
78
|
+
)
|
|
79
|
+
elif name == "actionableMessage/executeAction":
|
|
80
|
+
await self.on_teams_o365_connector_card_action(turn_context, value)
|
|
81
|
+
return self._create_invoke_response()
|
|
82
|
+
elif name == "composeExtension/queryLink":
|
|
83
|
+
return self._create_invoke_response(
|
|
84
|
+
await self.on_teams_app_based_link_query(turn_context, value)
|
|
85
|
+
)
|
|
86
|
+
elif name == "composeExtension/anonymousQueryLink":
|
|
87
|
+
return self._create_invoke_response(
|
|
88
|
+
await self.on_teams_anonymous_app_based_link_query(
|
|
89
|
+
turn_context, value
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
elif name == "composeExtension/query":
|
|
93
|
+
query = MessagingExtensionQuery.model_validate(value)
|
|
94
|
+
return self._create_invoke_response(
|
|
95
|
+
await self.on_teams_messaging_extension_query(
|
|
96
|
+
turn_context, query
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
elif name == "composeExtension/selectItem":
|
|
100
|
+
return self._create_invoke_response(
|
|
101
|
+
await self.on_teams_messaging_extension_select_item(
|
|
102
|
+
turn_context, value
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
elif name == "composeExtension/submitAction":
|
|
106
|
+
return self._create_invoke_response(
|
|
107
|
+
await self.on_teams_messaging_extension_submit_action_dispatch(
|
|
108
|
+
turn_context, value
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
elif name == "composeExtension/fetchTask":
|
|
112
|
+
return self._create_invoke_response(
|
|
113
|
+
await self.on_teams_messaging_extension_fetch_task(
|
|
114
|
+
turn_context, value
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
elif name == "composeExtension/querySettingUrl":
|
|
118
|
+
return self._create_invoke_response(
|
|
119
|
+
await self.on_teams_messaging_extension_configuration_query_setting_url(
|
|
120
|
+
turn_context, value
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
elif name == "composeExtension/setting":
|
|
124
|
+
await self.on_teams_messaging_extension_configuration_setting(
|
|
125
|
+
turn_context, value
|
|
126
|
+
)
|
|
127
|
+
return self._create_invoke_response()
|
|
128
|
+
elif name == "composeExtension/onCardButtonClicked":
|
|
129
|
+
await self.on_teams_messaging_extension_card_button_clicked(
|
|
130
|
+
turn_context, value
|
|
131
|
+
)
|
|
132
|
+
return self._create_invoke_response()
|
|
133
|
+
elif name == "task/fetch":
|
|
134
|
+
task_module_request = TaskModuleRequest.model_validate(value)
|
|
135
|
+
return self._create_invoke_response(
|
|
136
|
+
await self.on_teams_task_module_fetch(
|
|
137
|
+
turn_context, task_module_request
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
elif name == "task/submit":
|
|
141
|
+
task_module_request = TaskModuleRequest.model_validate(value)
|
|
142
|
+
return self._create_invoke_response(
|
|
143
|
+
await self.on_teams_task_module_submit(
|
|
144
|
+
turn_context, task_module_request
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
elif name == "tab/fetch":
|
|
148
|
+
return self._create_invoke_response(
|
|
149
|
+
await self.on_teams_tab_fetch(turn_context, value)
|
|
150
|
+
)
|
|
151
|
+
elif name == "tab/submit":
|
|
152
|
+
return self._create_invoke_response(
|
|
153
|
+
await self.on_teams_tab_submit(turn_context, value)
|
|
154
|
+
)
|
|
155
|
+
else:
|
|
156
|
+
return await super().on_invoke_activity(turn_context)
|
|
157
|
+
except Exception as err:
|
|
158
|
+
if str(err) == "NotImplemented":
|
|
159
|
+
return InvokeResponse(status=int(HTTPStatus.NOT_IMPLEMENTED))
|
|
160
|
+
elif str(err) == "BadRequest":
|
|
161
|
+
return InvokeResponse(status=int(HTTPStatus.BAD_REQUEST))
|
|
162
|
+
raise
|
|
163
|
+
|
|
164
|
+
async def on_teams_card_action_invoke(
|
|
165
|
+
self, turn_context: TurnContext
|
|
166
|
+
) -> InvokeResponse:
|
|
167
|
+
"""
|
|
168
|
+
Handles card action invoke.
|
|
169
|
+
|
|
170
|
+
:param turn_context: The context object for the turn.
|
|
171
|
+
:return: An InvokeResponse.
|
|
172
|
+
"""
|
|
173
|
+
raise NotImplementedError("NotImplemented")
|
|
174
|
+
|
|
175
|
+
async def on_teams_config_fetch(
|
|
176
|
+
self, turn_context: TurnContext, config_data: Any
|
|
177
|
+
) -> ConfigResponse:
|
|
178
|
+
"""
|
|
179
|
+
Handles config fetch.
|
|
180
|
+
|
|
181
|
+
:param turn_context: The context object for the turn.
|
|
182
|
+
:param config_data: The config data.
|
|
183
|
+
:return: A ConfigResponse.
|
|
184
|
+
"""
|
|
185
|
+
raise NotImplementedError("NotImplemented")
|
|
186
|
+
|
|
187
|
+
async def on_teams_config_submit(
|
|
188
|
+
self, turn_context: TurnContext, config_data: Any
|
|
189
|
+
) -> ConfigResponse:
|
|
190
|
+
"""
|
|
191
|
+
Handles config submit.
|
|
192
|
+
|
|
193
|
+
:param turn_context: The context object for the turn.
|
|
194
|
+
:param config_data: The config data.
|
|
195
|
+
:return: A ConfigResponse.
|
|
196
|
+
"""
|
|
197
|
+
raise NotImplementedError("NotImplemented")
|
|
198
|
+
|
|
199
|
+
async def on_teams_file_consent(
|
|
200
|
+
self,
|
|
201
|
+
turn_context: TurnContext,
|
|
202
|
+
file_consent_card_response: FileConsentCardResponse,
|
|
203
|
+
) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Handles file consent.
|
|
206
|
+
|
|
207
|
+
:param turn_context: The context object for the turn.
|
|
208
|
+
:param file_consent_card_response: The file consent card response.
|
|
209
|
+
:return: None
|
|
210
|
+
"""
|
|
211
|
+
if file_consent_card_response.action == "accept":
|
|
212
|
+
return await self.on_teams_file_consent_accept(
|
|
213
|
+
turn_context, file_consent_card_response
|
|
214
|
+
)
|
|
215
|
+
elif file_consent_card_response.action == "decline":
|
|
216
|
+
return await self.on_teams_file_consent_decline(
|
|
217
|
+
turn_context, file_consent_card_response
|
|
218
|
+
)
|
|
219
|
+
else:
|
|
220
|
+
raise ValueError("BadRequest")
|
|
221
|
+
|
|
222
|
+
async def on_teams_file_consent_accept(
|
|
223
|
+
self,
|
|
224
|
+
turn_context: TurnContext,
|
|
225
|
+
file_consent_card_response: FileConsentCardResponse,
|
|
226
|
+
) -> None:
|
|
227
|
+
"""
|
|
228
|
+
Handles file consent accept.
|
|
229
|
+
|
|
230
|
+
:param turn_context: The context object for the turn.
|
|
231
|
+
:param file_consent_card_response: The file consent card response.
|
|
232
|
+
:return: None
|
|
233
|
+
"""
|
|
234
|
+
raise NotImplementedError("NotImplemented")
|
|
235
|
+
|
|
236
|
+
async def on_teams_file_consent_decline(
|
|
237
|
+
self,
|
|
238
|
+
turn_context: TurnContext,
|
|
239
|
+
file_consent_card_response: FileConsentCardResponse,
|
|
240
|
+
) -> None:
|
|
241
|
+
"""
|
|
242
|
+
Handles file consent decline.
|
|
243
|
+
|
|
244
|
+
:param turn_context: The context object for the turn.
|
|
245
|
+
:param file_consent_card_response: The file consent card response.
|
|
246
|
+
:return: None
|
|
247
|
+
"""
|
|
248
|
+
raise NotImplementedError("NotImplemented")
|
|
249
|
+
|
|
250
|
+
async def on_teams_o365_connector_card_action(
|
|
251
|
+
self, turn_context: TurnContext, query: O365ConnectorCardActionQuery
|
|
252
|
+
) -> None:
|
|
253
|
+
"""
|
|
254
|
+
Handles O365 connector card action.
|
|
255
|
+
|
|
256
|
+
:param turn_context: The context object for the turn.
|
|
257
|
+
:param query: The O365 connector card action query.
|
|
258
|
+
:return: None
|
|
259
|
+
"""
|
|
260
|
+
raise NotImplementedError("NotImplemented")
|
|
261
|
+
|
|
262
|
+
async def on_teams_signin_verify_state(
|
|
263
|
+
self, turn_context: TurnContext, query: SigninStateVerificationQuery
|
|
264
|
+
) -> None:
|
|
265
|
+
"""
|
|
266
|
+
Handles sign-in verify state.
|
|
267
|
+
|
|
268
|
+
:param turn_context: The context object for the turn.
|
|
269
|
+
:param query: The sign-in state verification query.
|
|
270
|
+
:return: None
|
|
271
|
+
"""
|
|
272
|
+
raise NotImplementedError("NotImplemented")
|
|
273
|
+
|
|
274
|
+
async def on_teams_signin_token_exchange(
|
|
275
|
+
self, turn_context: TurnContext, query: SigninStateVerificationQuery
|
|
276
|
+
) -> None:
|
|
277
|
+
"""
|
|
278
|
+
Handles sign-in token exchange.
|
|
279
|
+
|
|
280
|
+
:param turn_context: The context object for the turn.
|
|
281
|
+
:param query: The sign-in state verification query.
|
|
282
|
+
:return: None
|
|
283
|
+
"""
|
|
284
|
+
raise NotImplementedError("NotImplemented")
|
|
285
|
+
|
|
286
|
+
async def on_teams_app_based_link_query(
|
|
287
|
+
self, turn_context: TurnContext, query: AppBasedLinkQuery
|
|
288
|
+
) -> MessagingExtensionResponse:
|
|
289
|
+
"""
|
|
290
|
+
Handles app-based link query.
|
|
291
|
+
|
|
292
|
+
:param turn_context: The context object for the turn.
|
|
293
|
+
:param query: The app-based link query.
|
|
294
|
+
:return: A MessagingExtensionResponse.
|
|
295
|
+
"""
|
|
296
|
+
raise NotImplementedError("NotImplemented")
|
|
297
|
+
|
|
298
|
+
async def on_teams_anonymous_app_based_link_query(
|
|
299
|
+
self, turn_context: TurnContext, query: AppBasedLinkQuery
|
|
300
|
+
) -> MessagingExtensionResponse:
|
|
301
|
+
"""
|
|
302
|
+
Handles anonymous app-based link query.
|
|
303
|
+
|
|
304
|
+
:param turn_context: The context object for the turn.
|
|
305
|
+
:param query: The app-based link query.
|
|
306
|
+
:return: A MessagingExtensionResponse.
|
|
307
|
+
"""
|
|
308
|
+
raise NotImplementedError("NotImplemented")
|
|
309
|
+
|
|
310
|
+
async def on_teams_messaging_extension_query(
|
|
311
|
+
self, turn_context: TurnContext, query: MessagingExtensionQuery
|
|
312
|
+
) -> MessagingExtensionResponse:
|
|
313
|
+
"""
|
|
314
|
+
Handles messaging extension query.
|
|
315
|
+
|
|
316
|
+
:param turn_context: The context object for the turn.
|
|
317
|
+
:param query: The messaging extension query.
|
|
318
|
+
:return: A MessagingExtensionResponse.
|
|
319
|
+
"""
|
|
320
|
+
raise NotImplementedError("NotImplemented")
|
|
321
|
+
|
|
322
|
+
async def on_teams_messaging_extension_select_item(
|
|
323
|
+
self, turn_context: TurnContext, query: Any
|
|
324
|
+
) -> MessagingExtensionResponse:
|
|
325
|
+
"""
|
|
326
|
+
Handles messaging extension select item.
|
|
327
|
+
|
|
328
|
+
:param turn_context: The context object for the turn.
|
|
329
|
+
:param query: The query.
|
|
330
|
+
:return: A MessagingExtensionResponse.
|
|
331
|
+
"""
|
|
332
|
+
raise NotImplementedError("NotImplemented")
|
|
333
|
+
|
|
334
|
+
async def on_teams_messaging_extension_submit_action_dispatch(
|
|
335
|
+
self, turn_context: TurnContext, action: MessagingExtensionAction
|
|
336
|
+
) -> MessagingExtensionActionResponse:
|
|
337
|
+
"""
|
|
338
|
+
Handles messaging extension submit action dispatch.
|
|
339
|
+
|
|
340
|
+
:param turn_context: The context object for the turn.
|
|
341
|
+
:param action: The messaging extension action.
|
|
342
|
+
:return: A MessagingExtensionActionResponse.
|
|
343
|
+
"""
|
|
344
|
+
if action.bot_message_preview_action:
|
|
345
|
+
if action.bot_message_preview_action == "edit":
|
|
346
|
+
return await self.on_teams_messaging_extension_message_preview_edit(
|
|
347
|
+
turn_context, action
|
|
348
|
+
)
|
|
349
|
+
elif action.bot_message_preview_action == "send":
|
|
350
|
+
return await self.on_teams_messaging_extension_message_preview_send(
|
|
351
|
+
turn_context, action
|
|
352
|
+
)
|
|
353
|
+
else:
|
|
354
|
+
raise ValueError("BadRequest")
|
|
355
|
+
else:
|
|
356
|
+
return await self.on_teams_messaging_extension_submit_action(
|
|
357
|
+
turn_context, action
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
async def on_teams_messaging_extension_submit_action(
|
|
361
|
+
self, turn_context: TurnContext, action: MessagingExtensionAction
|
|
362
|
+
) -> MessagingExtensionActionResponse:
|
|
363
|
+
"""
|
|
364
|
+
Handles messaging extension submit action.
|
|
365
|
+
|
|
366
|
+
:param turn_context: The context object for the turn.
|
|
367
|
+
:param action: The messaging extension action.
|
|
368
|
+
:return: A MessagingExtensionActionResponse.
|
|
369
|
+
"""
|
|
370
|
+
raise NotImplementedError("NotImplemented")
|
|
371
|
+
|
|
372
|
+
async def on_teams_messaging_extension_message_preview_edit(
|
|
373
|
+
self, turn_context: TurnContext, action: MessagingExtensionAction
|
|
374
|
+
) -> MessagingExtensionActionResponse:
|
|
375
|
+
"""
|
|
376
|
+
Handles messaging extension message preview edit.
|
|
377
|
+
|
|
378
|
+
:param turn_context: The context object for the turn.
|
|
379
|
+
:param action: The messaging extension action.
|
|
380
|
+
:return: A MessagingExtensionActionResponse.
|
|
381
|
+
"""
|
|
382
|
+
raise NotImplementedError("NotImplemented")
|
|
383
|
+
|
|
384
|
+
async def on_teams_messaging_extension_message_preview_send(
|
|
385
|
+
self, turn_context: TurnContext, action: MessagingExtensionAction
|
|
386
|
+
) -> MessagingExtensionActionResponse:
|
|
387
|
+
"""
|
|
388
|
+
Handles messaging extension message preview send.
|
|
389
|
+
|
|
390
|
+
:param turn_context: The context object for the turn.
|
|
391
|
+
:param action: The messaging extension action.
|
|
392
|
+
:return: A MessagingExtensionActionResponse.
|
|
393
|
+
"""
|
|
394
|
+
raise NotImplementedError("NotImplemented")
|
|
395
|
+
|
|
396
|
+
async def on_teams_messaging_extension_fetch_task(
|
|
397
|
+
self, turn_context: TurnContext, action: MessagingExtensionAction
|
|
398
|
+
) -> MessagingExtensionActionResponse:
|
|
399
|
+
"""
|
|
400
|
+
Handles messaging extension fetch task.
|
|
401
|
+
|
|
402
|
+
:param turn_context: The context object for the turn.
|
|
403
|
+
:param action: The messaging extension action.
|
|
404
|
+
:return: A MessagingExtensionActionResponse.
|
|
405
|
+
"""
|
|
406
|
+
raise NotImplementedError("NotImplemented")
|
|
407
|
+
|
|
408
|
+
async def on_teams_messaging_extension_configuration_query_setting_url(
|
|
409
|
+
self, turn_context: TurnContext, query: MessagingExtensionQuery
|
|
410
|
+
) -> MessagingExtensionResponse:
|
|
411
|
+
"""
|
|
412
|
+
Handles messaging extension configuration query setting URL.
|
|
413
|
+
|
|
414
|
+
:param turn_context: The context object for the turn.
|
|
415
|
+
:param query: The messaging extension query.
|
|
416
|
+
:return: A MessagingExtensionResponse.
|
|
417
|
+
"""
|
|
418
|
+
raise NotImplementedError("NotImplemented")
|
|
419
|
+
|
|
420
|
+
async def on_teams_messaging_extension_configuration_setting(
|
|
421
|
+
self, turn_context: TurnContext, settings: Any
|
|
422
|
+
) -> None:
|
|
423
|
+
"""
|
|
424
|
+
Handles messaging extension configuration setting.
|
|
425
|
+
|
|
426
|
+
:param turn_context: The context object for the turn.
|
|
427
|
+
:param settings: The settings.
|
|
428
|
+
:return: None
|
|
429
|
+
"""
|
|
430
|
+
raise NotImplementedError("NotImplemented")
|
|
431
|
+
|
|
432
|
+
async def on_teams_messaging_extension_card_button_clicked(
|
|
433
|
+
self, turn_context: TurnContext, card_data: Any
|
|
434
|
+
) -> None:
|
|
435
|
+
"""
|
|
436
|
+
Handles messaging extension card button clicked.
|
|
437
|
+
|
|
438
|
+
:param turn_context: The context object for the turn.
|
|
439
|
+
:param card_data: The card data.
|
|
440
|
+
:return: None
|
|
441
|
+
"""
|
|
442
|
+
raise NotImplementedError("NotImplemented")
|
|
443
|
+
|
|
444
|
+
async def on_teams_task_module_fetch(
|
|
445
|
+
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
|
|
446
|
+
) -> TaskModuleResponse:
|
|
447
|
+
"""
|
|
448
|
+
Handles task module fetch.
|
|
449
|
+
|
|
450
|
+
:param turn_context: The context object for the turn.
|
|
451
|
+
:param task_module_request: The task module request.
|
|
452
|
+
:return: A TaskModuleResponse.
|
|
453
|
+
"""
|
|
454
|
+
raise NotImplementedError("NotImplemented")
|
|
455
|
+
|
|
456
|
+
async def on_teams_task_module_submit(
|
|
457
|
+
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
|
|
458
|
+
) -> TaskModuleResponse:
|
|
459
|
+
"""
|
|
460
|
+
Handles task module submit.
|
|
461
|
+
|
|
462
|
+
:param turn_context: The context object for the turn.
|
|
463
|
+
:param task_module_request: The task module request.
|
|
464
|
+
:return: A TaskModuleResponse.
|
|
465
|
+
"""
|
|
466
|
+
raise NotImplementedError("NotImplemented")
|
|
467
|
+
|
|
468
|
+
async def on_teams_tab_fetch(
|
|
469
|
+
self, turn_context: TurnContext, tab_request: TabRequest
|
|
470
|
+
) -> TabResponse:
|
|
471
|
+
"""
|
|
472
|
+
Handles tab fetch.
|
|
473
|
+
|
|
474
|
+
:param turn_context: The context object for the turn.
|
|
475
|
+
:param tab_request: The tab request.
|
|
476
|
+
:return: A TabResponse.
|
|
477
|
+
"""
|
|
478
|
+
raise NotImplementedError("NotImplemented")
|
|
479
|
+
|
|
480
|
+
async def on_teams_tab_submit(
|
|
481
|
+
self, turn_context: TurnContext, tab_submit: TabSubmit
|
|
482
|
+
) -> TabResponse:
|
|
483
|
+
"""
|
|
484
|
+
Handles tab submit.
|
|
485
|
+
|
|
486
|
+
:param turn_context: The context object for the turn.
|
|
487
|
+
:param tab_submit: The tab submit.
|
|
488
|
+
:return: A TabResponse.
|
|
489
|
+
"""
|
|
490
|
+
raise NotImplementedError("NotImplemented")
|
|
491
|
+
|
|
492
|
+
async def on_conversation_update_activity(self, turn_context: TurnContext):
|
|
493
|
+
"""
|
|
494
|
+
Dispatches conversation update activity.
|
|
495
|
+
|
|
496
|
+
:param turn_context: The context object for the turn.
|
|
497
|
+
:return: None
|
|
498
|
+
"""
|
|
499
|
+
if turn_context.activity.channel_id == "msteams":
|
|
500
|
+
channel_data = (
|
|
501
|
+
TeamsChannelData.model_validate(turn_context.activity.channel_data)
|
|
502
|
+
if turn_context.activity.channel_data
|
|
503
|
+
else None
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
if (
|
|
507
|
+
turn_context.activity.members_added
|
|
508
|
+
and len(turn_context.activity.members_added) > 0
|
|
509
|
+
):
|
|
510
|
+
return await self.on_teams_members_added_dispatch(
|
|
511
|
+
turn_context.activity.members_added,
|
|
512
|
+
channel_data.team if channel_data else None,
|
|
513
|
+
turn_context,
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
if (
|
|
517
|
+
turn_context.activity.members_removed
|
|
518
|
+
and len(turn_context.activity.members_removed) > 0
|
|
519
|
+
):
|
|
520
|
+
return await self.on_teams_members_removed(turn_context)
|
|
521
|
+
|
|
522
|
+
if not channel_data or not channel_data.event_type:
|
|
523
|
+
return await super().on_conversation_update_activity(turn_context)
|
|
524
|
+
|
|
525
|
+
event_type = channel_data.event_type
|
|
526
|
+
|
|
527
|
+
if event_type == "channelCreated":
|
|
528
|
+
return await self.on_teams_channel_created(turn_context)
|
|
529
|
+
elif event_type == "channelDeleted":
|
|
530
|
+
return await self.on_teams_channel_deleted(turn_context)
|
|
531
|
+
elif event_type == "channelRenamed":
|
|
532
|
+
return await self.on_teams_channel_renamed(turn_context)
|
|
533
|
+
elif event_type == "teamArchived":
|
|
534
|
+
return await self.on_teams_team_archived(turn_context)
|
|
535
|
+
elif event_type == "teamDeleted":
|
|
536
|
+
return await self.on_teams_team_deleted(turn_context)
|
|
537
|
+
elif event_type == "teamHardDeleted":
|
|
538
|
+
return await self.on_teams_team_hard_deleted(turn_context)
|
|
539
|
+
elif event_type == "channelRestored":
|
|
540
|
+
return await self.on_teams_channel_restored(turn_context)
|
|
541
|
+
elif event_type == "teamRenamed":
|
|
542
|
+
return await self.on_teams_team_renamed(turn_context)
|
|
543
|
+
elif event_type == "teamRestored":
|
|
544
|
+
return await self.on_teams_team_restored(turn_context)
|
|
545
|
+
elif event_type == "teamUnarchived":
|
|
546
|
+
return await self.on_teams_team_unarchived(turn_context)
|
|
547
|
+
|
|
548
|
+
return await super().on_conversation_update_activity(turn_context)
|
|
549
|
+
|
|
550
|
+
async def on_message_update_activity(self, turn_context: TurnContext):
|
|
551
|
+
"""
|
|
552
|
+
Dispatches message update activity.
|
|
553
|
+
|
|
554
|
+
:param turn_context: The context object for the turn.
|
|
555
|
+
:return: None
|
|
556
|
+
"""
|
|
557
|
+
if turn_context.activity.channel_id == "msteams":
|
|
558
|
+
channel_data = channel_data = (
|
|
559
|
+
TeamsChannelData.model_validate(turn_context.activity.channel_data)
|
|
560
|
+
if turn_context.activity.channel_data
|
|
561
|
+
else None
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
event_type = channel_data.event_type if channel_data else None
|
|
565
|
+
|
|
566
|
+
if event_type == "undeleteMessage":
|
|
567
|
+
return await self.on_teams_message_undelete(turn_context)
|
|
568
|
+
elif event_type == "editMessage":
|
|
569
|
+
return await self.on_teams_message_edit(turn_context)
|
|
570
|
+
|
|
571
|
+
return await super().on_message_update_activity(turn_context)
|
|
572
|
+
|
|
573
|
+
async def on_message_delete_activity(self, turn_context: TurnContext) -> None:
|
|
574
|
+
"""
|
|
575
|
+
Dispatches message delete activity.
|
|
576
|
+
|
|
577
|
+
:param turn_context: The context object for the turn.
|
|
578
|
+
:return: None
|
|
579
|
+
"""
|
|
580
|
+
if turn_context.activity.channel_id == "msteams":
|
|
581
|
+
channel_data = channel_data = (
|
|
582
|
+
TeamsChannelData.model_validate(turn_context.activity.channel_data)
|
|
583
|
+
if turn_context.activity.channel_data
|
|
584
|
+
else None
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
event_type = channel_data.event_type if channel_data else None
|
|
588
|
+
|
|
589
|
+
if event_type == "softDeleteMessage":
|
|
590
|
+
return await self.on_teams_message_soft_delete(turn_context)
|
|
591
|
+
|
|
592
|
+
return await super().on_message_delete_activity(turn_context)
|
|
593
|
+
|
|
594
|
+
async def on_teams_message_undelete(self, turn_context: TurnContext) -> None:
|
|
595
|
+
"""
|
|
596
|
+
Handles Teams message undelete.
|
|
597
|
+
|
|
598
|
+
:param turn_context: The context object for the turn.
|
|
599
|
+
:return: None
|
|
600
|
+
"""
|
|
601
|
+
return
|
|
602
|
+
|
|
603
|
+
async def on_teams_message_edit(self, turn_context: TurnContext) -> None:
|
|
604
|
+
"""
|
|
605
|
+
Handles Teams message edit.
|
|
606
|
+
|
|
607
|
+
:param turn_context: The context object for the turn.
|
|
608
|
+
:return: None
|
|
609
|
+
"""
|
|
610
|
+
return
|
|
611
|
+
|
|
612
|
+
async def on_teams_message_soft_delete(self, turn_context: TurnContext) -> None:
|
|
613
|
+
"""
|
|
614
|
+
Handles Teams message soft delete.
|
|
615
|
+
|
|
616
|
+
:param turn_context: The context object for the turn.
|
|
617
|
+
:return: None
|
|
618
|
+
"""
|
|
619
|
+
return
|
|
620
|
+
|
|
621
|
+
async def on_teams_members_added_dispatch(
|
|
622
|
+
self,
|
|
623
|
+
members_added: List[ChannelAccount],
|
|
624
|
+
team_info: TeamInfo,
|
|
625
|
+
turn_context: TurnContext,
|
|
626
|
+
) -> None:
|
|
627
|
+
"""
|
|
628
|
+
Dispatches processing of Teams members added to the conversation.
|
|
629
|
+
Processes the members_added collection to get full member information when possible.
|
|
630
|
+
|
|
631
|
+
:param members_added: The list of members being added to the conversation.
|
|
632
|
+
:param team_info: The team info object.
|
|
633
|
+
:param turn_context: The context object for the turn.
|
|
634
|
+
:return: None
|
|
635
|
+
"""
|
|
636
|
+
teams_members_added = []
|
|
637
|
+
|
|
638
|
+
for member in members_added:
|
|
639
|
+
# If the member has properties or is the agent/bot being added to the conversation
|
|
640
|
+
if len(member.properties) or (
|
|
641
|
+
turn_context.activity.recipient
|
|
642
|
+
and turn_context.activity.recipient.id == member.id
|
|
643
|
+
):
|
|
644
|
+
|
|
645
|
+
# Convert the ChannelAccount to TeamsChannelAccount
|
|
646
|
+
# TODO: Converter between these two classes
|
|
647
|
+
teams_member = TeamsChannelAccount.model_validate(
|
|
648
|
+
member.model_dump(by_alias=True, exclude_unset=True)
|
|
649
|
+
)
|
|
650
|
+
teams_members_added.append(teams_member)
|
|
651
|
+
else:
|
|
652
|
+
# Try to get the full member details from Teams
|
|
653
|
+
try:
|
|
654
|
+
teams_member = await TeamsInfo.get_member(turn_context, member.id)
|
|
655
|
+
teams_members_added.append(teams_member)
|
|
656
|
+
except Exception as err:
|
|
657
|
+
# Handle case where conversation is not found
|
|
658
|
+
if "ConversationNotFound" in str(err):
|
|
659
|
+
teams_channel_account = TeamsChannelAccount(
|
|
660
|
+
id=member.id,
|
|
661
|
+
name=member.name,
|
|
662
|
+
aad_object_id=getattr(member, "aad_object_id", None),
|
|
663
|
+
role=getattr(member, "role", None),
|
|
664
|
+
)
|
|
665
|
+
teams_members_added.append(teams_channel_account)
|
|
666
|
+
else:
|
|
667
|
+
# Propagate any other errors
|
|
668
|
+
raise
|
|
669
|
+
|
|
670
|
+
await self.on_teams_members_added(teams_members_added, team_info, turn_context)
|
|
671
|
+
|
|
672
|
+
async def on_teams_members_added(
|
|
673
|
+
self,
|
|
674
|
+
teams_members_added: List[TeamsChannelAccount],
|
|
675
|
+
team_info: TeamInfo,
|
|
676
|
+
turn_context: TurnContext,
|
|
677
|
+
) -> None:
|
|
678
|
+
"""
|
|
679
|
+
Handles Teams members added.
|
|
680
|
+
|
|
681
|
+
:param turn_context: The context object for the turn.
|
|
682
|
+
:return: None
|
|
683
|
+
"""
|
|
684
|
+
await self.on_members_added_activity(teams_members_added, turn_context)
|
|
685
|
+
|
|
686
|
+
async def on_teams_members_removed_dispatch(
|
|
687
|
+
self,
|
|
688
|
+
members_removed: List[ChannelAccount],
|
|
689
|
+
team_info: TeamInfo,
|
|
690
|
+
turn_context: TurnContext,
|
|
691
|
+
) -> None:
|
|
692
|
+
"""
|
|
693
|
+
Dispatches processing of Teams members removed from the conversation.
|
|
694
|
+
"""
|
|
695
|
+
teams_members_removed = []
|
|
696
|
+
for member in members_removed:
|
|
697
|
+
teams_members_removed.append(
|
|
698
|
+
TeamsChannelAccount.model_validate(
|
|
699
|
+
member.model_dump(by_alias=True, exclude_unset=True)
|
|
700
|
+
)
|
|
701
|
+
)
|
|
702
|
+
return await self.on_teams_members_removed(
|
|
703
|
+
teams_members_removed, team_info, turn_context
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
async def on_teams_members_removed(
|
|
707
|
+
self,
|
|
708
|
+
teams_members_removed: List[TeamsChannelAccount],
|
|
709
|
+
team_info: TeamInfo,
|
|
710
|
+
turn_context: TurnContext,
|
|
711
|
+
) -> None:
|
|
712
|
+
"""
|
|
713
|
+
Handles Teams members removed.
|
|
714
|
+
|
|
715
|
+
:param turn_context: The context object for the turn.
|
|
716
|
+
:return: None
|
|
717
|
+
"""
|
|
718
|
+
await self.on_members_removed_activity(teams_members_removed, turn_context)
|
|
719
|
+
|
|
720
|
+
async def on_teams_channel_created(
|
|
721
|
+
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
|
|
722
|
+
) -> None:
|
|
723
|
+
"""
|
|
724
|
+
Handles Teams channel created.
|
|
725
|
+
|
|
726
|
+
:param turn_context: The context object for the turn.
|
|
727
|
+
:return: None
|
|
728
|
+
"""
|
|
729
|
+
return
|
|
730
|
+
|
|
731
|
+
async def on_teams_channel_deleted(
|
|
732
|
+
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
|
|
733
|
+
) -> None:
|
|
734
|
+
"""
|
|
735
|
+
Handles Teams channel deleted.
|
|
736
|
+
|
|
737
|
+
:param turn_context: The context object for the turn.
|
|
738
|
+
:return: None
|
|
739
|
+
"""
|
|
740
|
+
return
|
|
741
|
+
|
|
742
|
+
async def on_teams_channel_renamed(
|
|
743
|
+
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
|
|
744
|
+
) -> None:
|
|
745
|
+
"""
|
|
746
|
+
Handles Teams channel renamed.
|
|
747
|
+
|
|
748
|
+
:param turn_context: The context object for the turn.
|
|
749
|
+
:return: None
|
|
750
|
+
"""
|
|
751
|
+
return
|
|
752
|
+
|
|
753
|
+
async def on_teams_team_archived(
|
|
754
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
755
|
+
) -> None:
|
|
756
|
+
"""
|
|
757
|
+
Handles Teams team archived.
|
|
758
|
+
|
|
759
|
+
:param turn_context: The context object for the turn.
|
|
760
|
+
:return: None
|
|
761
|
+
"""
|
|
762
|
+
return
|
|
763
|
+
|
|
764
|
+
async def on_teams_team_deleted(
|
|
765
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
766
|
+
) -> None:
|
|
767
|
+
"""
|
|
768
|
+
Handles Teams team deleted.
|
|
769
|
+
|
|
770
|
+
:param turn_context: The context object for the turn.
|
|
771
|
+
:return: None
|
|
772
|
+
"""
|
|
773
|
+
return
|
|
774
|
+
|
|
775
|
+
async def on_teams_team_hard_deleted(
|
|
776
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
777
|
+
) -> None:
|
|
778
|
+
"""
|
|
779
|
+
Handles Teams team hard deleted.
|
|
780
|
+
|
|
781
|
+
:param turn_context: The context object for the turn.
|
|
782
|
+
:return: None
|
|
783
|
+
"""
|
|
784
|
+
return
|
|
785
|
+
|
|
786
|
+
async def on_teams_channel_restored(
|
|
787
|
+
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
|
|
788
|
+
) -> None:
|
|
789
|
+
"""
|
|
790
|
+
Handles Teams channel restored.
|
|
791
|
+
|
|
792
|
+
:param turn_context: The context object for the turn.
|
|
793
|
+
:return: None
|
|
794
|
+
"""
|
|
795
|
+
return
|
|
796
|
+
|
|
797
|
+
async def on_teams_team_renamed(
|
|
798
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
799
|
+
) -> None:
|
|
800
|
+
"""
|
|
801
|
+
Handles Teams team renamed.
|
|
802
|
+
|
|
803
|
+
:param turn_context: The context object for the turn.
|
|
804
|
+
:return: None
|
|
805
|
+
"""
|
|
806
|
+
return
|
|
807
|
+
|
|
808
|
+
async def on_teams_team_restored(
|
|
809
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
810
|
+
) -> None:
|
|
811
|
+
"""
|
|
812
|
+
Handles Teams team restored.
|
|
813
|
+
|
|
814
|
+
:param turn_context: The context object for the turn.
|
|
815
|
+
:return: None
|
|
816
|
+
"""
|
|
817
|
+
return
|
|
818
|
+
|
|
819
|
+
async def on_teams_team_unarchived(
|
|
820
|
+
self, team_info: TeamInfo, turn_context: TurnContext
|
|
821
|
+
) -> None:
|
|
822
|
+
"""
|
|
823
|
+
Handles Teams team unarchived.
|
|
824
|
+
|
|
825
|
+
:param turn_context: The context object for the turn.
|
|
826
|
+
:return: None
|
|
827
|
+
"""
|
|
828
|
+
return
|
|
829
|
+
|
|
830
|
+
async def on_event_activity(self, turn_context: TurnContext) -> None:
|
|
831
|
+
"""
|
|
832
|
+
Dispatches event activity.
|
|
833
|
+
|
|
834
|
+
:param turn_context: The context object for the turn.
|
|
835
|
+
:return: None
|
|
836
|
+
"""
|
|
837
|
+
if turn_context.activity.channel_id == "msteams":
|
|
838
|
+
if turn_context.activity.name == "application/vnd.microsoft.readReceipt":
|
|
839
|
+
return await self.on_teams_read_receipt(turn_context)
|
|
840
|
+
elif turn_context.activity.name == "application/vnd.microsoft.meetingStart":
|
|
841
|
+
return await self.on_teams_meeting_start(turn_context)
|
|
842
|
+
elif turn_context.activity.name == "application/vnd.microsoft.meetingEnd":
|
|
843
|
+
return await self.on_teams_meeting_end(turn_context)
|
|
844
|
+
elif (
|
|
845
|
+
turn_context.activity.name
|
|
846
|
+
== "application/vnd.microsoft.meetingParticipantJoin"
|
|
847
|
+
):
|
|
848
|
+
return await self.on_teams_meeting_participants_join(turn_context)
|
|
849
|
+
elif (
|
|
850
|
+
turn_context.activity.name
|
|
851
|
+
== "application/vnd.microsoft.meetingParticipantLeave"
|
|
852
|
+
):
|
|
853
|
+
return await self.on_teams_meeting_participants_leave(turn_context)
|
|
854
|
+
|
|
855
|
+
return await super().on_event_activity(turn_context)
|
|
856
|
+
|
|
857
|
+
async def on_teams_meeting_start(
|
|
858
|
+
self, meeting: MeetingStartEventDetails, turn_context: TurnContext
|
|
859
|
+
) -> None:
|
|
860
|
+
"""
|
|
861
|
+
Handles Teams meeting start.
|
|
862
|
+
|
|
863
|
+
:param turn_context: The context object for the turn.
|
|
864
|
+
:return: None
|
|
865
|
+
"""
|
|
866
|
+
return
|
|
867
|
+
|
|
868
|
+
async def on_teams_meeting_end(
|
|
869
|
+
self, meeting: MeetingEndEventDetails, turn_context: TurnContext
|
|
870
|
+
) -> None:
|
|
871
|
+
"""
|
|
872
|
+
Handles Teams meeting end.
|
|
873
|
+
|
|
874
|
+
:param turn_context: The context object for the turn.
|
|
875
|
+
:return: None
|
|
876
|
+
"""
|
|
877
|
+
return
|
|
878
|
+
|
|
879
|
+
async def on_teams_read_receipt(
|
|
880
|
+
self, read_receipt: ReadReceiptInfo, turn_context: TurnContext
|
|
881
|
+
) -> None:
|
|
882
|
+
"""
|
|
883
|
+
Handles Teams read receipt.
|
|
884
|
+
|
|
885
|
+
:param turn_context: The context object for the turn.
|
|
886
|
+
:return: None
|
|
887
|
+
"""
|
|
888
|
+
return
|
|
889
|
+
|
|
890
|
+
async def on_teams_meeting_participants_join(
|
|
891
|
+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
|
|
892
|
+
) -> None:
|
|
893
|
+
"""
|
|
894
|
+
Handles Teams meeting participants join.
|
|
895
|
+
|
|
896
|
+
:param turn_context: The context object for the turn.
|
|
897
|
+
:return: None
|
|
898
|
+
"""
|
|
899
|
+
return
|
|
900
|
+
|
|
901
|
+
async def on_teams_meeting_participants_leave(
|
|
902
|
+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
|
|
903
|
+
) -> None:
|
|
904
|
+
"""
|
|
905
|
+
Handles Teams meeting participants leave.
|
|
906
|
+
|
|
907
|
+
:param turn_context: The context object for the turn.
|
|
908
|
+
:return: None
|
|
909
|
+
"""
|
|
910
|
+
return
|