MORITOMOMENT

登山好きエンジニアのテックブログ

プログラミング・アウトドア関連を中心に発信

Slack APIを使ってチャットボットを作ってみる 勉強編#1

簡単に作ってみた成果物はページの最後にあります。

めちゃくちゃ簡単な成果物

なぜ勉強しようと思ったか

AmazonKindle unlimetedに加入しているのですが,偶然「Node.jsとPythonを使ったSlack API 活用術 - チャットボットの活用で仕事効率化」というタイトルのkindle本を見つけました。

これを学んでみようと思った動機は

  • 単純に面白そう
  • botをうまく利用すれば仕事効率化ができると書いてあるから学んでおいて損はないんじゃない?
  • 所属している大学の研究室ではSlackを用いてイベントのアナウンス、情報の共有をおこなっている。もしかしたら研究室でおこなっている事務的なめんどくさいこともbotで解決できるんじゃないか

ということで、上記のkindle本からnode.jsもしくはpythonからSlack APIを活用する基本を学んでみる。

実行環境

ちなみにMac OS Mojaveで実行しているので、あしからず。

チャットボット開発のための下準備

まずはチャットボットとして働いてくれるボットを作成する必要があります。 ボットと呼んでいるけれど、正式には「Slack App」と呼ばれます。 Slack Appにボットとして働いてもらうためには、自分のSlackのワークステーションにSlack Appをインストールする必要があります。

Slack Appのインストール手順

  1. https://api.slack.comにアクセス
  2. アクセス後、画面右上の「Your Apps」をクリック
  3. 「Create New App」をクリックし、指示に従って名前やインストール先のワークステーション等を入力して作成完了!

インストール後重要となる情報

ボットアプリケーションのプログラムを実行するために認証コードが必要となります。 認証コードは作成したSlack AppのOAuth & Permissionsタブから確認可能です(下図の赤いとこ、このコードは秘匿!!)。

f:id:moritomo7315:20181130173523p:plain

次は作成したSlack Appから自分のSlackのチャンネルにメッセージを送信します。

メッセージを送信する

メッセージを送信するために必要なメソッドは、

chat.postMessageです。メソッドの詳細は下記urlからどうぞ。

chat.postMessage method | Slack

それと先ほど認証コードが表示されているページを下にスクロールすると、Scopeという欄がでてきます。

f:id:moritomo7315:20181130173947p:plain

Scopeとは、

Scopes define the API methods this app is allowed to call, and thus which infomation and capabilities are available on a workspace it’s installed on. Many scopes are restricted to specific resources like channels or files.

と書かれています。要するに、scopeを追加していってSlack Appの機能を拡張していきます。

今回はメッセージを送信するので、メッセージ送信機能を持つscope「chat:write:bot」を追加します。select permission scopeに入力すればでてきます。

その後プログラムを書いて実行するだけ。

node.jsの場合

実際のプログラムはこんな感じ。

var WebClient = require('@slack/client').WebClient; //公式のsdkからWebClientをインポート
var token = process.env.SLACK_TOKEN; 
var web = new WebClient(token); 
var channelId = '#ボットテスト'; //メッセージを送信したいチャンネル名を指定

//このchat.postMessageが重要!
//引数textに送信したいメッセージを記述
web.chat.postMessage({channel:channelId, text:'Hi there'})
     .then( (res)=> {console.log('Message sent: ', res.ts);})
     .catch(console.error);

実行手順は、

  1. export SLACK_TOKEN=認証コード
  2. node ファイル名.js

ターミナルには、

Message sent:  1543563728.000100

と出力され、実際にSlackにメッセージが送信された。

f:id:moritomo7315:20181130164541p:plain

pythonの場合

「slackclient」というモジュールが必要となるので、「pip」でインストールする必要があります。僕はpython3を使っているので

pip3 install slackclient

でインストールしました。

実際のプログラムは、

import os
from slackclient import SlackClient 

slack_token = os.environ["SLACK_TOKEN"]
sc = SlackClient(slack_token)

sc.api_call(
     "chat.postMessage", #メッセージ送信に必要なメソッド
     channel="#ボットテスト", #送信先チャンネル名 
     text="Hello from python!" #送信するメッセージ内容
)

実行手順は、

  1. export SLACK_TOKEN=認証コード
  2. python3 ファイル名.py

画像ファイルをアップロードする

問題発生

ここは備忘録的に書いておきます。 kindle本の通りにやってみたんだけど、なぜかnode.jsとpythonからslackに画像をアップロードができない、、、 同じ現象に当たっている人は必見。

node.jsを出力した際にでたエラーメッセージはこんな感じ。

{ Error: An API error occurred: missing_scope
    at got.post.catch.then (/Users/moritomokana/Documents/slackbot開発/jsproject/node_modules/@slack/client/dist/WebClient.js:383:62)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
  code: 'slackclient_platform_error',
  data:
   { ok: false,
     error: 'missing_scope',
     needed: 'files:write:user',
     provided: 'identify,chat:write:bot',
     scopes: [ 'identify', 'chat:write:bot' ],
     acceptedScopes: [ 'files:write:user' ] } }

エラー内容がmissing_scopeとなっており、scopeには'identify', 'chat:write:bot'しかない。 おそらくファイルをアップロードするために必要な権限がないのではないか?? ちなみにエラーの見方は以下のurlを参考にしました。

azriton.github.io

改善

Slack APIのSlack Appsの設定から

Scopeに「files:write:user」を追加してみました。

そしたら成功!!

f:id:moritomo7315:20181130164548p:plain

ちなみにbotからファイルをアップロードするscopeはありませんでした。 まあアップロードの自動化がしたいだけなら、Userからでもbotからでもどっちでもいいですよね。

実際に役に立ちそうなbotをつくってみた

みんなに役立つかどうかはわからないけど、研究でシミュレーションやプログラムを長時間動かして、それが終わった時にSlackに通知してくれたら便利だなと思いました。

Shellと組み合わせれば、非常に単純に実行完了通知をSlackに通知することができます。

具体的なシミュレーションプログラムを載せることはできないので、 例として、簡単な(すぐ終わる)プログラムを動かして、それが終了したらSlackに完了通知するようにするものを紹介する。

print.py

for i in range(1,100):
    print(2*i)

sent_message.js

var WebClient = require('@slack/client').WebClient; //公式のsdkからWebClientをインポート
var token = process.env.SLACK_TOKEN; 
var web = new WebClient(token); 
var channelId = '#シミュレーション'; //メッセージを送信したいチャンネル名を指定

//このchat.postMessageが重要!
//引数textに送信したいメッセージを記述
web.chat.postMessage({channel:channelId, text:'プログラム終わったよ!!'})
     .then( (res)=> {console.log('Message sent: ', res.ts);})
     .catch(console.error);

この二つのプログラムを自動で順に実行すればいいだけなので、

test.sh

export SLACK_TOKEN=認証コード
python3 print.py
node sent_message.js

を作成しターミナルでsh test.shと実行するだけ。

画質荒いですが、あしからず。ターミナル内でsh test.shを実行すると、pythonプログラムがうごき、完了するとSlackに完了通知が届く様子がわかります。

f:id:moritomo7315:20181130183646g:plain

まとめ

今回はkindle本からSlack APIの基本を学び、研究で使えそうなbotを作ってみました。

とりあえず、Scopeが大事。笑

まだkindle本は36%しか読めていないので、さらに学習を進めてもっといいbotが作れたらシェアしたいなと思います。