SANANEBLOG
GAS PR

Slackに投稿されたメッセージを自動でスプレッドシートに転記する方法【GAS】

記事内に商品プロモーションを含む場合があります

はじめに

SANANE

今回の記事では、Slack上の特定のチャンネルに投稿されたメッセージを自動でGoogleスプレッドシートに記録する方法を紹介します。

プロジェクトの管理や分析を目的として、Slack内のチャンネルのメッセージをスプレッドシートに記録したいと思ったことはないでしょうか?

今回はGoogle Apps Script(GAS)を使用して、自動化を実現します。

GASは30分ごとや1時間ごとなど、定期的に実行させることが可能なため、一度設定すればこれまでの手動でのメッセージのコピーやペースト、またはSlackからのエクスポート作業は不要になります。

動作イメージ

SANANE

まずは簡単に本自動化処理の動作について説明します。

記録を行いたいSlackのチャンネル上でテスト投稿を行います。

記録用のスプレッドシートには以下のように記載が行われます。

投稿内容だけでなく、メッセージへの添付ファイルをGoogleドライブに保存するツールも紹介しております。コチラも合わせてご参考くださいませ。

Slackに投稿された添付ファイルを自動でGoogleドライブに保存し記録する【GAS】 はじめに 今回の記事では、Slackのメッセージに添付されたファイルを自動的にGoogleドライブに保存し、ログをGoogleス...

作成方法

本自動化処理は以下の流れで作成します。

  1. Slack Appの作成
  2. Slack Appをチャンネルに追加する
  3. Googleスプレッドシートの作成
  4. GASの作成、定期実行トリガーの作成

Slack Appの作成

Slack APIにアクセスします。

このとき、自動化したいチャンネルがあるワークスペースでログインします。

[Create New App] をクリックし、[From scratch]をクリックします。

任意のアプリ名を入力、ワークスペースを選択し、 [Create App]をクリックします。

スコープの設定

左側のメニューより、[OAuth & Permissions]をクリックします。

[Scopes]セクションにて、下記画像のようにBot Token Scopesに以下3つをスコープとして[Add an OAuth Scope]をクリックして登録してください。

  • channels:history
  • channels:read
  • users:read

アプリをワークスペースにインストールする

スコープを設定した後、[OAuth & Permissions]の一番上のページにある[Install to Workspace]をクリックします。

権限をリクエストされるため、[許可する]をクリックします。

インストール完了後は、Bot User OAuth Token が生成されますのでコチラをコピーして控えておいてください。

Slack Appをチャンネルに追加する

Slackに移動し、今回の自動化処理を適用したいチャンネルに移動します。

メッセージ入力欄にて「/」と入力することでショートカットが開きます。

左メニューに新しくインストールしたAppがあることを確認し、[このチャンネルにアプリを追加する]をクリックします。

Googleスプレッドシートの作成

Googleスプレッドシートにアクセスします。

作成したスプレッドシートの拡張機能からApps Script をクリックします。

GASの作成

GASのスクリプトエディタが別タブで開きます。

スクリプトのペースト

もともと記載してある以下コードは削除します。

function myFunction() {

}

代わりに、以下のコードをコピーしてペーストします。

このとき、2〜3行目の各” ”で囲まれたところに控えておいたトークンやIDに書き換えます。

YOUR_SLACK_BOT_TOKEN:Bot User OAuth Token

YOUR_CHANNEL_ID:記録を行いたいSlackのチャンネルのID

Slack チャンネルIDの探し方 はじめに Slackを使用している方々、特にSlack APIを利用してBotなどを開発している方にとって、チャンネルIDはとき...
function saveMessagesToSheet() {
    var token = "YOUR_SLACK_BOT_TOKEN"; 
    var channel = "YOUR_CHANNEL_ID"; 
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  
    // ヘッダーの設定
    if (sheet.getRange("A3").getValue() === "") {
        sheet.getRange("A3").setValue("投稿時刻");
        sheet.getRange("B3").setValue("投稿者");
        sheet.getRange("C3").setValue("投稿内容");
    }

    var lastExecutionTime = sheet.getRange("A1").getValue();

    var apiUrl = "https://slack.com/api/conversations.history?channel=" + channel + "&limit=100";
    var options = {
        "method": "get",
        "headers": {
            "Authorization": "Bearer " + token
        }
    };
    
    var response = UrlFetchApp.fetch(apiUrl, options);
    var data = JSON.parse(response.getContentText());

    for (var i = 0; i < data.messages.length; i++) {
        var message = data.messages[i];
        processMessage(message, token, sheet, lastExecutionTime);
        if (message.reply_count > 0) {
            var repliesApiUrl = "https://slack.com/api/conversations.replies?channel=" + channel + "&ts=" + message.ts;
            var repliesResponse = UrlFetchApp.fetch(repliesApiUrl, options);
            var repliesData = JSON.parse(repliesResponse.getContentText());
            for (var j = 0; j < repliesData.messages.length; j++) {
                processMessage(repliesData.messages[j], token, sheet, lastExecutionTime);
            }
        }
    }

    var currentTimeJST = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss");
    sheet.getRange("A1").setValue(currentTimeJST);
}

function processMessage(message, token, sheet, lastExecutionTime) {
    var messageTimestamp = new Date(message.ts * 1000);
    if (messageTimestamp > lastExecutionTime) {
        var userApiUrl = "https://slack.com/api/users.info?user=" + message.user;
        var userResponse = UrlFetchApp.fetch(userApiUrl, {
            "method": "get",
            "headers": {
                "Authorization": "Bearer " + token
            }
        });
        var userData = JSON.parse(userResponse.getContentText());
        var userName = userData.user ? userData.user.real_name : "Unknown User";
        var nextRow = sheet.getLastRow() + 1;
        sheet.getRange(nextRow, 1).setValue(messageTimestamp);
        sheet.getRange(nextRow, 2).setValue(userName);
        sheet.getRange(nextRow, 3).setValue(message.text);
    }
}

上部メニューの[プロジェクトを保存]ボタンをクリックして保存します。

トリガーの作成

SANANE

最後に定期的に実行するためのトリガーを作成します。

GASスクリプトエディタの左部のメニューから「トリガー」(時計のアイコン)をクリックし、画面下部の「+ トリガーを追加」をクリックします。

実行する関数を[saveMessagesToSheet]に設定し、イベントソースを[時間主導型]に、時間ベースのタイマーのトリガーのタイプを選択では[時間ベースのタイマー]に設定します。

時間の間隔を選択では[1時間おき]等、実行したい間隔を選択して保存をクリックします。

【補足】トリガー保存時にエラーが発生した場合は、スクリプトがうまく保存されていない場合がありますので、再度コードを書く画面に戻ってブラウザの更新をしてください。その後再度スクリプトをコピー&修正してください。

最初の関数の実行には権限が必要となるため、[承認が必要です]というモーダルが表示されたら、

  1. [権限を確認]をクリック
  2. [表示されているGoogleアカウント(Choose an account)]をクリック
  3. [詳細(Advanced)]をクリック
  4. [Go to 無題のプロジェクト(unsafe)]をクリック
  5. [許可(Allow)]をクリック

詳細については以下の記事を参考にしてください。

Google Apps Scriptで「承認が必要です」が表示されたときの対応方法について解説【GAS】 はじめに SANANE 今回はGoogle Apps Scriptを利用する際に表示される「アクセス権の承認」について手順を解説...

クリック後トリガーが作成されます。

動作テスト

GASの左部のメニューから「エディタ」をクリックします。

[▶実行]をクリックします。

問題なく実行が完了すると、作成したスプレッドシートのA1セルに実行した時間が記録され、直近100件のメッセージが記録されます。

以降はトリガーに設定した時間ごとにGASが実行され、A1セルに記載された最終実行時間以降に投稿されたメッセージを記録します。

初回の実行では直近100件のメッセージを取得しますが、最大1000件まで過去のメッセージを取得するようカスタマイズすることができます。

この場合はスクリプトの14行目の[“&limit=100”]の[100]を任意の値に修正してください。

GASおすすめ本

GASをもっと勉強したい!ほかにも自分で何か作成したい!という方には以下がおすすめです。仕事で使えるアイデアなども得ることができます。