File: README.md
Hubot
Note: v10.0.4 accidentally contains the removal of CoffeeScript; v10.0.5 puts it back in
Note: v11 removes CoffeeScript and converts this codebase to ESM
Hubot is a framework to build chat bots, modeled after GitHub's Campfire bot of the same name, hubot.
He's pretty cool. He's extendable with scripts and can work
on many different chat services.
This repository provides a library that's distributed by npm that you
use for building your own bots. See the documentation
for details on getting up and running with your very own robot friend.
In most cases, you'll probably never have to hack on this repo directly if you
are building your own bot. But if you do, check out CONTRIBUTING.md
Create your own Hubot instance
This will create a directory called myhubot in the current working directory.
npx hubot --create myhubot --adapter @hubot-friends/hubot-slack
npx hubot --create myhubot --adapter @hubot-friends/hubot-discord
npx hubot --create myhubot --adapter @hubot-friends/hubot-ms-teams
npx hubot --create myhubot --adapter @hubot-friends/hubot-ircReview scripts/example.mjs. Create more scripts in the scripts folder.
Command bus (robot.commands)
Hubot includes a deterministic command subsystem for slash-style commands. It is safe by default and does not interfere with legacy hear and respond listeners.
Basic Command Registration
export default (robot) => {
robot.commands.register({
id: 'tickets.create',
aliases: ['ticket new', 'new ticket'],
args: {
title: { type: 'string', required: true },
priority: { type: 'enum', values: ['low', 'medium', 'high'], default: 'medium' }
},
sideEffects: ['creates external ticket'],
handler: async (ctx) => {
return `Created ticket: ${ctx.args.title}`
}
})
}Invoke with addressing the bot:
@hubot tickets.create --title "VPN down" --priority high@hubot tickets.create title:"VPN down" priority:high
Commands that declare side effects will require confirmation before execution.
The user is asked to confirm. They do so like so:
@hubot yes
@hubot no
@hubot cancelAliases are for discovery and search only. They do not execute commands or create proposals. They are intent utterances.
Built-in Help Command
Hubot automatically registers a help command that provides command discovery and documentation:
@hubot help # List all commands
@hubot help tickets # Filter commands by prefix
@hubot help search "create ticket" # Search by keyword, alias, description, or exampleSearch for Commands
const results = robot.commands.search('ticket new')
// [{ id: 'tickets.create', score: 100, matchedOn: 'alias' }, ...]Custom Type Resolvers
Extend validation with custom argument types:
export default (robot) => {
// Register custom type resolver
robot.commands.registerTypeResolver('project_id', async (value, schema, context) => {
if (!value.startsWith('PRJ-')) {
throw new Error('must start with PRJ-')
}
return value.toUpperCase()
})
// Use it in a command
robot.commands.register({
id: 'projects.deploy',
args: {
projectId: { type: 'project_id', required: true }
},
handler: async (ctx) => {
return `Deploying ${ctx.args.projectId}`
}
})
}Configuration Options
When creating a CommandBus instance, you can configure:
prefix- Command prefix (default: '')proposalTTL- Timeout for pending confirmations in milliseconds (default: 300000 = 5 minutes)logPath- Path to NDJSON event log file (default:.data/commands-events.ndjson)disableLogging- Disable event logging to disk (default: true - logging is disabled by default)permissionProvider- Custom permission checking handler (optional)
Permissions
Control who can execute commands using room-based and role-based permissions.
Room-Based Permissions
Restrict command execution to specific chat rooms:
robot.commands.register({
id: 'sensitive.action',
permissions: {
rooms: ['#admin', '#ops'] // Only allowed in these rooms
},
handler: async (ctx) => {
return 'Action executed!'
}
})Users in other rooms get: Permission denied: command not allowed in this room
Role-Based Permissions
Restrict command execution to users with specific roles:
robot.commands.register({
id: 'deploy.production',
permissions: {
roles: ['admin', 'devops'] // Only users with these roles
},
handler: async (ctx) => {
return 'Deploying...'
}
})To enable role checking, provide a permissionProvider when creating CommandBus:
const commandBus = new CommandBus(robot, {
permissionProvider: {
hasRole: async (user, requiredRoles, context) => {
// Custom logic to check if user has any of the required roles
const userRoles = await fetchUserRoles(user.id)
return requiredRoles.some(role => userRoles.includes(role))
}
}
})Without a permission provider, role-based permissions are ignored (allow by default). Room-based permissions are always enforced.
License
See the LICENSE file for license rights and limitations (MIT).
Hubot History
The Most Important Startup's Hardest Worker Isn't a Person
File: docs/adapters/campfire.md
title: Campfire adapter layout: layouts/docs.html permalink: /adapters/campfire.html
Campfire adapter
Campfire is a web based chat application built by 37signals. The Campfire adapter is one of the original adapters in Hubot.
Getting Started
You will need a Campfire account to start.
Next, you will need to create a user on your Campfire account for your Hubot, then give it access so it can join to your rooms. You will need to create a room if you haven't already.
Hubot defaults to using its Shell, so to use Campfire instead, you can run hubot with -a Campfire:
% bin/hubot -a campfireIf you are using foreman, you need to make sure the hubot is called with -a Campfire in the Procfile:
web: bin/hubot -a campfire -n HubotConfiguring
The adapter requires the following environment variables.
HUBOT_CAMPFIRE_ACCOUNTHUBOT_CAMPFIRE_TOKENHUBOT_CAMPFIRE_ROOMS
Campfire API Token
This can be found by logging in with your hubot's account click the My Info
link and make a note of the API token.
Campfire Room IDs
If you join the rooms you want your hubot to join will see notice a numerical
ID for the room in the URL. Make a note of each ID for the rooms you want your
hubot to join.
Campfire Account
This is simply the first part of the domain you visit for your Campfire
account. For example if your Campfire was at hubot.campfirenow.com your
subdomain is hubot. Make a note of the subdomain.
Configuring the variables on UNIX
% export HUBOT_CAMPFIRE_TOKEN="..."
% export HUBOT_CAMPFIRE_ROOMS="123,321"
% export HUBOT_CAMPFIRE_ACCOUNT="..."Configuring the variables on Windows
Using PowerShell:
setx HUBOT_CAMPFIRE_TOKEN "..." /m
setx HUBOT_CAMPFIRE_ROOMS "123,321" /m
setx HUBOT_CAMPFIRE_ACCOUNT "..." /mFile: docs/adapters/development.md
title: Development adapter layout: layouts/docs.html permalink: /adapters/development.html
Development adapter
Adapter Basics
All adapters inherit from the Adapter class in the src/Adapter.mjs file.
const Adapter = require('hubot/index.mjs').Adapter;There are certain methods that you will want to override. Here is a basic stub of what an extended Adapter class would look like:
const Adapter = require('../adapter')
const User = require('../user')
const TextMessage = require('../message').TextMessage
class Sample extends Adapter {
constructor(robot) {
super(robot)
this.robot.logger.info('Constructor')
}
send(envelope, ...strings) {
this.robot.logger.info('Send')
}
reply(envelope, ...strings) {
this.robot.logger.info('Reply')
}
run() {
this.robot.logger.info('Run')
this.emit('connected') // The 'connected' event is required to trigger loading of Hubot scripts.
const user = new User(1001, 'Sample User')
const message = new TextMessage(user, 'Some Sample Message', 'MSG-001')
this.robot.receive(message)
}
}
exports.use = (robot) => new Sample(robot)Option 1. Setting Up Your Development Environment
- Create a new folder for your adapter
hubot-sample
mkdir hubot-sample
- Change your working directory to
hubot-sample
cd hubot-sample
- Run
npm initto create your package.json
- make sure the entry point is
src/sample.js
- Add your
.gitignoreto includenode_modules - Edit the
src/sample.jsfile to include the above stub for your adapter - Edit the
package.jsonto add a peer dependency onhubot
"dependencies": {
},
"peerDependencies": {
"hubot": ">=11"
}- Generate your Hubot using the
npx hubot --create myhubot - Change working directories to the
hubotyou created in step 7. - Now perform an
npm linkto add your adapter tohubot
npm link ../hubot-sample
- Run
hubot -a sample
Gotchas
There is a an open issue in the node community around npm linked peer dependencies not working. To get this working for our project you will need to do some minor changes to your code.
- For the import in your
hubot-sampleadapter, add the following code
let {Robot,Adapter,TextMessage,User} = {}
try {
{Robot,Adapter,TextMessage,User} = require('hubot')
} catch {
const prequire = require('parent-require')
{Robot,Adapter,TextMessage,User} = prequire('hubot')
}- In your
hubot-samplefolder, modify thepackage.jsonto include the following dependency so this custom import mechanism will work
"dependencies": {
"parent-require": "^1.0.0"
}- Now try running
hubot -a sampleagain and see that the imports are properly loaded. - Once this is working properly, you can build out the functionality of your adapter as you see fit. Take a look at some of the other adapters to get some ideas for your implementation.
- Once packaged and deployed via
npm, you won't need the dependency inhubotanymore since the peer dependency should work as an official module.
Option 2. Setting Up Your Development Environment
Another option is to load the file from local disk.
- Create a new folder for your adapter
hubot-sample
mkdir hubot-sample
- Change your working directory to
hubot-sample
cd hubot-sample
- Run
npm initto create your package.json
- make sure the entry point is
src/sample.js
- Add your
.gitignoreto includenode_modules - Edit the
src/sample.jsfile to include the above stub for your adapter - Edit the
package.jsonto add a peer dependency onhubot
"dependencies": {
},
"peerDependencies": {
"hubot": ">=11"
}- Run
npx hubot -p ./src -a sample.js
File: docs/adapters/shell.md
title: Shell adapter layout: layouts/docs.html permalink: /adapters/shell.html
Shell adapter
The shell adapter provides a simple read-eval-print loop for interacting with a hubot locally.
It can be useful for testing scripts before using them on a live hubot.
Getting Started
To use the Shell adapter you can simply omit the -a option when running
hubot as it will use the Shell adapter by default.
% bin/hubotConfiguring
This adapter doesn't require any configuration.
It supports two environment variables to make it possible to test scripts as different users:
- HUBOT_SHELL_USER_ID: default is 1
- HUBOT_SHELL_USER_NAME: default is Shell
File: docs/deploying/azure.md
title: Deploying to Azure layout: layouts/docs.html permalink: /deploying/azure.html
Deploying to Azure
If you've been following along with Getting Started, it's time to deploy so you can use it beyond just your local machine.
Azure is a way to deploy hubot.
You will need to install the azure-cli via npm after you have follow the initial instructions for your hubot.
% npm install azure-cliInside your new hubot directory, make sure you've created a git repository, and that your work is committed:
% git init
% git add .
% git commit -m "Initial commit"Then create a GitHub repository for your hubot. This is where Azure will pull your code from instead of needing to deploy directly from your dev machine to Azure.
% git remote add origin _your GitHub repo_
% git push -u origin mainOnce you have your GitHub repo, create an Azure website linked to your repo. In Azure, create a website and select integrated source control. When it asks "where is your source control" select GitHub and link this website to your git repo that you created in the previous step. If you have downloaded the Azure PowerShell modules, you can also do this via PowerShell.
% $creds = Get-Credential
% New-AzureWebsite mynewhubot -github -githubrepository yourgithubaccount/yourhubotreponame -githubcredentials $credsOnce you have done this, Azure will deploy your site any time you commit and push to GitHub. Your hubot won't run quite right yet, though. Next, you need to configure the deployment to tell Azure how to run hubot.
First, run the follow command to add deploy.cmd to your hubot directory. This is the file that Azure uses to know how to deploy your node application.
% azure site deploymentscript --nodeThen, edit this file and look for the sections that give you steps 1, 2 and 3. You're going to add a 4th step:
:: 4. Create Hubot file with a js extension
copy /Y "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\hubot" "%DEPLOYMENT_TARGET%\node_modules\hubot\bin\Hubot.mjs"Now, create a new file in the base directory of hubot called server.js and put these two lines into it:
module.exports = await import('hubot/bin/Hubot.mjs');Finally you will need to add the environment variables to the website to make sure it runs properly. You can either do it through the GUI (under configuration) or you can use the Azure PowerShell command line, as follows (example is showing slack as an adapter and mynewhubot as the website name).
% $settings = New-Object Hashtable
% $settings["HUBOT_ADAPTER"] = "Slack"
% $settings["HUBOT_SLACK_TOKEN"] = "yourslackapikey"
% Set-AzureWebsite -AppSettings $settings mynewhubotCommit your changes in git and push to GitHub and Azure will automatically pick up the changes and deploy them to your website.
% git commit -m "Add Azure settings for hubot"
% git pushAzure offers a marketplace where you can use the default hubot-redis-brain using Redis Cloud provided by Redis Labs. Alternatively, to add an Azure blob storage brain, you will need to create an Azure storage account. Then you can do the following in your base hubot directory.
% npm install hubot-azure-brain --saveThen add the following line in external-scripts.json in the list with the other external scripts
"hubot-azure-brain"Finally, add one more environment variables to your website. You can do this either via the GUI or the following PowerShell commands.
% $settings = New-Object Hashtable
% $settings["HUBOT_BRAIN_AZURE_CONNSTRING"] = "your Azure blob storage connection string"
% Set-AzureWebsite -AppSettings $settings mynewhubotNow any scripts that require a brain will function. You should look up other scripts or write your own by looking at the documentation. All of the normal scripts for hubot are compatible with hosting hubot on Azure.
Troubleshooting tips and tricks
Due to Azure being Windows-based, you may run into path length problems. To overcome this issue you can set the environment variable IN_PLACE_DEPLOYMENT to 1 and use custom deployment scripts to take advantage of NPM3 and flat module installation.
If you have your instance of hubot deploying directly from source control to Azure, it will perform various bootstrapping tasks along with calling npm install via kudu. Now that Azure supports npm5, this process generates a package-lock.json file which may result in some of your packages failing to install remotely. You can edit deploy.cmd to include --no-package-lock as part of the "Step 3" install command.
If using the free tier of Azure, you can also add a post-deployment step to ping the server on startup by setting the environment variable POST_DEPLOYMENT_ACTION with a script (relative to the src dir) such as startup.sh
An example of a startup script:
let retrys=0
while : ; do
STATUSCODE=$(curl --silent --output /dev/stderr --write-out "%{http_code}" https://${WEBSITE_SITE_NAME}.azurewebsites.net/hubot/keepalive)
echo $STATUSCODE
[[ $retrys -ne 5 ]] || break
echo $retrys
((retrys++))
[[ $STATUSCODE -ne 200 ]] || break
doneSlack Integration
Currently the Slack integration has trouble finding hubot when deployed to Azure. Adding a NODE_PATH application setting with the value D:\home\site\wwwroot\node_modules will allow the Slack module to find hubot.
File: docs/deploying/bluemix.md
title: Deploying to Bluemix layout: layouts/docs.html permalink: /deploying/bluemix.html
Deploying to Bluemix
If you've been following along with Getting Started, it's time
to deploy so you can use it beyond just your local machine.
IBM Bluemix is a way to deploy hubot. It is built on the open-source project
Cloud Foundry, so we'll be using the cf cli
throughout these examples.
Hubot was originally very closely coupled to Heroku, so there are a couple of
things to clean up first that we don't need or that might get in the way on
another platform:
remove
Procfileas we'll create themanifest.ymlthat Bluemix needs in a
momentremove the
hubot-heroku-keepaliveline fromexternal_scripts.jsonand also
remove the related npm module (it causes errors on other platforms):npm uninstall --save hubot-heroku-keepalive
In preparation for working with Bluemix, install the Cloud Foundry
CLI, and create a Bluemix
Account.
First we need to define a manifest.yml file in the root directory. The
contents of the manifest at the bare minimum should look like:
applications:
- name: myVeryOwnHubot
command: ./bin/hubot --adapter slack
instances: 1
memory: 512MIn this example, we're using the slack adapter, if you choose slack as your
adapter when creating a hubot this will work, otherwise add the hubot-slack
module to your package.json. Change the name of your hubot in themanifest.yml file because otherwise your application will clash with someone
else's who already deployed an app called this! There are many more useful
things you can change about your hubot using the manifest file, so check out
these docs
for more information.
You then need to connect your hubot project to Bluemix:
$ cd your_hubot_project
$ cf api https://api.ng.bluemix.net
$ cf loginNote that the cf api command changes per Bluemix region so to deploy somewhere
other than "US South", replace this api as appropriate. The cf login command
will prompt you with your login credentials.
Next, we need to set up our environment variables, but we need to create the app
first. It won't work properly without the environment variables it needs, so
we'll first of all use the --no-start flag to deploy but not attempt to start
it.
$ cf push NAME_OF_YOUR_HUBOT_APP --no-startNow the app exists, we can set its environment variables. To access slack,
you'll need a slack token from the "Apps and Integrations" page; it's visible
when you go to create a slackbot. Copy that token and set it as an environment
variable called HUBOT_SLACK_TOKEN, like this:
$ cf set-env NAME_OF_YOUR_HUBOT_APP HUBOT_SLACK_TOKEN TOKEN_VALUEIf you have other environment variables to set, such as configuring theREDIS_URL for hubot-redis-brain, this is a good time to do that.
Finally, we're ready to go! Deploy "for real" this time:
$ cf push NAME_OF_YOUR_HUBOT_APPYou should see your bot connect to slack!
Further Reading
- Deploying Cloud Foundry Apps To Bluemix
- Neploying Node.js Apps to Bluemix
- Setting up your manifest
- Understanding the CF CLI
- Setting up a Build Pipleline in Bluemix
Troubleshooting
Bot doesn't connect
Check your logs for more information using the command cf logs YOUR_APP_NAME --recent. If you have NodeJS installed locally, you can also try running the
bot on your local machine to inspect any output: simply do bin/hubot from the
top level of the project.
Bot crashes repeatedly
It is sometimes necessary to to assign more memory to your hubot, depending
which plugins you are using (if your app crashes with error 137, try increasing
the memory limit).
File: docs/deploying/unix.md
title: Deploying to Unix layout: layouts/docs.html permalink: /deploying/unix.html
Deploying to Unix
Because there are so many variations of Linux, and more generally UNIX, it's
difficult for the hubot team to have canonical documentation for installing and
deploying it to every version out there. So, this is an attempt to give an
overview of what's needed to get deploying.
There are 3 primary things to deploying and running hubot:
- node and npm
- a way to get source code updated on the server
- a way to start hubot, start it up if it crashes, and restart it when code
updates
node and npm
To start, your UNIX server will need node and npm. Check out the node.js wiki
for installing Node.js via package manager, Building on GNU/Linux and other UNIX.
Updating code on the server
The simplest way to update your hubot's code is going to be to have a git
checkout of your hubot's source code (that you've created during Getting Started, not the github/hubot repository, and just git pull to get change. This may
feel a dirty hack, but it works when you are starting out.
If you have a Ruby background, you might be more comfortable using
capistrano.
If you have a Chef background, there's a
deploy resource for managing
deployments.
Starting, stopping, and restarting hubot
Every hubot install has a bin/hubot script to handle starting up the hubot.
You can run this command from your git checkout on the server, but there are some problems you can encounter:
- you disconnect, and hubot dies
- hubot dies, for any reason, and doesn't start again
- it doesn't start up at boot automatically
For handling you disconnecting, you can start with running bin/hubot in
screen session or with
nohup.
For handling hubot dying, and restarting it automatically, you can imagine
running bin/hubot in a
bash while loop. But
really, you probably want some process monitoring using tools like
monit,
god,
bluepill,
upstart,
runit,
systemd.
For starting at boot, you can create an init script appropriate for your UNIX
distribution. If you are using one of the process monitoring tools above, make
sure it boots at startup. See the examples
for configuration examples.
Recommendations
This document has been deliberately light on strong recommendations. At a high
level though, it's strongly recommended to avoid anything that is overly manual
and non-repeatable. That would mean using your OS's packages and tools whenever
possible, and having a proper deploy tool to update hubot, and process
management to keep hubot running.
File: docs/deploying/windows.md
title: Deploying to Windows layout: layouts/docs.html permalink: /deploying/windows.html
Deploying to Windows
Hasn't been fully tested - YMMV
There are 4 primary steps to deploying and running hubot on a Windows machine:
- node and npm
- a way to get source code updated on the server
- setting up environment variables for hubot
- a way to start hubot, start it up if it crashes, and restart it when code updates
node and npm
To start, your windows server will need node and npm.
The best way to do this is with chocolatey using the nodejs.install package.
I've found that sometimes the system path variable is not correctly set; ensure you can run node/npm from the command line. If needed set the PATH variable with set PATH=%PATH%;\"C:\Program Files\nodejs\"
Your other option is to install directly from NodeJS and run the current download (v0.12.4 as of this documentation). This should set your PATH variables for you.
Updating code on the server
To get the code on your server, you can follow the instructions at Getting Started on your local development machine or directly on the server. If you are building locally, push your hubot to GitHub and clone the repo onto your server. Don't clone the normal github/hubot repository, make sure you're using npx hubot --create myhubot to build your own hubot.
Setting up environment vars
You will want to set up your hubot environment variables on the server where it will run. You can do this by opening an administrative PowerShell and typing the following:
[Environment]::SetEnvironmentVariable("HUBOT_ADAPTER", "Campfire", "Machine")This is equivalent to going into the system menu -> selecting advanced system settings -> environment vars and adding a new system variable called HUBOT_ADAPTER with the value of Campfire.
Starting, stopping, and restarting hubot
Every hubot install has a bin/hubot script to handle starting up the hubot.
You can run this command directly from your hubot folder by typing the following:
.\bin\hubot βadapter campfireThere are a few issues if you call it manually, though.
- you disconnect, and hubot dies
- hubot dies, for any reason, and doesn't start again
- it doesn't start up at boot automatically
To fix this, you will want to create a .ps1 file with whatever name makes you happy that you will call from your hubot directory. There is a copy of this file in the examples directory here. It should contain the following:
Write-Host "Starting Hubot Watcher"
While (1)
{
Write-Host "Starting Hubot"
Start-Process powershell -ArgumentList ".\bin\hubot βadapter slack" -wait
}Remember to allow local unsigned PowerShell scripts if you are using the .ps1 file to run hubot. Run this command in an Administrator PowerShell window.
Set-ExecutionPolicy RemoteSignedYou can set this .ps1 as scheduled task on boot if you like or some other way to start your process.
Expanding the documentation
Not yet fleshed out. Help contribute by submitting a pull request, please?
File: docs/adapters.md
title: Adapters layout: layouts/docs.html permalink: /adapters.html
Adapters
Adapters are the interface to the service you want your hubot to run on.
Hubot includes two official adapters:
There are Third-party adapters available for most chat services. Here are the most popular ones:
Browse all repositories with the hubot-adapter topic on GitHub or search for adapters on NPM. Add the hubot-adapter topic to your repository on GitHub to include it in this list.
Writing Your Own Adapter
Interested in adding your own adapter? Check out our documentation for developing adapters