private async Task SendEventMessageAsync(EventMessage eventMessage)
        {
            // Send the message
            try
            {
                await eventMessage.SendAsync(this.connectorClientFactory);

                this.logProvider.LogInfo($"Message {eventMessage.Id} sent successfully");
            }
            catch (Exception ex)
            {
                this.logProvider.LogError($"Failed to send message {eventMessage.Id}", ex, new Dictionary <string, string>
                {
                    { "EventId", eventMessage.EventId },
                    { "OccurrenceId", eventMessage.OccurrenceId },
                    { "ConversationId", eventMessage.Activity.Conversation?.Id },
                    { "LastAttemptTime", DateTimeOffset.UtcNow.ToString() },
                    { "LastAttemptStatusCode", eventMessage.MessageSendResult?.StatusCode.ToString() },
                    { "ResponseBody", eventMessage.MessageSendResult?.ResponseBody },
                });
                throw;
            }
            finally
            {
                // Record the result of the send
                await this.eventDataProvider.UpdateEventMessageAsync(eventMessage);
            }
        }
Пример #2
0
        // Send the list of events as a carousel card
        private async Task SendMultipleEventNotificationsAsync(string teamId, List <EventNotificationData> notifications)
        {
            var firstNotification = notifications.First();

            // Build the attachments and entities
            notifications.Sort((left, right) => StringComparer.InvariantCulture.Compare(left.User.DisplayName, right.User.DisplayName));
            var attachments = notifications
                              .Select(x => x.GetCard())
                              .ToList();
            var entities = notifications
                           .Select(x => x.GetMention())
                           .Distinct(new MentionEqualityComparer())
                           .AsEnumerable <Entity>()
                           .ToList();

            // Build the text message
            string allButLastEvent = string.Join(
                ", ",
                notifications.Take(notifications.Count - 1).Select(x => x.GetMessage()));
            var message = string.Format(Strings.MultipleEventsMessage, allButLastEvent, notifications[notifications.Count - 1].GetMessage());

            // Create the activity
            var activity = new Activity(ActivityTypes.Message)
            {
                Conversation = new ConversationAccount {
                    Id = teamId
                },
                AttachmentLayout = AttachmentLayoutTypes.Carousel,
                Text             = message,
                Summary          = Strings.MultipleEventsSummary,
                Attachments      = attachments,
                Entities         = entities,
                ServiceUrl       = firstNotification.User.ServiceUrl,
            };

            // Add new entry to EventMessages collection for message type "preview" to track the status of message sent
            var eventMessage = new EventMessage
            {
                EventId      = null,    // This is a collection of events, so there is no single event or occurrence ID
                OccurrenceId = null,
                Activity     = activity,
                TenantId     = firstNotification.User.TenantId,
                MessageType  = MessageType.Event,
                ExpireAt     = firstNotification.Occurrence.GetLastAllowableTimeToSendNotification(),
            };

            eventMessage = await this.eventDataProvider.AddEventMessageAsync(eventMessage);

            // Send the message
            try
            {
                await eventMessage.SendAsync(this.connectorClientFactory);

                this.logProvider.LogInfo($"Event notifications sent to {teamId} for events {string.Join(",", notifications.Select(x => x.Event.Id))}");
            }
            catch (Exception ex)
            {
                this.logProvider.LogError($"Failed to send notifications to team {teamId}", ex, new Dictionary <string, string>
                {
                    { "EventId", eventMessage.EventId },
                    { "OccurrenceId", eventMessage.OccurrenceId },
                    { "TeamId", teamId },
                    { "LastAttemptTime", DateTimeOffset.UtcNow.ToString() },
                    { "LastAttemptStatusCode", eventMessage.MessageSendResult?.StatusCode.ToString() },
                    { "ResponseBody", eventMessage.MessageSendResult?.ResponseBody },
                });
                throw;
            }
            finally
            {
                // Record the result of the send
                await this.eventDataProvider.UpdateEventMessageAsync(eventMessage);
            }
        }
Пример #3
0
        // Send the event individually
        private async Task SendSingleEventNotificationAsync(string teamId, EventNotificationData notification)
        {
            // Ideally this should send a single message with text and card, but because of message splitting,
            // such a message is split into two (text-only and card-only). As a workaround, we start a reply chain
            // with the text message, then send the card as a reply to this post.

            // Create the activity
            var activity = new Activity(ActivityTypes.Message)
            {
                Conversation = new ConversationAccount {
                    Id = teamId
                },
                AttachmentLayout = AttachmentLayoutTypes.Carousel,
                Text             = notification.GetMessage(),
                Summary          = Strings.MultipleEventsSummary,
                Attachments      = new List <Attachment> {
                    notification.GetCard()
                },
                Entities = new List <Entity> {
                    notification.GetMention()
                },
                ServiceUrl = notification.User.ServiceUrl,
            };

            // Add new entry to EventMessages collection for message type "preview" to track the status of message sent
            var eventMessage = new EventMessage
            {
                EventId      = notification.Event.Id,
                OccurrenceId = notification.Occurrence.Id,
                Activity     = activity,
                TenantId     = notification.User.TenantId,
                MessageType  = MessageType.Event,
                ExpireAt     = notification.Occurrence.GetLastAllowableTimeToSendNotification(),
            };

            eventMessage = await this.eventDataProvider.AddEventMessageAsync(eventMessage);

            // Send the message
            try
            {
                await eventMessage.SendAsync(this.connectorClientFactory);

                this.logProvider.LogInfo($"Event notifications sent to {teamId} for event {notification.Event.Id}");
            }
            catch (Exception ex)
            {
                this.logProvider.LogError($"Failed to send notifications to team {teamId}", ex, new Dictionary <string, string>
                {
                    { "EventId", eventMessage.EventId },
                    { "OccurrenceId", eventMessage.OccurrenceId },
                    { "TeamId", teamId },
                    { "LastAttemptTime", DateTimeOffset.UtcNow.ToString() },
                    { "LastAttemptStatusCode", eventMessage.MessageSendResult?.StatusCode.ToString() },
                    { "ResponseBody", eventMessage.MessageSendResult?.ResponseBody },
                });
                throw;
            }
            finally
            {
                // Record the result of the send
                await this.eventDataProvider.UpdateEventMessageAsync(eventMessage);
            }
        }
        // Send a messsage to the owner of the given event, reminding them that their event is coming up
        private async Task SendEventReminderAsync(CelebrationEvent celebrationEvent, DateTimeOffset currentDateTimeOffset)
        {
            this.logProvider.LogInfo($"Sending reminder for event {celebrationEvent.Id} (owner={celebrationEvent.OwnerAadObjectId}, date={celebrationEvent.Date.ToShortDateString()})");

            // Determine the next occurrence of the event
            var deliveryTimeZone = TimeZoneInfo.FindSystemTimeZoneById(celebrationEvent.TimeZoneId);
            var currentTimeInDeliveryTimeZone = TimeZoneInfo.ConvertTimeFromUtc(currentDateTimeOffset.UtcDateTime, deliveryTimeZone);
            var upcomingEventDateTime         = Common.GetNextOccurrenceAfterDateTime(celebrationEvent.Date.Add(this.timeToPostPreview), currentTimeInDeliveryTimeZone);
            var upcomingEventDateTimeInUTC    = TimeZoneInfo.ConvertTimeToUtc(upcomingEventDateTime, deliveryTimeZone);

            // Do not send reminder if the next occurrence is not in the window
            var timeUntilNextOccurrence = upcomingEventDateTimeInUTC - currentDateTimeOffset;

            if ((timeUntilNextOccurrence.TotalMinutes < 0) ||
                (upcomingEventDateTimeInUTC - currentDateTimeOffset) > TimeSpan.FromDays(this.daysInAdvanceToSendEventPreview))
            {
                this.logProvider.LogInfo($"Next occurrence of event {celebrationEvent.Id} is not in the next {this.daysInAdvanceToSendEventPreview} days");
                return;
            }

            // Add an entry to Occurrence collection for the event, so we know that we processed it
            var eventOccurrence = new EventOccurrence
            {
                EventId          = celebrationEvent.Id,
                OwnerAadObjectId = celebrationEvent.OwnerAadObjectId,
                DateTime         = upcomingEventDateTimeInUTC,
            };

            eventOccurrence = await this.eventDataProvider.AddEventOccurrenceAsync(eventOccurrence);

            // Do not send reminder if we are within the period specified in the configuration
            if ((upcomingEventDateTimeInUTC - currentDateTimeOffset) < this.minimumTimeToProcessEvent)
            {
                this.logProvider.LogInfo($"Not sending reminder for event {celebrationEvent.Id} which is due in less than {(int)this.minimumTimeToProcessEvent.TotalHours} hours");
                return;
            }

            // Get event owner information
            var user = await this.userManagementHelper.GetUserByAadObjectIdAsync(celebrationEvent.OwnerAadObjectId);

            await this.EnsureConversationWithUserAsync(user);

            // Send reminder of event to the owner
            var previewCard = CelebrationCard.GetPreviewCard(celebrationEvent, eventOccurrence.Id, user.DisplayName);
            var message     = string.Format(Strings.EventPreviewMessageText, user.DisplayName);
            var activity    = new Activity(ActivityTypes.Message)
            {
                Conversation = new ConversationAccount {
                    Id = user.ConversationId
                },
                Recipient = new ChannelAccount {
                    Id = user.TeamsId
                },
                Text        = message,
                Summary     = message,
                Attachments = new List <Attachment> {
                    previewCard.ToAttachment()
                },
                ServiceUrl = user.ServiceUrl,
            };

            // Add new entry to EventMessages collection for message type "preview" to track the status of message sent
            var eventMessage = new EventMessage
            {
                EventId      = celebrationEvent.Id,
                OccurrenceId = eventOccurrence.Id,
                Activity     = activity,
                TenantId     = user.TenantId,
                MessageType  = MessageType.Preview,
                ExpireAt     = upcomingEventDateTimeInUTC.AddHours(24),
            };

            eventMessage = await this.eventDataProvider.AddEventMessageAsync(eventMessage);

            // Send the message
            try
            {
                await eventMessage.SendAsync(this.connectorClientFactory);

                this.logProvider.LogInfo($"Reminder message sent to the owner of event {celebrationEvent.Id}");
            }
            catch (Exception ex)
            {
                this.logProvider.LogError($"Failed to send reminder for event {celebrationEvent.Id}", ex, new Dictionary <string, string>
                {
                    { "EventId", eventMessage.EventId },
                    { "OccurrenceId", eventMessage.OccurrenceId },
                    { "ConversationId", user.ConversationId },
                    { "OccurrenceDateTime", eventOccurrence.DateTime.ToString() },
                    { "LastAttemptTime", DateTimeOffset.UtcNow.ToString() },
                    { "LastAttemptStatusCode", eventMessage.MessageSendResult?.StatusCode.ToString() },
                    { "ResponseBody", eventMessage.MessageSendResult?.ResponseBody },
                });
                throw;
            }
            finally
            {
                // Record the result of the send
                await this.eventDataProvider.UpdateEventMessageAsync(eventMessage);
            }
        }