Edited at
ProgateDay 21

Slash CommandsとGASでSlackのオリジナルコマンドをつくる

Progate Advent Calendar 2017 21日目です!

今回は、SlackのSlash CommandsとGAS(Google Apps Script)を使って、

Slackで使えるオリジナルコマンドをつくる方法を紹介します!


Slash Commands

Slash Commandsというのは、その名の通り、/から始まるコマンドのことです。

標準で用意されているものだと、/remindがあります。けっこう便利でよく使っています。


Google Apps Script

Google Apps Script (GAS)は、JavaScriptをベースにしたスクリプト言語です。

JavaScriptが書ければ普通に扱えます。ただ、ES6の記法には対応していません。

GASの魅力は2つあります。

1つ目は、Googleのサービスと連携ができることです。これは今回活用しないので説明は割愛します。

2つ目は、Googleがサーバー環境を無料で提供してくれることです。

WebAPIとして公開したり、cronのように時間主導型のトリガーを設定したりすることができます。

ケチなので、個人的には無料ってところに魅力を感じます。。


今回つくるもの

登場人物の紹介は済んだので、早速オリジナルコマンドをつくっていきます!

今回は、NetatmoのAPIを使って現在のCO2濃度や湿度を確認できるコマンドをつくります。

具体的には、/netatmo co2と入力すると、CO2濃度を教えてくれるコマンドです。

Netatmoって何?という方は、3日目の記事をご覧ください。

(もし読んでくださったら「いいね」もお願いします笑)

Netatmoと言っても今回使うのはただのWebAPIです。

Netatmo持っていないよーという方でも参考にしていただけると思います!

スモールステップで進めていくので長くなると思いますが、よろしければ最後までお付き合いください!


オリジナルコマンドの作成


a. 流れを理解する

実際につくり始める前に、どのように登場人物が活躍するか確認しましょう。

図で示すと以下のようになります。

NetatmoのAPIは4番の中で使われる、というイメージです。

この画像はこれから何回か登場するので、覚えなくて大丈夫です!


b. GASのプロジェクトを作成する

流れが理解できたら、まずコマンドを受け付けるサーバー側を用意します。

https://script.google.com を開いてみましょう。

Googleアカウントにログインしている状態であれば、新規のプロジェクトがつくられるはずです。

ログインしていない場合は、Google Apps Scriptのページに飛ぶと思います。

その場合は「Start Scripting」ボタンから進めば大丈夫です!

画像からわかるように、GASはブラウザ上のエディターで開発します。

まずは簡単にログを出力してみましょう。


コード.gs

function myFunction() {

Logger.log('console.logじゃないよ!');
}

これで保存します。

保存するときにプロジェクト名を聞かれますが、今回はNetatmoAppにしました。

ちなみに、このプロジェクトはGoogleドライブのマイドライブ直下に保存されます。

関数の実行は、動画の再生ボタンみたいなボタンでできます。

また、ログは、メニューの「表示」=>「ログ」から確認できます。

これでもうGAS初心者は卒業です!


c. POSTのリクエストを受けられるようにする

GAS初心者も脱したところで、早速GASでPOSTのリクエストを受けられるようにしましょう!

画像での3番に当たります。

GASでは、doPostという関数でPOSTのリクエストを受けるようになっています。

まずはdoPost関数を定義しましょう。


コード.gs

function doPost(e) {

}

引数eにパラメータなどが入ってきます。

ついでに4番、メッセージの用意もしてしまいましょう。

メッセージはJSONで用意します。


コード.gs

function doPost(e) {

var response = { text: 'テストメッセージ' };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


returnのところが少し複雑ですが、このようにすることでJSONを返せます。

最後に、このプロジェクトをWebアプリケーションとして公開します。

メニューの「公開」=>「ウェブ アプリケーションとして導入...」のように進みます。

そうするとダイアログが出てきます。

画像のように設定をしましょう。

3つ目のアプリケーションにアクセスできるユーザーはデフォルトでは自分になっています。

忘れずに変更しましょう。

これで「導入」ボタンを押せば見事Webアプリケーションとして公開されます!

次のダイアログで出てくるURLは取っておいてください。あとで必要になります。

ここまでで、画像の3と4の部分を簡単にですが実装することができました!


d. Slack Appをつくる

さて、先に画像の3番と4番を実装してしまいましたが、ここで画像の1番の用意をします。

ここまででひとまずコマンドが正常に実行できるようになります!

まずは https://api.slack.com/apps にアクセスしましょう。

Slackのログインができていなければログインします。

ログインできていれば、右側に「Create New App」というボタンが表示されるはずです。

そこからアプリをつくりましょう!

今回はApp NameをNetatmoAppにします。

Workspaceは、コマンドを使えるようにしたいWorkspaceを選択します。

入力できたら「Create App」でAppを作成します!

Appが作成できたら、Settings画面に遷移します。

はじめに、どの機能を使うか選びます。

いろいろ並んでいますが、今回はSlash Commandsです。

次に「Create New Command」で新しくコマンドを作成します。

今回はコマンドを/netatmoにします。

リクエストURLは、GASを公開したときに取っておいたURLにします。

短い説明や使い方のヒントは、コマンド入力時に表示されます。

このフォームの下のプレビューで確認しながら設定してみましょう。

コマンドがつくれたら、SettingsのBasic Informationに戻ります。

そうすると「Add features and functionality」にチェックが付いているはずです。

できていたらAppをworkspaceにインストールします!

ボタンを押して、遷移先で承認ボタンを押せば完了です!

注意: workspaceの管理権限を持っていない場合は、管理権限のあるユーザーの承認が必要になります。

インストールが完了すれば、もうコマンドが使えるようになっているはずです!

Slackで/netatmoと実行して、メッセージが返ってくるか試してみましょう。

テストメッセージが返ってくればうまくいっています!

ここまでで一通りコマンドが動くようになりました!

Slack App側の設定はこれでおしまいです。


e. パラメータを使う

ここからはGASに戻ります。

次は、コマンドの入力をGASで受け取って、それに応じてメッセージを変えてみます。

現状のGASのコードは以下のようになっています。


コード.gs

function doPost(e) {

var response = { text: 'テストメッセージ' };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


引数eにパラメータが入っていると前に述べました。

結論から言いますと、e.parameter.textにコマンドの中身が入っています。

試しにオウム返しさせてみましょう。


コード.gs

function doPost(e) {

var command = e.parameter.text;
var response = { text: command };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


GASはコードを更新したら、再度公開設定をする必要があります。

メニューの「公開」=>「ウェブ アプリケーションとして導入...」ですね。

注意ですが、プロジェクト バージョン新規作成にする必要があります。

これは更新する度に必要ですので、忘れないようにしましょう。

更新してもURLは変わらないので、早速Slackで試してみましょう。

画像のように、/netatmoは含まれずにメッセージが返ってくると思います。

コマンドの入力を取り出したい場合は、e.parameter.textを使いましょう!

もう一点、パラメータ関連でやっておくべき項目があります。

それはVerification Tokenのチェックです。

Slack Appには、Verification Tokenというものがあります。

このTokenはパラメータで渡ってくるので、この値を確認することで、

「このリクエストは自分がつくったAppから送られたものだ!」というチェックができます。

Verification TokenはAppのBasic Information画面で確認できます。

Tokenが確認できたら、GASでこのTokenをチェックするコードを書きましょう。

Tokenはe.parameter.tokenで取得できます。


コード.gs

function doPost(e) {

var verificationToken = e.parameter.token;
if (verificationToken != 'XXXXXXXXXX') { // AppのVerification Tokenを入れる
throw new Error('Invalid token');
}

var command = e.parameter.text;
var response = { text: command };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


このようにすることで、期待しないリクエストにはエラーを返すことができます。

更新する際は公開設定し直すことを忘れずに!


休憩

ここまでで、GASでSlash Commandsをつくる基礎を紹介しました。

もう、自分の思い通りのオリジナルコマンドをつくる土台は整っています!

あとは、

を読みながら、理想のオリジナルコマンドをつくりましょう!

長くなってしまったのでここで休憩です。

ここから先は、オリジナルコマンドの一例として、はじめに紹介したAppをつくっていきます。

よろしければ引き続きお付き合いください。


NetatmoAppを完成させる


a. NetatmoのAPIを確認する

今回はNetatmo Weather StationのGetstationsdataというAPIを使います。

Developer登録やApp登録など必要になりますが、こちらは割愛します。

APIの仕様は以下のようになっています。Responseは今回使うものだけ抜粋しました。

Request

GET https://api.netatmo.com/api/getstationsdata?access_token=[TOKEN]

Response


{
body: {
devices: [
{
dashboard_data: {
CO2: 600,
Humidity: 30,
},
},
],
},
}


b. NetatmoのAPIにリクエストを送る

APIの確認ができたので、GASでデータを取って、CO2濃度をメッセージとして返してみます。

GASでリクエストを送るときはUrlFetchAppというものを使います。


コード.gs

function doPost(e) {

var verificationToken = e.parameter.token;
if (verificationToken != 'XXXXXXXXXX') { // AppのVerification Tokenを入れる
throw new Error('Invalid token');
}

var accessToken = 'XXXXXXXX'; // NetatmoのAccess Tokenを入れる
var url = 'https://api.netatmo.com/api/getstationsdata?access_token=' + accessToken;

var response = UrlFetchApp.fetch(url);
var json = JSON.parse(response.getContentText());
var dashboardData = json.body.devices[0].dashboard_data;
var co2Data = dashboardData.CO2;

var response = { text: 'CO2濃度は' + co2Data + 'ppmです!' };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


これを公開するときには、外部サービスへの接続の許可をする必要があります。

実行してみると以下のようになります。うまく値が取れています!


c. コマンドによってメッセージを変える

仕上げに、コマンドによってCO2の値を返すか湿度の値を返すか変えるようにします!


コード.gs

function doPost(e) {

var verificationToken = e.parameter.token;
if (verificationToken != 'XXXXXXXXXX') { // AppのVerification Tokenを入れる
throw new Error('Invalid token');
}

var accessToken = 'XXXXXXXX'; // NetatmoのAccess Tokenを入れる
var url = 'https://api.netatmo.com/api/getstationsdata?access_token=' + accessToken;

var response = UrlFetchApp.fetch(url);
var json = JSON.parse(response.getContentText());
var dashboardData = json.body.devices[0].dashboard_data;

var command = e.parameter.text;
var text = '';

if (/co2/i.test(command)) {
var co2Data = dashboardData.CO2;
text = 'CO2濃度は' + co2Data + 'ppmです!';
} else if (/humidity/i.test(command)) {
var humidityData = dashboardData.Humidity;
text = '湿度は' + humidityData + '%です!';
} else {
text = '正しくコマンドが指定されませんでした';
}

var response = { text: text };

return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}


これで、/netatmo co2で実行されたらCO2の値を、

/netatmo humidityで実行されたら湿度の値を返すようになりました。

また、コマンドを間違えたときはそれが分かるようなメッセージを返すようにしています。

これで完成です!


終わりに

Slash CommandsとGASでオリジナルコマンドをつくってみました。

GASはGoogleスプレッドシートなどのサービスと連携ができるのも強みです。

これを活用できれば、さらにできることの幅が広がります!

個人的にはBotやInteractive Componentにも挑戦したいと思っています!

皆さんもGoogle先生に感謝しながら、オリジナルコマンドをつくってみてください!

最後までお読みいただきありがとうございました!


おまけ


a. GASが間違っていたとき

GASに不備がある状態でコマンドを実行するとhtmlらしきものがずらずらっと出力されます笑

でもその中にエラーメッセージが含まれているので問題解決に役立ちます。


b. 実際に動かしているNetatmoAppの紹介

今回つくったのは、実際に動かしているNetatmoAppの簡易版でした。

本物のNetatmoAppは、複数同時に出力できたりフォーマットが整っていたりします。