microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.
MIT License
7.48k stars 2.44k forks source link

Slack bot receives duplicate messages #3515

Closed IanLeatherbury closed 6 years ago

IanLeatherbury commented 6 years ago

Bot Info

Issue Description

I receive 2 messages with each Slack message sent via Direct message to bot.

It works fine on the emulator. It is also being reported here and here

Code Example

        /// receive a message from a user and send replies
        /// </summary>
        /// <param name="activity"></param>
        [ResponseType(typeof(void))]
        public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
        {
            if (activity != null)
            {
                // one of these will have an interface and process it
                switch (activity.GetActivityType())
                {
                    case ActivityTypes.Message:
                        await Conversation.SendAsync(activity, MakeRootDialog);                       
                        break;

                    case ActivityTypes.ConversationUpdate:                
                    case ActivityTypes.ContactRelationUpdate:
                    case ActivityTypes.Typing:
                    case ActivityTypes.DeleteUserData:
                    default:
                        Trace.TraceError($"Unknown activity type ignored: {activity.GetActivityType()}");
                        break;
                }
            }
            return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
        }
    public class CompetitionEntry
    {
        [Prompt("Which team would you like to vote for? {||}")]
        public CompetitionEntries? Entry;

        public static IForm<CompetitionEntry> BuildForm()
        {
            return new FormBuilder<CompetitionEntry>()
                    .Message("Welcome to the Intelligent Cloud Competition Voting Bot!")
                    .OnCompletion(async (context, entry) =>
                    {
                    context.UserData.SetValue<string>(  
                        "Entry", entry.Entry.ToString());
                        await context.PostAsync("Thanks for voting!");
                    })
                    .Build();
        }
    };

Reproduction Steps

  1. Deploy bot.
  2. Send 1 message directly to the bot.

Expected Behavior

Receive 1 reply

Actual Results

Receive 2 replies

Note ""@votebot2 hello" is not an entry option." image

IanLeatherbury commented 6 years ago

Also, the issue persists after updating to Microsoft.Bot.Builder 3.9.1.

JasonSowers commented 6 years ago

I am trying to reproduce, where are you calling CompetitionEntry from? also can you share the code for this type CompetitionEntries

IanLeatherbury commented 6 years ago

Calling from MessagesController:

namespace Microsoft.Bot.Sample.FormBot
{
    [BotAuthentication]
    public class MessagesController : ApiController
    {
        internal static IDialog<CompetitionEntry> MakeRootDialog()
        {
            return Chain.From(() => FormDialog.FromForm(CompetitionEntry.BuildForm));
        }

        /// <summary>
        /// POST: api/Messages
        /// receive a message from a user and send replies
        /// </summary>
        /// <param name="activity"></param>
        [ResponseType(typeof(void))]
        public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
        {
            if (activity != null)
            {
                // one of these will have an interface and process it
                switch (activity.GetActivityType())
                {
                    case ActivityTypes.Message:
                        await Conversation.SendAsync(activity, MakeRootDialog);                       
                        break;

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

CompetitionEntry

namespace Microsoft.Bot.Sample.FormBot
{
    public enum CompetitionEntries
    {
        XamCam, Hunt, PhotoSharing, Partner, Ent2
    };

    [Serializable]
    public class CompetitionEntry
    {
        [Prompt("Which team would you like to vote for? {||}")]
        public CompetitionEntries? Entry;

        public static IForm<CompetitionEntry> BuildForm()
        {
            return new FormBuilder<CompetitionEntry>()
                    .Message("Welcome to the Intelligent Cloud Competition Voting Bot!")
                    .OnCompletion(async (context, entry) =>
                    {
                    context.UserData.SetValue<string>(  
                        "Entry", entry.Entry.ToString());
                        await context.PostAsync("Thanks for voting!");
                    })
                    .Build();
        }
    };
}
IanLeatherbury commented 6 years ago

Also, I just followed this guide, this bot was just created from the FormBot template in the Azure portal, and I just changed some classes (namely, the Sandwich class) to fit my use case. You can probably just create and deploy that sample to reproduce the results.

JasonSowers commented 6 years ago

I tried much of the day, but unfortunately, I am unable to reproduce with the sample or the code given. It seems to work as intended.

image

I'm going to put my code in this repo can you please check it against yours and see if there is anything different, this may lead you to a fix.

IanLeatherbury commented 6 years ago

Interesting. Thanks for looking into it! I'll check against that repo.

JasonSowers commented 6 years ago

Let me know how it works out, we can keep looking into this if you still have the issue.

gcsonka commented 6 years ago

Hello, I am having the same issue in one (1) slack channel. I am getting multiple messages from that particular channel. However, all other Slack Channels, as well as Skype, Telegram and Facebook channels, are working fine.

This might be an issue with how some Slack users add the bot to their Slack instance. I suspect somehow during the OAuth between Slack and bot framework, 2 channels (Real Time API ?) are opened for the same user.

I don't know for sure, but I have tried everything I could and could not reproduce this user's issue. Even developed some code to detect rapid requests as attacks- but it is not the right way to deal with this issue.

Previously I could find the issue why, but I still don't have a way of detecting and solving this programmatically: https://stackoverflow.com/questions/46165894/microsoft-bot-framework-bot-duplicate-responses-in-slack/46166173#46166173

**

**

IanLeatherbury commented 6 years ago

Strangely enough the issue I was having resolved itself. I didn't change anything on my end, but it stopped happening, so I suspect there was some issue in the backend.

Petah commented 2 years ago

FWIW I had the same issue, it turns out the messages were getting retried because of a error response to the event API. You can check this using the x-slack-retry-num header.