導入
会社の同僚が出社したら元気が出る画像を投稿するslackbotを作っていたので、自分もやってみたくなりました。
毎日出社したらほめてくれるマーリン1のslackbotを作ります。
細かいトラップを回避しながらがんばって作ります。
システム構成
slackbotライブラリ → https://github.com/lins05/slackbot/
なおこのツールは、RTM APIを利用する方式のようです。
参考:https://qiita.com/namutaka/items/233a83100c94af033575
システム構成は以下のようになります。
- 出社すると、スマホのIFTTTアプリが特定の範囲に入ったことを検知し、IFTTTのトリガーが起動
- トリガーを受けてIFTTTがでslackに「しゅっしゃ」と送る
- slackがslackbotに投稿したことを送る
- slackbotは「しゅっしゃ」という文字列が入っていたら回答「おはよう!」を生成
- slackbotがslackに「おはよう!」を投稿する
※slackbotは最終的にheroku上にデプロイしますが、ローカルでも動作します
開発環境
Mac OS X 10.12.6
iOS 12.1.2
おおまかな手順
0. 事前準備
1. slackbotを動かしてみる
2. IFTTTのAppletを作ってslackに投稿する
3. slackbotをIFTTTに対応させる
4. いろんなパターンでほめてもらう処理を作る
5. herokuにデプロイ
0. 事前準備
PCでやっておくこと
- IFTTTのアカウント作成
- python3.6系インストール(今回は3.6.6)
- heroku cliインストール 参考
- gitインストール
- (slackアプリのインストール)
- slackにbot用のワークスペースとチャンネルを用意しておく
スマホでやっておくこと(今回はiOS)
- iPhoneにIFTTTアプリをインストール
1. slackbotを動かしてみる
まずは、slackで何か発言したら反応を返すslackbotを作ります。
構成図③〜⑤の部分です。
slack側でBotを登録し、そのBotとWebSocket通信するpythonツールを作ります。
1-1. Bot登録
slack側のBot登録は以下のページを開いて、「設定を追加」ボタンから。
https://slack.com/apps/A0F7YS25R-bots
するとBot登録画面になるので、適当にBotの名前を入力しましょう。
ここでは「merlin_bot」としています。

「ボットインテグレーションを追加する」を押すと、botが作成され、インテグレーション設定画面に遷移します。
APIトークンが表示されますので、どこかにメモしておきましょう。

このbotはslackからメンバとして見ることができます。
この時点で、bot用のチャンネル(今回はchaldeaにしました)に、このbotを招待しておきます。

1-2. slackbotの動作確認
次にslackbotを動かします。
(参考:https://qiita.com/sukesuke/items/1ac92251def87357fdf6)
まずは適当な場所にgit cloneでslackbotリポジトリをクローンします。
※ pip installでも入りますが、そのままだとIFTTTに対応してないので、あとで書き換え作業をするためにクローンします
git clone https://github.com/lins05/slackbot.git
そして、cloneしてきたリポジトリはいったんそのままにしておき、
別の場所に作業用のディレクトリを作ります。
mkdir merlin_bot
cd merlin_bot
さきほどクローンしたslackbotリポジトリから必要なファイルをコピーしてきます。
(ついでに今回は使わないファイルは消しておきます)
また、ボット起動用のファイルやpluginディレクトリ(あとで利用)もつくります。
# slackbotリポジトリのslackbotディレクトリをまるっとコピー
cp -r ~/git/slackbot/slackbot .
# 使わないファイルを削除
rm slackbot/VERSION
rm -r slackbot/plugins/
# requirementsもコピー
cp ~/git/slackbot/requirements.txt .
# bot起動用ファイル作成
touch run.py
touch slackbot_settings.py
# plugin
mkdir plugins
touch plugins/__init__.py
ディレクトリ構成はこんな感じ。
merlin_bot/
├── plugins
│ └── __init__.py
├── requirements.txt
├── run.py
├── slackbot
│ ├── __init__.py
│ ├── bot.py
│ ├── dispatcher.py
│ ├── manager.py
│ ├── settings.py
│ ├── slackclient.py
│ └── utils.py
└── slackbot_settings.py
requirementsをインストールします。
pip install -r requirements.txt
run.pyを以下のように編集します。
# -*- encoding: utf-8 -*-
from slackbot.bot import Bot
def main():
bot = Bot()
bot.run()
if __name__ == '__main__':
main()
slackbot_settings.pyを以下のように編集します。
# -*- encoding: utf-8 -*-
# botアカウントのトークンを指定
API_TOKEN = "(さきほどメモっておいたAPIトークン)"
# このbot宛のメッセージで、どの応答にも当てはまらない場合の応答文字列
DEFAULT_REPLY = "でふぉ"
# プラグインスクリプトを置いてあるサブディレクトリ名のリスト
PLUGINS = ['plugins']
# 投稿するslack上のチャンネル
ERRORS_TO = 'chaldea'
ここまでできたら、botを起動して動作確認します。
python run.py
chaldeaチャンネルで、merlin_bot宛にメッセージを送ると、デフォルトの発言が返ってきます。

1-3. 特定の文字列に反応させる
listen_toデコレータを使うと簡単にできます。
run.pyで、listen_toのインポートを追加し、listen_func関数を追加。
# -*- encoding: utf-8 -*-
from slackbot.bot import Bot
from slackbot.bot import listen_to
@listen_to('しゅっしゃ')
def listen_func(message):
message.send('おはよう!')
def main():
bot = Bot()
bot.run()
if __name__ == '__main__':
main()
runしてslackに「しゅっしゃ」と投げると...
python run.py
出社に反応してくれるようになりました!
2. IFTTTのAppletを作ってslackに投稿する
構成図①〜②の部分です。
※今回はiOSの解説になります
IFTTTのNew Appletから登録します。
今回は、位置情報トリガの本番用と、ボタンをポチッと押すデバッグ用の2つのAppletをつくります。
2-1. 位置情報トリガのIFTTT
「this」をタップすると、「Location」というメニューが出てくるのでタップ。

今回は出社なので、「You enter an area」を選択。

次のページの位置情報選択で、自分の会社の位置を選択します。
(なお私はしがないエンジニアなので皇居勤務ではありません...)

create an triggerでトリガーが作れます。
次は「that」を選択。
search servicesからslackと入れるとslackがでてきます。

Post to channelと選択し、ワークスペースやチャンネルの情報を入れます。
「Message」には「しゅっしゃ」を入れます。

「Create action」を押すと新しいAppletができます。
2-2. ボタントリガのIFTTT
位置情報トリガだと、動作確認のために毎回スマホを持って行ったり来たりする必要があります。
なので、ボタンを押すとslackに投稿するデバッグ用IFTTTを作っておきます。
「this」の部分で、buttonと入力すると「Button widget」が出てきます。
次の画面で「Button press」をタップすると「this」のところがボタンになります。

thatの部分は2-1と同じ、slackへの投稿を設定します。
ボタンは、MyAppletsから登録したAppletを選択し、「Widget settings」を選択、次の画面でボタンアイコンをタップするとボタンを押す画面に遷移します

ボタンを押すと、slackのチャンネルにIFTTTから投稿が確認できます。

ただし、このままではslackbotが反応しません。
3. slackbotをIFTTTに対応させる
こちらの記事に書いたんですが、IFTTTの投稿フォーマットが通常のそれと異なるため、このままではIFTTTの発言にbotが反応してくれません。
なので、slackbot/dispacher.pyというファイルを修正します。
def _dispatch_msg_handler(self, category, msg):
responded = False
for func, args in self._plugins.get_plugins(category, msg.get('text', None)):
if func:
responded = True
try:
def _dispatch_msg_handler(self, category, msg):
responded = False
text = None
if 'text' in msg:
text = msg.get('text', None)
elif 'attachments' in msg and len(msg.get('attachments')) > 0:
text = msg['attachments'][0].get('pretext', None)
for func, args in self._plugins.get_plugins(category, text):
if func:
responded = True
try:
修正後、slackbotを起動してからIFTTT経由で投稿すると、ちゃんと反応が返ってきます。

4. いろんなパターンでほめてもらう処理を作る
「おはよう!」だけだと味気ないので、毎日いろんなパターンで出社をほめてもらいます。
4-1. pluginsを作成
さきほどのlisten_toの処理をplugins以下に新しくファイルを作って移動します。
touch plugins/good_morning.py
# -*- encoding: utf-8 -*-
from slackbot.bot import Bot
def main():
bot = Bot()
bot.run()
if __name__ == '__main__':
main()
# -*- encoding: utf-8 -*-
from slackbot.bot import listen_to
@listen_to('しゅっしゃ')
def listen_func(message):
message.send('おはよう!')
4-2. ほめセリフを収集
出社したらほめてくれるといえばコウペンちゃんです。
今回はコウペンちゃんbotから出社したり起きたりしたらほめてくれるセリフを収集し、マーリン風に加筆修正したものを使います。
一行一セリフの以下のようなテキストファイルを作りpluginsの下に置きます。
今日も出勤するなんて、君はえらいね。
今日もえらいね。
今日も1日頑張ってね。
ちゃんと起きられたなんて、えらいじゃないか!
電車に乗れたのかい?えらいね!
これを読み込んでランダムに出すようにgood_morning.pyを修正します。
from slackbot.bot import listen_to
import random
serif = []
serif_file = "plugins/serif_merlin.txt"
with open(serif_file, 'r') as f:
serif = [l.strip() for l in f.readlines()]
prefix = ['おはよう!', 'おはようマスター。']
@listen_to('しゅっしゃ')
def listen_func(message):
message.send(random.choice(prefix) + random.choice(serif))
python run.pyして動作確認します。

だいぶマーリンに近づいてきました。
4-3. アイコンや名前を整える
slackのアイコンや名前がデフォルトのままだったので、slackのBot管理画面から編集します。
APIトークンが表示されてた画面を下にスクロールすると画像や名前を設定できます。

インテグレーションを保存して、slack画面に戻ると名前やアイコンが反映されてます。

おお!!マーリンがほめてくれた!!
5. herokuにデプロイ
実際に運用する際、ローカルでpythonを実行しつづけるのは辛いので、herokuにデプロイします。
5-1. デプロイ用のファイルを準備
merlin_botディレクトリ直下にファイルを作ります。
cat <<EOF > Procfile
worker: python run.py
EOF
cat <<EOF > runtime.txt
python-3.6.7
EOF
また、このへんを参考に.gitignoreを作ります。
現在のディレクトリ構成はこんな感じ。
merlin_bot
├── .gitignore
├── Procfile
├── plugins
│ ├── __init__.py
│ ├── good_morning.py
│ └── serif_merlin.txt
├── requirements.txt
├── run.py
├── runtime.txt
├── slackbot
│ ├── __init__.py
│ ├── bot.py
│ ├── dispatcher.py
│ ├── manager.py
│ ├── settings.py
│ ├── slackclient.py
│ └── utils.py
└── slackbot_settings.py
5-2. herokuにデプロイ
gitのfirst commitを作っておく。
git init
git add .
git commit -m "first commit"
herokuにログインして、新しくアプリを作る。
heroku login
heroku create
herokuにデプロイ
git push heroku master
しばらく待つとデプロイが完了します。
Herokuのプロセスをworkerにすると、デプロイしただけではプロセスが立ち上がりません。
なので、Herokuの管理画面の「Resources」から、workerをオンにします。

heroku ps
Free dyno hours quota remaining this month: 998h 20m (99%)
Free dyno usage for this app: 0h 0m (0%)
For more information on dyno sleeping and how to upgrade, see:
https://devcenter.heroku.com/articles/dyno-sleeping
=== release (Free): /bin/sh -c 'if curl $HEROKU_RELEASE_LOG_STREAM --silent --connect-timeout 10 --retry 3 --retry-delay 1 >/tmp/log-stream; then
chmod u+x /tmp/log-stream
/tmp/log-stream /bin/sh -c '"'"'python run.py'"'"'
else
python run.py
fi' (1)
release.2746: up 2019/01/20 16:24:03 +0900 (~ 21s ago) ### あがってます
いかがでしたか?
マーリンのセリフはちょっとバリエーションが少ないので、同じ仕組みでキュケオーン(@QK_otabe)とトリスタン(@wtsknsi)も追加してみました2。
弊カルデアは今日も平和です。

ソースコード
大いなる参考記事
- Slack Botの種類と大まかな作り方
- PythonのslackbotライブラリでSlackボットを作る
- PythonのslackbotライブラリでSlackボットとIFTTTを連携
- Google Home MiniからIFTTTを経由し、Slackに投稿してPS4を操作する
- Heroku(Free Dyno)のWorkerでSlackのBotkitを動かしてみよう!
- コウペンちゃんbot
- キュケオーンをお食べ
- 悲しいトリスタン卿bot


