8000 Port: [Teams] Add support for meeting participants added/removed even… · fkatada/ms-botbuilder-python@b8dd205 · GitHub
[go: up one dir, main page]

Skip to content

Commit b8dd205

Browse files
authored
Port: [Teams] Add support for meeting participants added/removed events (microsoft#2137)
* [Teams] Add support for meeting participants added/removed events * test case issue and code format fix * code format fix for microsoft_app_credentials.py * removing unnecessary else
1 parent cea5ccc commit b8dd205

File tree

5 files changed

+189
-4
lines changed

5 files changed

+189
-4
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
TaskModuleResponse,
2828
TabRequest,
2929
TabSubmit,
30+
MeetingParticipantsEventDetails,
3031
)
3132
from botframework.connector import Channels
3233
from ..serializer_helper import deserializer_helper
@@ -913,6 +914,20 @@ async def on_event_activity(self, turn_context: TurnContext):
913914
return await self.on_teams_meeting_end_event(
914915
turn_context.activity.value, turn_context
915916
)
917+
if (
918+
turn_context.activity.name
919+
== "application/vnd.microsoft.meetingParticipantJoin"
920+
):
921+
return await self.on_teams_meeting_participants_join_event(
922+
turn_context.activity.value, turn_context
923+
)
924+
if (
925+
turn_context.activity.name
926+
== "application/vnd.microsoft.meetingParticipantLeave"
927+
):
928+
return await self.on_teams_meeting_participants_leave_event(
929+
turn_context.activity.value, turn_context
930+
)
916931

917932
return await super().on_event_activity(turn_context)
918933

@@ -941,3 +956,29 @@ async def on_teams_meeting_end_event(
941956
:returns: A task that represents the work queued to execute.
942957
"""
943958
return
959+
960+
async def on_teams_meeting_participants_join_event(
961+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
962+
): # pylint: disable=unused-argument
963+
"""
964+
Override this in a derived class to provide logic for when meeting participants are added.
965+
966+
:param meeting: The details of the meeting.
967+
:param turn_context: A context object for this turn.
968+
969+
:returns: A task that represents the work queued to execute.
970+
"""
971+
return
972+
973+
async def on_teams_meeting_participants_leave_event(
974+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
975+
): # pylint: disable=unused-argument
976+
"""
977+
Override this in a derived class to provide logic for when meeting participants are removed.
978+
979+
:param meeting: The details of the meeting.
980+
:param turn_context: A context object for this turn.
981+
982+
:returns: A task that represents the work queued to execute.
983+
"""
984+
return

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
TabRequest,
3333
TabSubmit,
3434
TabContext,
35+
MeetingParticipantsEventDetails,
3536
)
3637
from botframework.connector import Channels
3738
from simple_adapter import SimpleAdapter
@@ -333,6 +334,22 @@ async def on_teams_meeting_end_event(
333334
turn_context.activity.value, turn_context
334335
)
335336

337+
async def on_teams_meeting_participants_join_event(
338+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
339+
):
340+
self.record.append("on_teams_meeting_participants_join_event")
341+
return await super().on_teams_meeting_participants_join_event(
342+
turn_context.activity.value, turn_context
343+
)
344+
345+
async def on_teams_meeting_participants_leave_event(
346+
self, meeting: MeetingParticipantsEventDetails, turn_context: TurnContext
347+
):
348+
self.record.append("on_teams_meeting_participants_leave_event")
349+
return await super().on_teams_meeting_participants_leave_event(
350+
turn_context.activity.value, turn_context
351+
)
352+
336353

337354
class NotImplementedAdapter(BotAdapter):
338355
async def delete_activity(
@@ -1157,3 +1174,57 @@ async def test_on_teams_meeting_end_event(self):
11571174
assert len(bot.record) == 2
11581175
assert bot.record[0] == "on_event_activity"
11591176
assert bot.record[1] == "on_teams_meeting_end_event"
1177+
1178+
async def test_on_teams_meeting_participants_join_event(self):
1179+
# arrange
1180+
activity = Activity(
1181+
type=ActivityTypes.event,
1182+
channel_id=Channels.ms_teams,
1183+
name="application/vnd.microsoft.meetingParticipantJoin",
1184+
value={
1185+
"members": [
1186+
{
1187+
"user": {"id": "123", "name": "name"},
1188+
"meeting": {"role": "role", "in_meeting": True},
1189+
}
1190+
],
1191+
},
1192+
)
1193+
1194+
turn_context = TurnContext(SimpleAdapter(), activity)
1195+
1196+
# Act
1197+
bot = TestingTeamsActivityHandler()
1198+
await bot.on_turn(turn_context)
1199+
1200+
# Assert
1201+
assert len(bot.record) == 2
1202+
assert bot.record[0] == "on_event_activity"
1203+
assert bot.record[1] == "on_teams_meeting_participants_join_event"
1204+
1205+
async def test_on_teams_meeting_participants_leave_event(self):
1206+
# arrange
1207+
activity = Activity(
1208+
type=ActivityTypes.event,
1209+
channel_id=Channels.ms_teams,
1210+
name="application/vnd.microsoft.meetingParticipantLeave",
1211+
value={
1212+
"members": [
1213+
{
1214+
"user": {"id": "id", "name": "name"},
1215+
"meeting": {"role": "role", "in_meeting": True},
1216+
}
1217+
],
1218+
},
1219+
)
1220+
1221+
turn_context = TurnContext(SimpleAdapter(), activity)
1222+
1223+
# Act
1224+
bot = TestingTeamsActivityHandler()
1225+
await bot.on_turn(turn_context)
1226+
1227+
# Assert
1228+
assert len(bot.record) == 2
1229+
assert bot.record[0] == "on_event_activity"
1230+
assert bot.record[1] == "on_teams_meeting_participants_leave_event"

libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
from ._models_py3 import TabSubmitData
7878
from ._models_py3 import TabSuggestedActions
7979
from ._models_py3 import TaskModuleCardResponse
80+
from ._models_py3 import UserMeetingDetails
81+
from ._models_py3 import TeamsMeetingMember
82+
from ._models_py3 import MeetingParticipantsEventDetails
8083

8184
__all__ = [
8285
"AppBasedLinkQuery",
@@ -155,4 +158,7 @@
155158
"TabSubmitData",
156159
"TabSuggestedActions",
157160
"TaskModuleCardResponse",
161+
"UserMeetingDetails",
162+
"TeamsMeetingMember",
163+
"MeetingParticipantsEventDetails",
158164
]

libraries/botbuilder-schema/botbuilder/schema/teams/_models_py3.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,3 +2506,65 @@ class MeetingEndEventDetails(MeetingDetailsBase):
25062506
def __init__(self, *, end_time: str = None, **kwargs):
25072507
super(MeetingEndEventDetails, self).__init__(**kwargs)
25082508
self.end_time = end_time
2509+
2510+
2511+
class UserMeetingDetails(Model):
2512+
"""Specific details of a user in a Teams meeting.
2513+
2514+
:param role: Role of the participant in the current meeting.
2515+
:type role: str
2516+
:param in_meeting: True, if the participant is in the meeting.
2517+
:type in_meeting: bool
2518+
"""
2519+
2520+
_attribute_map = {
2521+
"role": {"key": "role", "type": "str"},
2522+
"in_meeting": {"key": "inMeeting", "type": "bool"},
2523+
}
2524+
2525+
def __init__(self, *, role: str = None, in_meeting: bool = None, **kwargs) -> None:
2526+
super(UserMeetingDetails, self).__init__(**kwargs)
2527+
self.in_meeting = in_meeting
2528+
self.role = role
2529+
2530+
2531+
class TeamsMeetingMember(Model):
2532+
"""Data about the meeting participants.
2533+
2534+
:param user: The channel user data.
2535+
:type user: TeamsChannelAccount
2536+
:param meeting: The user meeting details.
2537+
:type meeting: UserMeetingDetails
2538+
"""
2539+
2540+
_attribute_map = {
2541+
"user": {"key": "user", "type": "TeamsChannelAccount"},
2542+
"meeting": {"key": "meeting", "type": "UserMeetingDetails"},
2543+
}
2544+
2545+
def __init__(
2546+
self,
2547+
*,
2548+
user: TeamsChannelAccount = None,
2549+
meeting: UserMeetingDetails = None,
2550+
**kwargs
2551+
) -> None:
2552+
super(TeamsMeetingMember, self).__init__(**kwargs)
2553+
self.user = user
2554+
self.meeting = meeting
2555+
2556+
2557+
class MeetingParticipantsEventDetails(Model):
2558+
"""Data about the meeting participants.
2559+
2560+
:param members: The members involved in the meeting event.
2561+
:type members: list[~botframework.connector.models.TeamsMeetingMember]
2562+
"""
2563+
2564+
_attribute_map = {
2565+
"conversations": {"key": "members", "type": "[TeamsMeetingMember]"},
2566+
}
2567+
2568+
def __init__(self, *, members: List[TeamsMeetingMember] = None, **kwargs) -> None:
2569+
super(MeetingParticipantsEventDetails, self).__init__(**kwargs)
2570+
self.members = members

libraries/botframework-connector/botframework/connector/auth/microsoft_app_credentials.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,15 @@ def get_access_token(self, force_refresh: bool = False) -> str:
5454
auth_token = self.__get_msal_app().acquire_token_for_client(scopes=scopes)
5555
if "access_token" in auth_token:
5656
return auth_token["access_token"]
57-
else:
58-
error = auth_token["error"] if "error" in auth_token else "Unknown error"
59-
error_description = auth_token["error_description"] if "error_description" in auth_token else "Unknown error description"
60-
raise PermissionError(f"Failed to get access token with error: {error}, error_description: {error_description}")
57+
error = auth_token["error"] if "error" in auth_token else "Unknown error"
58+
error_description = (
59+
auth_token["error_description"]
60+
if "error_description" in auth_token
61+
else "Unknown error description"
62+
)
63+
raise PermissionError(
64+
f"Failed to get access token with error: {error}, error_description: {error_description}"
65+
)
6166

6267
def __get_msal_app(self):
6368
if not self.app:

0 commit comments

Comments
 (0)
0