RACCOON TECH BLOG

株式会社ラクーンホールディングス 技術戦略部より、
tipsやノウハウなど技術的な話題を
発信いたします。

Google Apps Script(GAS)でサクッとデジタルトランスフォーメーション

こんにちは、たむらです。

最近私は組織運営などが主要な業務になっていてめっきりコードを書く機会が減ってしまっているのですが、だからこそ開発業務以外で一杯一杯になった時にコードを無性に書きたくなったりします。

いきなり話は逸れますが、エンジニアをしていると親戚親兄弟から突然電話が鳴り、「なんかテレビが変なのよ~」とか、「何もしてないのにスマホの画面から鈴木さんと撮った旅行の写真が消えたんだけど~」とか『ITやってるんだから、機械とか電気とか色々詳しいんでしょ?』的な雑な括りで頼られること ってありませんか?
私は「あの・・・僕、そっち系のスキルインストールしてない人間なんですよ。ゴメンねー」と返答するのですが、この時感じている若干の苛立ちと悲しみの感情は、「(サクッと解決して)さっすが~~!!」と言われたいという願望の裏返しだったりもするのです。。。

そんな悶々と湧く感情を払拭してくれるツールが今回のトピック 『Google Apps Script(GAS)』 です!
弊社は事業部を中心にまだまだメールやExcelを人手を介して業務に組み込んでいる部分が多かったり、新規企画のプロトタイプ的なライトウェイトな開発要件があったりします。そんなちょっとした業務効率化や機能開発にGASはめちゃくちゃ便利で、最近は何かあるとまるで脊髄反射のようにGASを使うことを前提に考えてしまっています。

GASの一番の良さは「手軽さ」!
サクッと作ってサクッと利用できる点に尽きます。「すっご~~い!」とか「ありがとう!」、「愛してる😍」などの評価を得るには スピードは超大事! うまく使えば願望を満たしてくれること請け合いです!

そんな訳で、今回は先日作ったGAS+SlackのちょっとしたAPIを紹介しつつGASの手軽さをお伝えします。
前置きとして、粗い実装をしますが、"Done is better than perfect" の言葉通り(?)チャチャっと作ることにフォーカスしてますのでそのつもりでお読み下さい~

作ったもの

端的に言うと、slackのあるチャネルのメッセージを日次で監視し、リアクションが付いていないメッセージがあったらその通知を別チャネルに流すというだけのものです。何だそのチープな機能wと思われるかもしれませんが、実業務上でのちょっとした不満なんてこんなもので解決できたりします。

制作の背景としては、社内のある業務で

  1. 担当者が成果物を作成
  2. 作成が完了したらslackの依頼チャネルにレビュー依頼を投稿
  3. レビュー可能なメンバーが投稿にリアクションを返すことでレビュー担当としてレビューする

というフローがありました。多くの場合、3. のリアクションは誰かが拾えるのですが、業務状況や依頼の過多により埋もれてしまいフローが滞るということがあったのです。そこで、今回のAPIでメッセージのリアクションを定期的に監視し、リアクションがない場合はリーダーにアラートを飛ばして担当を割当てる形で運用を補完することを考えました。

slack APIの準備

早速実装です。まずはslack APIから。

App 新規作成

[slackメニュー] - [その他管理項目] - [アプリを管理する] から slack app directory を開き、[ビルド]-[Your Apps]を開きましょう。

そして、[Create New App]

名前等を適当に入力します

[OAuth & Permissions]の設定

まずは[Scopes]から設定しましょう。今回はslackAPIの conversations.history を使ってメッセージデータを取得するので、必要なscopeを指定していきます。
(対象がpublicチャネルならchannels:historyだけで十分です)

[Incoming Webhooks]の設定

アラート投稿部分もchat.postMessageを使えばプログラム的にはキレイなのですが、Incoming WebhooksがAPI作成時にペロッと設定できるので、あるものは使ってしまいます。
そんな訳で、Incoming Webhookの設定も行いましょう。[Activate Incoming Webhooks]をOnにして、[Add New Webhook to WorkSpace]から通知先チャネルを指定します。Webhook URL(★1 GASのコードで使います)が発行されます。

アプリのインストール

[Tokens for Your Workspace]で[Install App]し、Access Token(★2 GASのコードで使います)を発行します。

更に監視対象チャネルにもAPIを追加します。bot Tokenを使うのでAPIをメンバーとして追加してあげないとメッセージの取得ができません。
通知先チャネルはIncoming Webhooksで設定したタイミングで勝手に追加されているはずです。

channelIdを調べる

conversations.history ではchannelIdが必要です。channels.list で調べてもいいのですが、チャネル名右クリック-[リンクをコピー]で取得できます

このリンクのURL末尾部分がchannelIdになります。
こちらを確保(★3 GASのコードで使います)しておきます

GASの作成

GASコードを書く

G Suite Developers Hub から、[新しいプロジェクトを選択]し、コードを書いていきます。
といっても大した内容ではありません。

先に少しだけコードの補足をすると・・・

// slack 関係
const imurl = 'https://hooks.slack.com/services/★1 incoming webhookで取得したURL'
const gtoken = 'xoxb-★2 発行したOAuthトークン'
const channelid = '★3 監視対象チャネルID'

// spreadsheet 関係
const spreadsheet = SpreadsheetApp.openById('スプレッドシートを指定するハッシュ値')
const sheet_name = 'ts_save'
const sheet = spreadsheet.getSheetByName(sheet_name);

function checkSlack() {
try{
  var sendmessage ='';

  // conversations.historyをコールしてメッセージデータを取得
  var url = "https://slack.com/api/conversations.history?token=" + gtoken + "&channel=" + channelid + "&oldest=" + sheet.getRange(1, 1).getDisplayValue();
  var response = UrlFetchApp.fetch(url);
  var json = response.getContentText();
  var res = JSON.parse(json);

  for (var i=0; i<res.messages.length; i++) {
    if(!res.messages[i].reactions && !res.messages[i].thread_ts && !res.messages[i].bot_id){
    // リアクション無し 且つ スレッドブロードキャスト投稿ではない 且つ botの投稿では無い
      sendmessage = sendmessage  + res.messages[i].text + '\n'
      break;
    }
  }

  // 次回実行用に読込済のメッセージタイムスタンプをセット
  sheet.getRange(1, 1).setValue(res.messages[0].ts)

  if(sendmessage){
    sendmessage= '担当が付いていないものがあります。割当して下さい\n' + sendmessage;
  }
} catch(err){
  sendmessage = sendmessage + 'n' + err.message
} finally {
  if(sendmessage){
    // 送信
    var options =
    {
      "method" : "post",
      "contentType" : "application/json",
      "payload" : JSON.stringify(
        {
          "text" : sendmessage
        }
      )
    };

    UrlFetchApp.fetch(imurl, options);
  }
}
}

トリガーの設定

定期実行のトリガーを設定します。GASはここら辺も楽チンですねー。
GASの[メニュー]-[編集]-[現在のプロジェクトのトリガー]から設定します。

動かす!

ぺぺっと作ったので、早速試してみましょう!
実行すると、、、動きますね👍

スレッドのブロードキャストやボットメッセージを弾くためにtesterで調べたりしたのでちょっと時間は掛かりましたが、1時間程度 で作成し確認までできました。これが強いっ!

終わりに

いかがでしたか?まぁ実質大したことはやってないのですが、途中にも書いている通り、実業務のちょっとした不満の解消なんてこんなものの積み重ねなんじゃないかなーと思っていたりします。世間的にはデジタルトランスフォーメーション(DX)なんて言葉が流行っていますが、大げさに捉えずこういったところから初めて見るのもいいかもしれません。
GASは、Web/APIとの連携、Webサービス化、Googleドキュメントとの連携などプラガブルな点は勿論、jsで記載ができるという意味でも敷居が低く非常に強力なツールになると思います。使ってない方は是非使ってみて下さい。それでは!

(おまけ)そう言えば以前、GASでsantabotを作った記事を書いてました。。この時もGASを絶賛しています^^;
GAS+Slackでサンタからメッセージが届く[イベントアプリ]

蛇足コラム

slackと業務について

slackは元々はエンジニアリング業界から利用が広がったツールだと思いますが、今では多様な業種・業務で広く使われるようになり、業務上の情報のセンターハブとなっている側面があります。
ですが、slackは基本的にはフロー型のコミュニケーションツールであり、状態管理や、認知(既読)管理、情報の一元管理など、業務上の情報管理ツールとしては機能が不十分と感じることもままあります。そして、それらを対処できるのがslackAPIといった外部連携のインターフェースになる訳です。
今回のツールは今挙げた例で言えば、"状態管理的な" 極々小さな機能を実現しただけですが、こういった「業務上必要となる機能」にフォーカスすることでより汎用的な機能となり、業務フローの多くの問題を解決することに繋がるかもしれません。

「小さく始める」際の品質について

弊社では新しい企画が立ち上がり、「取り敢えず試してみよう/やってみよう!」と実行に移ることが良くあります。
そんな際、いきなりその業務のシステムを完全に作り込むことって殆どありません。「まずは手動で」とか、小さく始めて、効果の増大やフローの洗練を踏まえて本格的にシステム化を考えるというプロセスが一般的だと思います。
ただ、ここで注意すべきは小さく始めるとはいえ、正しく運用できること をできる限り担保すべきということです。特に人手を介する場合、どうしても漏れや抜けが発生し、積もり積もって大きな負債となることがあります。これをできる限り低減できるように(小さく始める)設計を行うことはとても重要です。課題の発生を未然に防ぐ/課題が出た時に対処できる仕組みも当然小さく抑える必要が出てくるのですが、それを実現する手段を持っているというのは大きな武器になります。これはGASだけではなく様々な手段が考えられると思いますが、小さく始める最低限の仕組みには、正しく運用できる最低限の仕組みも必要であることを忘れないようにしましょう。

関連記事

運営会社:株式会社ラクーンホールディングス(c)2000 RACCOON HOLDINGS, Inc