ママはゆるキャリ!

ヲタママエンジニアが興味の向くままに書く雑記ブログ

ママはゆるキャリ!

【Slack+GAS】特定の発言に反応して何らかの返答を返す

SlackのOutgoingWebHooksを使って、

「Slackで特定の発言をトリガーにしてGoogleAppsScript(以下GAS)でとあるサイトのスクレイピングをし、得た情報をSlackに返す」

ということをしてみようと思いました。

ネットを探せば結構ありふれたネタなのですが、これが如何せんGAS初心者の私にはつまずきの連続でした。。

そこで、恥ずかしながらつまずいた点と共に、段階的に進めていった記録をここに記そうと思います。

今回やってみたこと

Slackのあるチャンネルにおいて、特定のキーワードを発言すると何らかの返答が返ってくる

f:id:tomo-sankaku:20180417200204p:plain:w500

例えば「プリキュア」を含む発言があった場合に、「○○さんが#XXXチャンネルで『(プリキュアを含む発言)』と言いました」とSlackにPOSTすることができます。

#backlog チャンネルでこんな投稿をすると…
f:id:tomo-sankaku:20180417235653p:plain:w500

  ↓ こうお知らせされます。

f:id:tomo-sankaku:20180417233124p:plain:w500

手順

  • 【Slack】OutgoingWebHooksの設定
    • トリガーになるキーワード
    • 対象のチャンネル
    • POST先URL(GASのスクリプト作成後に登録)
  • 【Slack】APIアクセストークンの取得
  • 【GAS】スクリプト作成
    • SlackAppライブラリ追加
    • スクリプトプロパティの登録
    • スクリプトの公開(ウェブアプリケーションとして導入)

出来上がってからあらためて見返すとほとんど下記の記事の通りなのですが、あちこちつまずいている時はこの通りに上手くいかず苦戦しました。。

qiita.com

【Slack】OutgoingWebHooksの設定

f:id:tomo-sankaku:20180417015626p:plain:w300

「Administration」>「Manage Apps」から「Custom Integrations」>「Outgoing WebHooks」をクリック。

「Add Configuration」ボタンを押し、「Add Outgoing WebHooks integration」ボタンを押すと設定画面に移ります。

Integration Settingsの以下項目をそれぞれ入力し、保存します。

項目 内容
Channel 起動させる対象チャンネル(publicのみ)を指定。「Any」にすると全てのpublicチャンネルが対象となる。
Trigger Word(s) トリガーとなるキーワード。発言の冒頭に来る場合のみ反応する(文中・文末は不可)。
URL(s) 起動時に情報をPOSTするURLを指定。今回の場合はGASスクリプトのウェブアプリケーションURL。
Customize Name (任意)このWebHookの名前を入力。通知時に表示される。後述のGASでも設定可なのでデフォルトのままでもOK
Customize Icon (任意)このWebHookのアイコンを指定。通知時に表示される。後述のGASでも設定可なのでデフォルトのままでもOK

ここでWebHookの「Token」が表示されますが、後で使用するのでコピーしておきます。

【Slack】APIアクセストークンの取得

Slack API: Applications | Slackにアクセスし、「Create new app」からアプリを作成します。

f:id:tomo-sankaku:20180418003157p:plain:w300

作成後、「Install your app to your workspace」にある「permission scope」のリンクをクリックします。
(もしくは左カラムの「OAuth & Permissions」から行っても同じURLにたどり着きます)

f:id:tomo-sankaku:20180418004309p:plain:w300

Scopesでスコープのプルダウンから「Send messages as (アプリ名)」を選択し保存すると、「Install App to Workspace」ボタンが活性化するのでそれを押します。

「Authorize」ボタンを押すとAPIトークンが発行されます。

理由は後述しますが、これだけなのに地味にハマりました。。

これらの手順は、以下記事がとても参考になりました。

qiita.com

【GAS】スクリプト作成

Apps Script – Google Apps Scriptから新規スクリプトを作成します。

SlackAppライブラリ追加

先人による有難いライブラリがあるので、ありがたくこれを使うことにします。

qiita.com

「リソース」>「ライブラリ」から「ライブラリの追加」の欄に以下ライブラリキーを登録します。

M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO

スクリプトプロパティの登録

「ファイル」>「プロジェクトのプロパティ」から「スクリプトのプロパティ」を選択し、先ほど取得したトークンをそれぞれ登録します。

名前は何でもいいのですが、わかりやすいように以下のようにしました。

  • verifyToken:OutgoingWebHooks設定時に発行されたトークン
  • slackToken:SlackAPIのアプリ作成時に発行されたトークン

f:id:tomo-sankaku:20180418011103p:plain:w400

スクリプト作成・公開
function doPost(e) {
  //スクリプトプロパティ取得
  var prop = PropertiesService.getScriptProperties().getProperties();
  var bot_name = "testbot";
  var bot_icon = ":tada:";
  
  var app = SlackApp.create(prop.slackToken);
  //POSTされた情報を使ってメッセージを作る
  var message = e.parameter.user_name + "さんが" + e.parameter.channel_name + "で" + e.parameter.text + "と言いました";
  
  //POST元が違っていたらエラー
  if (prop.verifyToken != e.parameter.token) {
    throw new Error("invalid token.");
  }
  
  //特定のチャンネルにメッセージをPOSTする
  return app.postMessage("#test", message , {
    username: bot_name,
    icon_emoji: bot_icon
  });
}

プロジェクトを保存し、「公開」>「ウェブアプリケーションとして導入」をクリックします。

f:id:tomo-sankaku:20180418013130p:plain:w300

プロジェクトバージョンを「新規作成*1」にし、アクセスできるユーザーを「全員(匿名ユーザーを含む)」にして導入(更新)ボタンを押します。
(初回は承認を求められるので承認もします)

この時に表示される「ウェブアプリケーションのURL」を、OutgoingWebHooks設定画面の「URL(s)」に入力すれば完成です。

つまずいた点

使うトークンを間違えていた(SlackAPIを登録していなかった)

これは単純に私の勘違いですが、SlackApp.create()で渡すトークンをOutgoingWebHooksのトークンにしてしまっていました。。

しかもSlackAppを作った方の記事(承前)をきちんと読んでおらず、SlackAPIのトークン発行をしていませんでした。

SlackAPIサイト内で迷子になった

トークン間違いに気づいたものの、いざSlackAPIのトークン発行をしようとすると、初見では発行までの導線が複雑でたどり着くだけでかなりの時間を要してしまいました。。

いくつかのサイトを参考にしたのですが、参考サイトの画面キャプチャと実際の画面とが一致しない*2こともしばしば。。「このメニュー出てないけど?!」「こんなリンクないけど?!」「遷移先違うんだけど?!」とハテナだらけでパニックでした。

公式リファレンスなので常に最新の状態を保っているんだと思いますが、パッと見導線がわかりにくい*3のは辛いなぁ…と思いました。

レガシートークンと推奨トークンの存在を知らなかった

SlackAPIのトークンは2017年ごろから変わったようで、旧式のものをレガシートークンと呼ぶそうです。

参考にしたサイトの中にはこのレガシートークンが現行トークンだった頃に書かれたものもあり、現在と導線や遷移先が違うのはそのせいだったようです。。

OutgoingWebHooksのトークン、SlackAPIのレガシートークン、推奨トークンの3つのトークンに翻弄され、たったこれだけのことを初めて動かせるようになるまで遠回りしてしまいました。

次回予告

Slackで呼ぶと返るようにはできたので、次回はGASでサイトのスクレイピングをするところを書いていきたいと思います。

またそれなりに苦戦すると思うので、更新は気長にお待ちくださいw

(追記) 【悲報】スクレイピングしようと思っていたサイトが閉鎖されてしまいました…

www.yururito.net

*1:更新時も毎回「新規作成」にします。

*2:この記事もいずれそうなりそうな予感がしますね…。。

*3:単に私が英語苦手だから、というのもあるかもしれないですが。。慣れれば平気かもしれませんが、初見殺しに感じました。