Google Apps ScriptでSlack botを作った

1泊2日で山登りをしてきたので、それをネタにしたSlack botを作った。既にそのSlackチームには複数botが存在しており、ちょっとした事情もあってか、それらはAzure上で動いているものが多い。

個人的にAzureを使いたくなかったのと、AWSの無料枠を使うのももったいないし、GCPは大きすぎるし、Firebaseは無料プランだと外にリクエストを投げられない、といろいろ考えた結果Google Apps Scriptで作成した。

完成品はこちら。

github.com

# Google Apps Script (以下、GAS)

Googleが提供しているJavaScriptっぽい何かで書いたプログラムを実行できるサービス。Googleアカウントがあれば誰でもGoogleドライブ上で作成することができ、Googleの各種サービス(SpreadsheetやGmailなど)と連携もできるので、Excelのマクロのように扱うこともできる。また、手動だけでなく、時間や外部からのリクエストなどをトリガーにして実行もできる。

以前もこんなのを作ったことがあった。

inaab.hatenablog.com

# API概要

Outgoing/Incoming Webhooksを使うのが、Slack botを作る上で一番手っ取り早い。しかし、Outgoing Webhook では文頭のトリガーワードを指定することしかできず、文中に含まれる言葉に反応することができない。今回作成したbotも、文中に含まれる単語に応答したかったため、Events APIを使用した。

qiita.com

処理フローは

  1. リクエストを受け取る
  2. トリガー一覧が書かれたSpreadsheetから、トリガーにマッチするかチェックする
  3. マッチしたトリガーに対応するレスポンスをpostする

という単純なもので、変なことをしなければわりとさくっと実装できる。

# しんどかった部分

今回、Slackとの連携やトリガー検索のためにSpreadsheetと連携のために、トークンやIDを保持する必要があったが、何を思ったのかライブラリ化してしまった。実際にはPropertiesServiceという、プロジェクトのプロパティに環境変数のように追加できる機能があるのでそちらを使うべきだった。

GASでは他に作成したGASプロジェクトをライブラリとして導入できる。Underscore.jsのライブラリなんかもあったりする。公開範囲は自分で設定できるため、自分だけに公開にするとコードを完全に分離することができる。もともとGithubとかでバージョン管理しようと考えていたため、トークンやIDの部分を含まれないようにこの構成になった。

もちろんローカルで実行する際には、何かしらでモックする必要があり、単純にそれ用のコードをかいてrequireしても動かすことはできない。というのも、JavaScriptっぽい何かであって、ブラウザ/nodeのどちらとも異なっており、GASではトップレベルに書いた関数を実行する方式だからである。そういうわけで、ブラウザでも実行できず、nodeのrequireも使うこともできない。

browserifyと、それで生成したものを実行できるように変更してくれるgasifyを利用して、グローバル環境をglobalに入るようにしているため、別途tryRequireという関数を実装した。

module.exports = function tryRequire(modulePath, moduleName) {
  if (global[moduleName]) {
    return global[moduleName];
  } else {
    return require(modulePath);
  }
}

ライブラリを使用している箇所で、globalにこいつを先に読み込み、この関数でrequireする。

global.tryRequire = require('./try_require.js');
const Token = require('./token.js', 'Token');

この解消に一番時間がかかったし、しんどかった。

# 感想

Web系の開発は結構用意するものが多いせいでしんどいイメージがあったけれど、これくらいだったらある程度は楽に作れるように感じた。これが単純なbotだったから良かったものの、これより大きいものをやろうとするとさすがにしんどすぎるのでやらないと思う。

今度個人で何かフロントエンドを実装することになったら、Elmが楽しそうな感じがしてるのでそっちでなんとかやる。


ニューアルバムでたぞ

youtu.be