hedwig-im / hedwig

An Adapter-based Bot Framework for Elixir Applications
MIT License
650 stars 73 forks source link

A single message can trigger multiple responses #64

Open wasnotrice opened 7 years ago

wasnotrice commented 7 years ago

Hi, thanks for Hedwig. I've learned a lot from it already :)

I have a bot that I want to respond to both overheard and direct messages of the same kind, but respond differently to direct messages. For example:

me: @a_friend tell me what you think!
bot: yes, do tell!
...
me @bot tell me what you think!
bot: @me LGTM <3

If I add both a hear and a respond handler that match the same message shape, then for direct messages, both handlers are triggered, which feels weird in the chat:

me @bot tell me what you think!
bot: yes, do tell!
bot: @me LGTM <3

Ideally, in this case, I'd like Hedwig to only execute the respond handler. Maybe it makes sense to execute the hear handler if no respond handler matches, but maybe it makes sense to only consider hear handlers for overheard messages.

I'd be happy to pursue this if it seems like a good change. Cheers!

scrogson commented 7 years ago

@wasnotrice can you show me your regexes for your hear and respond? You may just need to build them with a bit more care.

The way the responders work is completely async. Each incoming message is dispatched to all responders. If a message matches a responder it will be run.

wasnotrice commented 7 years ago

@scrogson here's an example set of hear/respond invocations with regexes:

  hear ~r/let (.*) know/, message do
    sendRandomKnowledge message
  end

  respond ~r/let (.*) know/, message do
    replyOrEmoteRandomly message
  end

As you see, the regexes are the same. I guess my confusion comes from the fact that I don't expect the hear responder to fire in the case where the regex matches, but the message is addressed to my bot. In that case, I only expect the respond responder to fire. Likewise, if the regex matches, but the message is not addressed to my bot, then I expect the hear responder to fire and not the respond responder.

I don't think I articulated the issue well initially. You're right, of course, the responders are async so it doesn't make sense to talk about "if no respond handler matches". The issue is really that (according to my mental model) hear responders should only match messages that are not addressed to the bot, and respond responders should only match messages that are addressed to the bot.

Am I thinking about it all wrong?

scrogson commented 7 years ago

@wasnotrice re-writing your hear responder to this should work:

hear ~r/^let (.*) know/i, msg do
  send_random_knowledge msg
end

That would ensure that it would only respond if the message begins with let.

In any case, I guess I would need to see where other use-cases might really require a different implementation than I currently have.

krekbot commented 7 years ago

@scrogson hmmmmm, I see how anchoring the regex would filter out direct messages, so that is a workaround. But it would also mean that I can't match a message like please let me know.

I could write a much more complicated regex that filtered out only messages starting with my bot's name/alias, but I'm looking for the framework to provide a macro for that, rather than having to code the regex for individual responders. If hear is specifically designed to have this behavior, maybe there is the possibility of adding a third macro like overhear, which would only fire for messages that are not addressed to the bot? I guess I could just write that here in my bot. Maybe that's a good place to start if it doesn't fit into Hedwig just yet.

FWIW, I am porting these responders from a Hubot bot, where they work as I expect (i.e. the hear responder does not fire on direct messages).

Thanks!

scrogson commented 7 years ago

@krekbot,

Gotcha. I will work on a solution. Thanks.

wasnotrice commented 7 years ago

@scrogson thanks! happy to pitch in and/or draft something if its helpful :)