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は他人に関係ない情報を気兼ねなく流せるため、応用が効きそうです。