This package includes a web client that makes it simple to use the Slack Web API methods. Here are some of the goodies you get right out of the box:
Here are some of the common recipies for using the WebClient
class.
Your app will interact with the Web API through the WebClient
object, which a top level export
from this package. At a minimum, you need to instantiate it with a token. The example below shows
how to post a message into a channel, DM, MPDM, or group. This will require either the
chat:user:write
or chat:bot:write
scopes.
const { WebClient } = require('@slack/client');
// An access token (from your Slack app or custom integration - xoxp, xoxb, or xoxa)
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);
// The first argument can be a channel ID, a DM ID, a MPDM ID, or a group ID
const channelId = 'C1232456';
// See: https://api.slack.com/methods/chat.postMessage
web.chat.postMessage(channelId, 'Hello there')
.then((res) => {
// `res` contains information about the posted message
console.log('Message sent: ', res.ts);
})
.catch(console.error);
NOTE: While most Web API methods have a function signature that puts all required arguments in order as see on the method’s documentation table on https://api.slack.com/methods, a few methods do not follow this convention:
chat.delete
chat.update
chat.unfurl
See the ___Facet
reference documentation or the source code for the correct parameter ordering.
Each method can also take optional arguments in an object after its required arguments. Let’s post a message like above, but with attachments for a more rich UI.
web.chat.postMessage(channelId, 'Hello there', {
attachments: [
{
"fallback": "Required plain-text summary of the attachment.",
"color": "#36a64f",
"author_name": "Bobby Tables",
"author_link": "http://flickr.com/bobby/",
"author_icon": "http://flickr.com/icons/bobby.jpg",
"title": "Slack API Documentation",
"title_link": "https://api.slack.com/",
"text": "Optional text that appears within the attachment",
"fields": [
{
"title": "Priority",
"value": "High",
"short": false
}
],
"image_url": "http://my-website.com/path/to/image.jpg",
"thumb_url": "http://example.com/path/to/thumb.png",
"footer": "Slack API",
"footer_icon": "https://platform.slack-edge.com/img/default_application_icon.png",
"ts": 123456789
}
]
})
.then((res) => {
// `res` contains information about the posted message
console.log('Message sent: ', res.ts);
})
.catch(console.error);
NOTE: See the Message Builder for a playground where you can prototype your message’s look.
The files.upload
method can be used to upload a file, cool! This will require files:write:user
scope.
const fs = require('fs');
const { WebClient } = require('@slack/client');
// An access token (from your Slack app or custom integration - xoxp, xoxb, or xoxa)
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);
// Slack needs a file name for the upload
// This file is located in the current directory (`process.pwd()`)
var fileName = 'test_file.csv';
// See: https://api.slack.com/methods/chat.postMessage
web.files.upload(fileName, {
// You can use a ReadableStream or a Buffer for the file option
file: fs.createReadStream(`./${fileName}`),
// Or you can use the content property (but not both)
// content: 'plain string content that will be editable in Slack'
})
.then((res) => {
// `res` contains information about the uploaded file
console.log('File uploaded: ', res.file.id);
})
.catch(console.error);
The channels.list
method can be used to get a list of all the public channels (and private
channels from the user who authorized) when using a user token with scope channels:read
. Or, it
would the public channels are all private channels a bot user is a member of when using a bot token.
const { WebClient } = require('@slack/client');
// An access token (from your Slack app or custom integration - xoxp, xoxb, or xoxa)
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);
// See: https://api.slack.com/methods/channels.list
web.channels.list()
.then((res) => {
// `res` contains information about the channels
res.channels.forEach(c => console.log(c.name));
})
.catch(console.error);
});
Every web API method can also be called with a callback function that takes cb(error, response)
.
If you prefer callbacks over promises, here is the example above translated for callbacks:
web.channels.list((err, res) => {
if (err) {
return console.error(err);
}
// `res` contains information about the channels
res.channels.forEach(c => console.log(c.name));
});
The WebClient
will retry any request that fails for a recoverable error. The policy is
configurable, but the default is retrying forever with an exponential backoff, capped at thirty
minutes but with some randomization. You can use the retryConfig
option to customize that policy.
The value is an options
object as described in the following library:
https://github.com/tim-kos/node-retry.
const { WebClient } = require('@slack/client');
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token, {
retryConfig: {
// This would turn the retrying feature off
retries: 0,
},
});
The WebClient
maintains a queue of requests to make sure a limited number of requests are in
flight at a time. It also helps with rate limit management. The default concurrency is set to three
but you can configure this with the maxRequestConcurrency
option.
const { WebClient } = require('@slack/client');
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token, {
retryConfig: {
// Allow up to 10 requests to be in-flight at a time
maxRequestConcurrency: 10,
},
});
The WebClient
also logs interesting events as it operates. By default, the log level is set to
INFO
and it should not log anything as long as nothing goes wrong. You can adjust the log level
using the logLevel
option and use any of the
npm log levels.
You can also capture the logs without writing them to stdout by setting the logger
option. It
should be set to a function that takes fn(level: string, message: string)
.
const fs = require('fs');
const { WebClient } = require('@slack/client');
// open a file to write logs
// TODO: make sure to call `logStream.end()` when the app is shutting down
const logStream = fs.createWriteStream('/tmp/app.log');
const token = process.env.SLACK_TOKEN;
logStream.on('open', () => {
const web = new WebClient(token, {
// increased logging, great for debugging
logLevel: 'debug',
logger: (level, message) => {
// write to disk
logStream.write(`[${level}]: ${message}`);
}
});
});
If you need to send all your HTTP requests through a proxy, the WebClient
class allows for you
to do this with the transport
option.
const { WebClient } = require('@slack/client');
const { proxiedRequestTransport } = require('@slack/client/lib/clients/transports/request');
const web = new WebClient(token, {
transport: proxiedRequestTransport('your proxy url')
});
There’s one method that doesn’t require a token
, and that’s because it generates the token
for
you: oauth.access
. You’ll be using this method at the end of the OAuth flow for a distributed
Slack app. To do this, just initialize without a token.
Or, if you are using the Passport authentication framework, this step is handled for you using the
@aoberoi/passport-slack
Strategy.
const { WebClient } = require('@slack/client');
const client = new WebClient();
const clientId = process.env.SLACK_CLIENT_ID;
const clientSecret = process.env.SLACK_CLIENT_SECRET;
// Not shown: did some OAuth to recieve `code` grant
client.oauth.access(clientId, clientSecret, code)
.then((res) => {
// Good idea to save the access token to your database
console.log(res.access_token);
})
.catch(console.error);