Hubot Adapter for Discourse


(Jeff Wong) #1

I built a Hubot adapter for Discourse.

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.

(This kind of thing might belong in #plugin:extras – if so please move!)


Create Own Bots?
Reply bot for Discourse?
Setting up a smart chatbot on discourse :robot:
Discobot for training
Automated Discobot Replies
Question about Discobot
Customization of Discobot
(Sam Saffron) #2

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


(Jeff Wong) #3

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.


(Jeff Wong) #4

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.


(Jan P.) #5

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: hubot-discourse-adapter/discourse.js at master · janpio/hubot-discourse-adapter · GitHub [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?

(Jeff Wong) #6

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!


Discobot for training
(Jan P.) #7

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.


(Jeff Wong) #8

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.


(Jeff Wong) #9

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!


(Timothy Vail) #10

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. Babble - A Chat Plugin

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.


(Jeff Wong) #11

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:


(Timothy Vail) #12

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.


(Jeff Wong) #13

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.


(Timothy Vail) #14

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!' }

(James Kiesel) #15

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:


(Jeff Wong) #16

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:

“reply” uses the reply_to_post_number parameter, which works great for standard topics, but appears to not get handled well in Babble land.


(James Kiesel) #18

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?


(Jeff Wong) #19

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.


(Timothy Vail) #20

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.


(Jeff Wong) #21

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.