New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConversationUpdate with UserState data store issue #1013

Open
Arincon opened this Issue Jun 7, 2018 · 13 comments

Comments

Projects
None yet
6 participants
@Arincon

Arincon commented Jun 7, 2018

I am working with Bot Framework v4, and I am having a problem with the ConversationUpdate Activity.
I think it is related with #536, but i am not sure it is exactly the same.

I am using UserState Data Store in CosmosDB, which uses a key like user/directline/USERID . It works fine all the time, but I am having a problem with ConversationUpdate.
The problem is that I am automatically receiving a ConversationUpdate activity with the members added and removed (which is correct), but the properties of this activity seem weird to me. In this activity, I am receiving, activity.From.Id is not the USERID of the user joining the conversation, is the ConversationId. So, the UserState is storing one element in database for this "user", and another for the real user, thus duplicating the number of total elements in UserState database.

Is this on purpose because any reason, or is this a bug?

Thank you in advance.

@compulim compulim added the Support label Jun 13, 2018

@compulim

This comment has been minimized.

Collaborator

compulim commented Jun 13, 2018

Do you think it's a bug on BotBuilder side?

@JasonSowers

This comment has been minimized.

Member

JasonSowers commented Jun 13, 2018

@Arincon can you walk us through your setup and how you are setting the UserID for reproduction purposes?

@Arincon

This comment has been minimized.

Arincon commented Jun 13, 2018

@compulim I am not sure. I think that either this is on purpose (so I want to know why it has to be this way), or it is a bug in some part of the directline communication.

@JasonSowers I am doing something like this:

        var userId = "";
        var possibleChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        for (var i = 0; i < 30; i++) {
            userId += possibleChars.charAt(Math.floor(Math.random() * possibleChars.length));
        }
        console.log(userId);
        var user = { id: userId, name: "Yo" };
        var bot = { id: "bot_dev" };
        var botConnection = new BotChat.DirectLine({
            secret: "XXXXXXXXX",
            domain: 'https://europe.directline.botframework.com/v3/directline',
            webSocket: true
        });
        BotChat.App({
            botConnection: botConnection,
            user: user,
            bot: bot,
            locale: "es-es",
        }, document.getElementById("bot"));

And I am sending an event to the bot:

        var pageData = { courseName: "Curso TEST", courseId: "IDCurso", url: "aaaa" };
        botConnection
            .postActivity({ type: "event", value: pageData, from: { id: userId, name: "Yo" }, name: "PageContextData" })
            .subscribe(id => {
                console.log("Success sending data.");
                console.log(pageData);
            });

But this is not the problem, because I changed almost everything to try to solve it, and nothing worked.

Thanks in advance.

@compulim

This comment has been minimized.

Collaborator

compulim commented Jun 15, 2018

@Arincon it sounds like a bug on BotBuilder side. But I cannot find any similar issues using the keyword conversationUpdate and id.

Can you post the question over there? I think they will be able to answer your question much more quickly.

@billba

This comment has been minimized.

Member

billba commented Jun 16, 2018

This is correct behavior, but it's not desirable. It's a longstanding issue.

Direct Line doesn't have a first-class notion of identity. Each activity sent from the client contains a from object, and the id from that object is used as part of the key for the user state. Pass a different id, get different state.

Meanwhile, conversationUpdate is a synthetic event sent from Direct Line to the bot when the conversation starts. You'll notice that the relevant API doesn't include any notion of user id. So Direct Line just puts the conversation ID in there. (To make life more confusing, other channels do correctly put the user id in there).

The workaround is to ignore conversationUpdate and instead have your client send an event activity via the backchannel, with the from object set to the user id.

@dhinag

This comment has been minimized.

dhinag commented Jun 27, 2018

@billba I am following exactly what you have mentioned above and as you said, conversationUpdate does not have a notion of the userid, so I am triggering an event to send my userid so that I would like the bot to reply "hello, ".

I have setup switch cases for "conversationUpdate" and "event" and the code to execute is one and the same.

 IConversationUpdateActivity updatetest = activity;
                        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
                        {
                            var client = scope.Resolve<IConnectorClient>();
                            var reply = activity.CreateReply();
                            reply.Text = $"Welcome activity.From.Id";
                            await client.Conversations.ReplyToActivityAsync(reply);
                        }

The problem is that the await client.Conversations.ReplyToActivityAsync(reply) code executes, but no reply is sent to the user when called from the switch case set up for "event".
However, when the switch case for "conversationUpdate" executes, the user gets the reply from the bot appropriately.

I notice that "conversationUpdate" and "event" have different Activity ID and Conversation ID. Is that how it is intended?

@UsamaAslam

This comment has been minimized.

UsamaAslam commented Jul 24, 2018

i am using below code to pass the value to bot ActivityTypes.ConversationUpdate but i am not able to get any value in bot under ActivityTypes.ConversationUpdate. Can you help me ? Don't able to pass the value.
Full address is local variable on html page that have value like in this i-e if i want to pass London to bot and in conversation start bot display London .

<script type="text/javascript">
        // for location of user....
        var fulladdress ='landon';
 
 alert(fulladdress);
         // for Bot  .......
        const speechOptions = {
            speechRecognizer: new CognitiveServices.SpeechRecognizer({ subscriptionKey: 'key' }),
            speechSynthesizer: new CognitiveServices.SpeechSynthesizer({
                gender: CognitiveServices.SynthesisGender.Female,
                subscriptionKey: 'key',
                voiceName: 'Microsoft Server Speech Text to Speech Voice (en-US, JessaRUS)'
            })
        };
      
        var model = {
            "userId": '_' + Math.random().toString(36).substr(2, 9),
            "userName": "User Name",
            "botId": "Chatbot Main Tree",
            "botIconUrl": "//bot-framework.azureedge.net/bot-icons-v1/bot-framework-default-8.png",
            "botName": "Chatbot Main Tree",
            "secret": "Direct Line Secret",
            "iconUrl": "//bot-framework.azureedge.net/bot-icons-v1/bot-framework-default-8.png",
            "directLineUrl": "https://webchat.botframework.com/v3/directline",
            "webSocketEnabled": "True"
        };

        var dl = new BotChat.DirectLine(
            {
                  secret: model.secret,
                  token: model.token,
                  domain: model.directLineUrl,
                  webSocket: true,
                  sendTyping: true
            });

        BotChat.App({
            botConnection: {
                botConnection: dl,
                postActivity: activity => dl.postActivity({
                    from: { id: 'userid', name: 'username' },
                    name: 'postLocationData',
                    text: 'I said my location is ' + fulladdress,
                    type: 'ConversationUpdate',
                    value: fulladdress,
                    channelData: fulladdress
                })
                    .subscribe(function (id) {
                        console.log(fulladdress);
                    })
            },
            sendTyping: true,
            user: { id: model.userId, name: model.userName },
            bot: { id: model.botId, name: model.botName },
            speechOptions: speechOptions,
            resize: 'window',
        }, document.getElementById("BotChatElement"));
</script>
@Arincon

This comment has been minimized.

Arincon commented Jul 24, 2018

@UsamaAslam
What you are doing semms a little weird to me. First, I think is a little strange to 'force' all the messages to be typed as "ConversationUpdate", and to modify its text.
Next, I am not sure if it is your problem, but if you don't send a message from the user to bot, you are not going to see anything in the bot, because what you are doing is modifying the method that posts the activity and changing its behaviour, not manually sending a predefined message from the page to the bot after initialization.
Is this all correct?

@UsamaAslam

This comment has been minimized.

UsamaAslam commented Jul 24, 2018

i just want to send variable value to bot . i want to send location without any button click like . i don't know how to to do. i tried this method as well but don't able to get any value in bot activity event .

i don't have any button click . this was the method that i get from : https://stackoverflow.com/questions/47227251/how-can-i-let-users-share-their-location-in-bot-framework-webchat-channel/51493362#51493362

kindly guide me the way i can do this .
thanks

@Arincon

This comment has been minimized.

Arincon commented Jul 24, 2018

@UsamaAslam
But I think this is similar to what you want to do.
Forget the button click event, what you have there is a function, that you can execute when you want (if directline is already initialized), that sends a message, with these properties, to the bot.
For example, what you can do is execute this function inmediately after bot initialization. However, you have to have in mind that the type of the message you are sending, because in the web api you will have to filter and read it.

@UsamaAslam

This comment has been minimized.

UsamaAslam commented Jul 24, 2018

but how can i fetch the value in bot if i use that method ?

this is what i have in my controller:

` public async Task Post([FromBody]Activity activity)
{
switch (activity.GetActivityType())
{

            case ActivityTypes.Message:
                ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                Activity isTypingReply = activity.CreateReply();
                isTypingReply.Type = ActivityTypes.Typing;
                await connector.Conversations.ReplyToActivityAsync(isTypingReply);
                await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
                break;

            case ActivityTypes.ConversationUpdate:
                IConversationUpdateActivity update = activity;
                var url_chk = activity.ServiceUrl;
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
                {
                    var client = scope.Resolve<IConnectorClient>();
                    if (update.MembersAdded.Any())
                    {
                        var reply1 = activity.CreateReply();
                        foreach (var newMember in update.MembersAdded)
                        {
                            if (newMember.Id != activity.Recipient.Id)
                            {

                            }
                            else
                            {
                                string first_message = "Welcome! I’m EnvolveBot. \n" + Environment.NewLine + "I’m here to help you find a Primary Care Provider in your area. I see you’re in"+activity.From.Name+" \n " + Environment.NewLine + "Is this correct?";
                               
                            }
                        }
                    }
                }
                break;

            case ActivityTypes.ContactRelationUpdate:
                
                break;

            case ActivityTypes.Typing:
            case ActivityTypes.DeleteUserData:
            case ActivityTypes.Ping:
            default:
                Trace.TraceError($"Unknown activity type ignored: {activity.GetActivityType()}");
                break;
        }
        return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
    }` 
@Arincon

This comment has been minimized.

Arincon commented Jul 24, 2018

@UsamaAslam
There you will have a case in the switch for ActivityTypes.Event, where you will react to events like this.

@UsamaAslam

This comment has been minimized.

UsamaAslam commented Jul 24, 2018

i use the method that you describe . and now the problem is that when i run the code first time my conversation type is conversationupdate and after that if i type then message .. activity type Event never run. how can i solve this i don't have any button on my html page . can you guide me how can i get activity event ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment