Permalink
Browse files

Merge branch 'slack-ephemeral' of https://github.com/jonchurch/botkit

  • Loading branch information...
benbrown committed Aug 29, 2017
2 parents 4243f28 + 0af2df7 commit d92d161f4743277515829b1568b8b2b8d3ee0c0b
Showing with 135 additions and 1 deletion.
  1. +71 −0 docs/readme-slack.md
  2. +6 −0 lib/Slack_web_api.js
  3. +58 −1 lib/Slackbot_worker.js
View
@@ -220,6 +220,77 @@ bot.startRTM(function(err, bot, payload) {
setTimeout(bot.destroy.bind(bot), 10000)
```
### Ephemeral Messages
Using the Web API, messages can be sent to a user "ephemerally" which will only show to them, and no one else. Learn more about ephemeral messages at the [Slack API Documentation](https://api.slack.com/methods/chat.postEphemeral). When sending an ephemeral message, you must specify a valid `user` and `channel` id. Valid meaning the specified user is in the specified channel. Currently, updating interactive messages are not supported by ephemeral messages, but you can still create them and listen to the events. They will not have a reference to the original message, however.
#### Ephemeral Message Authorship
Slack allows you to post an ephemeral message as either the user you have an auth token for (would be your bot user in most cases), or as your app. The display name and icon will be different accordingly. The default is set to `as_user: true` for all functions except `bot.sendEphemeral()`. Override the default of any message by explicitly setting `as_user` on the outgoing message.
#### bot.whisper()
| Argument | Description
|--- |---
| src | Message object to reply to, **src.user is required**
| message | _String_ or _Object_ Outgoing response
| callback | _Optional_ Callback in the form function(err,response) { ... }
Functions the same as `bot.reply()` but sends the message ephemerally. Note, src message must have a user field set in addition to a channel
`bot.whisper()` defaults to `as_user: true` unless otherwise specified on the message object. This means messages will be attributed to your bot user, or whichever user who's token you are making the API call with.
#### bot.sendEphemeral()
| Argument | Description
|--- |---
| message | _String_ or _Object_ Outgoing response, **message.user is required**
| callback | _Optional_ Callback in the form function(err,response) { ... }
To send a spontaneous ephemeral message (which slack discourages you from doing) use `bot.sendEphemeral` which functions similarly as `bot.say()` and `bot.send()`
```javascript
controller.hears(['^spooky$'], function(bot, message) {
// default behavior, post as the bot user
bot.whisper(message, 'Booo! This message is ephemeral and private to you')
})
controller.hears(['^spaghetti$'], function(bot, message) {
// attribute slack message to app, not bot user
bot.whisper(message, {as_user: false, text: 'I may be a humble App, but I too love a good noodle'})
})
controller.on('custom_triggered_event', function(bot, trigger) {
// pretend to get a list of user ids from out analytics api...
fetch('users/champions', function(err, userArr) {
userArr.map(function(user) {
// iterate over every user and send them a message
bot.sendEphemeral({
channel: 'general',
user: user.id,
text: "Pssst! You my friend, are a true Bot Champion!"})
})
})
})
```
#### Ephemeral Conversations
To reply to a user ephemerally in a conversation, pass a message object to `convo.say()` `convo.sayFirst()` `convo.ask()` `convo.addMessage()` `convo.addQuestion()` that sets ephemeral to true.
When using interactive message attachments with ephemeral messaging, Slack does not send the original message as part of the payload. With non-ephemeral interactive messages Slack sends a copy of the original message for you to edit and send back. To respond with an edited message when updating ephemeral interactive messages, you must construct a new message to send as the response, containing at least a text field.
```javascript
controller.hears(['^tell me a secret$'], 'direct_mention, ambient, mention', function(bot, message) {
bot.startConversation(message, function(err, convo) {
convo.say('Better take this private...')
convo.say({ ephemeral: true, text: 'These violent delights have violent ends' })
})
})
```
### Slack Threads
View
@@ -41,6 +41,7 @@ module.exports = function(bot, config) {
'channels.unarchive',
'chat.delete',
'chat.postMessage',
'chat.postEphemeral',
'chat.update',
'chat.unfurl',
'dnd.endDnd',
@@ -177,6 +178,11 @@ module.exports = function(bot, config) {
slack_api.callAPI('chat.postMessage', options, cb);
};
slack_api.chat.postEphemeral = function(options, cb) {
sanitizeOptions(options);
slack_api.callAPI('chat.postEphemeral', options, cb);
};
slack_api.chat.update = function(options, cb) {
sanitizeOptions(options);
slack_api.callAPI('chat.update', options, cb);
View
@@ -4,7 +4,6 @@ var slackWebApi = require(__dirname + '/Slack_web_api.js');
var HttpsProxyAgent = require('https-proxy-agent');
var Back = require('back');
module.exports = function(botkit, config) {
var bot = {
type: 'slack',
@@ -338,6 +337,10 @@ module.exports = function(botkit, config) {
};
bot.send = function(message, cb) {
if (message.ephemeral) {
bot.sendEphemeral(message, cb)
return
}
botkit.debug('SAY', message);
/**
@@ -413,6 +416,39 @@ module.exports = function(botkit, config) {
cb && cb(err);
}
}
}
bot.sendEphemeral = function (message, cb) {
botkit.debug('SAY EPHEMERAL', message);
/**
* Construct a valid slack message.
*/
var slack_message = {
type: message.type || 'message',
channel: message.channel,
text: message.text || null,
user: message.user,
as_user: message.as_user || false,
parse: message.parse || null,
link_names: message.link_names || null,
attachments: message.attachments ?
JSON.stringify(message.attachments) : null,
};
console.log({message})
console.log({slack_message})
bot.msgcount++;
if (!bot.config.token) {
throw new Error('Cannot use web API to send messages.');
}
bot.api.chat.postEphemeral(slack_message, function(err, res) {
if (err) {
cb && cb(err);
} else {
cb && cb(null, res);
}
});
};
/**
@@ -615,6 +651,27 @@ module.exports = function(botkit, config) {
if (src.thread_ts) {
msg.thread_ts = src.thread_ts;
}
if (msg.ephemeral && ! msg.user) {
msg.user = src.user
msg.as_user = true
}
bot.say(msg, cb);
};
bot.whisper = function(src, resp, cb) {
var msg = {};
if (typeof(resp) == 'string') {
msg.text = resp;
} else {
msg = resp;
}
msg.channel = src.channel;
msg.user = src.user;
msg.as_user = true
msg.ephemeral = true
bot.say(msg, cb);
};

0 comments on commit d92d161

Please sign in to comment.