ちょっと話題の記事

Google Apps Script で緊急対応時の Slack 操作を自動化してみた

GAS(Google Apps Script)と Slack API の組み合わせでよく使いそうな関数をご紹介しています。
2021.02.19

こんにちは。筧です。

クラスメソッドでは、2020年10月22日に発生した AWS 障害で検知後30分で以下を行いました。

そしてこの度、さらに迅速に情報をお届けしたい・・・!という想いから、下記を自動化する AWS 大規模障害時の緊急対応支援ツールを新たに開発しました。

  • 障害専用の Slack チャンネルの作成
  • 作成チャンネルにおける、発生確定後の各対応指示
  • 社内メンバーへの情報共有
  • お客様向け通知内容の原稿作成

今回は当該ツール用に書いた Google Apps Script の関数を紹介します。 それでは早速やっていく!!

slack.gs

Slack 関連の処理をまとめたファイルです。 API の制限については 各 Slack API のドキュメントを参照ください。

チャンネルを作成する

チャンネルを作成して、チャンネル ID を返す関数です。 引数 channel_name には自動作成したいチャンネル名を指定します。 既に存在するチャンネル名を指定するとエラーが発生するのでご注意ください。 利用している Slack API については、 conversations.create method | Slack API を参照ください。

function createChannel(channel_name) {
    var method_url = 'https://slack.com/api/conversations.create';
    var payload = {
        "token": SLACK_TOKEN,
        "name": channel_name,
    };
    var option = {
        "method": "POST",
        "payload": payload,
    };
    try {
        var res = UrlFetchApp.fetch(method_url, option);
        var json = JSON.parse(res.getContentText());
        return {
            'channel_id': json["channel"]["id"],
        }
    }
    catch (e) {
        Logger.log('error occured when createChannel.' + e);
    }
}

ユーザ ID のリストを作成する

引数で指定したユーザ ID とユーザーグループ ID を元に、ユーザー ID のリストを作成する関数です。 引数の users, usergroup には Slack ユーザ ID, ユーザグループ ID をリスト形式で指定します。 getUserGroupMember 関数は getUsers 関数から呼び出され、ユーザーグループ ID からグループに含まれるユーザ ID を返します。 利用している Slack API については、 usergroups.users.list method | Slack を参照ください。

function getUsers(users, usergroup) {

    var users = users.concat(getUserGroupMember(usergroup)['users']);
    users = [...new Set(users)];
    Logger.log(users.length);
    users = users.join(',');
    Logger.log(users);
    return users;
}


function getUserGroupMember(usergroup) {
    var usergroup_member = [];
    var method_url = 'https://slack.com/api/usergroups.users.list';
    for (var i in usergroup) {
        var payload = {
            "token": SLACK_TOKEN,
            "usergroup": usergroup[i],
        };
        var option = {
            "method": "GET",
            "payload": payload,
        };
        try {
            var res = UrlFetchApp.fetch(method_url, option);
            var json = JSON.parse(res.getContentText());
            usergroup_member = usergroup_member.concat(json["users"]);
        }
        catch (e) {
            Logger.log('error occured when getUserGroupMember.' + e);
        }
    }
    return {
        'users': usergroup_member
    }
}

チャンネルにメンバーを招待する

引数で指定したチャンネル ID のチャンネルに、引数で指定したユーザ ID のメンバーを招待する関数です。 利用している Slack API については、 conversations.invite method | Slack を参照ください。

function inviteUsers(channel_id, users) {
    var method_url = 'https://slack.com/api/conversations.invite';
    var payload = {
        "token": SLACK_TOKEN,
        "channel": channel_id,
        "users": users,
    };
    var option = {
        "method": "POST",
        "payload": payload,
    };
    try {
        var res = UrlFetchApp.fetch(method_url, option);
        var json = JSON.parse(res.getContentText());
    }
    catch (e) {
        Logger.log('error occured when inviteUsers.' + e);
    }
}

チャンネルにメッセージを投稿する

postMessage は引数で指定したチャンネル ID のチャンネルに、引数で指定したメッセージを投稿する関数です。 addMessage はチャンネル ID とメッセージに加えて、postMessage の戻り値である ts を指定することで、対象のメッセージのスレッドにメッセージを投稿する関数です。 利用している Slack API については、 chat.postMessage method | Slack を参照ください。

function postMessage(channel_id, text) {
    var method_url = 'https://slack.com/api/chat.postMessage';
    var payload = {
        "token": SLACK_TOKEN,
        "channel": channel_id,
        "text": text,
    };
    var option = {
        "method": "POST",
        "payload": payload,
    };
    try {
        var res = UrlFetchApp.fetch(method_url, option);
        var json = JSON.parse(res.getContentText());
        return {
            'ts': json['ts'],
        }
    }
    catch (e) {
        Logger.log('error occured when postMessage.' + e);
    }
}


function addMessage(channel_id, ts, text) {
    var method_url = 'https://slack.com/api/chat.postMessage';
    var payload = {
        "token": SLACK_TOKEN,
        "channel": channel_id,
        "thread_ts": ts,
        "text": text,
    };
    var option = {
        "method": "POST",
        "payload": payload,
    };
    try {
        var res = UrlFetchApp.fetch(method_url, option);
        var json = JSON.parse(res.getContentText());
    }
    catch (e) {
        Logger.log('error occured when addMessage.' + e);
    }
}

gdoc.gs

Google ドキュメント 関連の処理をまとめたファイルです。

テンプレートを元にドキュメントを作成する

テンプレートをコピーして、指定したフォルダに指定したファイル名でドキュメントを作成する関数です。 引数 template_id には、テンプレートとなるドキュメントのファイル ID を指定します 引数 file_name にはファイル名を指定します。 引数 folder_id には保存先のフォルダ ID を指定します。 利用しているメソッドの制限や必要な権限については、以下を参照してください。

function createDocument(template_id, file_name, folder_id) {
  try {
    var template = DriveApp.getFileById(template_id);
    var folder = DriveApp.getFolderById(folder_id);
    var file = template.makeCopy(file_name, folder);
    var doc_url = 'https://docs.google.com/document/d/' + file.getId();
    return {
      'doc_url': doc_url,
    }
  }
  catch (e) {
    Logger.log('error occured when createDocument of' + file_name + '.' + e);
  }
}

使用例

紹介した関数を利用して、以下の処理を実行する Slack App を作成してみます。

  1. チャンネル作成
  2. 作成したチャンネルにメッセージ投稿
  3. テンプレートを元に Google ドキュメント作成
  4. 作成したスプレッドの URL を投稿したメッセージのスレッドに投稿
  5. 作成したチャンネルにメンバー招待

Slack App の作成

slack api から新しいアプリを作成してください。

OAuth & Permissions を開き、Bot Token Scopes に各関数の実行に必要な OAuth Scope を追加します。 実行する関数に必要な OAuth Scope は 各関数ごとに紹介しているリファレンスを開き、Facts の Required scope(s) を参照ください。 今回は以下を追加します。

  • channels:manage
  • channels:read
  • chat:write
  • usergroups:read

hander.gs

関数を呼び出すハンドラーとなるファイルです。 事前に作成した Slack App の Bot User OAuth Access Token を GAS のプロパティに保存します。 また環境変数をご自身の環境に合わせて編集します。 編集が完了したら当該コードを hander.gs として保存します。

var props = PropertiesService.getScriptProperties();
var SLACK_TOKEN = props.getProperty('SLACK_TOKEN'); //プロパティに保存した token 情報を取得
var CHANNEL_NAME = test;
var MSG = `
  これはテストです。
  `;
var DOC_TEMPLATE_ID = 'AAAAAAAAAAAAAAAAAAAA'; //テンプレートのファイルID
var FILE_NAME = 'test';
var FOLDER_ID = 'BBBBBBBBBBBBBBBBBBBB'; //保存先のフォルダID
var USERS = ['XXXXXXXXX']; //Slack のユーザID
var USERGROUPS = ['YYYYYYYYY', 'ZZZZZZZZZ']; //Slack のユーザグループID

function testFunc() {
  // 1.チャンネル作成
  var channel_id = createChannel(CHANNEL_NAME)['channel_id'];
  // 2.作成したチャンネルにメッセージ投稿
  var res = postMessage(channel_id, MSG);
  // 3.テンプレートを元に Google ドキュメント作成
  var doc_url = createDocument(DOC_TEMPLATE_ID, FILE_NAME, FOLDER_ID)['doc_url'];
  // 4.作成したドキュメントの URL を投稿したメッセージのスレッドに投稿
  addMessage(channel_id, res['ts'], doc_url);
  // 5.作成したチャンネルにメンバー招待
  var users = getUsers(USERS, USERGROUPS);
  inviteUsers(channel_id, users);
}

実行する

Google Apps Script の画面から、testFunc を実行すれば対象の処理が自動実行されます。

終わりに

紹介した関数を組み合わせることで、色々な場面で利用できるかと思います。 API 制限などに注意しつつご利用ください。 本投稿が誰かの参考になると幸いです!