示例#1
0
        public override async Task Execute(CancellationToken cancellationToken)
        {
            string returnText = "Your [GivenName] [Surname] working from Tenant: [TenantId]";

            try
            {
                IList <ChannelAccount> teamMembers = (await TurnContext.TurnState.Get <IConnectorClient>().Conversations
                                                      .GetConversationMembersAsync(TurnContext.Activity.GetChannelData <TeamsChannelData>().Team.Id)
                                                      .ConfigureAwait(false));

                foreach (ChannelAccount ca in teamMembers)
                {
                    MicrosoftTeamUser u = Newtonsoft.Json.JsonConvert.DeserializeObject <MicrosoftTeamUser>(ca.Properties.ToString());

                    if (u.ObjectId == TurnContext.Activity.From.AadObjectId)
                    {
                        returnText = returnText.Replace("[ObjectId]", u.ObjectId);
                        returnText = returnText.Replace("[UserPrincipalName]", u.UserPrincipalName);
                        returnText = returnText.Replace("[GivenName]", u.GivenName);
                        returnText = returnText.Replace("[Surname]", u.Surname);
                        returnText = returnText.Replace("[TenantId]", u.TenantId);
                    }
                }
            }
            catch (Exception ex)
            {
                returnText = "The Command returned the following error: " + ex.Message;
            }

            await TurnContext.SendActivityAsync(MessageFactory.Text(returnText), cancellationToken);
        }
示例#2
0
        public async Task AllowInterceptionOfDeliveryOnSend()
        {
            bool responsesSent = false;

            void ValidateResponses(Activity[] activities)
            {
                responsesSent = true;
                Assert.True(false); // Should not be called. Interceptor did not work
            }

            var a = new SimpleAdapter(ValidateResponses);
            var c = new TurnContext(a, new Activity());

            int count = 0;

            c.OnSendActivities((context, activities, next) =>
            {
                Assert.NotNull(activities); // Null Array passed in
                count = activities.Count();

                // Do not call next.
                return(Task.FromResult <ResourceResponse[]>(null));
            });

            await c.SendActivityAsync(TestMessage.Message());

            Assert.True(count == 1);
            Assert.False(responsesSent, "Responses made it to the adapter.");
        }
示例#3
0
        public async Task InterceptAndMutateOnSend()
        {
            bool foundIt = false;

            void ValidateResponses(Activity[] activities)
            {
                Assert.NotNull(activities);
                Assert.True(activities.Length == 1);
                Assert.True(activities[0].Id == "changed");
                foundIt = true;
            }

            var a = new SimpleAdapter(ValidateResponses);
            var c = new TurnContext(a, new Activity());

            c.OnSendActivities(async(context, activities, next) =>
            {
                Assert.NotNull(activities); // Null Array passed in
                Assert.True(activities.Count() == 1);
                Assert.True(activities[0].Id == "1234", "Unknown Id Passed In");
                activities[0].Id = "changed";
                return(await next());
            });

            await c.SendActivityAsync(TestMessage.Message());

            // Intercepted the message, changed it, and sent it on to the Adapter
            Assert.True(foundIt);
        }
示例#4
0
        public async Task TraceActivitiesDoNoSetResponded()
        {
            var a = new SimpleAdapter();
            var c = new TurnContext(a, new Activity());

            Assert.False(c.Responded);

            // Send a Trace Activity, and make sure responded is NOT set.
            var trace = Activity.CreateTraceActivity("trace");
            await c.SendActivityAsync(trace);

            Assert.False(c.Responded);

            // Just to sanity check everything, send a Message and verify the
            // responded flag IS set.
            var msg = TestMessage.Message().AsMessageActivity();
            await c.SendActivityAsync(msg);

            Assert.True(c.Responded);
        }
示例#5
0
        public async Task SendAndSetResponded()
        {
            var a = new SimpleAdapter();
            var c = new TurnContext(a, new Activity());

            Assert.False(c.Responded);
            var response = await c.SendActivityAsync(TestMessage.Message("testtest"));

            Assert.True(c.Responded);
            Assert.True(response.Id == "testtest");
        }
示例#6
0
        public async Task SendAndSetRespondedUsingIMessageActivity()
        {
            var a = new SimpleAdapter();
            var c = new TurnContext(a, new Activity());

            Assert.False(c.Responded);

            var msg = TestMessage.Message().AsMessageActivity();
            await c.SendActivityAsync(msg);

            Assert.True(c.Responded);
        }
        public async Task ProcessActivityAsync(Activity activity, string msAppId, ConversationReference conversationRef, BotCallbackHandler callback, CancellationToken cancellationToken)
        {
            BotAssert.ActivityNotNull(activity);

            activity.ApplyConversationReference(conversationRef, true);

            await ContinueConversationAsync(
                msAppId,
                conversationRef,
                async (ITurnContext proactiveContext, CancellationToken ct) =>
            {
                using (var contextWithActivity = new TurnContext(this, activity))
                {
                    contextWithActivity.TurnState.Add(proactiveContext.TurnState.Get <IConnectorClient>());
                    await base.RunPipelineAsync(contextWithActivity, callback, cancellationToken);

                    if (contextWithActivity.Activity.Name == "handoff.status")
                    {
                        var conversationStateAccessors = _conversationState.CreateProperty <LoggingConversationData>(nameof(LoggingConversationData));
                        var conversationData           = await conversationStateAccessors.GetAsync(contextWithActivity, () => new LoggingConversationData());

                        Activity replyActivity;
                        var state = (contextWithActivity.Activity.Value as JObject)?.Value <string>("state");
                        if (state == "typing")
                        {
                            replyActivity = new Activity
                            {
                                Type = ActivityTypes.Typing,
                                Text = "agent is typing",
                            };
                        }
                        else if (state == "accepted")
                        {
                            replyActivity = MessageFactory.Text("An agent has accepted the conversation and will respond shortly.");
                            await _conversationState.SaveChangesAsync(contextWithActivity);
                        }
                        else if (state == "completed")
                        {
                            replyActivity = MessageFactory.Text("The agent has closed the conversation.");
                        }
                        else
                        {
                            replyActivity = MessageFactory.Text($"Conversation status changed to '{state}'");
                        }

                        await contextWithActivity.SendActivityAsync(replyActivity);
                    }
                }
            },
                cancellationToken).ConfigureAwait(false);
        }
示例#8
0
        public async Task SendOneActivityToAdapter()
        {
            bool foundActivity = false;

            void ValidateResponses(Activity[] activities)
            {
                Assert.True(activities.Count() == 1, "Incorrect Count");
                Assert.True(activities[0].Id == "1234");
                foundActivity = true;
            }

            var a = new SimpleAdapter(ValidateResponses);
            var c = new TurnContext(a, new Activity());
            await c.SendActivityAsync(TestMessage.Message());

            Assert.True(foundActivity);
        }
示例#9
0
        public async Task CallOnSendBeforeDelivery()
        {
            var a = new SimpleAdapter();
            var c = new TurnContext(a, new Activity());

            int count = 0;

            c.OnSendActivities(async(context, activities, next) =>
            {
                Assert.NotNull(activities); // Null Array passed in
                count = activities.Count();
                return(await next());
            });

            await c.SendActivityAsync(TestMessage.Message());

            Assert.True(count == 1);
        }
示例#10
0
        public async Task PassResourceResponsesThrough()
        {
            void ValidateResponses(Activity[] activities)
            {
                // no need to do anything.
            }

            var a = new SimpleAdapter(ValidateResponses);
            var c = new TurnContext(a, new Activity());

            var activityId = Guid.NewGuid().ToString();
            var activity   = TestMessage.Message();

            activity.Id = activityId;

            var resourceResponse = await c.SendActivityAsync(activity);

            Assert.IsTrue(resourceResponse.Id == activityId, "Incorrect response Id returned");
        }
示例#11
0
        public async Task ThrowExceptionInOnSend()
        {
            var a = new SimpleAdapter();
            var c = new TurnContext(a, new Activity());

            c.OnSendActivities((context, activities, next) =>
            {
                throw new Exception("test");
            });

            try
            {
                await c.SendActivityAsync(TestMessage.Message());

                Assert.True(false); // Should not get here
            }
            catch (Exception ex)
            {
                Assert.True(ex.Message == "test");
            }
        }
示例#12
0
        public async Task OutgoingActivityIdsAreNotSent()
        {
            // Arrange
            var mockCredentialProvider = new Mock <ICredentialProvider>();
            var mockConnector          = new MemoryConnectorClient();
            var mockHttpMessageHandler = new Mock <HttpMessageHandler>();
            var httpClient             = new HttpClient(mockHttpMessageHandler.Object);
            var adapter = new BotFrameworkAdapter(mockCredentialProvider.Object, customHttpClient: httpClient);

            var incomingActivity = new Activity("test")
            {
                Id           = "testid",
                ChannelId    = Channels.Directline,
                ServiceUrl   = "https://fake.service.url",
                Conversation = new ConversationAccount
                {
                    Id = "cid",
                }
            };

            var reply = MessageFactory.Text("test");

            reply.Id = "TestReplyId";

            // Act
            using (var turnContext = new TurnContext(adapter, incomingActivity))
            {
                turnContext.TurnState.Add <IConnectorClient>(mockConnector);

                var responseIds = await turnContext.SendActivityAsync(reply, default);
            }

            var sentActivity = mockConnector.MemoryConversations.SentActivities.FirstOrDefault(f => f.Type == ActivityTypes.Message);

            // Assert - assert the reply's id is not sent
            Assert.IsNull(sentActivity.Id);
        }
        public override async Task Execute(CancellationToken cancellationToken)
        {
            QueryExpression q = new QueryExpression("contact");

            q.ColumnSet = new ColumnSet("fullname", "firstname", "lastname", "jobtitle", "mobilephone", "emailaddress1", "telephone1");
            q.Criteria.FilterOperator = LogicalOperator.And;

            // get the contacts for the Account that matches our current Channel
            LinkEntity le = new LinkEntity("contact", "account", "parentcustomerid", "accountid", JoinOperator.Inner);

            le.LinkCriteria.AddCondition("crmcs_msteams_channelid", ConditionOperator.Equal, base.ChannelId);
            q.LinkEntities.Add(le);

            if (!String.IsNullOrEmpty(base.ValueTitle))
            {
                FilterExpression f = new FilterExpression();
                f.FilterOperator = LogicalOperator.Or;
                f.AddCondition("fullname", ConditionOperator.Like, "%" + base.ValueTitle + "%");
                q.Criteria.AddFilter(f);
            }
            else
            {
                // just get all the Contacts back
            }

            EntityCollection contacts = base.DynamicsService.RetrieveMultiple(q);

            if (contacts.Entities.Count == 0)
            {
                // nothing to return
                await TurnContext.SendActivityAsync(MessageFactory.Text("Sorry - I couldn't find any matching contacts"), cancellationToken);
            }
            else
            {
                var card = new ListCard();

                card.content = new Content();
                List <Item> items  = new List <Item>();
                int         itemNo = 0;

                // loop through the information we have and display into Teams
                foreach (Microsoft.Xrm.Sdk.Entity c in contacts.Entities)
                {
                    string openUrl  = string.Empty;
                    string subTitle = string.Empty;
                    openUrl = base.ToDynamicsConnection.dynamicsUrl + "/main.aspx?forceUCI=1&etn=" + "contact" + "&id=" + c.Id + "&pagetype=entityrecord";

                    var item = new Item();
                    item.id    = itemNo.ToString();
                    item.type  = "resultItem";
                    item.title = c.GetValue <string>("fullname", string.Empty);

                    // quick routine to summarise the attributes from Dynamics as an Info List in Teams
                    if (c.Contains("jobtitle"))
                    {
                        subTitle += "<p><b>Job Title:</b> " + c.GetValue("jobtitle", string.Empty) + "</p>";
                    }
                    if (c.Contains("mobilephone"))
                    {
                        subTitle += "<p><b>Mobille:</b> " + c.GetValue("mobilephone", string.Empty) + "</p>";
                    }
                    else
                    {
                        // only show telephone if mobile is blank
                        if (c.Contains("telephone1"))
                        {
                            subTitle += "<p><b>Telephone:</b> " + c.GetValue("telephone1", string.Empty) + "</p>";
                        }
                    }
                    if (c.Contains("emailaddress1"))
                    {
                        subTitle += "<p><b>Email Address:</b> " + c.GetValue("emailaddress1", string.Empty) + "</p>";
                    }
                    item.subtitle = subTitle;

                    openUrl = openUrl.Replace(" ", "%20");

                    item.tap = new Tap()
                    {
                        type  = "openUrl",
                        value = openUrl
                    };

                    itemNo++;

                    items.Add(item);
                }

                card.content.items = items.ToArray();

                Attachment attachment = new Attachment();
                attachment.ContentType = card.contentType;
                attachment.Content     = card.content;

                await TurnContext.SendActivityAsync(MessageFactory.Attachment(attachment));
            }
        }
示例#14
0
 public async Task SendTextAsync(string textActivity)
 {
     await TurnContext.SendActivityAsync(MessageFactory.Text(textActivity), CancellationToken);
 }
示例#15
0
        public override async Task Execute(CancellationToken cancellationToken)
        {
            QueryExpression q = new QueryExpression(this.Table);

            // determine what columns to pull back from Dynamics
            q.ColumnSet = new ColumnSet();
            foreach (ColumnDefinition ra in this.Columns)
            {
                q.ColumnSet.AddColumn(ra.DatabaseName);
            }

            q.Criteria.FilterOperator = LogicalOperator.And;
            q.Criteria.AddCondition("statecode", ConditionOperator.Equal, 0);

            // get the contacts for the Account that matches our current Channel
            LinkEntity le = new LinkEntity(this.Table, "account", this.RelationshipToAccount, "accountid", JoinOperator.Inner);

            le.LinkCriteria.AddCondition("crmcs_msteams_channelid", ConditionOperator.Equal, base.ChannelId);
            q.LinkEntities.Add(le);

            if (!String.IsNullOrEmpty(base.ValueTitle))
            {
                FilterExpression f = new FilterExpression();
                f.FilterOperator = LogicalOperator.Or;

                foreach (ColumnDefinition ra in this.Columns)
                {
                    if (ra.Searchable)
                    {
                        f.AddCondition(ra.DatabaseName, ConditionOperator.Like, "%" + base.ValueTitle + "%");
                    }
                }
                q.Criteria.AddFilter(f);
            }
            else
            {
                // just get all the Contacts back
            }

            EntityCollection records = base.DynamicsService.RetrieveMultiple(q);

            if (records.Entities.Count == 0)
            {
                // nothing to return
                await TurnContext.SendActivityAsync(MessageFactory.Text("Sorry - I couldn't find any matching records"), cancellationToken);
            }
            else
            {
                var card = new ListCard();

                card.content = new Content();
                List <Item> items  = new List <Item>();
                int         itemNo = 0;

                // loop through the information we have and display into Teams
                foreach (Microsoft.Xrm.Sdk.Entity c in records.Entities)
                {
                    string openUrl  = string.Empty;
                    string title    = string.Empty;
                    string subTitle = string.Empty;
                    openUrl = base.ToDynamicsConnection.dynamicsUrl + "/main.aspx?forceUCI=1&etn=" + this.Table + "&id=" + c.Id + "&pagetype=entityrecord";

                    // note - this is simplifed to be a good example
                    // if you were taking this to production - you would look at the Metadata Service to avoid manual entry of the
                    foreach (ColumnDefinition ra in this.Columns)
                    {
                        if (ra.Title == true)
                        {
                            if (!String.IsNullOrEmpty(title))
                            {
                                title += ", ";
                            }
                            title += c.GetValue <string>(ra.DatabaseName, string.Empty);
                        }
                        else
                        {
                            // quick routine to summarise the attributes from Dynamics as an Info List in Teams
                            if (c.Contains(ra.DatabaseName))
                            {
                                if (!String.IsNullOrEmpty(ra.DisplayName))
                                {
                                    subTitle += "<p><b>" + ra.DisplayName + ":</b> " + c.GetValue(ra.DatabaseName, string.Empty) + "</p>";
                                }
                                else
                                {
                                    // sometimes we may want a description field shown as a Memo and avoid a Column Title
                                    subTitle += "<p>" + c.GetValue(ra.DatabaseName, string.Empty) + "</p>";
                                }
                            }
                        }
                    }

                    var item = new Item();
                    item.id       = itemNo.ToString();
                    item.type     = "resultItem";
                    item.title    = title;
                    item.subtitle = subTitle;

                    // needed for Teams to process the URL as an Action correctly
                    openUrl = openUrl.Replace(" ", "%20");

                    item.tap = new Tap()
                    {
                        type  = "openUrl",
                        value = openUrl
                    };

                    itemNo++;

                    items.Add(item);
                }

                card.content.items = items.ToArray();

                Attachment attachment = new Attachment();
                attachment.ContentType = card.contentType;
                attachment.Content     = card.content;

                await TurnContext.SendActivityAsync(MessageFactory.Attachment(attachment));
            }
        }
 public override async Task Execute(CancellationToken cancellationToken)
 {
     await TurnContext.SendActivityAsync(MessageFactory.Text("Finished the Example Action!"), cancellationToken);
 }
示例#17
0
        public override async Task Execute(CancellationToken cancellationToken)
        {
            // our first step is to parse the user's input from Teams
            // we can do this in multiple ways
            // and ideally could use a Task in Teams or a Simple Form to collect the information
            // but if we want a quick flowing command from a Bot that avoids Fields and Data Types, we can do it this way
            // Parse the input from the User in the following steps:
            // (1) Remove the Command Name from the incoming Command
            // (2) Divide the command by a comma (,) or semi-colon (;)
            // (3) Interpret the first section of the Command as the Title
            // (4) Interpret the second section as the Description
            // This is not as good as it could be - we could use better data in Teams - or use follow-up commands to further detail the Record
            // we are creating in Dynamics (and so allowing a CREATE then UPDATE style approach)
            // but gives a simple interface to use when say capturing Tasks or Cases from a Meeting in quick time

            HttpClient         client     = new HttpClient();
            HttpRequestMessage webRequest =
                new HttpRequestMessage(new System.Net.Http.HttpMethod("POST"), FlowHttpTrigger);
            string requestJSON = string.Empty;

            try
            {
                FlowRequest request = new FlowRequest();

                request.TeamId         = base.TeamId;
                request.ChannelId      = base.ChannelId;
                request.UserId         = string.Empty;
                request.ConversationId = base.ConversationId;
                request.Content        = base.ValueTitle;
                request.Description    = base.ValueDescription;

                requestJSON = request.ToJSON();
                if (!string.IsNullOrEmpty(requestJSON))
                {
                    webRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    //webRequest.Headers.Add("content-type", "application/json");
                    webRequest.Content = new StringContent(requestJSON, Encoding.UTF8, "application/json");
                }

                if (!String.IsNullOrEmpty(_startingMessage))
                {
                    TurnContext.SendActivityAsync(MessageFactory.Text(_startingMessage), cancellationToken);
                }
            }
            catch (Exception prepEx)
            {
                // error calling out to the Flow Http Trigger
                await TurnContext.SendActivityAsync(MessageFactory.Text("Error whilst building the Request: " + prepEx.Message), cancellationToken);
            }

            try
            {
                HttpResponseMessage webResponse = await client.SendAsync(webRequest).ConfigureAwait(false);

                FlowResponse response = null;

                string responseContent = "No Response";

                if (webResponse.Content != null)
                {
                    responseContent = await webResponse.Content.ReadAsStringAsync().ConfigureAwait(false);

                    // response = Newtonsoft.Json.JsonConvert.DeserializeObject<FlowResponse>(responseContent);
                }

                if (response != null)
                {
                    // do something with the response from outcome of our Flow?
                }

                if (_debugMode)
                {
                    await TurnContext.SendActivityAsync(MessageFactory.Text("Response from Flow: " + responseContent + " - RequestJSON: " + requestJSON), cancellationToken);
                }
            }
            catch (Exception ex)
            {
                // error calling out to the Flow Http Trigger
                await TurnContext.SendActivityAsync(MessageFactory.Text("Error when placing the Request to Flow: " + ex.Message), cancellationToken);
            }

            if (!String.IsNullOrEmpty(_finishingMessage))
            {
                TurnContext.SendActivityAsync(MessageFactory.Text(_finishingMessage), cancellationToken);
            }
        }
示例#18
0
 public static async Task Send(string id)
 {
     Context.Activity.Conversation.Id = id;
     await Context.SendActivityAsync("abc");
 }
示例#19
0
        public override async Task Execute(CancellationToken cancellationToken)
        {
            string output = "Finished the Example Action at " + DateTime.Now.ToString("dd/MM/YYYY") + ".";

            await TurnContext.SendActivityAsync(MessageFactory.Text(output), cancellationToken);
        }