From f1bca0c26f0063f2372319ecc8b0a321267640f9 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Thu, 27 Jul 2023 15:53:44 -0300 Subject: [PATCH 1/5] Add teams meeting participants events --- .../Teams/TeamsActivityHandler.cs | 32 ++++++++++ .../MeetingParticipantsAddedEventDetails.cs | 58 +++++++++++++++++++ .../MeetingParticipantsRemovedEventDetails.cs | 58 +++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs create mode 100644 libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs diff --git a/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs b/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs index 06b57931db..2d929901d6 100644 --- a/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs +++ b/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs @@ -809,6 +809,10 @@ protected override Task OnEventActivityAsync(ITurnContext turnCo return OnTeamsMeetingStartAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); case "application/vnd.microsoft.meetingEnd": return OnTeamsMeetingEndAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); + case "application/vnd.microsoft.meetingParticipantsAdded": + return OnTeamsMeetingParticipantsAddedAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); + case "application/vnd.microsoft.meetingParticipantsRemoved": + return OnTeamsMeetingParticipantsRemovedAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); } } @@ -857,6 +861,34 @@ protected virtual Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, return Task.CompletedTask; } + /// + /// Invoked when a Teams Participants Added event activity is received from the connector. + /// Override this in a derived class to provide logic for when meeting participants are added. + /// + /// The details of the meeting. + /// A strongly-typed context object for this turn. + /// A cancellation token that can be used by other objects + /// or threads to receive notice of cancellation. + /// A task that represents the work queued to execute. + protected virtual Task OnTeamsMeetingParticipantsAddedAsync(MeetingParticipantsAddedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + /// + /// Invoked when a Teams Participants Removed event activity is received from the connector. + /// Override this in a derived class to provide logic for when meeting participants are removed. + /// + /// The details of the meeting. + /// A strongly-typed context object for this turn. + /// A cancellation token that can be used by other objects + /// or threads to receive notice of cancellation. + /// A task that represents the work queued to execute. + protected virtual Task OnTeamsMeetingParticipantsRemovedAsync(MeetingParticipantsRemovedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + /// /// Invoked when an message update activity is received. /// activities, such as the conversational logic. diff --git a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs new file mode 100644 index 0000000000..7bd75bb843 --- /dev/null +++ b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Bot.Schema.Teams +{ + /// + /// Specific details of a Teams meeting participants added event. + /// + public partial class MeetingParticipantsAddedEventDetails : MeetingEventDetails + { + /// + /// Initializes a new instance of the class. + /// + public MeetingParticipantsAddedEventDetails() + { + CustomInit(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The meeting's Id, encoded as a BASE64 string. + /// The URL used to join the meeting. + /// The title of the meeting. + /// The meeting's type. + /// The added participant accounts. + public MeetingParticipantsAddedEventDetails( + string id, + Uri joinUrl = null, + string title = null, + string meetingType = "Scheduled", + IList participantsAdded = default) + : base(id, joinUrl, title, meetingType) + { + ParticipantsAdded = participantsAdded; + + CustomInit(); + } + + /// + /// Gets the added meeting participants. + /// + /// + /// The added participant accounts. + /// + [JsonProperty(PropertyName = "ParticipantsAdded")] + public IList ParticipantsAdded { get; private set; } = new List(); + + /// + /// An initialization method that performs custom operations like setting defaults. + /// + partial void CustomInit(); + } +} diff --git a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs new file mode 100644 index 0000000000..ab9216d12c --- /dev/null +++ b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Bot.Schema.Teams +{ + /// + /// Specific details of a Teams meeting participants removed event. + /// + public partial class MeetingParticipantsRemovedEventDetails : MeetingEventDetails + { + /// + /// Initializes a new instance of the class. + /// + public MeetingParticipantsRemovedEventDetails() + { + CustomInit(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The meeting's Id, encoded as a BASE64 string. + /// The URL used to join the meeting. + /// The title of the meeting. + /// The meeting's type. + /// The removed participant accounts. + public MeetingParticipantsRemovedEventDetails( + string id, + Uri joinUrl = null, + string title = null, + string meetingType = "Scheduled", + IList participantsRemoved = default) + : base(id, joinUrl, title, meetingType) + { + ParticipantsRemoved = participantsRemoved; + + CustomInit(); + } + + /// + /// Gets the removed meeting participants. + /// + /// + /// The removed participant accounts. + /// + [JsonProperty(PropertyName = "ParticipantsRemoved")] + public IList ParticipantsRemoved { get; private set; } = new List(); + + /// + /// An initialization method that performs custom operations like setting defaults. + /// + partial void CustomInit(); + } +} From 5cc161457cc008446917d870d573da0c1696c95f Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Thu, 27 Jul 2023 15:54:02 -0300 Subject: [PATCH 2/5] Add unit tests for the new classes and methods --- .../Teams/TeamsActivityHandlerTests.cs | 88 +++++++++++++++++++ ...etingParticipantsAddedEventDetailsTests.cs | 48 ++++++++++ ...ingParticipantsRemovedEventDetailsTests.cs | 48 ++++++++++ 3 files changed, 184 insertions(+) create mode 100644 tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs create mode 100644 tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs diff --git a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs index f13d0326d0..092209dfc3 100644 --- a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs +++ b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs @@ -1270,6 +1270,80 @@ void CaptureSend(Activity[] arg) Assert.Equal("10101010", activitiesToSend[0].Text); } + [Fact] + public async Task TestMeetingParticipantsAddedEvent() + { + // Arrange + var activity = new Activity + { + ChannelId = Channels.Msteams, + Type = ActivityTypes.Event, + Name = "application/vnd.microsoft.meetingParticipantsAdded", + Value = JObject.Parse(@"{ + ParticipantsAdded: [ + {Id: 'id', Name: 'name'} + ] + }"), + }; + + Activity[] activitiesToSend = null; + void CaptureSend(Activity[] arg) + { + activitiesToSend = arg; + } + + var turnContext = new TurnContext(new SimpleAdapter(CaptureSend), activity); + + // Act + var bot = new TestActivityHandler(); + await ((IBot)bot).OnTurnAsync(turnContext); + + // Assert + Assert.Equal(2, bot.Record.Count); + Assert.Equal("OnEventActivityAsync", bot.Record[0]); + Assert.Equal("OnTeamsMeetingParticipantsAddedAsync", bot.Record[1]); + Assert.NotNull(activitiesToSend); + Assert.Single(activitiesToSend); + Assert.Equal("id", activitiesToSend[0].Text); + } + + [Fact] + public async Task TestMeetingParticipantsRemovedEvent() + { + // Arrange + var activity = new Activity + { + ChannelId = Channels.Msteams, + Type = ActivityTypes.Event, + Name = "application/vnd.microsoft.meetingParticipantsRemoved", + Value = JObject.Parse(@"{ + ParticipantsRemoved: [ + {Id: 'id', Name: 'name'} + ] + }"), + }; + + Activity[] activitiesToSend = null; + void CaptureSend(Activity[] arg) + { + activitiesToSend = arg; + } + + var turnContext = new TurnContext(new SimpleAdapter(CaptureSend), activity); + + // Act + var bot = new TestActivityHandler(); + await ((IBot)bot).OnTurnAsync(turnContext); + + // Assert + Assert.Equal(2, bot.Record.Count); + Assert.Equal("OnEventActivityAsync", bot.Record[0]); + Assert.Equal("OnTeamsMeetingParticipantsRemovedAsync", bot.Record[1]); + Assert.NotNull(activitiesToSend); + Assert.Single(activitiesToSend); + Assert.Equal("id", activitiesToSend[0].Text); + } + [Fact] public async Task TestMessageUpdateActivityTeamsMessageEdit() { @@ -1536,6 +1610,20 @@ protected override Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, return Task.CompletedTask; } + protected override Task OnTeamsMeetingParticipantsAddedAsync(MeetingParticipantsAddedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + { + Record.Add(MethodBase.GetCurrentMethod().Name); + turnContext.SendActivityAsync(meeting.ParticipantsAdded[0].Id); + return base.OnTeamsMeetingParticipantsAddedAsync(meeting, turnContext, cancellationToken); + } + + protected override Task OnTeamsMeetingParticipantsRemovedAsync(MeetingParticipantsRemovedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + { + Record.Add(MethodBase.GetCurrentMethod().Name); + turnContext.SendActivityAsync(meeting.ParticipantsRemoved[0].Id); + return base.OnTeamsMeetingParticipantsRemovedAsync(meeting, turnContext, cancellationToken); + } + // Invoke protected override Task OnInvokeActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) { diff --git a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs new file mode 100644 index 0000000000..9063f78116 --- /dev/null +++ b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs @@ -0,0 +1,48 @@ +// Copyright(c) Microsoft Corporation.All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Bot.Schema.Teams; +using Xunit; + +namespace Microsoft.Bot.Schema.Tests.Teams +{ + public class MeetingParticipantsAddedEventDetailsTests + { + [Fact] + public void MeetingParticipantsAddedEventDetailsInits() + { + // Arrange + var meetingId = "meetingId"; + var meetingJoinUrl = new Uri("http://meetingJoinUrl"); + var meetingTitle = "meetingTitle"; + var meetingType = "meetingType"; + var participant = new TeamsChannelAccount("id", "name", "givenName", "surname", "email", "userPrincipalName"); + var participantsAdded = new List() { participant }; + + // Act + var meeting = new MeetingParticipantsAddedEventDetails(meetingId, meetingJoinUrl, meetingTitle, meetingType, participantsAdded); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + Assert.Equal(meetingId, meeting.Id); + Assert.Equal(meetingJoinUrl, meeting.JoinUrl); + Assert.Equal(meetingTitle, meeting.Title); + Assert.Equal(meetingType, meeting.MeetingType); + Assert.StrictEqual(participantsAdded, meeting.ParticipantsAdded); + } + + [Fact] + public void MeetingParticipantsAddedEventDetailsInitsWithNoArgs() + { + // Act + var meeting = new MeetingParticipantsAddedEventDetails(); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + } + } +} diff --git a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs new file mode 100644 index 0000000000..b5234b4305 --- /dev/null +++ b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Bot.Schema.Teams; +using Xunit; + +namespace Microsoft.Bot.Schema.Tests.Teams +{ + public class MeetingParticipantsRemovedEventDetailsTests + { + [Fact] + public void MeetingParticipantsRemovedEventDetailsInits() + { + // Arrange + var meetingId = "meetingId"; + var meetingJoinUrl = new Uri("http://meetingJoinUrl"); + var meetingTitle = "meetingTitle"; + var meetingType = "meetingType"; + var participant = new TeamsChannelAccount("id", "name", "givenName", "surname", "email", "userPrincipalName"); + var participantsRemoved = new List() { participant }; + + // Act + var meeting = new MeetingParticipantsRemovedEventDetails(meetingId, meetingJoinUrl, meetingTitle, meetingType, participantsRemoved); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + Assert.Equal(meetingId, meeting.Id); + Assert.Equal(meetingJoinUrl, meeting.JoinUrl); + Assert.Equal(meetingTitle, meeting.Title); + Assert.Equal(meetingType, meeting.MeetingType); + Assert.StrictEqual(participantsRemoved, meeting.ParticipantsRemoved); + } + + [Fact] + public void MeetingParticipantsRemovedEventDetailsInitsWithNoArgs() + { + // Act + var meeting = new MeetingParticipantsRemovedEventDetails(); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + } + } +} From ed49b5ffeb8a1c81f0e3a0460f6d278bffdd4e94 Mon Sep 17 00:00:00 2001 From: JhontSouth Date: Fri, 11 Aug 2023 12:33:51 -0500 Subject: [PATCH 3/5] modify participant meeting events models --- .../Teams/TeamsActivityHandler.cs | 16 ++--- .../MeetingParticipantsAddedEventDetails.cs | 58 ------------------- .../Teams/MeetingParticipantsEventDetails.cs | 44 ++++++++++++++ .../MeetingParticipantsRemovedEventDetails.cs | 58 ------------------- .../Teams/TeamsMeetingMember.cs | 42 ++++++++++++++ .../Teams/UserMeetingDetails.cs | 31 ++++++++++ .../Teams/TeamsActivityHandlerTests.cs | 48 +++++++-------- ...etingParticipantsAddedEventDetailsTests.cs | 48 --------------- .../MeetingParticipantsEventDetailsTests.cs | 41 +++++++++++++ ...ingParticipantsRemovedEventDetailsTests.cs | 48 --------------- 10 files changed, 191 insertions(+), 243 deletions(-) delete mode 100644 libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs create mode 100644 libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsEventDetails.cs delete mode 100644 libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs create mode 100644 libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs create mode 100644 libraries/Microsoft.Bot.Schema/Teams/UserMeetingDetails.cs delete mode 100644 tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs create mode 100644 tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsEventDetailsTests.cs delete mode 100644 tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs diff --git a/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs b/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs index 2d929901d6..1701b7c793 100644 --- a/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs +++ b/libraries/Microsoft.Bot.Builder/Teams/TeamsActivityHandler.cs @@ -809,10 +809,10 @@ protected override Task OnEventActivityAsync(ITurnContext turnCo return OnTeamsMeetingStartAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); case "application/vnd.microsoft.meetingEnd": return OnTeamsMeetingEndAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); - case "application/vnd.microsoft.meetingParticipantsAdded": - return OnTeamsMeetingParticipantsAddedAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); - case "application/vnd.microsoft.meetingParticipantsRemoved": - return OnTeamsMeetingParticipantsRemovedAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); + case "application/vnd.microsoft.meetingParticipantJoin": + return OnTeamsMeetingParticipantsJoinAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); + case "application/vnd.microsoft.meetingParticipantLeave": + return OnTeamsMeetingParticipantsLeaveAsync(JObject.FromObject(turnContext.Activity.Value).ToObject(), turnContext, cancellationToken); } } @@ -862,7 +862,7 @@ protected virtual Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, } /// - /// Invoked when a Teams Participants Added event activity is received from the connector. + /// Invoked when a Teams Participants Join event activity is received from the connector. /// Override this in a derived class to provide logic for when meeting participants are added. /// /// The details of the meeting. @@ -870,13 +870,13 @@ protected virtual Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, /// A cancellation token that can be used by other objects /// or threads to receive notice of cancellation. /// A task that represents the work queued to execute. - protected virtual Task OnTeamsMeetingParticipantsAddedAsync(MeetingParticipantsAddedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + protected virtual Task OnTeamsMeetingParticipantsJoinAsync(MeetingParticipantsEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) { return Task.CompletedTask; } /// - /// Invoked when a Teams Participants Removed event activity is received from the connector. + /// Invoked when a Teams Participants Leave event activity is received from the connector. /// Override this in a derived class to provide logic for when meeting participants are removed. /// /// The details of the meeting. @@ -884,7 +884,7 @@ protected virtual Task OnTeamsMeetingParticipantsAddedAsync(MeetingParticipantsA /// A cancellation token that can be used by other objects /// or threads to receive notice of cancellation. /// A task that represents the work queued to execute. - protected virtual Task OnTeamsMeetingParticipantsRemovedAsync(MeetingParticipantsRemovedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + protected virtual Task OnTeamsMeetingParticipantsLeaveAsync(MeetingParticipantsEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) { return Task.CompletedTask; } diff --git a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs deleted file mode 100644 index 7bd75bb843..0000000000 --- a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsAddedEventDetails.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.Bot.Schema.Teams -{ - /// - /// Specific details of a Teams meeting participants added event. - /// - public partial class MeetingParticipantsAddedEventDetails : MeetingEventDetails - { - /// - /// Initializes a new instance of the class. - /// - public MeetingParticipantsAddedEventDetails() - { - CustomInit(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The meeting's Id, encoded as a BASE64 string. - /// The URL used to join the meeting. - /// The title of the meeting. - /// The meeting's type. - /// The added participant accounts. - public MeetingParticipantsAddedEventDetails( - string id, - Uri joinUrl = null, - string title = null, - string meetingType = "Scheduled", - IList participantsAdded = default) - : base(id, joinUrl, title, meetingType) - { - ParticipantsAdded = participantsAdded; - - CustomInit(); - } - - /// - /// Gets the added meeting participants. - /// - /// - /// The added participant accounts. - /// - [JsonProperty(PropertyName = "ParticipantsAdded")] - public IList ParticipantsAdded { get; private set; } = new List(); - - /// - /// An initialization method that performs custom operations like setting defaults. - /// - partial void CustomInit(); - } -} diff --git a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsEventDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsEventDetails.cs new file mode 100644 index 0000000000..cd0e143956 --- /dev/null +++ b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsEventDetails.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Bot.Schema.Teams +{ + /// + /// Data about the meeting participants. + /// + public partial class MeetingParticipantsEventDetails + { + /// + /// Initializes a new instance of the class. + /// + public MeetingParticipantsEventDetails() + { + CustomInit(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The members involved in the meeting event. + public MeetingParticipantsEventDetails( + IList members = default) + { + Members = members; + CustomInit(); + } + + /// + /// Gets the meeting participants info. + /// + /// + /// The participant accounts info. + /// + [JsonProperty(PropertyName = "Members")] + public IList Members { get; private set; } = new List(); + + partial void CustomInit(); + } +} diff --git a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs deleted file mode 100644 index ab9216d12c..0000000000 --- a/libraries/Microsoft.Bot.Schema/Teams/MeetingParticipantsRemovedEventDetails.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.Bot.Schema.Teams -{ - /// - /// Specific details of a Teams meeting participants removed event. - /// - public partial class MeetingParticipantsRemovedEventDetails : MeetingEventDetails - { - /// - /// Initializes a new instance of the class. - /// - public MeetingParticipantsRemovedEventDetails() - { - CustomInit(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The meeting's Id, encoded as a BASE64 string. - /// The URL used to join the meeting. - /// The title of the meeting. - /// The meeting's type. - /// The removed participant accounts. - public MeetingParticipantsRemovedEventDetails( - string id, - Uri joinUrl = null, - string title = null, - string meetingType = "Scheduled", - IList participantsRemoved = default) - : base(id, joinUrl, title, meetingType) - { - ParticipantsRemoved = participantsRemoved; - - CustomInit(); - } - - /// - /// Gets the removed meeting participants. - /// - /// - /// The removed participant accounts. - /// - [JsonProperty(PropertyName = "ParticipantsRemoved")] - public IList ParticipantsRemoved { get; private set; } = new List(); - - /// - /// An initialization method that performs custom operations like setting defaults. - /// - partial void CustomInit(); - } -} diff --git a/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs b/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs new file mode 100644 index 0000000000..25d94bcdf2 --- /dev/null +++ b/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Newtonsoft.Json; + +namespace Microsoft.Bot.Schema.Teams +{ + /// + /// Data about the joined meeting participants. + /// + public partial class TeamsMeetingMember + { + /// + /// Initializes a new instance of the class. + /// + /// The channel user data. + /// The user meeting details. + public TeamsMeetingMember(TeamsChannelAccount user, UserMeetingDetails meeting) + { + User = user; + Meeting = meeting; + } + + /// + /// Gets or sets the joined meeting participant. + /// + /// + /// The joined participant account. + /// + [JsonProperty(PropertyName = "user")] + public TeamsChannelAccount User { get; set; } + + /// + /// Gets or sets the joined users meeting details. + /// + /// + /// The joined users meeting details. + /// + [JsonProperty(PropertyName = "Meeting")] + public UserMeetingDetails Meeting { get; set; } + } +} diff --git a/libraries/Microsoft.Bot.Schema/Teams/UserMeetingDetails.cs b/libraries/Microsoft.Bot.Schema/Teams/UserMeetingDetails.cs new file mode 100644 index 0000000000..c3f30f06d5 --- /dev/null +++ b/libraries/Microsoft.Bot.Schema/Teams/UserMeetingDetails.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Newtonsoft.Json; + +namespace Microsoft.Bot.Schema.Teams +{ + /// + /// Specific details of a user in a Teams meeting. + /// + public partial class UserMeetingDetails + { + /// + /// Gets or sets a value indicating whether the user is in the meeting. + /// + /// + /// The user in meeting indicator. + /// + [JsonProperty(PropertyName = "InMeeting")] + public bool InMeeting { get; set; } + + /// + /// Gets or sets the value of the user's role. + /// + /// + /// The user's role. + /// + [JsonProperty(PropertyName = "Role")] + public string Role { get; set; } + } +} diff --git a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs index 092209dfc3..adedab0f4d 100644 --- a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs +++ b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs @@ -314,7 +314,7 @@ public async Task TestConversationUpdateTeamsChannelRestored() // Arrange var activity = new Activity { - Type = ActivityTypes.ConversationUpdate, + Type = ActivityTypes.ConversationUpdate, ChannelData = new TeamsChannelData { EventType = "channelRestored" }, ChannelId = Channels.Msteams, }; @@ -333,7 +333,7 @@ public async Task TestConversationUpdateTeamsChannelRestored() [Fact] public async Task TestConversationUpdateTeamsTeamArchived() { - // Arrange + // Arrange var activity = new Activity { Type = ActivityTypes.ConversationUpdate, @@ -351,7 +351,7 @@ public async Task TestConversationUpdateTeamsTeamArchived() Assert.Equal("OnConversationUpdateActivityAsync", bot.Record[0]); Assert.Equal("OnTeamsTeamArchivedAsync", bot.Record[1]); } - + [Fact] public async Task TestConversationUpdateTeamsTeamDeleted() { @@ -1139,7 +1139,7 @@ void CaptureSend(Activity[] arg) // Act var bot = new TestActivityHandler(); await ((IBot)bot).OnTurnAsync(turnContext); - + // Assert Assert.Equal(2, bot.Record.Count); Assert.Equal("OnInvokeActivityAsync", bot.Record[0]); @@ -1271,17 +1271,18 @@ void CaptureSend(Activity[] arg) } [Fact] - public async Task TestMeetingParticipantsAddedEvent() + public async Task TestMeetingParticipantsJoinEvent() { // Arrange var activity = new Activity { ChannelId = Channels.Msteams, Type = ActivityTypes.Event, - Name = "application/vnd.microsoft.meetingParticipantsAdded", + Name = "application/vnd.microsoft.meetingParticipantJoin", Value = JObject.Parse(@"{ - ParticipantsAdded: [ - {Id: 'id', Name: 'name'} + Members: [ + {User: {Id: 'id', Name: 'name'}, + Meeting: {Role: 'role', InMeeting: true}} ] }"), }; @@ -1301,24 +1302,25 @@ void CaptureSend(Activity[] arg) // Assert Assert.Equal(2, bot.Record.Count); Assert.Equal("OnEventActivityAsync", bot.Record[0]); - Assert.Equal("OnTeamsMeetingParticipantsAddedAsync", bot.Record[1]); + Assert.Equal("OnTeamsMeetingParticipantsJoinAsync", bot.Record[1]); Assert.NotNull(activitiesToSend); Assert.Single(activitiesToSend); Assert.Equal("id", activitiesToSend[0].Text); } [Fact] - public async Task TestMeetingParticipantsRemovedEvent() + public async Task TestMeetingParticipantsLeaveEvent() { // Arrange var activity = new Activity { ChannelId = Channels.Msteams, Type = ActivityTypes.Event, - Name = "application/vnd.microsoft.meetingParticipantsRemoved", + Name = "application/vnd.microsoft.meetingParticipantLeave", Value = JObject.Parse(@"{ - ParticipantsRemoved: [ - {Id: 'id', Name: 'name'} + Members: [ + {User: {Id: 'id', Name: 'name'}, + Meeting: {Role: 'role', InMeeting: false}} ] }"), }; @@ -1338,7 +1340,7 @@ void CaptureSend(Activity[] arg) // Assert Assert.Equal(2, bot.Record.Count); Assert.Equal("OnEventActivityAsync", bot.Record[0]); - Assert.Equal("OnTeamsMeetingParticipantsRemovedAsync", bot.Record[1]); + Assert.Equal("OnTeamsMeetingParticipantsLeaveAsync", bot.Record[1]); Assert.NotNull(activitiesToSend); Assert.Single(activitiesToSend); Assert.Equal("id", activitiesToSend[0].Text); @@ -1536,7 +1538,7 @@ protected override Task OnTeamsChannelRenamedAsync(ChannelInfo channelInfo, Team Record.Add(MethodBase.GetCurrentMethod().Name); return base.OnTeamsChannelRenamedAsync(channelInfo, teamInfo, turnContext, cancellationToken); } - + protected override Task OnTeamsChannelRestoredAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext turnContext, CancellationToken cancellationToken) { Record.Add(MethodBase.GetCurrentMethod().Name); @@ -1559,7 +1561,7 @@ protected override Task OnTeamsTeamHardDeletedAsync(TeamInfo teamInfo, ITurnCont { Record.Add(MethodBase.GetCurrentMethod().Name); return base.OnTeamsTeamHardDeletedAsync(teamInfo, turnContext, cancellationToken); - } + } protected override Task OnTeamsTeamRenamedAsync(TeamInfo teamInfo, ITurnContext turnContext, CancellationToken cancellationToken) { @@ -1610,18 +1612,18 @@ protected override Task OnTeamsReadReceiptAsync(ReadReceiptInfo readReceiptInfo, return Task.CompletedTask; } - protected override Task OnTeamsMeetingParticipantsAddedAsync(MeetingParticipantsAddedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + protected override Task OnTeamsMeetingParticipantsJoinAsync(MeetingParticipantsEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) { Record.Add(MethodBase.GetCurrentMethod().Name); - turnContext.SendActivityAsync(meeting.ParticipantsAdded[0].Id); - return base.OnTeamsMeetingParticipantsAddedAsync(meeting, turnContext, cancellationToken); + turnContext.SendActivityAsync(meeting.Members[0].User.Id); + return base.OnTeamsMeetingParticipantsJoinAsync(meeting, turnContext, cancellationToken); } - protected override Task OnTeamsMeetingParticipantsRemovedAsync(MeetingParticipantsRemovedEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) + protected override Task OnTeamsMeetingParticipantsLeaveAsync(MeetingParticipantsEventDetails meeting, ITurnContext turnContext, CancellationToken cancellationToken) { Record.Add(MethodBase.GetCurrentMethod().Name); - turnContext.SendActivityAsync(meeting.ParticipantsRemoved[0].Id); - return base.OnTeamsMeetingParticipantsRemovedAsync(meeting, turnContext, cancellationToken); + turnContext.SendActivityAsync(meeting.Members[0].User.Id); + return base.OnTeamsMeetingParticipantsLeaveAsync(meeting, turnContext, cancellationToken); } // Invoke @@ -1833,7 +1835,7 @@ private class RosterHttpMessageHandler : HttpMessageHandler protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = new HttpResponseMessage(HttpStatusCode.OK); - + // GetMembers (Team) if (request.RequestUri.PathAndQuery.EndsWith("team-id/members")) { diff --git a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs deleted file mode 100644 index 9063f78116..0000000000 --- a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsAddedEventDetailsTests.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright(c) Microsoft Corporation.All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using Microsoft.Bot.Schema.Teams; -using Xunit; - -namespace Microsoft.Bot.Schema.Tests.Teams -{ - public class MeetingParticipantsAddedEventDetailsTests - { - [Fact] - public void MeetingParticipantsAddedEventDetailsInits() - { - // Arrange - var meetingId = "meetingId"; - var meetingJoinUrl = new Uri("http://meetingJoinUrl"); - var meetingTitle = "meetingTitle"; - var meetingType = "meetingType"; - var participant = new TeamsChannelAccount("id", "name", "givenName", "surname", "email", "userPrincipalName"); - var participantsAdded = new List() { participant }; - - // Act - var meeting = new MeetingParticipantsAddedEventDetails(meetingId, meetingJoinUrl, meetingTitle, meetingType, participantsAdded); - - // Assert - Assert.NotNull(meeting); - Assert.IsType(meeting); - Assert.Equal(meetingId, meeting.Id); - Assert.Equal(meetingJoinUrl, meeting.JoinUrl); - Assert.Equal(meetingTitle, meeting.Title); - Assert.Equal(meetingType, meeting.MeetingType); - Assert.StrictEqual(participantsAdded, meeting.ParticipantsAdded); - } - - [Fact] - public void MeetingParticipantsAddedEventDetailsInitsWithNoArgs() - { - // Act - var meeting = new MeetingParticipantsAddedEventDetails(); - - // Assert - Assert.NotNull(meeting); - Assert.IsType(meeting); - } - } -} diff --git a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsEventDetailsTests.cs b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsEventDetailsTests.cs new file mode 100644 index 0000000000..5c9c6a0076 --- /dev/null +++ b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsEventDetailsTests.cs @@ -0,0 +1,41 @@ +// Copyright(c) Microsoft Corporation.All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Microsoft.Bot.Schema.Teams; +using Xunit; + +namespace Microsoft.Bot.Schema.Tests.Teams +{ + public class MeetingParticipantsEventDetailsTests + { + [Fact] + public void MeetingParticipantsEventDetailsInits() + { + // Arrange + var user = new TeamsChannelAccount("id", "name", "givenName", "surname", "email", "userPrincipalName"); + var member = new TeamsMeetingMember(user, new UserMeetingDetails { InMeeting = true, Role = "user" }); + var eventMembers = new List() { member }; + + // Act + var meeting = new MeetingParticipantsEventDetails(eventMembers); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + + Assert.StrictEqual(eventMembers, meeting.Members); + } + + [Fact] + public void MeetingParticipantsEventDetailsInitsWithNoArgs() + { + // Act + var meeting = new MeetingParticipantsEventDetails(); + + // Assert + Assert.NotNull(meeting); + Assert.IsType(meeting); + } + } +} diff --git a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs b/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs deleted file mode 100644 index b5234b4305..0000000000 --- a/tests/Microsoft.Bot.Schema.Tests/Teams/MeetingParticipantsRemovedEventDetailsTests.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using Microsoft.Bot.Schema.Teams; -using Xunit; - -namespace Microsoft.Bot.Schema.Tests.Teams -{ - public class MeetingParticipantsRemovedEventDetailsTests - { - [Fact] - public void MeetingParticipantsRemovedEventDetailsInits() - { - // Arrange - var meetingId = "meetingId"; - var meetingJoinUrl = new Uri("http://meetingJoinUrl"); - var meetingTitle = "meetingTitle"; - var meetingType = "meetingType"; - var participant = new TeamsChannelAccount("id", "name", "givenName", "surname", "email", "userPrincipalName"); - var participantsRemoved = new List() { participant }; - - // Act - var meeting = new MeetingParticipantsRemovedEventDetails(meetingId, meetingJoinUrl, meetingTitle, meetingType, participantsRemoved); - - // Assert - Assert.NotNull(meeting); - Assert.IsType(meeting); - Assert.Equal(meetingId, meeting.Id); - Assert.Equal(meetingJoinUrl, meeting.JoinUrl); - Assert.Equal(meetingTitle, meeting.Title); - Assert.Equal(meetingType, meeting.MeetingType); - Assert.StrictEqual(participantsRemoved, meeting.ParticipantsRemoved); - } - - [Fact] - public void MeetingParticipantsRemovedEventDetailsInitsWithNoArgs() - { - // Act - var meeting = new MeetingParticipantsRemovedEventDetails(); - - // Assert - Assert.NotNull(meeting); - Assert.IsType(meeting); - } - } -} From d041084a2ebdd7d20ee41639c39cc577e64d10a8 Mon Sep 17 00:00:00 2001 From: JhontSouth Date: Mon, 14 Aug 2023 10:48:32 -0500 Subject: [PATCH 4/5] clean participants models --- .../Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs b/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs index 25d94bcdf2..eddca61cc6 100644 --- a/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs +++ b/libraries/Microsoft.Bot.Schema/Teams/TeamsMeetingMember.cs @@ -6,7 +6,7 @@ namespace Microsoft.Bot.Schema.Teams { /// - /// Data about the joined meeting participants. + /// Data about the meeting participants. /// public partial class TeamsMeetingMember { @@ -22,7 +22,7 @@ public TeamsMeetingMember(TeamsChannelAccount user, UserMeetingDetails meeting) } /// - /// Gets or sets the joined meeting participant. + /// Gets or sets the meeting participant. /// /// /// The joined participant account. @@ -31,10 +31,10 @@ public TeamsMeetingMember(TeamsChannelAccount user, UserMeetingDetails meeting) public TeamsChannelAccount User { get; set; } /// - /// Gets or sets the joined users meeting details. + /// Gets or sets the user meeting details. /// /// - /// The joined users meeting details. + /// The users meeting details. /// [JsonProperty(PropertyName = "Meeting")] public UserMeetingDetails Meeting { get; set; } From 0798135c2013da81a6baa41b02407d34e98b0a31 Mon Sep 17 00:00:00 2001 From: JhontSouth Date: Mon, 14 Aug 2023 11:05:14 -0500 Subject: [PATCH 5/5] formar members object --- .../Teams/TeamsActivityHandlerTests.cs | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs index adedab0f4d..4cc3263efb 100644 --- a/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs +++ b/tests/Microsoft.Bot.Builder.Tests/Teams/TeamsActivityHandlerTests.cs @@ -1281,8 +1281,18 @@ public async Task TestMeetingParticipantsJoinEvent() Name = "application/vnd.microsoft.meetingParticipantJoin", Value = JObject.Parse(@"{ Members: [ - {User: {Id: 'id', Name: 'name'}, - Meeting: {Role: 'role', InMeeting: true}} + { + User: + { + Id: 'id', + Name: 'name' + }, + Meeting: + { + Role: 'role', + InMeeting: true + } + } ] }"), }; @@ -1319,8 +1329,18 @@ public async Task TestMeetingParticipantsLeaveEvent() Name = "application/vnd.microsoft.meetingParticipantLeave", Value = JObject.Parse(@"{ Members: [ - {User: {Id: 'id', Name: 'name'}, - Meeting: {Role: 'role', InMeeting: false}} + { + User: + { + Id: 'id', + Name: 'name' + }, + Meeting: + { + Role: 'role', + InMeeting: true + } + } ] }"), };