Help us understand the problem. What is going on with this article?

Slack BotをGASでいい感じで書くためのライブラリを作った

More than 1 year has passed since last update.

全国のGoogle Apps Scriptファンの皆様こんにちは
Apps Scriptガチ勢の大橋です。

今年でGoogle Apps Scriptアドベントカレンダーも3年目になりました。
年々人は減っている気がしますが、BigQueryとの連携など他のアドベントカレンダーに名前が出ることが増えてきて、嬉しい限りです。

さて、ちょいSlack BotをGASで作る機会があったのでSlack API周りをGASで扱うためのLibraryを作りました。
今回はこのLibraryとそれを使って作った会議予約Botのサンプルコードについて書いていきたいと思います。

なお知らない方も多いので書いておくと、GASのLibrary機能は丁寧に作ると補完が非常に効くようになり、開発効率が10倍以上変わります。

26_12_08_10_55.png

Libraryについて詳しくは以下の記事を見て下さい。

ライブラリ SlackApp

基本情報

使い方

前提として https://script.google.com からGoogle Apps Scriptプロジェクトを作成して下さい。
当然GASガチ勢の皆様はブラウザのアドレスバーにscぐらいまで打てば上記URLが補完され、
GASエディターが起動できる状態になっていると思います。

Libraryを導入

プロジェクトにLibraryを導入します。
GASのライブラリを使って楽したい① とりあえず使ってみる(:3」∠)」を参考に、下記キーのライブラリを導入して下さい。

M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO

Slack API Tokenの取得

APIへアクセスするためのtokenを取得します。
tokenは https://api.slack.com/web の「Authentication」から取得できるはずです。

Slack_API___Slack.png

取得したらGASプロジェクトのScript Propertiesあたりに保存しておきます。

save.gs
function saveToken() {
  PropertiesService.getScriptProperties().setProperty("token", "取得したトークン");
}

なお、Slack APIにはOAuth2による認証方式が有り、Library自体もそれに対応しているのですが、めんど... 複雑なためドキュメント化していません。
ほとんど過去に作ったTypeTalkのLibraryと同じ作りなので、そちらを参考にしていただくとやれると思います。

投稿してみる

Tokenを使って投稿しています。

postMessage.gs
function postMessage() {
  var prop = PropertiesService.getScriptProperties().getProperties();

  //slackApp インスタンスの取得
  var slackApp = SlackApp.create(prop.token);

  //適当にchannel idを取得
  var channelId = slackApp.channelsList().channels[0].id;

 //投稿
  slackApp.postMessage(channelId, "ハロー世界", {
    username : "MyFirstBot"
  });
}

このLibraryの各メソッド名はSlackAppのAPI名と同じです。
例えばチャネル情報を取得する「channels.info」APIであれば「slackApp.channelsInfo(channelId)」が対応します。

Botとして動かしてみる

Slackへの投稿に対して反応するBotを作成する場合は、Slackの「Outgoing Webhook」とGASのdoGetを利用します。

GASにdoGetを作る

2013年度版 5分で始めるWebアプリケーション(Google Apps Script)」を参考にGASプロジェクトにてdoGet関数をつくり、HTTP GETアクセスできるようにします。

この時入り口のURL(https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxx/exec)をメモっておいて下さい。

なおSlackからは何も認証を行っていない、単純なGetリクエストが来るため、「ウェブアプリケーションとして導入」する際に「アプリケーションにアクセスできるユーザー」を「全員(匿名ユーザーを含む)」にしておいて下さい。
Google Appsのアカウントを利用している場合Apps側の設定によってはこのオプションが選べないのでご注意下さい。
=諦めて下さい。

無題のプロジェクト.png

doGet.gs
function doGet(e) {

  return null;
}

SlackにてOutgoing Webhookの設定を行う。

Slackのoutgoing-webhookの設定画面にアクセスします。

画面が表示されたら「Add Outgoing WebHooks Integration」をクリックします。
outgoing.png

次の画面が表示されたら下の方の「Integration Settings」に行き設定を行っていきます。

「Channel」はOutgoing WebHooksが動くChannelですね。
「Any」にしておくとどこでも動きます。Channelを絞りたい場合は何かしらのChannelを選択しておきます。

「Trigger Word(s)」は「Outgoing WebHooks」が動くためのTriggerとなる単語です。
例えば「MyFirstBot:」とかしておくと「MyFirstBot:」が先頭にあるときだけ動きます。

「URL(s)」に先ほどメモったURLを貼り付けておきます。

また必須ではないですが「Token」をメモって置くと良いです。TokenはSlackがGetリクエストを送ってくる際に渡してくれる検証用トークンです。
GASのdoGet内でSlackからのアクセスかどうか突合して置くと良いと思います。

outgoing-webhooksetting.png

GAS側でdoGet内のコードを書く

以下の感じでコードを書きます。

function doGet(e) {

  //Get properties.
  var prop =  PropertiesService.getScriptProperties().getProperties();
  if (!e) {

    //for Test. Slackからは以下のパラメータで飛んできます。
    e = {
      parameter : {
        token : prop.verifyToken,
        team_id : "T0001",
        channel_id : "C12345678910",
        channel_name : "test",
        timestamp : "1355517523.000005",
        user_id : "U2147483697",
        user_name : "Steve",
        text : "MyFirstBot: Hi",
        trigger_word : "MyFirstBot:"
      }
    };
  }

  if (prop.verifyToken != e.parameter.token) {
    throw new Error("invalid token.");
  }

  //Create an instance.
  var slackApp = SlackApp.create(prop.slackToken); 

  //My first Message!
  slackApp.chatPostMessage(e.parameter.channel_id, "Hi " + e.parameter.user_name, {
    username : "My First Bot",
    icon_emoji : ":+1:" 
  });

  return null;
}

なおコードの更新後、GASプロジェクトのバージョンを上げ、ウェブアプリケーションのバージョンを上げるのを忘れないで下さい。
何言っているかわからない人は多分「コード更新したんだけど動かない」ってなるはずです。
その時上の呪文を唱えて下さい。

Slackから送ってみる

実際に選択したSlackのchannelから上記Trigger Wordを付けてメッセージを送ってみましょう。
Botが返信してくれるはずです。

まとめ

いかがでしたでしょうか?
GASとSlackが混ざることによりかなりのことが自動化できます。
個人的に作っているものだと「会議予約Bot」というのがあって、
「会議予約: 2014/12/01 17:00-18:00 定例会議 人:"大橋、...." 場所:"A会議室"」
みたいな投稿をすると以下のことをしてくれます。

  • Google Calendarへのイベントの作成(参加者全員を呼び出し)
  • Goodle Docsの議事録フォーマットをコピーし人、場所、日時を設定
  • 会議日前日当日(朝、開始10分前)に事前作成した議事録のURLをSlackに貼り付け

これだけでかなりの自動化と、「会議室予約ミスの削減」「議事録の作り忘れ、テンプレートの場所がわからないから作らない問題の解決」「議事録どこだっけの無駄な時間の削除」ができます。
素敵ですね!

あとはBigQueryのQueryを投げると検索してそのまま返してくれるBotと、
グラフ化して返してくれるBotもいたりします。

BotとGASは色々相性が良いです。
またHubotなどのようにサーバを準備する必要が無いため、
必要になったその日にBotを運用開始できます。

ぜひ素敵なChatOpsライフを!

soundTricker
Google API、Google Apps、Google App Engine、Angular(1&2)、Google Apps Scriptらへんの人 一応Google Developer Expert(Apps Script)です。 https://developers.google.com/experts/people/keisuke-oohashi
https://plus.google.com/u/0/112329532641745322160/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした