Переадресация карты героя из Skype Chatbot с функциональными кнопками (или для создания ссылки на чат-бота и передачи ссылки) - PullRequest
0 голосов
/ 07 мая 2018

Есть ли способ создать карту героя, у которой есть кнопки, которые продолжают работать, когда она перенаправляется другому пользователю?

Мы хотим создать чат-бота, который позволит вам делиться вещами с кем-то еще. Итак, сначала вы говорите с чатботом (в основном с помощью кнопок), чтобы настроить что-то, а затем отправляете это одному из ваших контактов, чтобы они могли участвовать. С Facebook Messenger мы можем напрямую вызвать действие обмена, которое открывает диалоговое окно обмена, с помощью которого пользователь может переслать карточку контакту. Используя m.me/123?ref=456 URL в кнопке карты, получатель может открыть разговор с чат-ботом в правильном контексте. Мне удалось сделать нечто подобное для Telegram.

Я пытаюсь повторить это с другими службами. В Skype нет способа явно вызвать действие «Поделиться», но я могу написать сообщение «Пожалуйста, перешлите следующую карту пользователю, с которым вы хотите поделиться этим:» [и затем я отображаю эту карту]. Теперь я даю этой карточке кнопку с действием postBack, которое должно открыть правильный контекст, но эта кнопка кажется неработоспособной. При нажатии на нее сообщение не отправляется обратно в чатбота.

Есть ли способ реализовать что-то похожее на то, что я описал для Facebook Messenger с помощью Skype? Или есть способ, чтобы глубокая ссылка на чат-бота передавала какую-то ссылку?

(В любом случае, я предпочел бы использовать второй вариант для второго использования, когда пользователь помещает кнопку «Поделиться» на своем веб-сайте, которая затем открывает Skype в разговоре с чат-ботом, передавая ссылку. У меня это есть для Messenger и Telegram .)

Редактировать: Я бы хотел сделать следующее. Я использую nodejs, но только класс ChatConnector, а не класс UniversalBot.

connector.send([
    {
        type: 'message',
        address,
        textFomrat: 'plain',
        text: 'Forward the next message to people you want to share THING with:',
    },
    {
        type: 'message',
        address,
        attachments: [{
            contentType: 'application/vnd.microsoft.card.hero',
            content: {
                title: name,
                images: [{
                    url: image_url
                }],
                buttons: [{
                    type: 'postBack',
                    title: 'Chat with this bot about THING',
                    value: 'open:' + thing_id,
                }]
            }
        }],
    }
], callback);

1 Ответ

0 голосов
/ 25 мая 2018

Я не уверен, как вы отправляете карточки другому пользователю, но вот пример в .net, где отправленные кнопки будут работать, как и ожидалось, для другого пользователя:

using Microsoft.Bot.Builder.Dialogs;
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.FormFlow;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Microsoft.Bot.Builder.ConnectorEx;
using Newtonsoft.Json;

namespace CardsBot
{
    [Serializable]
    public class SendToUserDialog : IDialog<object>
    {
        static ConcurrentDictionary<string, ConversationReference> _cachedConversationReferences = new ConcurrentDictionary<string, ConversationReference>();
        private const string HelpString = "Enter 'Send Card' to send a card to another user. 'Send Message' to send a json message to another user.  Or 'List Users' to see who is ready to receive messages.";

        public async Task StartAsync(IDialogContext context)
        {
            context.Wait(this.MessageReceivedAsync);
        }

        public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
        {
            var message = await argument;

            string upperText = message.Text.Replace(" ", "").ToUpper();
            if (upperText == "SENDCARD")
            {
                IFormDialog<SendCardForm> form = new FormDialog<SendCardForm>(new SendCardForm(), SendCardForm.BuildForm, FormOptions.PromptInStart);
                context.Call(form, AfterSendCardComplete);
            }
            else if (upperText == "SENDMESSAGE")
            {
                IFormDialog<SendMessageForm> form = new FormDialog<SendMessageForm>(new SendMessageForm(), SendMessageForm.BuildForm, FormOptions.PromptInStart);
                context.Call(form, AfterSendMessageFormComplete);
            }
            else if (upperText == "LISTUSERS")
            {
                var names = String.Join(", ", _cachedConversationReferences.Keys);
                await context.PostAsync($"Users : {names}");
            }
            else
            {
                if (!context.UserData.ContainsKey("name"))
                {
                    var getNamePrompt = new PromptDialog.PromptString("What is your name?", "Please enter your name.", 3);
                    context.Call(getNamePrompt, AfterNamePrompt);
                }
                else
                {
                    await context.PostAsync($"You said: {message.Text} ({HelpString})");
                    context.Wait(MessageReceivedAsync);
                }
            }
        }
        private async Task AfterSendMessageFormComplete(IDialogContext context, IAwaitable<SendMessageForm> result)
        {
            var sendMessageForm = await result;
            if (string.IsNullOrEmpty(sendMessageForm.RecipientName))
            {
                await context.PostAsync("A recipient name was not provided.  Cannot send the message to nobody.");
            }
            else
            {
                ConversationReference conversation = null;
                if (_cachedConversationReferences.TryGetValue(sendMessageForm.RecipientName, out conversation))
                {
                    var originalReply = conversation.GetPostToBotMessage().CreateReply();
                    var replyMessage = GetMessage(originalReply, sendMessageForm.MessageJson);

                    var connector = new ConnectorClient(new Uri(originalReply.ServiceUrl));
                    await connector.Conversations.ReplyToActivityAsync(replyMessage);

                    await context.PostAsync($"Message was sent to {sendMessageForm.RecipientName} on {replyMessage.ChannelId} channel.");
                }
                else
                {
                    await context.PostAsync($"No recipient found matching the name {sendMessageForm.RecipientName}");
                }
            }
        }
        private async Task AfterNamePrompt(IDialogContext context, IAwaitable<string> result)
        {
            var name = await result;
            context.UserData.SetValue("name", name);
            await context.PostAsync($"Thanks.  What would you like to do now {name}? {HelpString}");

            var conversationReference = context.Activity.ToConversationReference();
            _cachedConversationReferences.AddOrUpdate(name, conversationReference, (oldVal, newVal) => conversationReference);
        }

        public Activity GetMessage(Activity originalReply, string messageJson)
        {
            var reply = JsonConvert.DeserializeObject<Activity>(messageJson);
            reply.ChannelId = originalReply.ChannelId;
            reply.Timestamp = originalReply.Timestamp;
            reply.From = originalReply.From;
            reply.Conversation = originalReply.Conversation;
            reply.Recipient = originalReply.Recipient;
            reply.Id = originalReply.Id;
            reply.ReplyToId = originalReply.ReplyToId;
            reply.ServiceUrl = originalReply.ServiceUrl;

            return reply;
        }

        private async Task AfterSendCardComplete(IDialogContext context, IAwaitable<SendCardForm> result)
        {
            var SendCardForm = await result;
            if (string.IsNullOrEmpty(SendCardForm.RecipientName))
            {
                await context.PostAsync("A recipient name was not provided.  Cannot send a card to nobody.");
            }
            else
            {
                ConversationReference conversation = null;
                if (_cachedConversationReferences.TryGetValue(SendCardForm.RecipientName, out conversation))
                {
                    var reply = conversation.GetPostToBotMessage().CreateReply();
                    reply.Attachments.Add(GetCard(SendCardForm.Text, SendCardForm.Buttons.Value));

                    var connector = new ConnectorClient(new Uri(reply.ServiceUrl));
                    await connector.Conversations.ReplyToActivityAsync(reply);
                }
                else
                {
                    await context.PostAsync($"No recipient found matching the name {SendCardForm.RecipientName}");
                }
            }
        }

        public Attachment GetCard(string text, int numberOfButtons)
        {
            var card = new HeroCard(text);
            card.Buttons = new List<CardAction>(GetCardActions(numberOfButtons));
            return card.ToAttachment();
        }

        private IEnumerable<CardAction> GetCardActions(int numberOfButtons)
        {
            for (int counter = 1; counter < numberOfButtons; counter++)
            {
                yield return new CardAction()
                {
                    Title = $"button{counter}",
                    Type = ActionTypes.ImBack,
                    Value = $"button{counter}"
                };
            }
        }
    }
    [Serializable]
    public class SendMessageForm
    {
        [Prompt("Who would you like to send this message to (enter the name of the recipient)?")]
        public string RecipientName { get; set; }
        [Prompt("Paste in the .json of the message you would like to Send.")]
        public string MessageJson { get; set; }

        public static IForm<SendMessageForm> BuildForm()
        {
            return new FormBuilder<SendMessageForm>()
                            .AddRemainingFields()
                            .Confirm("Is this information correct?{*}")
                            .Build();
        }
    }
    [Serializable]
    public class SendCardForm
    {
        [Prompt("What would you like for the card text?")]
        public string Text { get; set; }

        [Prompt("How many buttons?")]
        public int? Buttons { get; set; }

        [Prompt("Who would you like to send the card to?")]
        public string RecipientName { get; set; }

        public static IForm<SendCardForm> BuildForm()
        {
            return new FormBuilder<SendCardForm>()
                            .AddRemainingFields()
                            .Confirm("Is this information correct?{*}")
                            .Build();
        }
    }
}
...