Hubot Adapter for Discourse

I built a Hubot adapter for Discourse.

https://github.com/featheredtoast/hubot-discourse-adapter

This should work moderately well for communities that desire bot integrations. There are a few gotchas (see the readme) but for the most part it has been pretty incredible to tinker with so far.

Something my community desired was a dice roller, which I knew existed as a hubot plugin. While there have been other attempts at integrating dice rollers into discourse, if I was going to run a bot against my Discourse instance, I wanted the full power of hubot plugins at my disposal. My aim here was to have there be an easy way to integrate such reply features into a Discourse community using an existing and well known bot.

This adapter is about adding a bot that directly listens in to topics and replies in Discourse itself. It differs from a previous Hubot integration topic as that seemed to be aimed at querying a discourse community in an existing integration (irc, slack, etc) to get discourse stats, and possibly post to a remote Discourse instance.

The bot now polls for messages over Discourseā€™s message bus.

I created the repository as hubot-discourse-integration, as hubot-discourse was already takenā€¦ Sadly this also had no documentation, code, or announcements here. I wasnā€™t inclined to trust it, so I built this.

17 Likes

You really should use the message bus here, its both faster and significantly less resource intensive.

5 Likes

Ah right, thanks for the tip! Iā€™ll look into that today ā€“ Iā€™ve been putting off learning more about the message bus in general, just to get things working.

1 Like

Alright, I have practically torn apart your message-bus javascript client and adapted it for node and itā€™s working great! Polling is now done over message bus, so it should be a lot more responsive now! :thumbsup:

One more question - Is there any way for me to get the current user, given a user API key? It would be great if a 3rd party app could figure out their own username + id without having to configure it separately.

6 Likes

So, hey, hi, you sent me here in my topic asking for bots.

This bot can jump in if he is @ mentioned in a topic and then do *** magic *** which can then ouput in a post in that topic. Correct?

(Thank god for http://js2.coffee/ by the way: https://github.com/janpio/hubot-discourse-adapter/blob/master/src/discourse.js [my terrible JS is better than my non-existant Coffescript])

Some absolute newbie questions:

  • Can you show how you for example would configure it to do the dice rolling thing you mentioned above?
  • Is the adapter also able to receive/read all new topics being created? (or would I have to modify it to do this?)
  • Is there a diagram/flowchart/list online somewhere which methods of your adapter are called in which order when?

Hubot can be configured with both pre-written plug-in scrips, as well as ad-hoc scripts. You can get started with hubot pretty quickly over commandline for local barebones testing of responses. This adapter is only here to allow it to ā€œspeakā€ and respond over discourse.

I ended up splitting up my bot from my custom configuration, so that I could run tests against my custom scripts.

The dice roller can be seen here and I have an additional (and much simpler) ā€œif you here anything about ā€˜the dealsā€™ respond in kindā€ script for fun.

You can set it up that way - The adapter responds via discourseā€™s native notifications. Basically, if thereā€™s a discourse notification of a message, the bot will see it. In the botā€™s Discourse profile, you can edit and add to the watched categories to allow it to automatically see new topics/replies/etc without a direct @.

EG: for your use case, you would probably want to add your interested categories to ā€œwatching first postā€ and set the ā€œwhen I post in a topic set that topic toā€ normal. That way, the bot gets notified on new topics, but does not continue to monitor/reply afterwards.

Not currently - It follows the same patterns from other hubot adapters - aside from setting up what hubot ā€œhearsā€ in discourse, you really shouldnā€™t have to mind much about the internals. Mostly youā€™d be interested in the API, and the difference between function hooks like robot.hear vs robot.respond. See the docs for examples!

1 Like

Thanks for replying, will take a deeper look later.

While reading I got an idea: Can your adapter already send private messages instead of post to topics? ā€œModerating in privateā€ might be an interesting concept to have to call out the people in public but nudge them to add the information in private.

Not currently; it was out of my use case, but it would be possible to extend/ modify how the bot replies to send private messages rather than replying inline.

2 Likes

Little bit of work on this tonight ā€“

Itā€™s admittedly a little bit of a custom workaround as hubot doesnā€™t currently have a concept of PM replying, so Iā€™m relying on a ā€œpmā€ attribute to be set in res.envelope to imply that we want the bot to respond privately.

Hereā€™s an example:

robot.hear /private hello/i, (res) ->
    res.envelope.pm = true
    res.send "I will reply hello privately!"

The new PM is titled ā€œAbout your post in {topic title}ā€, and has the first line as the URL to the topic in question.

If the bot is already hearing a message within a PM, it replies as normal.

It would be nice if Hubot had the concept of a whisper, but thatā€™s unfortunately out of my hands at the moment.

I also added the ability to arbitrarily add messages to other topics, or trigger sending of messages by way of the robot.messageRoom action to be able to generate PMs or reply to arbitrary topics by topic number.

Hope this helps!

2 Likes

Hi @awole20, I got everything set up, thanks a million for this adapter! It works great, but my hubot canā€™t respond or operate in the chat box made possible by the Babble plugin. https://meta.discourse.org/t/babble-a-chat-plugin/31753

Is there a way to get it working in there? I set the bot to the room but it doesnā€™t hear/ pick up anything from the chat channel.

Iā€™m assuming you are expecting the bot to respond to an unprompted reply. You need to ā€œbecomeā€ the bot (admin ā†’ users) and add that topic to ā€œwatchingā€ as stated above:

3 Likes

I understand that, and I think it sees it but canā€™t send a message somehow. The problem is that it doesnā€™t operate like a regular topic, because you canā€™t ā€œwatchā€ it. Maybe @gdpelican , the plugin creator, could provide some insight.

Oh I understand now - sorry, I donā€™t have much experience with the ins and outs of babble, and have not attempted to set up a Hubot to listen in on a Babble install. If Babbleā€™s notification flow is outside of the normal Discourse notifications, that would block your bot from seeing those messages.

1 Like

It seems it sees it somehow, but canā€™t send back, in my console, this is what I get

[Tue Mar 06 2018 00:51:58 GMT+0000 (UTC)] INFO Constructor
[Tue Mar 06 2018 00:51:58 GMT+0000 (UTC)] INFO Run
[Tue Mar 06 2018 00:51:58 GMT+0000 (UTC)] INFO /var/discourse/hubot/scripts/test.js is using deprecated documentation syntax
[Tue Mar 06 2018 00:51:59 GMT+0000 (UTC)] INFO hubot-redis-brain: Using default redis on localhost:6379
[Tue Mar 06 2018 00:52:11 GMT+0000 (UTC)] INFO got notification:  { notification_type: 1,
  post_number: 6,
  topic_title: 'Test',
  topic_id: 38,
  excerpt: '@hubot hi',
  username: 'TimothyVail',
  post_url: '/t/test/38/6' }
[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Emitting robot action: greeting, {}
[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Reply { topic_id: 38,
  reply_to_post_number: 6,
  message: 'How\'s it going?' }
[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Reply { topic_id: 38, reply_to_post_number: 6, message: 'Hi there!' }

I think this is pretty close to working out of the box, but Iā€™m missing some bit of context or code here to get a fix.

This line:

[Tue Mar 06 2018 00:52:11 GMT+0000 (UTC)] INFO got notification:  { notification_type: 1,

gets called in hubot-discourse-adapter/discourse.coffee#100, which then calls this.emit with some info.
That info then goesā€¦ somewhere (to the script youā€™ve written for your bot?), which is then seemingly creating a post, but not emitting properly to the server (babble operates on a separate message bus channel from regular topics). So the bit that Iā€™m missing is 'where is the code which generates the lines beginning with ā€˜Emitting robot action: greetingā€™?

[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Emitting robot action: greeting, {}
[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Reply { topic_id: 38,
  reply_to_post_number: 6,
  message: 'How\'s it going?' }
[Tue Mar 06 2018 00:52:12 GMT+0000 (UTC)] INFO Reply { topic_id: 38, reply_to_post_number: 6, message: 'Hi there!' }

Disclaimer: Iā€™m not familiar with hubot at all :sweat_smile:

1 Like

So something strange is going on with babbleā€™s handling of replying via the API. Hereā€™s a rundown:

The ā€œemitting robot actionā€ log there is in his script. Hubot adapters work by ā€œhearingā€ messages that emit messages to a userā€™s script to handle them (Containing such logic as hearing ā€œhelloā€ I want to reply with ā€œoh hi thereā€). The script has hooks to ā€œreplyā€ or ā€œrespondā€ again using the adapterā€™s say or reply method.

Those methods in my adapter simply hook into the Discourse posts.json API endpoint here:

https://github.com/featheredtoast/hubot-discourse-adapter/blob/master/src/discourse.coffee#L142

ā€œreplyā€ uses the reply_to_post_number parameter, which works great for standard topics, but appears to not get handled well in Babble land.

2 Likes

What is the result of that post? It seems to me like the most likely thing thatā€™s happening is that the /posts.json call is creating the post just fine, but that the core Discourse code isnā€™t able to broadcast to the babble message channel. @Timothy_Vail are you able to figure out whether that /posts.json call actually creates a post or not, and if not, what the response to that request is?

1 Like

I donā€™t currently log thatā€¦ :zipper_mouth_face:

Iā€™ll spin up a babble dev instance soon to dig into the cause of this, and make the bot and plugin be a little more friendly - I think it would be excellent if Babble and Hubot ā€“ both intending to be used as ā€œchatā€ like features ā€“ played well together.

2 Likes

Sometimes it responds in the chat, but most of the time not. It responded two or three times, but like an hour or more later. In the private messages it was immediate.

So after some testing, it definitely appears that Babbleā€™s message channel doesnā€™t expect post replies via the API. The response to the /post.json is that itā€™s fine, 200 OK, with the body containing the details of the new post as expected.

I went ahead and installed a test Discourse env with Babble, and wired up a Hubot to communicate with. The Hubot reply posts will show up in the correct order, but only after a refresh. Before that, itā€™s like the bot isnā€™t saying anything. After refreshing the page, all of Hubotā€™s messages show up in the correct order.

Willing to work with you if Iā€™m able to in order to get this resolved - Iā€™m on the opposite side, where Iā€™m not familiar with Babbleā€™s message notification systems at all.

2 Likes