Josh Lospinoso home posts about
Setting Up a Matterbot with Slack via ngrok October 14, 2016
Running a Matterbot on Slack with ngrok

When matterbot was introduced, we configured it to work with an instance of Mattermost that we hosted. In this post, we’ll get it working with Slack, which will already hosted be for us. The major challenge is that your bot may not be routable from Slack’s servers (i.e. the internet). If you are behind a firewall, NATed behind a router, etc., you will be able to POST messages into chatrooms via incoming webhooks but you won’t receive messages from Slack when people try to trigger your bot. ngrok is a beautiful solution for situations like this. After signing up and downloading a client, you’ll get a subdomain that will tunnel traffic to you (even if you aren’t routable!)


Setting up an account with ngrok is simple and free. Just follow the instructions, then download the client. I put the client binary on my PATH so that I can invoke it from anywhere in my command prompt (I suggest that you do the same).

Once you’ve signed up for an account and you’ve downloaded the client, you’ll need to install your authtoken (this will be available from your dashboard.) Just run ngrok with the issued token:


Now, you’ll be able to expose any local port you’d like to the internet (be careful!) We are about to bind Matterbot to local port 8000, so all you need to do is issue the command

ngrok http 8000

You’ll end up with some output that looks like this:

ngrok by @inconshreveable                  (Ctrl+C to quit)

Session Status                online
Account                       Josh Lospinoso (Plan: Free)
Version                       2.1.14
Region                        United States (us)
Web Interface       
Forwarding           -> localhost:8000
Forwarding           -> localhost:8000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

You can navigate to in your browser, and you’ll be able to interact with ngrok through a nice web app. Notice that you’ve now got an internet-routable domain that is mapped to a local port on your machine! In my case, it’s

Unless you have a paid plan with ngrok, this subdomain will change whenever you restart ngrok. Keep this in mind as you’re developing!


Now, sign up for a Slack account. You’ll need administrative privileges to enable webhooks for Matterbot, so create a new team (or continue along with a team that you have administrative privileges for).

  1. From the team homepage, click the top-right icon to get into the drop-down menu.
  2. Select “Apps & Integrations”. Alternatively, just point your browser to where MY-TEAM-NAME is the appropriate subdomain.
  3. In the search bar, type “Incoming WebHooks” and click on the Incoming WebHooks icon when it pops up.
  4. Click on “Add Configuration”
  5. Choose the channel you’d like the Matterbot to interact with in the drop-down menu.
  6. Click on “Add Incoming WebHooks integration.”
  7. Surf right over all the setup instructions (Matterbot will handle all of these details for you!) Save the “Webhook URL”. You’ll need this when setting up your Matterbot.
  8. Optionally, you can give your bot a descriptive label, customize its name, give it a custom icon, etc.
  9. When you’re done customizing your bot, click on “Save Settings.”

We are going to follow a similar pattern for the Outgoing WebHooks; go back to the “Apps & Integrations” search, and continue: 10. In the search bar, type “Outgoing WebHooks” and click on the Outgoing WebHooks icon when it pops up. 11. Click on “Add Outgoing WebHooks Configuration” 12. Choose the channel you’d like the Matterbot to interact with in the drop-down menu. This should match the channel you selected for Incoming WebHooks. 13. As in the Mattermost case, you’ll need to choose some trigger words that your bot will respond to. Put these in the “Trigger Word(s)” textbox and separate them with a comma. 14. In the “URL(s)” box, put your internet-routable ngrok URL. In my case, it is Note again that if you restart ngrok on your machine, you will need to change the settings of your Outgoing WebHooks! 15. Save the “Token”. You’ll need this when setting up your Matterbot. 8. Optionally, you can give your bot a descriptive label, customize its name, give it a custom icon, etc. 9. When you’re done customizing your bot, click on “Save Settings.”


You are now ready to build Matterbot and wire it into Slack. Pull down the latest version from github:

git clone

Open matterbot/Matterbot.sln in Visual Studio. In the MatterbotSample project, open main.cpp in Source Files. You’ll notice several TODO sections to fill in. The only requirement to get things up and running is to paste your routes and tokens:

//TODO: Put your own routes and tokens here
wstring mattermost_url = L"", // URL to the incoming webhook for Mattermost/Slack
  incoming_hook_route = L"services/AAAAAAAAA/BBBBBBBBB/CCCCCCCCCCCCCCCCCCCCCCCC", // Route
  outgoing_hook_route = L"", // URL of the box running matterbot
  outgoing_hook_token = L"CCCCCCCCCCCCCCCCCCCCCCCC";

Take the route portion of the URL you copied when setting up your Incoming WebHooks and put this into the incoming_hook_route variable. Put your Outgoing WebHook token into outgoing_hook_token. If you set up ngrok to listen on :8000 then you are all set. If not, modify outgoing_hook_route to bind to the correct port.


Navigate to the slack channel that you’ve configured Matterbot to interact with. Using your trigger word for the bot (mine is matterbot), broadcast this message into the channel:

matterbot help

If all is well, you should receive a helpful message from your bot telling you that it supports the echo command. You can follow up by issuing an echo:

matterbot echo Hello, world!

Your matterbot should echo the given message back to you.

See the original post on Matterbot to see how to write your own functionality into the bot!


Please post any issues or bugs you find!

Twitter Subliminal 0.2.0 September 5, 2016
Twitter Subliminal Now Dockerized

Getting twitter-subliminal setup can be a pain, especially in non-Linux environments. Docker is a great solution for making software portable, and in version 0.2, I’ve Dockerized twitter-subliminal. You still need to signup for Twitter API credentials, but these are now injectable as command line parameters:

docker run -it --rm \
     -e consumer.key="ABCD1234" \
     -e secret.key="ABCD1234" \
     -e access.token="ABCD1234-ABCD1234" \
     -e access.token.secret="ABCD1234" \

By using the -it option, you’ll get an interactive session with the Docker container. The working directory will contain all of the usual binaries available from v0.1.0:

  • tse: message encryption
  • tsd: message decryption
  • tsr: reset all retweets
  • tsp: performance testing for selecting block size
  • tst: unit testing
  • tsl: check rate limit status with Twitter API

You can also run these binaries directly. To send, e.g.:

docker run \
     -e consumer.key="ABCD1234" \
     -e secret.key="ABCD1234" \
     -e access.token="ABCD1234-ABCD1234" \
     -e access.token.secret="ABCD1234" \
     jlospinoso/twitter-subliminal ./tse "Hello, world!"

There are two locations where the twitter-subliminal containers are published:



Please post any issues or bugs you find!

Matterbot June 14, 2016
A C++ Framework for Creating Simple Mattermost/Slack Bots

matterbot is a framework for making Mattermost/Slack bots. It uses the Webhooks APIs exposed by both Mattermost and Slack to send and receive messages. In the twitter-subliminal project, we tried out Poco Libraries to handle our web communications. matterbot tries out something different: Microsoft’s C++ REST SDK a.k.a. Casablanca.

Getting started

First, you’ll need a running Mattermost/Slack service. If you already have one, skip ahead to the next section. For the remainder of the post, we use Mattermost, but the webhook APIs are compatible.

I highly recommend using docker while you are developing your bot. You can set up the service with this one-liner (Note: You should NOT use this command to set up a production instance!):

$ docker run --name mattermost-preview -d --publish 8065:8065 mattermost/mattermost-preview

You can see your docker container’s status with docker ps:

$ docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED
f25bbb6897ca        mattermost/mattermost-preview   "/bin/sh -c ./docker-"   3 minutes ago
     STATUS              PORTS                              NAMES
     Up 3 minutes        3306/tcp,>8065/tcp   mattermost-preview

You’ll note that the container has mapped the docker host’s port 8065. If you point a web browser at http://[my-docker-ip]:8065, you should be greeted with a friendly user signup screen. Follow the on-screen instructions or see the docs to set up a username and a team.

Setting up Webhooks

Once you’ve set up a team, you’ll need to enable webhooks. Full documentation is here, but the gist is that you’ll need to go to the System Console and click “Enable Incoming Webhooks” and “Enable Outgoing Webhooks”. The System Console can be accessed by clicking on the three vertical dots in the upper-left of the team site. It should be the seventh entry from the top in the drop-down menu that appears.

Go back to your team site. Webhooks are created at the team-level. Click again on the three vertical dots, and this time an “Integrations” option should appear. Click it.

You’ll need to create the webhooks individually. First, setup the Incoming Webhook. Click on the Incoming Webhook icon, then click “Add Incoming Webhook”. The display name and description do not correspond to what will actually appear in the chat window–they are just for administrative accounting purposes. Select the channel that you want the bot to post messages into, then click save. Take note of the resulting URL, e.g.:

Next, setup an Outgoing Webhook by clicking on the “Outgoing Webhooks” option under the “Integrations” header at the top of the screen. Click on “Add Outgoing Webhook”. The display name and description are again just for administrative accounting purposes. The “Channel” is actually optional–if you want the bot to listen to all channels, don’t select anything here. The trigger words are important–Mattermost won’t send your bot a message unless it begins with one of the trigger words listed here.

Finally, you’ll need to specify your callback URL. Locate the IP of the machine you’ll be running your matterbot from, and enter it in the “Callback URLs” box, e.g.:

Also take note of the token that gets created for your outgoing webhook, e.g.:

Token: omy7rqidk3dqdqky39yssm4bao

Configure your firewall!

Your bot is going to need to listen to port 80. Configure your firewall to allow this. If you are just running Mattermost in a docker container, you may be able to get away with default firewall rules.

Building an example bot

Pull down matterbot from github:

git clone

Open up Visual Studio as an Administrator (so that you can bind to a local port when debugging). There are two projects in the solution:

  • Matterbot is the project containing the matterbot (static) library.
  • MatterbotSample is the project containing a sample bot

Both libraries require that NuGet has successfully installed the C++ REST SDK. Right click on “References” > “Manage NuGet Packages” > “Installed” and make sure that version 2.8.0 is correctly installed.

MatterbotSample contains one file, main.cpp, but it illustrates the main features of the library. In main(), we create a bot by injecting four parameters:

wstring mattermost_url = L"",
	incoming_hook_token = L"ktjckuh9ptrnmgoiunadsitgmc",
	outgoing_hook_route = L"",
	outgoing_hook_token = L"omy7rqidk3dqdqky39yssm4bao";
Matterbot bot(mattermost_url, incoming_hook_token, outgoing_hook_route, outgoing_hook_token);

These parameters are self explanatory–we set up all the webhooks in the previous section, and you are providing all of the route and token information to the framework here.

Once the bot has been initialized, you can post messages to the channel specified in the Incoming Webhooks by using the following:

bot.post_message(L"Bot is up.");

Easy peasy. But the interesting stuff is in implementing commands. Commands are routines that the bot will run when prompted. These routines give a response, which is posted into the same channel as post_message. Implementing commands is super simple. Just inherit ICommand. MatterbotSample gives an example echo command:

class EchoCommand : public ICommand {
	wstring get_name() override {
		return L"echo";

	wstring get_help() override {
		return L"`echo [MESSAGE]`\n===\n`echo` will respond with whatever
		message you give it.";

	wstring handle_command(wstring team, wstring channel, wstring user,
		wstring command_text) override {
		return command_text;

There are three functions in ICommand:

  • get_name is the command name that the bot will look for when it receives an outgoing webhook. So if we registered our bot to listen for #chatbot, then EchoCommand would get a callback when someone typed #chatbot echo Hello, world!.
  • get_help is an optionally-markdown flavored response that explains to the user how the command works. More on help in a moment.
  • handle_command is a callback whenever Mattermost/Slack alerts us via outgoing webhook that someone has triggered the bot. We get information like the team, channel, and user, as well as the full command text. The wstring result returned by handle_command is sent back by the bot.

You’ll register all of your commands with the bot by passing it a shared pointer:


When a user prompts your bot for help, they will get a listing of all commands supported by the bot, e.g.

user > #chatbot help

bot > Supported commands
bot > echo [MESSAGE]
bot > echo will respond with whatever message you give it.
bot > checkbuild [build_id]
bot > checkbuild will retrieve the status of the build with build_id
bot > haiku
bot > bot will send you the haiku of the day

You can also ask for help about a specific command, e.g.

user > #chatbot help echo

bot > echo [MESSAGE]
bot > echo will respond with whatever message you give it.

The default logger will push messages from matterbot into wclog, but you can customize this behavior by implementing your own ILogger:

class CustomLogger : public ILogger {
	void info(const wstring &msg) override {
		wcout << "INFO: " << msg;
	void warn(const wstring &msg) override {
		wcout << "WARN: " << msg;
	void error(const wstring &msg) override {
		wcerr << "INFO: " << msg;

Overwrite the default logger with set_logger:


One other feature of Matterbot is that it accepts GET requests at the same URL as the Outgoing Webhook URL (this comes basically for free since we need to) bind to the port anyway. The default response is a status webpage that gives basic statistics about the bot:

MattermostBot Status

Web requests served: 17
Messages posted: 165
Commands served: 2135
Supported commands:

Implementation details

That’s really all you need to get started building your own bot, but in case you would like to repurpose some (or all) of the matterbot source, here’s a brief overview of how the pieces fit together.

The Matterbot.h header is designed around the PIMPL idiom. The practical upshot of this design choice is that Matterbot.h is the only non-standard library header that gets imported:

#pragma once
#include <memory>
#include <string>

namespace lospi {
	class ILogger {

	class ICommand {

	class MatterbotImpl;
	class Matterbot {
		std::shared_ptr<MatterbotImpl> impl;

This is helpful because (a) changing implementation details does not necessarily require a recompiling of classes depending on Matterbot, and (b) compile times are generally faster due to less includes.

The low level details of translating HTTP semantics into C++ classes are all handled by the MattermostWebhooks class. If you wanted to write a much more involved bot (or bot framework), you could begin with this class to build on top:

class MattermostWebhooks
	MattermostWebhooks(const std::wstring &mattermost_url,
		const std::wstring &incoming_hook_token,
		const std::wstring &outgoing_hook_route,
		const std::wstring &outgoing_hook_token);
	void post_message(const std::wstring &message);
	void register_message_handler(const std::function<std::wstring(const Message&)>
	void register_web_handler(const std::function<WebResponse()> &web_handler);
	void listen();
	void die();

For outgoing traffic from Mattermost/Slack, you can register a std::function callback to handle Message objects:

class Message {
	bool token_is_valid() const;
	long get_timestamp() const;
	std::wstring get_channel() const;
	std::wstring get_team() const;
	std::wstring get_text() const;
	std::wstring get_user() const;
	std::wstring get_trigger_word() const;

For incoming web traffic (i.e. GET requests), you instead handle WebResponse object:

class WebResponse {
	std::wstring get_content_type() const;
	std::wstring get_content() const;

The content_types is the MIME Type of the content received by the request.


Please post any issues or bugs you find!

Fork me on GitHub