/// <summary>
        /// Activity Handler for Meeting end event
        /// </summary>
        /// <param name="meeting"></param>
        /// <param name="turnContext"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected override async Task OnTeamsMeetingEndAsync(MeetingEndEventDetails meeting, ITurnContext <IEventActivity> turnContext, CancellationToken cancellationToken)
        {
            var conversationStateAccessors = _conversationState.CreateProperty <MeetingData>(nameof(MeetingData));
            var conversationData           = await conversationStateAccessors.GetAsync(turnContext, () => new MeetingData());

            await turnContext.SendActivityAsync(MessageFactory.Attachment(GetAdaptiveCardForMeetingEnd(meeting, conversationData)));
        }
 /// <summary>
 /// Invoked when a Teams Meeting End event activity is received from the connector.
 /// Override this in a derived class to provide logic for when a meeting is ended.
 /// </summary>
 /// <param name="meeting">The details of the meeting.</param>
 /// <param name="turnContext">A strongly-typed context object for this turn.</param>
 /// <param name="cancellationToken">A cancellation token that can be used by other objects
 /// or threads to receive notice of cancellation.</param>
 /// <returns>A task that represents the work queued to execute.</returns>
 protected virtual Task OnTeamsMeetingEndAsync(MeetingEndEventDetails meeting, ITurnContext <IEventActivity> turnContext, CancellationToken cancellationToken)
 {
     return(Task.CompletedTask);
 }
        /// <summary>
        /// Sample Adaptive card for Meeting End event.
        /// </summary>
        private Attachment GetAdaptiveCardForMeetingEnd(MeetingEndEventDetails meeting, MeetingData conversationData)
        {
            TimeSpan meetingDuration     = meeting.EndTime - conversationData.StartTime;
            var      meetingDurationText = meetingDuration.Minutes < 1 ?
                                           Convert.ToInt32(meetingDuration.Seconds) + "s"
                : Convert.ToInt32(meetingDuration.Minutes) + "min " + Convert.ToInt32(meetingDuration.Seconds) + "s";

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion("1.2"))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock
                    {
                        Text    = meeting.Title + "- ended",
                        Weight  = AdaptiveTextWeight.Bolder,
                        Spacing = AdaptiveSpacing.Medium,
                    },
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Text = "End Time : ",
                                        Wrap = true,
                                    },
                                    new AdaptiveTextBlock
                                    {
                                        Text = "Total duration : ",
                                        Wrap = true,
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Text = Convert.ToString(meeting.EndTime.ToLocalTime()),
                                        Wrap = true,
                                    },
                                    new AdaptiveTextBlock
                                    {
                                        Text = meetingDurationText,
                                        Wrap = true,
                                    },
                                },
                            },
                        },
                    },
                }
            };

            return(new Attachment()
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }