Common functionality for botkit slack bots
npm install @shopkeep/bot-scripts
Copy an example from the examples/
directory and use as a starting point for
your next bot project. Rename the .env.example
file to .env
and get the bot
set up by adding a SLACK_BOT_TOKEN
into the .env
.
Run npm install
to install the dependencies and then start your bot with
npm start
. For any further requirements, check the README.md
file of your
chosen example.
bot-scripts
aims to extact common functionality and tooling, used by botkit
slack bots, into a centralised repository. It provides three commands:
bot-scripts lint
provides consistent tooling versions and configuration for linting rules using ESLint (and associated plugins) and Prettier.bot-scripts test
provides consistent tooling versions and configuration for running tests using Jest.bot-scripts start
provides consistent tooling versions and configuration for Botkit, as well as setting up boilerplate functionality and starting your bot.
All bots using this set of scripts will have these slack commands by default:
ping
slack command- eg.
@your-bot ping
- Bot will reply with
pong
- eg.
help
slack command- eg.
@your-bot help
- Bot will reply a list of slack commands, using the
## Commands
section of the README as the source of this data. (Seeexamples/
for readme files where this has been used.)
- eg.
status
slack command- eg.
@your-bot status
- Bot will reply with useful status information including host name, IP address and bot-scripts version. Additional data can be added to this response.
- eg.
Your bot should have an entry point at src/index.js
which exports a function.
On start
, bot-scripts
will call this function and provide it with a
setupBot
function as a single parameter.
Basic Example:
You can get a complete runnable setup of this example at
examples/basic-example/
// This emoji will prefix the slack command in the `help` slack command output
const customEmojis = {
"my name is": ":wave:"
};
// This will be visible in the `status` slack command output
const statusData = {
isExampleBot: true
};
// The bot will listen to slack commands prefixed with the botname string;
// This means you can call the bot without directly mentioning it.
// eg. If you had a bot under the handle `@HiBot` you could still call this bot
// via `example-bot my name is Alice`. This can be of use as part of reminders.
const botname = "example-bot";
module.exports = function(setupBot) { // Function called by bot-scripts start
logger.debug("Setting up clients"); // Global `logger` object available
// Bot instance and `listen` function provided from `setupBot`
const { bot, listen } = setupBot({ botname, customEmojis, statusData });
// Sets up case insensitive listener for "my name is" slack command
// This can be called via a direct message, @ mention in a channel
// or when it's prefixed by the `botname`
listen("my name is (.+)", function(bot, message) {
// Implement your slack command logic here, eg:
// https://botkit.ai/docs/core.html#botreply
bot.reply(message, `Hi ${message.match[1]}!`);
});
};
Your entry point function will be provided with a setupBot
function. This
function should be called with an object, which can contain:
botname
- (optional) Name of the bot when called ambiently- Defaults to
bot
- eg.
bot ping
would call theping
slack command
- Defaults to
customEmojis
- (optional) Mapping of slack command string to emoji forhelp
output- Used to prefix slack commands with memorable emoji in
help
output. Defaults to:point_right:
. For simplicity, this will match on slack commands starting with the provided object key, so the entire slack command string isn't required.
- Used to prefix slack commands with memorable emoji in
statusData
- (optional) Object of data to add tostatus
output
This function returns an object containing the bot
BotKit instance and a
listen
function.
- Generally the
bot
BotKit instance won't be used; but it can be required as a parameter by some of the utility functions (documented later). - The
listen
function is used to add slack commands to your bot. The providedlisten
function takes a string to listen for (which can contain regex syntax), which is then converted to a case insensitive regular expression and bound to both targetted means of communication (direct message, direct mention, etc.) and ambient targetting based on the providedbotname
(defaults to "bot"). This allows for calling the bot as part of Slacks reminder functionality.
A global logger
variable is provided to output a standard log format to the
console. Log level output can be set via environment variable:
LOGGING_LEVEL
- (optional) Level of logging to output.- Defaults to
info
(supportsdebug
for verbose logging) - Follows the Syslog severity levels.
- Defaults to
There are some helpful utilities available which can be imported separately.
These are provided under @shopkeep/bot-scripts/utils
which will provide a
single util
object containing:
getUser
function takes a bot instance and a user ID and returns a promise which will resolve to a standardised user object, which looks like:{ id, name, handle, email, avatar, tz }
- User ID most commonly comes from
message.user
, when looking up the caller
outputError
function takes a bot instance, the message and an error message (or error object) and will reply to the user with the error details.generateListener
function takes the bot name, a bot instance and an array of the means by which it should listen and returns a function which can be used to set up listeners (like thelisten
function provided bysetupBot
).- This should be used when the provided
listen
function isn't suitable and a custom setup for the listen function is required. - Example:
const { generateListener } = require("@shopkeep/bot-scripts/utils"); const botname = "example-bot"; module.exports = function(setupBot) { const { bot } = setupBot(); const directListener = generateListener(botname, bot, [ // You can add as many or few message events here as you want to bind to // https://botkit.ai/docs/core.html#incoming-message-events 'direct_message' // This listener will only bind to direct messages ]); directListener("my name is (.+)", function(bot, message) { bot.reply(message, `Hi ${message.match[1]}!`); }); };
- This should be used when the provided
A healthcheck endpoint is exposed which can be used to determine the health of
the bot. This returns a 200
when the Slack real-time messaging websocket
connection available, and a 503
when it is not.
HEALTH_CHECK_PORT
- (optional) Port used for health check endpoint.- Defaults to
9000
- Defaults to
Pull requests on this repository are very welcome. There is test and linting tooling in place. Formatting is provided by prettier. This project uses the same linting and testing tooling as provided to any bots which use these scripts.
Use docker-compose
to build the environment, and run tests and lint.
docker-compose build test
docker-compose run test # Test and lint
Make sure you have Node.js and npm available locally. Install dependencies and run the test and linting tasks.
npm install
npm test # Run all tests with jest
npm run lint # Lint the codebase with eslint