Safie Engineers' Blog!

Safieのエンジニアが書くブログです

初心者向け解説_SlackAPI & GASでGoogleスプレッドシート上からSlack通知を送る方法

本記事では、GoogleスプレッドシートからSlackAPIとSlackApp(Slackbot)を使って通知を送る仕組みの作り方を、SlackAPI・GAS初心者にも分かりやすく画像付きで解説します。

はじめに

なんでやろうと思ったか

Slackにて、ある特定(かつ大勢)の人達に連絡をする機会があり、対象者リストを元に連絡用チャンネル作って連絡を実施していました。

この業務ですが、めんどくさいポイントが複数ありました。例として数個あげるなら、

  • 招待する人数が多いと招待する作業だけで骨が折れる
  • 目が滑って抜け漏れが発生しやすい
  • リマインドで何回も@channelするのも腰が引けるetc….

こういった連絡系のタスクを楽にできないかと考えた結果、「対象者リストにはメアドも記載されているので、わざわざ手打ちせずとも対象者リストを元に連絡作業をボタン1つで完了できるようにすればいいんじゃない?」と考え、作成に至りました。

また、SlackAPPやSlackAPIを使う事が初めてだったので備忘録として残しておこうと思い、執筆する運びとなりました。

用語解説

SlackAppとは?

Slackが提供する開発者用の拡張プラットフォーム全体のことを指します。WebhookやSlashコマンド、イベントハンドラーなど複数の機能をパッケージ化できます。

例えば外部サービス(Googleカレンダー、GitHub、Trelloなど)から通知を受け取ることができたり、ワークフローの自動化が実現できます。

slack.com

Slackbotとは?

Slackbotとは、SlackAppの機能の1つで、Slack上で自動的にメッセージを投稿したり、ユーザーの指示に従って情報を提供するBotのことです。
Slackbotを使うことで、定型的な通知やリマインダーなどを自動化し、作業の効率化を図ることができます。

slack.com

Slack APIとは?

Slack APIとは、Slackの機能をプログラムから利用するための仕組みです。
Slack APIを使えば、外部のアプリケーションやサービスからメッセージを投稿したり、Slackのデータを取得したりすることができます。

今回はこのSlack APIを使って、スプレッドシートの情報をSlackへ送信する仕組みを作ります。

api.slack.com

Slackbot作成~Token発行まで

まずはSlackアプリを作成します。

  1. Slack APIページへアクセスして、新しいSlackアプリを作成します。
    赤枠で囲った【Create New App】を押下します

  2. Create an App のポップアップウィンドウが表示されるので【From scratch】を押下します

  3. アプリ名とワークスペースを入力する画面が表示されるので、該当箇所に必要な情報を入力します。
    今回は「Slackbot_test」というアプリ名で作成します。ワークスペースは各自の環境を選択してください。

    入力後、【Create App】を押下します。

  4. 今しがた作成したアプリ名の設定画面が表示されます。
    これでSlackアプリ自体の作成は完了です!簡単ですね

  5. アプリにScopeの設定を行います。左側メニューから「OAuth & Permissions」を選択し、Scopes項目の赤枠で囲った 【Add an OAuth Scope】を 押下します。

  6. ここでどういうアクションを許可するか設定します。
    今回作りたい物を分解すると

    ①スプシ上のセルに書き込まれているメアドを参照して、紐づいているSlackIDを取得後(users:read)

    ②SlackID宛にリマインドメッセージを飛ばす(chat:write)

    となるので、chat:writeusers:read の2つを追加します

  7. Scopeを設定したら、このアプリをワークスペースへインストールします。
    インストールすることで、Slack ワークスペース上でアプリを使用できるようになります。
    「OAuth & Permissions」の上の方にある「OAuth Token」項の【Install to xxx(ワークスペース名)】を押下します。

  8. SlackAppが ワークスペースにアクセスする権限をリクエストしてくるので、許可してあげましょう

  9. 無事このアプリ用のOAuth Tokenが発行されました!(黒くフィルターされている箇所にTokenが表示されています)

    このTokenを使用することで、SlackAPIを利用することができます

動作確認

本当にAPIを使用できるかどうか、実際にテストしてみましょう

テスト用データ作成

Googleスプレッドシートの準備

新しいGoogleスプレッドシートを作成し、テストデータをセルへ書き込んでいきます。
とりあえず以下画面のようなデータを作成しました。

GASの設定

  1. GASにSlackAPP用のライブラリを設定します。
    スプレッドシートからGASを開き、画面左側にあるライブラリの”+” をクリック → 以下のスプリクトIDを入力し、検索します。
    1on93YOYfSmV92R5q59NpKmsyWIQD8qnoLYk-gkQBI92C58SPyA2x1-bq

  2. SlackAPPが見つかったら【追加】ボタンを押下します。
    追加後、以下画面のようにライブラリ欄に「SlackAPP」が追加されている事を確認してください

    これでGASの設定は完了です

SlackIDを取得してみる

以下のようなスクリプトを作成しましたので、このコードをGASへ張り付けます。
※あくまでテストなのでtoken直書きになっていますがご承知おきください(後ほど隠す方法も記載します)

function GetSlackUserId(){
    // トークン
  const slack_OAuth_token = "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  // スプレッドシートの B2 からメールアドレスを取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const email = sheet.getRange("B2").getValue();

  const url = "https://slack.com/api/users.lookupByEmail"
  const options = {
    "method": "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": slack_OAuth_token ,
      "email": email
    }
  };
  const response = UrlFetchApp.fetch(url, options);
  let res = JSON.parse(response);
  let user_id = res.user.id;
  // 取得結果をシートの C2 に書き込む
  sheet.getRange(2, 3).setValue(user_id);
}
  1. 貼り付けたら、赤枠の「▷実行」ボタンを押下します。
    スプシの構成通りなら、実行ログに「実行完了」と表示されます。

  2. スプシを見てみましょう。SlackID欄にIDが書き込まれているはずです

    [

    やったぜ

このSlackIDって正しいの???

という事で、ぱぱっと確認してみます。

①まず、生成されたC2セルのSlackIDをコピーします。
②Slackアプリ上で、新規DMを作成します。
③送信先入力欄に先ほどコピーしたSlackIDを張り付けます

直接メアドや登録名を記入せずとも、コピペだけで宛先欄にユーザーが表示されることが確認できます

DMを送信してみる

上項でメアドからSlackIDを取得できる事は確認できました。次は、SlackBotを介してメッセージを送ってみましょう。

前項のSlackIDを取得するスクリプトに手を加え、以下のようなスクリプトを作成しました。やっている事は簡単で、

①誤実行防止用のメッセージボックスを表示後に
②B列に入っているメアド取得
③slack_message_textで送信したい文章を作ってから
④B列のメアドをGetSlackUserId()に渡して個々のSlackIDを取得
⑤個々のSlackIDを元に、slack_App.postMessageでSlackID宛にDMを飛ばす
⑥行数分④~⑤を繰り返す

以上です

function SlackBot() {
  //誤実行防止
  let result = Browser.msgBox("Slackに通知文を送信します。よろしいですか?", Browser.Buttons.OK_CANCEL);
  if (result == "cancel"){
    return;
  }
    const slack_OAuth_token = "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  const slack_App = SlackApp.create(slack_OAuth_token);

  let sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // スプレッドシート最終行の行番号を取得
  let lastRow = sheet.getLastRow();
  // B列の2行目から最終行までを指定
  let emailRange = sheet.getRange(2, 2, lastRow - 1, 1); // (開始行, 開始列, 行数, 列数)
  // 空白を除く
  let emails = emailRange.getValues().filter(row => row[0]); 

  // 送信文
  let slack_message_text = "test"
  
  for(let email of emails){
   let user_id = GetSlackUserId(email[0],slack_OAuth_token)
   let slack_message = "<@" + user_id + ">" + slack_message_text
   slack_App.postMessage(user_id, slack_message);
  }
}

function GetSlackUserId(email,token){
  const url = "https://slack.com/api/users.lookupByEmail"
  const options = {
    "method": "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": token,
      "email": email
    }
  };
  const response = UrlFetchApp.fetch(url, options);
  let res = JSON.parse(response);
  return res.user.id;
}

上記スクリプトでGASを実行すると、作成したSlackアプリからメッセージが届きます

こんな感じ

直書きtokenをなんとかする

先ほど上の方でも触れましたが、token丸出しは余りにもセキュリティ意識や見栄えが悪すぎるため、この丸出し状態をなんとかします。

GASでは「プロパティ」として公開したくない情報を管理できる方法があります。

  1. GASの画面左側にあるメニュー一覧から、赤枠の設定アイコン(歯車マーク)を押下して、プロジェクトの設定画面を開きます

  2. プロジェクトの設定画面最下段に、スクリプト プロパティ項があります。
    【スクリプトプロパティを追加】ボタンを押下します

  3. プロパティ欄に分かり易い名称を付け、値欄にtoken等を格納します。
    入力後、【スクリプトプロパティを保存】を押下します。

  4. プロパティを登録して満足してはいけません(1敗)
    GASスクリプト内の直書きtokenにプロパティを適応する作業を行います

function SlackBot() {const slack_OAuth_token = "xoxb-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //直書き状態から
   ↓↓↓↓↓↓↓↓↓
  const slack_OAuth_token = PropertiesService.getScriptProperties().getProperty("SlackOAuthToken"); //プロパティサービスを適用}

プロパティサービスを使うためには、PropertiesServiceというクラスを使用します。getScriptPropertiesというメソッドを使用することで、スクリプトプロパティに登録済みのプロパティを取得することができます。
最後に、getPropaties()メソッドでプロパティ名を指定することによって、値を秘匿した状態で使用することが可能になります。

詳しくはコチラをご参照ください
developers.google.com

最終系は以下の通りです。

function SlackBot() {
  //誤実行防止
  let result = Browser.msgBox("Slackに通知文を送信します。よろしいですか?", Browser.Buttons.OK_CANCEL);
  if (result == "cancel"){
    return;
  }
  const slack_OAuth_token = PropertiesService.getScriptProperties().getProperty("SlackOAuthToken");
  const slack_App = SlackApp.create(slack_OAuth_token);

  let sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // スプレッドシート最終行の行番号を取得
  let lastRow = sheet.getLastRow();
  // B列の2行目から最終行までを指定
  let emailRange = sheet.getRange(2, 2, lastRow - 1, 1); // (開始行, 開始列, 行数, 列数)
  // 空白を除く
  let emails = emailRange.getValues().filter(row => row[0]); 

  // 送信文
  let slack_message_text = "\n test"
  
  for(let email of emails){
   let user_id = GetSlackUserId(email[0],slack_OAuth_token)
   let slack_message = "<@" + user_id + ">" + slack_message_text
   slack_App.postMessage(user_id, slack_message);
  }
}

function GetSlackUserId(email,token){
  const url = "https://slack.com/api/users.lookupByEmail"
  const options = {
    "method": "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": token,
      "email": email
    }
  };
  const response = UrlFetchApp.fetch(url, options);
  let res = JSON.parse(response);
  return res.user.id;
}

仕上げ

これで一通りの仕組みが出来上がりました。

ですが、現状わざわざGASを開いて都度「実行」を押しているので、ここをもっと簡単に実行できるようにします。

  1. スプレッドシートの「挿入」から図形描画を選択し、任意の図形を作成します。 作成したら「保存して閉じる」を押下します。

  2. 以下のように、シート上に図形が作成されます。  図形をクリックすると、右上にメニューアイコンが出てきます。アイコンを押下し、「スクリプトを割り当て」を押下します。

  3. この図形をクリックしたときに実行したいスクリプトを入力する画面が表示されます。  作成したスクリプトの「SlackBot」関数を指定します

  4. 「確定」を押下後、スプレッドシート画面が表示されます。 これで、図形を押下すればSlack通知を送れるようになりました。

 以下画像は、実際に図形をクリックした時の画面です。

終わりに

以上で、GoogleスプレッドシートからSlackAPIとSlackApp(Slackbot)を使ってSlackに通知を送る仕組みが出来上がりました!

とはいえ、上記スクリプトにはまだまだ手を加えるべきポイントがあります。
例えば・・・

  • メアドが存在しない場合の例外処理
  • その他エラーが発生した場合の例外処理
  • スクリプト実行時のタイムスタンプをセルに追加する
  • 送信文がGAS内にべた書きになっている

等々

もし機会があれば、本記事を元にGoogleフォームのアンケート機能と組み合わせて、回答確認 & リマインドの発展系バージョンもご紹介できればと考えています。

本記事を参考に、日常業務の中で発生する連絡・リマインド作業がある方の助けになれば幸いです。

セーフィーではエンジニアを積極的に募集しています。どのような職種があるのか気になる方はこちらをご覧ください!

safie.co.jp

カジュアル面談から受け付けておりますので、気軽に応募いただければと思います! 皆様のご応募、心よりお待ちしております!

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

© Safie Inc.