アプリ開発録

iPhoneアプリやその他開発で得られた知見をメモ

【最短・最速・最小限】Herokuで動かすSlack Botの作り方まとめ

初めてSlackで動くBotを作ったが、とりあえずそんなに凝ったものはいらなくて、以下の要件を満たしていればよかった。

  • 特定の言葉に反応
  • スケジュールで定期的に特定の言葉を投稿

たったこれだけのことだが、断片的な情報しかなく、まとまったページがなくて意外と苦労したので決定版として記録。

このページの対象

  • Heroku(Node.js)とBotkitとSlackを使用
  • HerokuもBotokitもよくわからない
  • BotkitをHerokuでCron実行する方法を知りたい

前提

  • Node.jsのインストール
  • Slackのチームを作っていてオーナーである
  • Herokuのアカウントを作っていてheroku用のコマンドツールもインストールしてある

上記の方法は割愛します。

参考にしたページ

今回のサンプルではデータ保存は未使用

BotkitとHubotの違い

Botkitは非同期でタスクが実行できるみたい。こっちの方が新しくて機能も充実していて実装も楽。らしい。

なのでこちらを採用。

SlackでBotを作成しAPIを取得する

省略

Herokuにログインしアプリを作成する

f:id:tak-dev:20170213171230p:plain

f:id:tak-dev:20170213171237p:plain

任意の名前で作成する。識別しやすい名前の方がよい。

今回はcron-for-slackで作成した。この先の紹介するコードで該当部分がある場合、ここで自分で作成した名前に置き換える。

HerokuはGithubを経由しなくても直接デプロイできる

今回初めて知ったが、Herokuはいつの間にかGithubリポジトリをアップしなくても、直接デプロイできるようになったみたい。

以前はGithubを経由しないとできない気がした。

f:id:tak-dev:20170213171531p:plain

アプリのダッシュボードのDeployというページを見ると上のようにわかりやすくデプロイ方法が書いてある。

必要な手順は以下の通りである。

サンプルをダウンロードする

github.com

$ git clone git@github.com:tac-tic-s/slack-botkit-cron-bot.git
$ cd slack-botkit-cron-bot

node modulesのインストール

$ npm install

Botを動かしたいチャンネルへ招待する

/invite @bot-name

招待したいチャンネルから上記コマンドを実行するか、UI上でボットのプロフィールから招待。

ローカルでテストする

token=YOUR_API_TOKEN node index.js

成功するとSlackのボットがオンラインになる。

Herokuへアップ

ローカルで動作確認が済んだら、Herokuへアップしそちらで動かす。
ちなみにHerokuで動かしてる同一のBotがいても、ローカルで同じBotを起動してもエラーは起きなかった。
ローカルのコードの動作が優先されたので、本番サーバーを動かしたままローカルでも気軽にテストができそう。

$ heroku login
$ heroku git:clone -a cron-for-slack
$ git push heroku master

Herokuのサーバー環境変数BotAPI TOKENを追加

heroku config:add token=YOUR_API_TOKEN

Heroku Schedulerアドオンを追加し、Botのサーバーを寝かせないようにする

無料プランで30分以上Webのトラフィックがないとdynoがスリープしてしまいます。Botはそもそも外部からのトラフィックが無いのですぐに寝てしまう事になります。なのでわざとHTTPサーバを立ち上げ、Heroku Schedulerから定期的にアプリへcurlしてdynoを起こしておくようにしています。 http://blog.horimisli.me/entry/botkit-heroku-redis

f:id:tak-dev:20170213173123p:plain

Add-onsからHeroku Schedulerを検索して追加する。

無料の枠で使う場合でも事前に支払い用カードの登録が必要。カードが登録されてない場合その旨のアナウンスが表示され追加できない。

スケジュールの登録

f:id:tak-dev:20170213173321p:plain

seq 1 13 | grep -qw $((10#`date -u "+%H"`)) && curl https://<your-app-name>.herokuapp.com > /dev/null 2>&1

<your-app-name>を置き換えのこと。

補足:チャンネルIDを特定する

チャンネルの文字列をそのまま指定してもダメらしく、チャンネルのIDをAPIで取得する必要がある。

動的に取得してもいいが、ここでは事前に取得して、取得したものをハードコーディングで使用。

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

'use strict'

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

let target_channel_name = 'チャンネルの名前';

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}です。`);
      }
    }
  }
});

上記をchannel.jsで保存し実行。

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

追記:平成29年2月22日

サンプルコードのjob2が現状動いてません。

原因不明なので調査中です。