コード例 #1
0
        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable <object> result)
        {
            var activity = await result as Activity;

            // User message
            string userMessage = activity.Text;

            AdaptiveCards.AdaptiveCard card = MessageHandler.GetCard(userMessage);
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    //Assuming that the api takes the user message as a query paramater
                    string RequestURI = "https://api.apixu.com/v1/forecast.json?key=ae5e72be6f5e41fc81f161958181903&q=" + userMessage;
                    HttpResponseMessage responsemMsg = await client.GetAsync(RequestURI);

                    if (responsemMsg.IsSuccessStatusCode)
                    {
                        var apiResponse = await responsemMsg.Content.ReadAsStringAsync();

                        //Post the API response to bot again
                        // await context.PostAsync($"Response is {apiResponse}");
                        await context.PostAsync(GetMessage(context, card, "Weather card"));
                    }
                }
            }
            catch (Exception ex)
            {
            }
            context.Wait(MessageReceivedAsync);
        }
コード例 #2
0
 /// <summary>
 /// Creates a new attachment from AdaptiveCard.
 /// </summary>
 /// <param name="card"> The instance of AdaptiveCard.</param>
 /// <returns> The generated attachment.</returns>
 public static Attachment ToAttachment(this AdaptiveCards.AdaptiveCard card)
 {
     return(new Attachment
     {
         Content = card,
         ContentType = AdaptiveCards.AdaptiveCard.ContentType,
     });
 }
コード例 #3
0
 public static AdaptiveCard ConvertToUwpCard(AdaptiveCards.AdaptiveCard sharedCard)
 {
     if (sharedCard == null)
     {
         return(null);
     }
     return(Parse(sharedCard.ToJson()));
 }
コード例 #4
0
        public async void Update(AdaptiveBlockContent block, AdaptiveBlock sourceBlock, PreviewBlockHostViewModel args)
        {
            this.Children.Clear();

            try
            {
                AdaptiveCards.AdaptiveCard card = (await m_renderer.TransformAsync(sourceBlock)).Result;

                this.Children.Add(SharedAdaptiveCardRenderer.RenderFromCard(card));
            }
            catch { }
        }
コード例 #5
0
        /// <summary>
        /// Handles the message activity asynchronously.
        /// </summary>
        /// <param name="turnContext">The turn context.</param>
        /// <returns>Task tracking operation.</returns>
        public async Task HandleMessageAsync(ITurnContext turnContext)
        {
            ITeamsContext teamsContext = turnContext.TurnState.Get <ITeamsContext>();

            string actualText = teamsContext.GetActivityTextWithoutMentions();

            if (actualText.Equals("Cards", StringComparison.OrdinalIgnoreCase))
            {
                // Demo card 1 - adaptive card with bot bulder actions
                AdaptiveCards.AdaptiveCard adaptiveCard = new AdaptiveCards.AdaptiveCard();
                adaptiveCard.Body.Add(new AdaptiveCards.AdaptiveTextBlock("Bot Builder actions"));

                var action1 = new CardAction("imback", "imBack", null, null, null, "text");
                var action2 = new CardAction("messageBack", "message back", null, "text received by bots", "text display to users", JObject.Parse(@"{ ""key"" : ""value"" }"));
                var action3 = new CardAction("invoke", "invoke", null, null, null, JObject.Parse(@"{ ""key"" : ""value"" }"));
                adaptiveCard.Actions.Add(action1.ToAdaptiveCardAction());
                adaptiveCard.Actions.Add(action2.ToAdaptiveCardAction());
                adaptiveCard.Actions.Add(action3.ToAdaptiveCardAction());

                // Task module action
                var taskModuleAction = new TaskModuleAction("Launch Task Module", @"{ ""hiddenKey"": ""hidden value from task module launcher"" }");

                // Demo card 2 - launch task module from adaptive card
                AdaptiveCards.AdaptiveCard taskModuleCard1 = new AdaptiveCards.AdaptiveCard();
                taskModuleCard1.Body.Add(new AdaptiveCards.AdaptiveTextBlock("Task Module Adaptive Card"));
                taskModuleCard1.Actions.Add(taskModuleAction.ToAdaptiveCardAction());

                // Demo card 3 - launch task module from hero card (or any bot-builder framework card)
                HeroCard taskModuleCard2 = new HeroCard("Launch Task Module", null, null, null, new List <CardAction> {
                    taskModuleAction
                });

                Activity replyActivity = turnContext.Activity.CreateReply();
                replyActivity.Attachments = new List <Attachment>()
                {
                    adaptiveCard.ToAttachment(),
                        taskModuleCard1.ToAttachment(),
                        taskModuleCard2.ToAttachment(),
                };
                await turnContext.SendActivityAsync(replyActivity).ConfigureAwait(false);
            }
            else
            {
                Activity replyActivity = turnContext.Activity.CreateReply();
                replyActivity.TextFormat = "xml";
                replyActivity.Text       = $"You said: {turnContext.Activity.Text}";
                await turnContext.SendActivityAsync(replyActivity).ConfigureAwait(false);
            }
        }
コード例 #6
0
        public void CardTests_AdaptiveCard_CardToAttachment()
        {
            AdaptiveCards.AdaptiveCard card = new AdaptiveCards.AdaptiveCard();
            card.Body.Add(new AdaptiveCards.AdaptiveTextBlock("some text on card"));

            var action = new AdaptiveCards.AdaptiveOpenUrlAction();

            action.Url = new Uri("https://microsoft.com");
            card.Actions.Add(action);

            Attachment attachment = card.ToAttachment();

            Assert.IsNotNull(attachment);
            Assert.IsNotNull(attachment.Content);
            Assert.IsNotNull(attachment.ContentType);
            Assert.AreEqual(attachment.ContentType, AdaptiveCards.AdaptiveCard.ContentType);
            Assert.IsTrue(JObject.DeepEquals(JObject.FromObject(card), JObject.FromObject(attachment.Content)));
        }
コード例 #7
0
        private IMessageActivity GetMessage(IDialogContext context, AdaptiveCards.AdaptiveCard card, string cardName)
        {
            var message = context.MakeMessage();

            if (message.Attachments == null)
            {
                message.Attachments = new List <Attachment>();
            }
            var attachment = new Attachment()
            {
                Content     = card,
                ContentType = "application/vnd.microsoft.card.adaptive",
                Name        = cardName
            };

            message.Attachments.Add(attachment);
            return(message);
        }
コード例 #8
0
        public static UIElement RenderFromCard(AdaptiveCards.AdaptiveCard card)
        {
            try
            {
                var uwpCard = AdaptiveCard.FromJsonString(card.ToJson()).AdaptiveCard;

                var renderer = Create();
                return(renderer.RenderAdaptiveCard(uwpCard).FrameworkElement);
            }
            catch (Exception ex)
            {
                return(new Windows.UI.Xaml.Controls.TextBlock()
                {
                    Text = ex.ToString(),
                    TextWrapping = TextWrapping.Wrap
                });
            }
        }
コード例 #9
0
        public AdaptiveCards.AdaptiveCard Create(AdaptiveCards.AdaptiveCard adaptiveCard, Func <dynamic, List <AdaptiveAction> > actions,
                                                 object obj)
        {
            if (actions == null)
            {
                return(adaptiveCard);
            }

            var createdActions = actions(obj);

            if (createdActions?.Any() != true)
            {
                return(adaptiveCard);
            }

            adaptiveCard.Actions.AddRange(createdActions);

            return(adaptiveCard);
        }
コード例 #10
0
        //public Attachment GetCardAttachment(ITurnContext turnContext)
        //{
        //    var teamsContext = turnContext.TurnState.Get<ITeamsContext>();
        //    TaskModuleRequest query = teamsContext.GetTaskModuleRequestData();
        //    string textValue = null;

        //    if (query.Data != null)
        //    {
        //        var data = JObject.FromObject(query.Data);
        //        textValue = data["userText"]?.ToString();
        //    }

        //    return this.GetResponseCard(query, textValue);
        //}

        // Builds the response card displayed in the task module
        public Attachment GetCard(TaskModuleRequest query, string textValue)
        {
            AdaptiveCards.AdaptiveCard adaptiveCard = new AdaptiveCards.AdaptiveCard();

            adaptiveCard.Body.Add(new AdaptiveCards.AdaptiveTextBlock("Your Request:")
            {
                Size   = AdaptiveCards.AdaptiveTextSize.Large,
                Weight = AdaptiveCards.AdaptiveTextWeight.Bolder,
            });

            adaptiveCard.Body.Add(new AdaptiveCards.AdaptiveContainer()
            {
                Style = AdaptiveCards.AdaptiveContainerStyle.Emphasis,
                Items = new List <AdaptiveCards.AdaptiveElement>
                {
                    new AdaptiveCards.AdaptiveTextBlock(JObject.FromObject(query).ToString())
                    {
                        Wrap = true,
                    },
                },
            });

            adaptiveCard.Body.Add(new AdaptiveCards.AdaptiveTextInput()
            {
                Id          = "userText",
                Placeholder = "Type text here...",
                Value       = textValue,
            });

            adaptiveCard.Actions.Add(new AdaptiveCards.AdaptiveSubmitAction()
            {
                Title = "Next",
                Data  = JObject.Parse(@"{ ""done"": false }"),
            });

            adaptiveCard.Actions.Add(new AdaptiveCards.AdaptiveSubmitAction()
            {
                Title = "Submit",
                Data  = JObject.Parse(@"{ ""done"": true }"),
            });

            return(adaptiveCard.ToAttachment());
        }
コード例 #11
0
        public void CardTests_AdaptiveCard_JsonToAttachment()
        {
            AdaptiveCards.AdaptiveCardParseResult card = AdaptiveCards.AdaptiveCard.FromJson(File.ReadAllText(@"Jsons\SampleAdaptiveCard.json"));
            Attachment attachment = card.ToAttachment();

            AdaptiveCards.AdaptiveCard expectedCard = new AdaptiveCards.AdaptiveCard();
            expectedCard.Body.Add(new AdaptiveCards.AdaptiveTextBlock("some text on card"));

            var action = new AdaptiveCards.AdaptiveOpenUrlAction();

            action.Url = new Uri("https://microsoft.com");
            expectedCard.Actions.Add(action);

            Assert.IsNotNull(attachment);
            Assert.IsNotNull(attachment.Content);
            Assert.IsNotNull(attachment.ContentType);
            Assert.AreEqual(attachment.ContentType, AdaptiveCards.AdaptiveCard.ContentType);
            Assert.IsTrue(JObject.DeepEquals(JObject.FromObject(expectedCard), JObject.FromObject(attachment.Content)));
        }
コード例 #12
0
        public void TaskModuleTests_AdaptiveCard()
        {
            AdaptiveCards.AdaptiveCard currentAdaptiveCard = new AdaptiveCards.AdaptiveCard();
            currentAdaptiveCard.Body.Add(new AdaptiveCards.AdaptiveTextBlock("some text on card"));

            var action = new AdaptiveCards.AdaptiveOpenUrlAction();

            action.Url = new Uri("https://microsoft.com");
            currentAdaptiveCard.Actions.Add(action);

            TaskModuleResponseEnvelope currentTaskModuleEnvelope = new TaskModuleResponseEnvelope
            {
                Task = new TaskModuleContinueResponse
                {
                    Value = new TaskModuleTaskInfo()
                    {
                        Title  = "Adaptive Card: Inputs",
                        Card   = currentAdaptiveCard.ToAttachment(),
                        Height = "small",
                        Width  = "small",
                    },
                    Type = "continue",
                }
            };

            var inputJson = File.ReadAllText(@"Jsons\SampleTaskModuleAdaptiveCardPayload.json");
            var expectedTaskModuleEnvelope = JObject.Parse(inputJson);

            Assert.IsTrue(expectedTaskModuleEnvelope != null);
            Assert.IsTrue(expectedTaskModuleEnvelope["task"] != null);
            Assert.IsTrue(expectedTaskModuleEnvelope["task"]["type"].ToString() == currentTaskModuleEnvelope.Task.Type);

            var expected = JsonConvert.DeserializeObject <TaskModuleTaskInfo>(expectedTaskModuleEnvelope["task"]["value"].ToString());
            var current  = (currentTaskModuleEnvelope.Task as TaskModuleContinueResponse).Value as TaskModuleTaskInfo;

            Assert.AreEqual(expected.Width, current.Width);
            Assert.AreEqual(expected.Title, current.Title);
            Assert.AreEqual(expected.Card.ContentType, current.Card.ContentType);
        }
コード例 #13
0
        public void CardTests_AdaptiveCard_BotBuilderAction_AdaptiveBotBuilderAction()
        {
            var wrapAction = new CardAction
            {
                Type        = "messageBack",
                Value       = "some value to bots",
                Title       = "button title",
                Text        = "text posting back to bots",
                DisplayText = "display text injected in chat stream"
            };

            var action = new AdaptiveBotBuilderAction(wrapAction);

            var expectedAction = JsonConvert.DeserializeObject(@"{
                ""type"": ""Action.Submit"",
                ""title"": ""button title"",
                ""data"": {
                    ""msteams"": {
                        ""type"": ""messageBack"",
                        ""value"": ""some value to bots"",
                        ""text"": ""text posting back to bots"",
                        ""displayText"": ""display text injected in chat stream"",
                    }
                }
            }");

            Assert.IsTrue(JObject.DeepEquals(JObject.FromObject(expectedAction), JObject.FromObject(action)));

            var card = new AdaptiveCards.AdaptiveCard();

            card.Body.Add(new AdaptiveCards.AdaptiveTextBlock());
            card.Actions.Add(action);

            Attachment attachment = card.ToAttachment();

            this.TestCard(attachment);
        }
コード例 #14
0
        public void CardTests_AdaptiveCard_BotBuilderAction_RepresentAsBotBuilderAction()
        {
            var wrapAction = new CardAction
            {
                Type  = "imback",
                Value = "Text",
                Title = "button title"
            };

            var action = new AdaptiveCards.AdaptiveSubmitAction();

            action.DataJson = @"{""key"": ""value""}";
            action.RepresentAsBotBuilderAction(wrapAction);

            var expectedAction = JsonConvert.DeserializeObject(@"{
                ""type"": ""Action.Submit"",
                ""title"": ""button title"",
                ""data"": {
                    ""key"": ""value"",
                    ""msteams"": {
                        ""type"": ""imback"",
                        ""value"": ""Text""
                    }
                }
            }");

            Assert.IsTrue(JObject.DeepEquals(JObject.FromObject(expectedAction), JObject.FromObject(action)));

            var card = new AdaptiveCards.AdaptiveCard();

            card.Body.Add(new AdaptiveCards.AdaptiveTextBlock());
            card.Actions.Add(action);

            Attachment attachment = card.ToAttachment();

            this.TestCard(attachment);
        }
コード例 #15
0
        async protected override Task NextAction(IDialogContext context, IAwaitable <IMessageActivity> message, LuisResult result)
        {
            System.Diagnostics.Trace.TraceInformation($"Luis query: {result.Query}. Entities: [{string.Join(",",result.Entities.Select(e=> $"{{{e.Type}, {e.Entity}}}").ToArray())}]");
            switch (_state)
            {
            case StateMachine.Initial:
                _state = StateMachine.InitialResponse;

                _model = new M.Model();

                goto case StateMachine.InitialResponse;

            case StateMachine.InitialResponse:
                if (I.AnimalTransportation != result.TopScoringIntent.Intent)
                {
                    await context.PostAsync($"Извините, но я не могу понять Ваш вопрос.");

                    context.Done(null as Object);
                    return;
                }

                await IntentAnimalTransportation(context, result);

                goto case StateMachine.Weight;

            case StateMachine.Weight:
                if (true == _model.IsWeightValid)
                {
                    goto case StateMachine.Dimension;
                }

                _state = StateMachine.WeightResponse;

                await context.PostAsync($"Укажите вес животного:");

                //PromptDialog.Number(context, this.PromptResponseWeight, "Укажите вес животного в килограммах");

                //goto case StateMachine.Weight;

                context.Wait(this.ResponseMessageReceived);
                break;

            case StateMachine.WeightResponse:
                //if (I.Weight != result.TopScoringIntent.Intent) { await CantUnderstand(context); }
                //else {
                await IntentWeight(context, result);

                //}

                goto case StateMachine.Weight;

            case StateMachine.Dimension:
                if (true == _model.IsDimensionValid)
                {
                    goto case StateMachine.TravelType;
                }

                _state = StateMachine.DimensionResponse;

                await context.PostAsync($"Укажите размеры клетки (длина, ширина и высота в сантиметрах):");

                context.Wait(this.ResponseTranslateWhenIntent);
                break;

            case StateMachine.DimensionResponse:
                //if (I.Dimension != result.TopScoringIntent.Intent) { await CantUnderstand(context); }
                //else {
                await IntentDimension(context, result);

                //}

                goto case StateMachine.Dimension;

            case StateMachine.TravelType:
                if (true == _model.IsTravelTypeValid)
                {
                    goto case StateMachine.LocationFrom;
                }

                _state = StateMachine.TravelTypeResponse;

                {
                    var m = context.MakeMessage();
                    m.Attachments.Add(
                        new ThumbnailCard(text: $"Где Вы желаете везти своё животное ?",
                                          buttons: new []
                    {
                        new CardAction(ActionTypes.ImBack, title: TravelTypeCabin, value: TravelTypeCabin),
                        new CardAction(ActionTypes.ImBack, title: TravelTypeCheckedIn, value: TravelTypeCheckedIn),
                    }).ToAttachment());
                    await context.PostAsync(m);
                }
                context.Wait(this.ResponseMessageReceived);
                break;

            case StateMachine.TravelTypeResponse:
            {
                var m = context.Activity?.AsMessageActivity()?.Text;
                if (TravelTypeCabin.Equals(m, StringComparison.InvariantCultureIgnoreCase))
                {
                    _model.TravelType = M.TravelType.Cabin;
                }
                else if (TravelTypeCheckedIn.Equals(m, StringComparison.InvariantCultureIgnoreCase))
                {
                    _model.TravelType = M.TravelType.CheckedIn;
                }
                else
                {
                    await CantUnderstand(context);
                }
            }

                goto case StateMachine.TravelType;

            case StateMachine.LocationFrom:
                if (true == _model.IsLocationFromValid)
                {
                    goto case StateMachine.LocationTo;
                }

                _state = StateMachine.LocationFromResponse;

                await context.PostAsync($"Откуда Вы вылетаете ?");

                context.Wait(this.ResponseTranslateWhenIntent);
                break;

            case StateMachine.LocationFromResponse:
            {
                //var n = await LuisHelpers.ProcessLocation(result.ScoreEntitiesGeography());
                //if (true == n.isProcessed) { _model.LocationFrom = n.geo?.normalized; }
                await ProcessGeoFromPredictive(new EntityRecommendation[] { new EntityRecommendation("PlaceName", entity: result.Query) }, _model);

                if (!_model.IsLocationFromValid)
                {
                    await CantUnderstand(context);
                }
            }

                goto case StateMachine.LocationFrom;

            case StateMachine.LocationTo:
                if (true == _model.IsLocationToValid)
                {
                    goto case StateMachine.Validation;
                }

                _state = StateMachine.LocationToResponse;

                await context.PostAsync($"Куда летите ?");

                context.Wait(this.ResponseTranslateWhenIntent);
                break;

            case StateMachine.LocationToResponse:
            {
                //var n = await LuisHelpers.ProcessLocation(result.ScoreEntitiesGeography());
                //if (true == n.isProcessed) { _model.LocationTo = n.geo?.normalized; }
                await ProcessGeoToPredictive(new EntityRecommendation[] { new EntityRecommendation("DestinationPlaceName", entity: result.Query) }, _model);

                if (!_model.IsLocationToValid)
                {
                    await CantUnderstand(context);
                }
            }

                goto case StateMachine.LocationTo;

            case StateMachine.Validation:
                _state = StateMachine.ValidationResponse;
                {
                    var card = new AdaptiveCards.AdaptiveCard()
                    {
                        Body = new List <AdaptiveCards.CardElement>()
                        {
                            new AdaptiveCards.TextBlock()
                            {
                                Text     = $"Проверьте, пожалуйста, правильно ли я всё понял:",
                                Size     = AdaptiveCards.TextSize.Medium,
                                Weight   = AdaptiveCards.TextWeight.Bolder,
                                IsSubtle = false
                            },
                            new AdaptiveCards.ColumnSet()
                            {
                                Separation = AdaptiveCards.SeparationStyle.Strong,
                                Columns    = new List <AdaptiveCards.Column>()
                                {
                                    new AdaptiveCards.Column()
                                    {
                                        Size  = "1",
                                        Items = new List <AdaptiveCards.CardElement>()
                                        {
                                            new AdaptiveCards.TextBlock()
                                            {
                                                Text  = _model.LocationFrom,
                                                Size  = AdaptiveCards.TextSize.ExtraLarge,
                                                Color = AdaptiveCards.TextColor.Accent
                                            }
                                        }
                                    },
                                    new AdaptiveCards.Column()
                                    {
                                        Size  = "auto",
                                        Items = new List <AdaptiveCards.CardElement>()
                                        {
                                            new AdaptiveCards.Image()
                                            {
                                                Url  = "http://messagecardplayground.azurewebsites.net/assets/airplane.png",
                                                Size = AdaptiveCards.ImageSize.Small
                                            }
                                        }
                                    },
                                    new AdaptiveCards.Column()
                                    {
                                        Size  = "1",
                                        Items = new List <AdaptiveCards.CardElement>()
                                        {
                                            new AdaptiveCards.TextBlock()
                                            {
                                                Text  = _model.LocationTo,
                                                Size  = AdaptiveCards.TextSize.ExtraLarge,
                                                Color = AdaptiveCards.TextColor.Accent,
                                                HorizontalAlignment = AdaptiveCards.HorizontalAlignment.Right
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        Actions = new List <AdaptiveCards.ActionBase>()
                        {
                            new AdaptiveCards.SubmitAction()
                            {
                                Title = ValidationOk, Data = ValidationOk
                            },
                            new AdaptiveCards.SubmitAction()
                            {
                                Title = ValidationError, Data = ValidationError
                            }
                        }
                    };

                    var m = context.MakeMessage();

                    //m.Attachments.Add(new Attachment()
                    //{
                    //    ContentType = AdaptiveCards.AdaptiveCard.ContentType,
                    //    Content = card
                    //});

                    m.Attachments.Add(
                        new ReceiptCard(title: $"Проверьте, пожалуйста, правильно ли я всё понял:",
                                        facts: FactsFromModel(_model).ToArray(),
                                        buttons: new[]
                    {
                        new CardAction(ActionTypes.ImBack, title: ValidationOk, value: ValidationOk),
                        new CardAction(ActionTypes.ImBack, title: ValidationError, value: ValidationError),
                    },
                                        total: "---" // HACK: stupid Windows Desktop Skype don't show Receipt Card without total field
                                        ).ToAttachment()
                        );
                    await context.PostAsync(m);
                }
                context.Wait(this.ResponseMessageReceived);
                break;

            case StateMachine.ValidationResponse:
            {
                var m = context.Activity?.AsMessageActivity()?.Text;
                if (true == ValidationOk.Equals(m, StringComparison.InvariantCultureIgnoreCase))
                {
                    _model.IsValid = true;
                }
                else if (true == ValidationError.Equals(m, StringComparison.InvariantCultureIgnoreCase))
                {
                    await context.PostAsync($"Хорошо. Давайте попробуем ещё раз.");

                    _model = new M.Model();
                    goto case StateMachine.Weight;
                }
                else
                {
                    await CantUnderstand(context);

                    goto case StateMachine.Validation;
                }
            }

                goto case StateMachine.Completed;

            case StateMachine.Completed:
                await context.PostAsync($"Стоимость провоза составит {_rnd.Next(3, 9) * 1000} рублей");

                context.Done(null as Object);
                return;

            default:
                throw new IllegalStateException("NextAction");
            }

            if (true == _isDebug)
            {
                await LogModel(context);
            }
        }
コード例 #16
0
        /// <summary>
        /// returns a thumbnail card for displaying the reults of the image analysis
        /// </summary>
        /// <returns></returns>
        private async Task DisplayImageFacts(IMessageActivity message, Models.ImageAnalysisResults image)
        {
            var img = image.Image;

            // create a new adaptive card
            var card = new AdaptiveCards.AdaptiveCard();

            // add a title
            card.Body.Add(new AdaptiveCards.AdaptiveTextBlock("Facts about the image:"));

            // create a container for each of the sections
            var container = new AdaptiveCards.AdaptiveContainer();

            container.Separator = true;
            card.Body.Add(container);

            #region Tags
            // create the fact set for the tags
            var tags = new AdaptiveCards.AdaptiveFactSet();

            // create facts for tags
            if (img.AnalysisResult.Tags == null || !img.AnalysisResult.Tags.Any())
            {
                tags.Facts.Add(new AdaptiveCards.AdaptiveFact("Tags: ", "no tags"));
            }
            else
            {
                var list = img.AnalysisResult.Tags.Select(t => new { Confidence = string.Format("{0}%", Math.Round(t.Confidence * 100)), Name = t.Name });
                foreach (var tag in list)
                {
                    tags.Facts.Add(new AdaptiveCards.AdaptiveFact(tag.Name, tag.Confidence.ToString()));
                }
            }

            // add the factset
            container.Items.Add(tags);
            #endregion

            #region Celebrities

            // create a fact set for celebrities and landmarks
            var celebs = new AdaptiveCards.AdaptiveFactSet();

            // create facts for celebs
            if (img.AnalysisResult?.Categories != null)
            {
                // just making sure the same celebs and landmarks dont get added twice
                List <string> celebnames = new List <string>();
                List <string> landnames  = new List <string>();

                foreach (var category in img.AnalysisResult.Categories.Where(c => c.Detail != null))
                {
                    dynamic detail = JObject.Parse(category.Detail.ToString());
                    if (detail.celebrities != null)
                    {
                        foreach (var celebrity in detail.celebrities)
                        {
                            Models.Celebrity celeb = JsonConvert.DeserializeObject <Models.Celebrity>(celebrity.ToString());
                            if (!celebnames.Contains(celeb.name))
                            {
                                celebnames.Add(celeb.name);
                                celebs.Facts.Add(new AdaptiveCards.AdaptiveFact(celeb.name, Math.Round(celeb.confidence * 100).ToString() + "%"));
                            }
                        }
                    }
                    else if (detail.landmarks != null)
                    {
                        foreach (var landmark in detail.landmarks)
                        {
                            Models.Landmark land = JsonConvert.DeserializeObject <Models.Landmark>(landmark.ToString());
                            if (!landnames.Contains(land.name))
                            {
                                landnames.Add(land.name);
                                celebs.Facts.Add(new AdaptiveCards.AdaptiveFact(land.name, Math.Round(land.confidence * 100).ToString() + "%"));
                            }
                        }
                    }
                }
            }

            container.Items.Add(celebs);

            #endregion



            // get the attchment
            Attachment att = new Attachment(contentType: AdaptiveCards.AdaptiveCard.ContentType, content: card);

            // add the attchment to the message
            message.Attachments.Add(att);
        }