Botkit: conversation.say doesn't output until you end the convo

Created on 11 Jul 2016  Â·  20Comments  Â·  Source: howdyai/botkit

I'm not sure if this is a bug or expected behavior, but it makes conversations much less useful.

Could we add a conversation.flush() method to output queued messages without ending the conversation?

I guess I can use bot.say() in these cases, but the conversation methods don't get a passed a reference to the bot (?) so I'd have to store/pass that around.


Use case:
If I have a conversation and in the middle I want to add a response, eg to a 'hint' or clarification if the user doesn't give an expected answer, there's no way to use bot.say without ending the whole conversation.

consider the snippet below

in this case if the user enters hint
I can try to convo.say("Rhymes with foo!");
but this will NOT output until I fire a convo.next()
doing that will however end the conversation.

I also tried with convo.repeat() and silentRepeat() but these seem to not behave as expected.

ConvoTest.start = function (bot, message) {
    debug("message", message);
    bot.startConversation(message, function (err, convo) {
        if (err) {
            console.log("err", err);
            return;
        }
        convo.say("Start single player game");
        // convo.ask("What color is the sky?", ConvoTest.quizQuestion);
        convo.ask("What color is the sky?", ConvoTest.multiResponse);

        convo.on('end', function (convo) {
            bot.say({
                text: "Game Over",
                channel: message.user
            });
            // convo.say("Done!");
            // convo.next();
            if(convo.status === 'completed') {
                console.log("end convo");
            }
        });

    });

};


ConvoTest.multiResponse = [
    {
        pattern: /hint/,
        callback: function (response, convo) {
            convo.say("Rhymes with foo!");
            // FIXME - this will exit the conversation
            // but without it, nothing is output
            convo.next();
        }
    },

    {
        pattern: /what/,
        callback: function (response, convo) {
            convo.say("Say what?");
            convo.repeat();
            convo.next();
        }
    },
    {
        pattern: /blue/,
        callback: function (response, convo) {
            convo.say("yes, you win!");
            convo.next();
        }
    },
    {
        default: true,
        callback: function(response, convo) {
            convo.say("no, try again");
            // convo.repeat();
            convo.silentRepeat();
            convo.next();
        }
    }
];
bug enhancement help wanted

Most helpful comment

happy anniversary, issue #318 🎉

All 20 comments

hint - will exit the game - it has to use .next()

image

what will work using convo.repeat() but then we also get the .ask prompt again

image

the default section (wrong answer)

If I use silentRepeat(); next();
will result in the conversation exiting
I think this must be a bug.

image

also note that the .say response in the callback comes _after_ the conversation finish block comment.

@dcsan yeah it's probably a bug
What I do in case of wrong answer is (roughly, with bot passed in):

bot.reply(conv.source_message, 'Beeeep, try again.');
conv.silentRepeat();

and not calling next() after that. This seems to be working fine and resuming/ending/cleaning up conversation as expected.

This does not work me, I have conversations nested into each other. I end up getting multiple conversations lingering around.

The workaround works for me. Would be cool to still be able to use say() and have it be flushed by silentRepeat().

worked for me as well. But, when there are more than one messages to be sent then reply does not take care of message ordering... I think to ensure message order i must use say() but, i can't use with silentRepeat(). don't know what to do here.

I have the same problem. How to chain multiple convo.ask and use convo.repeat in one of them if the user input is not right ?

Any news for that bug? Any idea for a fix (not the bot.reply workaround)? It's a really annoying one, as @manojkumar1412 mentioned, bot.reply doesn't fallow the normal order of a conversation :/

I am also facing same issue with this.

My use case:

I want to call some external method only after completing the conversations .

How can I do that ?

Any fix on this issue, I have the same problem. I am using interactive buttons and if the user types anything other than these button values, i want to send a message to user to use these buttons. how do i do it.

happy anniversary, issue #318 🎉

@PrajaktaNaik: bot.reply is the only way for now. If there is just 1 message to send to client then I don't think it is a bad idea to use it. It fails only in case of you need to send more than 1 messages to client and still wait for him to answer. Fails means it doesn't guarantee the order of messages.

This is on my radar now, this is a failing of docs and examples prolly,
since we show mostly simple flows. I think this can be achieved with some
smart threading, will sit down to give this my full attention hopefully
before monday! Thanks for not giving up on this one @dcsan
On Wed, Aug 30, 2017 at 9:52 PM manojkumar1412 notifications@github.com
wrote:

@PrajaktaNaik https://github.com/prajaktanaik: bot.reply is the only
way for now. If there is just 1 message to send to client then I don't
think it is a bad idea to use it. It fails only in case of you need to send
more than 1 messages to client and still wait for him to answer. Fails
means it doesn't guarantee the order of messages.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/howdyai/botkit/issues/318#issuecomment-326166706, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AMUR2-Puu7HwrtP1cGGe6RE3RW3vlyyyks5sdhHlgaJpZM4JJvI_
.

@jonchurch Any update on this issue now that you've had some time to look at it?

It is possible to use bot.reply to achieve this as mentioned above:

bot.reply(convo.source_message, 'This is a reply to the original message');

This will bypass the conversation system and send the message, leaving the conversation in the same state.

Another solution, as @jonchurch mentioned, would be to use conversation threads. You can create a thread, add messages, then use the special action property to automatically route the conversation back to where you wanted to start.

Something like this:

convo.ask('What color is the sky?',[
  {
      pattern: /hint/,
      callback: function (response, convo) {

          // create a thread with a hint message.
          // use the special `action` field to tell botkit
          // to go back to the `default` thread after sending it

          convo.addMessage({
            text: 'Rhymes with foo',
            action: 'default',
          }, 'hint');

          convo.gotoThread('hint');
      }
  },
  {
      pattern: /what/,
      callback: function (response, convo) {
          convo.say("Say what?");
          convo.repeat();
          convo.next();
      }
  },
  {
      pattern: /blue/,
      callback: function (response, convo) {
          convo.say("yes, you win!");
          convo.next();
      }
  },
  {
      default: true,
      callback: function(response, convo) {
          convo.say("no, try again");
          // convo.repeat();
          convo.silentRepeat();
          convo.next();
      }
  }
]);

Still facing the issue regardless of both the above approaches.
I'm observing this strange case where if I use short string in bot.reply(), it works as expected. But long strings are displayed after the convo.repeat() message.

For example:

convo.ask({text:'Question?'},[
{
    pattern : 'abc',
    callback: function(res1,convo)
    {
        bot.reply(convo.source_message, 'Some long string which is enough to cause problem.');  
        convo.repeat();
        convo.next();
    }
});

Displays 'Question?' first and then 'Some long string which is enough to cause problem.'
while if I use 'Short string' in bot.reply(), it works fine.

Is it because the bot.reply takes more time to display, enough to execute convo.repeat() first?

Please debug this case. Thanks.

@sudk97 Do not mix bot.reply and convo.*, this will cause out of order messages.

You might want to turn on the delivery confirmation option, which ensures messages are delivered in order. Sometimes messages with large payloads arrive after messages with shorter payloads even if sent first. The internet is weird.

@benbrown I am confused. Here you say "don't mix bot.reply and convo.*", but in the conversations above it seems this is the only way...

Can we please just make silentRepeat() work properly? (ie. allow user to answer again....)

Not sure if this is a good solution, but was able to "create a new question with the same answers" instead of trying to send and message and then call silentRepeat().

controller.hears(['gg'], 'direct_message,direct_mention', function (bot, message) {

        bot.startConversation(message, function (err, convo) {

            var answerThreads = [
                {
                    pattern: 'done',
                    callback: function (response, convo) {
                        convo.say('OK you are done!');
                        convo.next();
                    }
                },
                {
                    pattern: bot.utterances.yes,
                    callback: function (response, convo) {
                        convo.say('Great! I will continue...');
                        // do something else...
                        convo.next();

                    }
                },
                {
                    pattern: bot.utterances.no,
                    callback: function (response, convo) {
                        convo.say('Perhaps later.');
                        // do something else...
                        convo.next();
                    }
                },
                {
                    default: true,
                    callback: function (response, convo) {
                        convo.gotoThread('bad_answer')
                        convo.next();
                    }
                }
            ];

            convo.addQuestion('Shall we proceed Say YES, NO or DONE to quit.', answerThreads, {}, 'default');

            convo.addQuestion('Whoops! Please say YES, NO or DONE to quit.', answerThreads, {}, 'bad_answer');

        })

    })
Was this page helpful?
0 / 5 - 0 ratings

Related issues

simpixelated picture simpixelated  Â·  3Comments

dfischer picture dfischer  Â·  4Comments

fieldcorbett picture fieldcorbett  Â·  4Comments

iworkforthem picture iworkforthem  Â·  3Comments

RafaelCosman picture RafaelCosman  Â·  4Comments