
hubot-slack でDMを送るスクリプトを書きたかったが、 DMを送る方法が用意されてるにもかかわらず、単純に呼ぶだけでは利用できなかったので呼び方のメモ。
※ hubot-slackが利用するnode-slack-clientのバージョンが1.2時点での内容です。今後改善されると思います。
コード
module.exports = (robot) ->
sendDM = (slackUserName , message) ->
userId = robot.adapter.client.getUserByName(slackUserName)?.id
return unless userId?
if robot.adapter.client.getDMByID(userId)?
robot.send {room: slackUserName}, message
else
robot.adapter.client.openDM userId
# openをハンドルする手段がなさそうなので、仕方なくsetTimeout
setTimeout =>
robot.send {room: slackUserName}, message
, 1000
robot.respond /dm ([^\s]+) (.+)/, (msg) ->
userName = msg.match[1]
message = msg.match[2]
sendDM userName, message
slackhq/hubot-slackの sendメソッドを読むと、channel = @client.getChannelGroupOrDMByName envelope.roomなどとなっており、一見DMもユーザー名をチャンネル名のように渡せば送れそうではありますが、
hubot-slack が内部で利用している、slackhq/node-slack-client のコードを読むと、getChannelGroupOrDMByNameは中でgetDMByNameを呼んでおり、このメソッドは予めフィールドに持ってるDMオブジェクトを返すだけであることがわかります。
既にDMオブジェクトが存在するユーザーに対してはrobot.send {room: slackUserName}, messageでDMを送ることができますが、
そうでないユーザーには robot.adapter.client.openDM userId でDMオブジェクトを生成してやる必要があります。
しかし、このメソッドはAPI通信をするが外部からコールバックを設定できないため、しょうがなくsetTimeoutで1秒待ったら得られただろうという仮定で1秒待った後にsendしてます。
動作確認
↓

OK。
会社でGithubの自分のプルリクにコメントが付いたり、メンションが飛んだりしたらslack上でも本人だけにDMで通知するようにしています。 DMは他人に関係ない情報を気兼ねなく流せるため、応用が効きそうです。