the robot does not seem to react to messages sent by himself
docteurklein opened this issue · 14 comments
I'm not exactly sure why, but I'd like this to implement the !!
operator.
> gif me party hard
> http://giphy.net/funny-gif
> @alfred !!
> gif me party hard
> http://giphy.net/another-funny-gif
Currently, the bot sends the message, it is displayed, and the logs show it has arrived.
But the bot does not react. It seems to ignore himself.
Any ideas?
I'm not sure I understand what you're trying to do. Wouldn't that cause a loop?
it wouldn't.
I really only want the bot to re-interpret the last thing I messaged him.
So if I message him "!!", he should execute any responder that matches the last message I sent him.
There is an implementation of that in hubot, I just can't find the sources yet.
Shouldn't that just be a case of saving history in a separate process? Then '!!' could just query the latest history entry, and '!43' could re-apply entry #43, etc. It's probably better to feed it back to the bot internally, than take the indirect route over the chat room.
If the bot were to trigger on its own messages, it would indeed be very easy to cause a loop..
@jwarlander Agreed, and that's how I tried to implement it.
I have implemented a brain, (that is a simple KV store, named process).
I have a responder that hears any command (and store the last thing he hears in the brain).
I have another responder that listens to "!!" and answers with the last heard thing.
Strangely, it does not react to the last message (sent by himself)
I still didn't get it to work, but I'll post my attempts here.
Instead of making a round-trip and let the bot hear what he just said, I tried to directly ask him to interpret what was stored:
defmodule Edgar.Responder.NotNot do
use Hedwig.Responder
respond ~r/(.*)/i, msg do
case msg.matches[1] do
"!!" -> ""
_ -> Edgar.Brain.memorize(:lastmsg, msg.matches[1])
end
end
respond ~r/!!/i, msg do
remembered_msg = %{ msg | text: Edgar.Brain.remember(:lastmsg) }
pid = Hedwig.whereis("edgar")
send msg, Edgar.Robot.send(pid, remembered_msg)
end
end
getting an error:
16:58:20.481 [error] Task #PID<0.306.0> started from #PID<0.264.0> terminating
** (ArgumentError) argument error
:erlang.send(:undefined, {:"$gen_cast", {:send, %Hedwig.Message{adapter: {Hedwig.Adapters.Console, #PID<0.265.0>}, matches: %{0 => "@edgar !!"}, private: %{}, ref: #Reference<0.0.3.3237>, robot: %Hedwig.Robot{adapter: #PID<0.265.0>, aka: "@edgar", name: "Edgar Bot", opts: [robot: Edgar.Robot, otp_app: :edgar, responders: [{Hedwig.Responders.Help, []}, {Hedwig.Responders.Panzy, []}, {Hedwig.Responders.GreatSuccess, []}, {Hedwig.Responders.ShipIt, []}, {Edgar.Responder.Giphy, []}, {Edgar.Responder.NotNot, []}, {Edgar.Responder.Weather, []}, {Edgar.Responder.ItIsSomething, []}, {Edgar.Responder.OhYou, []}, {Edgar.Responder.TIL, []}, {Edgar.Responder.Bookmark, []}], adapter: Hedwig.Adapters.Console], responders: []}, room: nil, text: "it's something", type: "chat", user: "florian"}}})
(elixir) lib/gen_server.ex:639: GenServer.do_send/2
(edgar) lib/edgar/responder/NotNot.ex:26: Edgar.Responder.NotNot."__!!__"/2
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:40: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<2.28577963/0 in Hedwig.Responder.run_aysnc/2>
Args: []
Any idea how I should implement that?
@docteurklein what about calling Hedwig.Robot.handle_message/2
?
https://github.com/hedwig-im/hedwig/blob/master/lib/hedwig/robot.ex#L183-L185
And it looks like in your case that Hedwig.whereis("edgar")
is returning :undefined
. So it's not registered.
You should probably store the whole message in your brain process, instead of just the matches. Then you can run the whole message through Hedwig.Robot.handle_message(robot, msg)
Looks like the Console
adapter doesn't register the bot...so that's why you're getting :undefined
Thanks! I will try your propositions.
Hedwig.Robot.handle_message(robot, msg)
is casting, so I just get :ok
as a return value.
How could I get what is sent back by the responder that matches msg
?
mmh, now I get a working test with this code, but not with the console adapter:
code
respond ~r/!!/i, msg do
pid = Hedwig.whereis("Edgar Bot")
remembered = Edgar.Brain.remember(:lastmsg)
send msg, Hedwig.Robot.handle_message(pid, %{
remembered | robot: %{
remembered.robot | adapter: msg.robot.adapter
}
})
end
test (green)
@tag start_robot: true, name: "edgar", responders: [{Edgar.Responder.NotNot, []}, {Hedwig.Responders.Help, []}]
test "!! repeats last command", %{adapter: adapter, msg: msg} do
send adapter, {:message, %{msg | text: "edgar help"}}
send adapter, {:message, %{msg | text: "edgar !!"}}
assert_receive {:message, %{text: text}}
assert String.contains?(text, "help")
end
console adapter error:
00:53:02.115 [error] Task #PID<0.266.0> started from #PID<0.265.0> terminating
** (ArgumentError) invalid ANSI sequence specification: :ok
(elixir) lib/io/ansi.ex:167: IO.ANSI.format_sequence/1
(elixir) lib/io/ansi.ex:218: IO.ANSI.do_format/5
(hedwig) lib/hedwig/adapters/console.ex:109: Hedwig.Adapters.Console.Connection.print/1
(hedwig) lib/hedwig/adapters/console.ex:87: Hedwig.Adapters.Console.Connection.loop/3
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: &Hedwig.Adapters.Console.Connection.loop/3
Args: [#PID<0.265.0>, "florian", "Edgar Bot"]
Not sure I'm on the good path.
Also, if you think this issue is getting nowhere, or should be discussed elsewhere, don't hesitate to tell me :)
PS: I've locally modified the console adapter to do like the test one, i.e registering itself :after_init
, so that i don't get an :undefined
pid.
The bot is now registered in the console adapter under the :name
field in the config.
Ok...so I"ve been able to get this all working...
Hedwig Console - press Ctrl+C to exit.
The console adapter is useful for quickly verifying how your
bot will respond based on the current installed responders
scrogson> alfred hey
alfred> sup?
scrogson> alfred !!
alfred> sup?
scrogson>
Here's the NotNot
responder:
defmodule Alfred.Responders.NotNot do
use Hedwig.Responder
respond ~r/(.*)/i, msg do
case msg.matches[1] do
"!!" -> ""
_ -> Alfred.Brain.put(:lastmsg, msg)
end
end
respond ~r/!!/i, _msg do
msg = Alfred.Brain.get(:lastmsg)
pid = Hedwig.whereis("alfred")
Hedwig.Robot.handle_message(pid, msg)
end
end
Awesome! many thanks. Closing now.