BotKitからSlackの指定チャンネルにポストする

  • 16
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

これ、Hubotみたいにうまくいかなったのでメモです。

BotKitだとbot.say()コマンドで特定チャンネルのIDとメッセージを指定することでBOTに喋らせることができます。

単純な返信ならbot.reply()です。

bot.say does not work with # prefixed channel name #7にあるみたいに

bot.say({
    text: "Hello World!",
    channel: "#random"
});

という感じでSlackのチャンネル名を指定したいんですけど、実際は以下のように

bot.say({
    text: "Hello World!",
    channel: 'C0XXXXXXX'
});

という見慣れないC0XXXXXXXみたいな形式で指定する必要があります。これはHubotだといい感じに変換してくれてるっぽいんですけど、BotKitはまだ対応してない疑惑?でした。

そもそもこのC0XXXXXXXみたいな形式がBotKit側の仕様なのかと思ってたらSlackの仕様みたいですね。

SlackのChannel.list APIでうまいことできそう

Channel.list APIを使えば チャンネル名 -> IDを変換できそうです。

 Slackのトークン発行

まずはAPIを使うためのトークン発行です。

https://api.slack.com/web から発行します。


Generate test tokensを選択します。


トークン発行するチームの Create tokenを選択します。

Slackのパスワードを入力すると、

Confirmボタンが表示されるので選択します。

無事トークンが発行されました。

↑このトークンはすでに無効化してるので悪いことはできないですよ! (とか書いてないと会社の人に刺されそう。)

channel.list APIを試す

https://api.slack.com/methods/channels.list/test にアクセスしましょう。


Test Method を押すと

{
    "ok": true,
    "channels": [
        {
            "id": "C02SRLD8E",
            "name": "circle",
            "is_channel": true,
           ・
           ・
           ・
           (省略)

みたいなJSONが表示されます。これでIDをチャンネル名の変換ができそうです。

channel.list APIをNode.jsから叩く

channel.js
'use strict'

const request = require('request');
const token = 'トークンを指定';
const URL = `https://slack.com/api/channels.list?token=${token}&pretty=1`;

let target_channel_name = 'general';

request(URL, (error, response, body) => {
  if (!error && response.statusCode == 200) {
    let channels = JSON.parse(body).channels;
    for (let channel of channels) {
      if(channel.name === target_channel_name){
        console.log(`${channel.name}のチャンネルID${channel.id}です。`);
      }
    }
  }
});

実行

$ node channel.js
generalのチャンネルIDはC0ATTJVTQです。

これでチャンネル名 -> IDの指定ができました。

BotKitに組み込んでみる

request周りは共通化したいですがとりあえず。

mybotcommand.js
'use strict';

const request = require('request');
const token = 'トークンを指定';
const URL = `https://slack.com/api/channels.list?token=${token}&pretty=1`;

let target_channel_name = 'renraku';
let channel_id = '';

request(URL, (error, response, body) => {
  if (!error && response.statusCode == 200) {
    let channels = JSON.parse(body).channels;
    for (let channel of channels) {
      if(channel.name === target_channel_name){
        channel_id = channel.id;
        console.log(`${channel.name}のチャンネルID${channel.id}です。`);
      }
    }
  }
});

module.exports = (controller) => {
  controller.hears([''],'direct_message,direct_mention,mention', (bot, message) => {
    bot.say({
      text: 'my message text',
      channel: channel_id // a valid slack channel, group, mpim, or im ID
    });
  });
};

通常BotKitだとbot.jsのcontroller.hears()ごとにコマンドが記述してあると思うのですが、コマンドごとにファイル分けしたかったので僕のBotKitだとメインのbot.js側で各コマンドを読み込む感じにしてあるので、module.exportsしてます。

bot.js
require('mybotcommand.js')(controller);

みたいな感じで読み込んでます。

まとめ

BotKit側がすでに対応してたりするのか調べる前に記事書いちゃった (2016年4月)感じですけど、対応してくれるまではこのやり方がいいのかな。