Example #1
0
        public async Task CreateConversastionOverloadProperlySetsTenantId()
        {
            // Arrange
            const string ActivityIdName      = "ActivityId";
            const string ActivityIdValue     = "SendActivityId";
            const string ConversationIdName  = "Id";
            const string ConversationIdValue = "NewConversationId";
            const string TenantIdValue       = "theTenantId";
            const string EventActivityName   = "CreateConversation";

            Func <Task <HttpResponseMessage> > createResponseMessage = async() =>
            {
                var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                response.Content = new StringContent(new JObject {
                    { ActivityIdName, ActivityIdValue }, { ConversationIdName, ConversationIdValue }
                }.ToString());
                return(response);
            };

            var mockCredentialProvider = new Mock <ICredentialProvider>();
            var mockHttpMessageHandler = new Mock <HttpMessageHandler>();

            mockHttpMessageHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns((HttpRequestMessage request, CancellationToken cancellationToken) => createResponseMessage());

            var httpClient = new HttpClient(mockHttpMessageHandler.Object);

            var adapter = new BotFrameworkAdapter(mockCredentialProvider.Object, customHttpClient: httpClient);

            var activity = new Activity("test")
            {
                ChannelId   = Channels.Msteams,
                ServiceUrl  = "https://fake.service.url",
                ChannelData = new JObject
                {
                    ["tenant"] = new JObject
                    {
                        ["id"] = TenantIdValue
                    },
                },
                Conversation = new ConversationAccount
                {
                    TenantId = TenantIdValue
                },
            };

            var parameters = new ConversationParameters()
            {
                Activity = new Activity()
                {
                    ChannelData = activity.ChannelData,
                },
            };
            var reference   = activity.GetConversationReference();
            var credentials = new MicrosoftAppCredentials(string.Empty, string.Empty, httpClient);

            Activity newActivity = null;

            Task UpdateParameters(ITurnContext turnContext, CancellationToken cancellationToken)
            {
                newActivity = turnContext.Activity;
                return(Task.CompletedTask);
            }

            // Act
            await adapter.CreateConversationAsync(activity.ChannelId, activity.ServiceUrl, credentials, parameters, UpdateParameters, reference, new CancellationToken());

            // Assert - all values set correctly
            Assert.AreEqual(TenantIdValue, JObject.FromObject(newActivity.ChannelData)["tenant"]["tenantId"]);
            Assert.AreEqual(ActivityIdValue, newActivity.Id);
            Assert.AreEqual(ConversationIdValue, newActivity.Conversation.Id);
            Assert.AreEqual(TenantIdValue, newActivity.Conversation.TenantId);
            Assert.AreEqual(EventActivityName, newActivity.Name);
        }
Example #2
0
        /// <summary>
        /// Process incoming Service Bus messages, and create a new conversation with the user.
        /// This will call <see cref="MessageCallback(T, UserInfoEntity)"/> when teh new conversation was successfuly created.
        /// </summary>
        /// <param name="message">Service Bus message object.</param>
        /// <param name="cancellationToken" >(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>Task.</returns>
        private async Task ProcessMessagesAsync(Message message, CancellationToken cancellationToken)
        {
            var json          = Encoding.UTF8.GetString(message.Body);
            var parsedMessage = JsonConvert.DeserializeObject <T>(json);

            var logProperties = JsonConvert.DeserializeObject <Dictionary <string, string> >(json);

            logProperties.Add("ProactiveMessageType", GetType().Name);
            logProperties.Add("ServiceBusSequenceNumber", message.SystemProperties.SequenceNumber.ToString());

            var userInfos = await _table.RetrieveUserInfoAsync(parsedMessage.UserId);

            if (userInfos == null || userInfos.Count == 0)
            {
                await _queueClient.CompleteAsync(message.SystemProperties.LockToken);

                _telemetryClient.TrackEvent(
                    "Failed to send bot proactive message: User was not found in the bot's database.",
                    logProperties);
            }

            if (!_env.IsProduction())
            {
                userInfos = userInfos.Where(i => i.ChannelId == ChannelIds.Emulator).ToList();
            }

            foreach (var userInfo in userInfos)
            {
                try
                {
                    await _botFrameworkAdapter.CreateConversationAsync(
                        userInfo.ChannelId,
                        userInfo.ServiceUrl,
                        new MicrosoftAppCredentials(_endpoint.AppId, _endpoint.AppPassword),
                        new ConversationParameters(bot : userInfo.Bot, members : new List <ChannelAccount> {
                        userInfo.User
                    }, channelData : userInfo.ChannelData),
                        MessageCallback(parsedMessage, userInfo),
                        cancellationToken);

                    // Same with an existing conversation
                    // var conversation = new ConversationReference(
                    //   null,
                    //   userInfo.User,
                    //   userInfo.Bot,
                    //   new ConversationAccount(null, null, userInfo.CurrentConversation.Conversation.Id, null, null, null),
                    //   userInfo.ChannelId,
                    //   userInfo.ServiceUrl);
                    // await _botFrameworkAdapter.ContinueConversationAsync(_endpoint.AppId, conversation, MessageCallback(), cancellationToken);
                }
                catch (ErrorResponseException e)
                {
                    _telemetryClient.TrackException(
                        e,
                        new Dictionary <string, string>
                    {
                        { "Error message", e.Message },
                        { "Response body", e.Response.Content },
                        { "Request body", e.Request.Content },
                        { "Request uri", $"{e.Request.Method.ToString()} {e.Request.RequestUri.AbsoluteUri}" },
                        { "Request headers", e.Request.Headers.ToJson() },
                    });
                }
                catch (Exception e)
                {
                    _telemetryClient.TrackException(e);
                }
            }

            // Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed.
            // If queueClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
            // to avoid unnecessary exceptions.
            //
            // Complete the message so that it is not received again.
            // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
            await _queueClient.CompleteAsync(message.SystemProperties.LockToken);

            _telemetryClient.TrackEvent(
                "Proactive message sent by bot.",
                logProperties,
                new Dictionary <string, double>
            {
                { "Proactive message", 1 },
                { $"Proactive{GetType().Name}", 1 },
            });
        }