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.
@@ -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