howdyai / botkit

Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.
MIT License
11.45k stars 2.28k forks source link

Receiving duplicate messages on bot.reply #473

Closed liornaar closed 6 years ago

liornaar commented 7 years ago

Hi, Does anyone else encounter this issue? Whenever i do bot.reply i get duplicate message:

image

also in logs i see:

debug: CUSTOM FIND CONVO 1180150065384201 1180150065384201 debug: I HEARD [ 'hi', 'hello', 'bot', 'whats up', 'sup' ] debug: No handler for stats:heard_trigger debug: No handler for tick debug: GOT A MESSAGE HOOK debug: RECEIVED MESSAGE debug: CUSTOM FIND CONVO 1180150065384201 1180150065384201 debug: I HEARD [ 'hi', 'hello', 'bot', 'whats up', 'sup' ] debug: No handler for stats:heard_trigger debug: WEBHOOK SUCCESS { recipient_id: '1180150065384201', message_id: 'mid.1478100520671:324459a102' } debug: WEBHOOK SUCCESS { recipient_id: '1180150065384201', message_id: 'mid.1478100520939:d3d430cb89' }

when sending only one message...

agamrafaeli commented 7 years ago

Can you submit a simple code snippet with a bot that performs this behaviour?

Also, which integration are you using? and what version?

liornaar commented 7 years ago

Yes, Sorry for lack of details.. I'm using the bot with Facebook Messenger It happened since i started using Botkit.. even when I just pasted the code example from the readme file although im using my own express server

Botkit version: └── botkit@0.4.0

var Botkit = require('botkit');
var controller = Botkit.facebookbot({
        access_token: process.env.access_token,
        verify_token: process.env.verify_token,
})

var bot = controller.spawn({
});

//using my own server
server.listen(443, function () {
    console.log('gonna try to add web hook . . .');
    controller.createWebhookEndpoints(app, bot, function () {
        console.log('ONLINE!');
    });
});

// this is triggered when a user clicks the send-to-messenger plugin
controller.on('facebook_optin', function(bot, message) {

    bot.reply(message, 'Welcome to my app!');

});

// user said hello
controller.hears(['hello'], 'message_received', function(bot, message) {

    bot.reply(message, 'Hey there.');

});

controller.hears(['cookies'], 'message_received', function(bot, message) {

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

        convo.say('Did someone say cookies!?!!');
        convo.ask('What is your favorite type of cookie?', function(response, convo) {
            convo.say('Golly, I love ' + response.text + ' too!!!');
            convo.next();
        });
    });
});
jonchurch commented 7 years ago
  1. Hmmm you said this only happens with bot.reply, does it happen on every code block using a bot.reply, or just some? Does it happen every time within those offending code blocks, or intermittently?
  2. EDIT: This is inaccurate, whenever a message comes in botkit looks to see if its part of a conversation, hence the FIND CONVO in logs. Can you share the code and corresponding logs for a duplicate reply? To my understanding, you should only see CUSTOM FIND CONVO in logs within a conversation, and the code you shared here does not use a conversation to handle a hello.
  3. Can you confirm what events your webhook is subscribed to? I thought for a minute maybe it was responding to a message_echo event which your webhook can subscribe to, but that shouldn't allow a second message to be sent, since it will fail while trying to send the bot itself a message. However, since echos are still received as messages (which may be a bug, will look into it) it could be the echo itself triggering a response. I realize that does not explain the same message being sent twice, but could be a factor
liornaar commented 7 years ago

Thanks Jonathan, these are the details: 1)It happens every time im using bot.reply 3) these are the facebook events the app is registered to:

image

this is the full code snippet:


var Botkit = require('botkit');
var express = require('express');
var https = require('https');
var bodyParser = require('body-parser');
var request = require('request');

const fs = require('fs');

const options = {
    key: fs.readFileSync('server.key', 'utf8'),
    cert: fs.readFileSync('server.crt', 'utf8'),
    ca: [fs.readFileSync('server.ca-bundle', 'utf8')]
};

// --------------------- Bot Configuration ----------------------- //

var controller = Botkit.facebookbot({
    debug: true,
    access_token: 'my-access-token',
    verify_token: 'my-varify-token',
})

var bot = controller.spawn({});

// --------------------- Bot Configuration End ----------------------- //

// --------------------- Server Configuration ----------------------- //
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

var server = https.createServer(options, app);

server.listen(443, function () {
    console.log('gonna try to add web hook . . .');
    controller.createWebhookEndpoints(app, bot, function () {
        console.log('ONLINE!');
    });
});

request.post('https://graph.facebook.com/me/subscribed_apps?access_token=' + 'my-access-token',
    function (err, res, body) {
        if (err) {
            console.log('Could not subscribe to page messages');
        } else {
            console.log('Successfully subscribed to Facebook events:', body);
            controller.startTicking();
        }
    });

// --------------------- Server Configuration End ----------------------- //

var title;
var artist;

// this is triggered when a user clicks the send-to-messenger plugin
controller.on('facebook_optin', function (bot, message) {
    bot.say(message, 'Welcome!');
});

// user said hello
controller.hears(['hi', 'hello', 'bot', 'whats up', 'sup'], ['message_received'], function (bot, message) {

    bot.reply(message, 'Hi there!');
});

When sending messages like this:

image

the debug screen looks like this:

image

You can see already in the debug logs that it seems like the app receives two messages... something in Botkit configuration? Should I update or reinstall Botkit?

Thanks for the help!

Razvan-Miereanu commented 7 years ago

You might want to try

controller.hears(['hi', 'hello', 'bot', 'whats up', 'sup'], 'message_received', function(bot, message) {
    bot.reply(message, 'Hi there!');
});
liornaar commented 7 years ago

changing ['message_received'] to 'message_received' didn't seem to do anything different...

ghost commented 7 years ago

The reason of the issue is the 'message_received' event. It triggers with a lot of user's actions like type a message, and this is the reason you get double reply from bot, because the hear with the 'message_received' triggered 2 times: the first when you are typing the word 'hello', and the second when you press enter and send the word 'hello'. Just change the ['message_received'] for ['direct_message','direct_mention','mention']

liornaar commented 7 years ago

When I do that this is what I get in debug

debug: No handler for message_received

ghost commented 7 years ago

As i said, i really don't like 'message_received' because it is triggered with a lot of actions. DON'T USE IT. Use

controller.hears(['hi', 'hello', 'bot', 'whats up', 'sup'], ['direct_message','direct_mention','mention'], function (bot, message) {
    bot.reply(message, 'Hi there!');
});
liornaar commented 7 years ago

This is what I did, and that's what I get in the debug output when sending a message... and no message is sent back...

alexbudin commented 7 years ago

Can you try this one:

controller.hears(['quick'], 'message_received', function(bot, message) {

    bot.reply(message, {
        text: 'Hey! This message has some quick replies attached.',
        quick_replies: [
            {
                "content_type": "text",
                "title": "Yes",
                "payload": "yes",
            },
            {
                "content_type": "text",
                "title": "No",
                "payload": "no",
            }
        ]
    });

});

What do you get?

Also have you tried updating your botkit framework to 0.4.2 ?

thierryskoda commented 7 years ago

@EloyRedondo does ['direct_message','direct_mention','mention'] is supposed to work only for Slack? In Facebook we don't have any direct_mention or mention

ghost commented 7 years ago

@thierryskoda Yes, I was wrong... :(

itamarro commented 7 years ago

This happens to me as well - with a Slack bot. It doesn't always happen - it usually happens after a while the bot is already running. Just bumped into this and will try to collect more details and update.

Dan-Wood commented 7 years ago

Happening here using Facebook Messenger.

The only way around this that I've found is to detect the User ID of the bot and force it to ignore it in a hears()

A few ways to get the ID.

Print the id for all users, when the bot repeats it'll show it's own ID and you can block it

Bot.hears('.*', 'message_received', function(speech, message) {
    console.log(message.user); // when the bot repeats the message it'll output it's ID

    if (message.user == 234234234234) return;

    speech.reply(message, 'Hello');
});

Another option if you're using Messenger.com is to look at the URL when you're talking to the bot eg https://www.messenger.com/t/1333481079742333 where 1333481079742333 is the ID

itamarro commented 7 years ago

So, have been experiencing this with a Slack bot and unsure how to reproduce consistently or what the cause is. Below is the debug log output. What happened is that the user sent "here?" once, but the bot heard it three times.

Any insights would be appreciated.

0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: No handler for usertyping 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: No handler for usertyping 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: No handler for usertyping 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: I HEARD [ /^here/i, /are you there/i, /are you here/i ] 0|newsbot | debug: SAY { text: 'For you - always.', channel: 'D1JKYB259' } 0|newsbot | debug: chat.postMessage { type: 'message', 0|newsbot | channel: 'D1JKYB259', 0|newsbot_ | text: 'For you - always.', 0|newsbot | username: null, 0|newsbot | parse: null, 0|newsbot_ | linknames: null, 0|newsbot | attachments: null, 0|newsbot_ | unfurllinks: null, 0|newsbot | unfurlmedia: null, 0|newsbot | iconurl: null, 0|newsbot | iconemoji: null, 0|newsbot | asuser: true, 0|newsbot | token: '*' } 0|newsbot | info: ** API CALL: https://slack.com/api/chat.postMessage 0|newsbot | debug: No handler for heardtrigger 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: I HEARD [ /^here/i, /are you there/i, /are you here/i ] 0|newsbot | debug: SAY { text: 'For you - always.', channel: 'D1JKYB259' } 0|newsbot | debug: chat.postMessage { type: 'message', 0|newsbot | channel: 'D1JKYB259', 0|newsbot_ | text: 'For you - always.', 0|newsbot | username: null, 0|newsbot | parse: null, 0|newsbot_ | linknames: null, 0|newsbot | attachments: null, 0|newsbot_ | unfurllinks: null, 0|newsbot | unfurlmedia: null, 0|newsbot | iconurl: null, 0|newsbot | iconemoji: null, 0|newsbot | asuser: true, 0|newsbot | token: '*' } 0|newsbot | info: ** API CALL: https://slack.com/api/chat.postMessage 0|newsbot | debug: No handler for heardtrigger 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U033SK4SX D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: I HEARD [ /^here/i, /are you there/i, /are you here/i ] 0|newsbot | debug: SAY { text: 'For you - always.', channel: 'D1JKYB259' } 0|newsbot | debug: chat.postMessage { type: 'message', 0|newsbot | channel: 'D1JKYB259', 0|newsbot_ | text: 'For you - always.', 0|newsbot | username: null, 0|newsbot | parse: null, 0|newsbot_ | linknames: null, 0|newsbot | attachments: null, 0|newsbot_ | unfurllinks: null, 0|newsbot | unfurlmedia: null, 0|newsbot | iconurl: null, 0|newsbot | iconemoji: null, 0|newsbot | asuser: true, 0|newsbot | token: '*' } 0|newsbot_ | info: API CALL: https://slack.com/api/chat.postMessage 0|newsbot_ | debug: No handler for heardtrigger 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO U1JMPP23U D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: Got response null {"ok":true,"channel":"D1JKYB259","ts":"1485560409.001805","message":{"type":"message","user":"U1JMPP23U","text":"For you - always.","botid":"B1JMPP21Y","ts":"1485560409.001805"}} 0|newsbot | debug: No handler for tick 0|newsbot_ | debug: Got response null {"ok":true,"channel":"D1JKYB259","ts":"1485560409.001806","message":{"type":"message","user":"U1JMPP23U","text":"For you - always.","botid":"B1JMPP21Y","ts":"1485560409.001806"}} 0|newsbot | debug: Got response null {"ok":true,"channel":"D1JKYB259","ts":"1485560409.001807","message":{"type":"message","user":"U1JMPP23U","text":"For you - always.","botid":"B1JMPP21Y","ts":"1485560409.001807"}} 0|newsbot | debug: No handler for tick 0|newsbot | debug: No handler for tick 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO undefined D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: No handler for desktopnotification 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO undefined D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: No handler for desktopnotification 0|newsbot | debug: RECEIVED MESSAGE 0|newsbot | debug: CUSTOM FIND CONVO undefined D1JKYB259 0|newsbot | debug: DEFAULT SLACK MSG RECEIVED RESPONDER 0|newsbot_ | debug: No handler for desktop_notification

itamarro commented 7 years ago

By the way, the above suggested solution for FB Messenger doesn't seem to be applicable to the Slack module. The code there already checks if the message sender is the bot, in Slackbot.js:

                    if (message.user == bot.identity.id && message.bot_id) {
                        return false;
                    }
Dan-Wood commented 7 years ago

@itamarro could it be that bot.identity isn't set? Or message.bot_id for that matter.

itamarro commented 7 years ago

@Dan-Wood bot.identity is set correctly. _message.botid isn't set, but both messages seem to be coming from the actual user per the user ID in them - it seems like the sender isn't the bot.

I've compared the double messages and sadly they seem almost the same. The only different values are two members of Receiver (member of the WebSocket): expectBuffer and processing. Haven't yet looked at Botkit code to see if this is of any use for me to hack around or understand what's going on, but I'm not too optimistic given that it's the websocket internals. Insights welcome :)

itamarro commented 7 years ago

So, this issue seems related: https://github.com/howdyai/botkit/issues/393

What I'll do is simply store the last TS for each kind of the message my bot handles, if I receive it again with the same TS I'll ignore it. FYI.

jonchurch commented 7 years ago

@itamarro your logs show you getting user_typing events. Are you listening to message_received or direct_mesage or similar in the following way?

controller.on('message_received', function(bot, message) { //code }

itamarro commented 7 years ago

@jonchurch It's a Slack bot - I use: controller.hears(expression, 'direct_message,direct_mention,mention', function(bot, message) { ... });

Note that I usually do not get double messages. It sometimes starts happening after a long while that the bot has been connected. My workaround above fixes the situation. I probably need to have it performed for in-conversation messages too, have not done that yet, need to look where is best to elegantly put that check in there.

jonchurch commented 7 years ago

What version of botkit are you on? Are you using RTM, Events API, or both?

Its not too messy to check for this with events api, Id define a modified controller.handleWebhookPayload() function (from Slackbot.js) to check before the message is processed.

Still not sure what exactly causes this, a few people have reported this issue being solved at different points. On Tue, Feb 14, 2017 at 11:31 PM Itamar Rogel notifications@github.com wrote:

@jonchurch https://github.com/jonchurch It's a Slack bot - I use: controller.hears(expression, 'direct_message,direct_mention,mention', function(bot, message) { ... });

Note that I usually do not get double messages. It sometimes starts happening after a long while that the bot has been connected. My workaround above fixes the situation. I probably need to have it performed for in-conversation messages too, have not done that yet, need to look where is best to elegantly put that check in there.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/howdyai/botkit/issues/473#issuecomment-279914427, or mute the thread https://github.com/notifications/unsubscribe-auth/AMUR25nyX1P2RwRyoZGmhSCIggz56C77ks5rcn-dgaJpZM4KnYFB .

itamarro commented 7 years ago

I'm using 0.4.10. This happens with RTM, so the event isn't fired via a webhook (may have misunderstood you there).

jonchurch commented 7 years ago

Mmkay, I think unfortunately this is a flaw in the RTM itself, and not something in Botkit. Ive seen people come to that conclusion and switching to Events API has solved it.

In the meantime, it sounds like this is a great feature to add as a PR, so people can avoid this once and for all.

Curious what rtm is giving you that events api cant, is it typing indicators? Im curious about what youre building 💡 On Wed, Feb 15, 2017 at 1:19 AM Itamar Rogel notifications@github.com wrote:

I'm using 0.4.10. This happens with RTM, so the event isn't fired via a webhook (may have misunderstood you there).

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/howdyai/botkit/issues/473#issuecomment-279927001, or mute the thread https://github.com/notifications/unsubscribe-auth/AMUR29gEkjpyUxUiNSTWQIbx9XQa10doks5rcpkLgaJpZM4KnYFB .

itamarro commented 7 years ago

@jonchurch Thank you! Sadly I suspect you're right and it's an RTM issue... I'll look at creating a PR for that. I'm sure there's a central place in botkit's code where it can be done more elegantly than my 'userland' implementation, any guidance where this might best fit?

From our testing RTM simply gives a more fluid experience. When using the events API there's a noticeable lag, especially when the interaction is more conversational - has it not been the case for you?

Thanks for asking :) We're building an intelligent news bot for Slack. It's not out yet, but it's almost ready for release - you can check it out here or install it from here.

slambdin1 commented 7 years ago

This issue is occurring for me. It happens when the bot has already been authorized to the team, and then someone else comes in and authorizes the bot again. When that happens, it seems there are two bots running that then use the same RTM connection to post to the channel twice. Is there a fix for this or at least a work around?

Update

I was trying to pin down exactly where my issue was stemming from and was able to fix the issue by inserting the below code snippet in SlackBot.js around line: 528 after checking if it's a new team and before updating the DB. This was a quick and dirty fix that I messed around with, but could something similar be implemented?


var bot;

for (var b = 0; b < spawned_bots.length; b++) {
    if (spawned_bots[b].config.id) {
        if (spawned_bots[b].config.id == team.id) {
            // WAIT! We already have a bot spawned here.
            // so instead of using the new one, use the exist one.
            bot = spawned_bots[b];
        }
    }
}

if (!bot) {
    bot = slack_botkit.spawn(team);

    if (auth.incoming_webhook) {
        auth.incoming_webhook.token = auth.access_token;
        auth.incoming_webhook.createdBy = identity.user_id;
        team.incoming_webhook = auth.incoming_webhook;
        bot.configureIncomingWebhook(team.incoming_webhook);
        slack_botkit.trigger('create_incoming_webhook', [bot, team.incoming_webhook]);
    }

    if (auth.bot) {

        team.bot = {
            token: auth.bot.bot_access_token,
            user_id: auth.bot.bot_user_id,
            createdBy: identity.user_id,
            app_token: auth.access_token,
        };
        bot.configureRTM(team.bot);
        slack_botkit.trigger('create_bot', [bot, team.bot]);
    }
}
jonchurch commented 7 years ago

@slambdin1 Take a look at issue #663 and PR #694 as a means to potentially address this issue

MathRobin commented 7 years ago

Hi, I've exactly the same problem but with Sparkbot. Didn't try with Slack, maybe it comes from CoreBot

Abgaryan commented 7 years ago

Hi, I've exactly the same problem with facebook bot.

Dan-Wood commented 7 years ago

@Abgaryan

I posted a solution for this just above.

https://github.com/howdyai/botkit/issues/473#issuecomment-272678228

Alternatively you can use

if(message.is_echo) return; // If the message is from our bot, we ignore it.

Which seems to work just fine for me.

benbrown commented 6 years ago

As of v0.6.1, message echos no longer trigger message_received in Facebook. This should reduce the amount of confusion about who sent the message.