예제 #1
0
        /// <inheritdoc />
        public override async Task <DialogTurnResult> ExecuteAsync(DialogContext dc, CancellationToken cancellationToken)
        {
            string message = dc.Context.Activity.Text.ToLowerInvariant();

            var strings = message.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);

            var mobileNumber = strings[1];

            var trigger = new IncomingSms
            {
                Id                      = Guid.NewGuid().ToString(),
                SourceNumber            = mobileNumber,
                DestinationNumber       = null,
                Message                 = "bot--dialog--start afb-v6",
                DateReceived            = DateTime.UtcNow,
                UniqueLearnerNumber     = "uln_here",
                ApprenticeshipStartDate = DateTime.Now.AddYears(-1),
                StandardCode            = 23,
            };

            var queueMessage = new SmsIncomingMessage(trigger);

            await this.queue.SendAsync(dc.Context.Activity.Conversation.Id, queueMessage, this.notifyConfig.IncomingMessageQueueName);

            await dc.Context.SendActivityAsync($"OK. Sending survey to {mobileNumber}", cancellationToken : cancellationToken);

            return(await dc.ContinueDialogAsync(cancellationToken));
        }
        internal static BotMessage CreateMessage(string phoneNumber, string message)
        {
            var sms = new IncomingSms()
            {
                DateReceived =
                    DateTime.UtcNow,
                DestinationNumber = "00000000000",
                SourceNumber      = phoneNumber,
                Message           = message
            };

            var msg = new BotMessage();

            dynamic channelData = new ExpandoObject();

            channelData.NotifyMessage = sms;

            dynamic from = new ExpandoObject();

            from.Id = sms.SourceNumber;

            msg.ChannelData = channelData;
            msg.From        = from;

            return(msg);
        }
        public async Task HandleAsync(TriggerSurveyInvitesCommand command, CancellationToken cancellationToken = default(CancellationToken))
        {
            var batchSize         = _settingService.GetInt("ApprenticeBatchSize");
            var apprenticeDetails = await _surveyDetailsRepo.GetApprenticeSurveyInvitesAsync(batchSize);

            foreach (var apprenticeDetail in apprenticeDetails)
            {
                var now     = DateTime.Now;
                var trigger = new IncomingSms()
                {
                    Type                    = SmsType.SurveyInvitation,
                    Id                      = Guid.NewGuid().ToString(),
                    SourceNumber            = apprenticeDetail.MobileNumber.ToString(),
                    DestinationNumber       = null,
                    Message                 = $"bot--dialog--start {apprenticeDetail.SurveyCode}",
                    DateReceived            = now,
                    UniqueLearnerNumber     = apprenticeDetail.UniqueLearnerNumber,
                    StandardCode            = apprenticeDetail.StandardCode,
                    ApprenticeshipStartDate = apprenticeDetail.ApprenticeshipStartDate
                };

                await _surveyDetailsRepo.SetApprenticeSurveySentAsync(apprenticeDetail.Id);

                try
                {
                    var serviceBusMessage = new SmsIncomingMessage(trigger);
                    await _queueClient.SendAsync(serviceBusMessage);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Failed to put message on the queue for apprentice survey detail id: {apprenticeDetail.Id}. Reverting survey sent status");
                    await _surveyDetailsRepo.SetApprenticeSurveyNotSentAsync(apprenticeDetail.Id);
                }
            }
        }
        private static async Task PostToConversation(IncomingSms incomingSms, BotConversation conversation, ILogger log)
        {
            log.LogInformation($"Posting message to conversationId {conversation.ConversationId}");

            dynamic from = new ExpandoObject();

            from.id   = incomingSms.SourceNumber;
            from.name = incomingSms.SourceNumber;
            from.role = null;

            dynamic channelData = new ExpandoObject();

            channelData.UniqueLearnerNumber     = conversation.UniqueLearnerNumber;
            channelData.StandardCode            = conversation.StandardCode;
            channelData.ApprenticeshipStartDate = conversation.ApprenticeshipStartDate;
            channelData.NotifyMessage           = new NotifyMessage
            {
                Id                = incomingSms.Id,
                DateReceived      = incomingSms.DateReceived.ToString(CultureInfo.InvariantCulture),
                DestinationNumber = incomingSms.DestinationNumber,
                SourceNumber      = incomingSms.SourceNumber,
                Message           = incomingSms.Message,
                Type              = "callback",
            };

            var messageContent = new BotConversationMessage
            {
                Type        = "message",
                From        = from,
                Text        = incomingSms.Message,
                ChannelData = channelData
            };

            var         json    = JsonConvert.SerializeObject(messageContent);
            HttpContent content = new StringContent(json);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            HttpResponseMessage postMessageTask = await DirectLineClient.PostAsync($"/v3/directline/conversations/{conversation.ConversationId}/activities", content);

            if (postMessageTask.IsSuccessStatusCode)
            {
                string response = await postMessageTask.Content.ReadAsStringAsync();

                dynamic jsonResponse = JsonConvert.DeserializeObject(response);
                log.LogInformation($"Received response from Bot Client: {jsonResponse.id}");
            }
            else
            {
                var message = $"Could not post conversation to DirectLineClient. {postMessageTask.StatusCode}: {postMessageTask.ReasonPhrase}";
                throw new BotConnectorException(message);
            }
        }
        private static async Task StartNewConversation(IncomingSms incomingSms, ILogger log)
        {
            log.LogInformation($"Starting new conversation with {incomingSms.SourceNumber}");

            var content = new StringContent(string.Empty);

            var startConversationTask = await DirectLineClient.PostAsync("/v3/directline/conversations", content);

            var conversation = new BotConversation();

            if (startConversationTask.IsSuccessStatusCode)
            {
                string response = await startConversationTask.Content.ReadAsStringAsync();

                dynamic jsonResponse = JsonConvert.DeserializeObject(response);
                log.LogInformation($"Started new conversation with id {jsonResponse.conversationId}");

                // TODO: write the conversation ID to a session log with the mobile phone number
                conversation.UserId                  = incomingSms.SourceNumber; // TODO: [security] hash this please!
                conversation.ConversationId          = jsonResponse.conversationId;
                conversation.UniqueLearnerNumber     = incomingSms.UniqueLearnerNumber;
                conversation.StandardCode            = incomingSms.StandardCode;
                conversation.ApprenticeshipStartDate = incomingSms.ApprenticeshipStartDate;

                BotConversation newSession = await DocumentClient.UpsertItemAsync(conversation);

                if (newSession == null)
                {
                    var message = $"Could not create session object for conversation id {conversation.ConversationId}";
                    throw new BotConnectorException(message);
                }

                if (incomingSms.Message != null)
                {
                    await PostToConversation(incomingSms, conversation, log);
                }
            }
            else
            {
                var message = $"Could not start new conversation with DirectLineClient. {startConversationTask.StatusCode}: {startConversationTask.ReasonPhrase}";
                throw new BotConnectorException(message);
            }
        }
        public static async Task Run(
            [ServiceBusTrigger("%IncomingMessageQueueName%", Connection = "ServiceBusConnection")]
            string queueMessage,
            [Inject] SettingsProvider configuration,
            ILogger log,
            ExecutionContext context)
        {
            Configuration  = configuration;
            currentContext = context;
            IncomingSms incomingSms = JsonConvert.DeserializeObject <IncomingSms>(queueMessage);

            try
            {
                log.LogInformation($"Response received from {incomingSms.SourceNumber}, sending to bot...");

                string userId = incomingSms.SourceNumber; // TODO: [security] hash me please!
                // If we key this on unique survey to user then we can have different conversationId's per survey run for the same number
                BotConversation conversation = await GetConversationByUserId(userId);

                if (conversation == null)
                {
                    await StartNewConversation(incomingSms, log);
                }
                else
                {
                    await PostToConversation(incomingSms, conversation, log);
                }
            }
            catch (MessageLockLostException e)
            {
                log.LogError($"DeliverMessageToBot MessageLockLostException [{context.FunctionName}|{context.InvocationId}]", e, e.Message);
            }
            catch (Exception e)
            {
                log.LogError($"DeliverMessageToBot ERROR: {e.Message}", e, e.Message);
                DirectLineClient.CancelPendingRequests();
                throw new BotConnectorException("Something went wrong when relaying the message to the bot framework", e);
            }
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
            HttpRequest req,
            [ServiceBus("%IncomingMessageQueueName%", Connection = "ServiceBusConnection", EntityType = Microsoft.Azure.WebJobs.ServiceBus.EntityType.Queue)]
            IAsyncCollector <IncomingSms> queue,
            ILogger log,
            ExecutionContext context)
        {
            try
            {
                string      requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                IncomingSms receivedSms = JsonConvert.DeserializeObject <IncomingSms>(requestBody);
                receivedSms.Type = SmsType.NotifySms;

                log.LogInformation($"Message received from {receivedSms.SourceNumber}");

                if (receivedSms.Message == null || receivedSms.DestinationNumber == null || receivedSms.SourceNumber == null)
                {
                    return(new BadRequestObjectResult(
                               "Expecting a text message payload. Please see the Notify callback documentation for details: https://www.notifications.service.gov.uk/callbacks"));
                }

                await queue.AddAsync(receivedSms);

                return(new OkObjectResult(receivedSms));
            }
            catch (MessageLockLostException e)
            {
                log.LogError($"ReceiveNotifyMessage MessageLockLostException [{context.FunctionName}|{context.InvocationId}]", e, e.Message);
                return(new ExceptionResult(e, true));
            }
            catch (Exception e)
            {
                log.LogError($"ReceiveNotifyMessage ERROR: {e.Message}", e, e.Message);
                return(new ExceptionResult(e, true));
            }
        }
 public SmsIncomingMessage(IncomingSms trigger) : base(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(trigger)))
 {
 }