【初心者向け】Google Apps ScriptでSlackへ猫画像を届けてみた

データアナリティクス事業本部の岩澤です。

クラスメソッドでは社内ツールとしてSlackを使っており、たくさんのチャンネルが存在します。
その中には、猫好きの猫好きによる猫好きのための猫チャンネルが存在します。
このチャンネルは各社員自慢のお猫様画像がUpされ続けるという至福のものとなっています。

このチャンネルを発見した時点でかなりの画像がUpされているうえに現在でも増え続けているため、全画像を追うのは大変になっています。

猫がみたい、しかし時間がない...

そうだ、せめて少しずつでも猫様の画像が定期的に届くようにしよう。

というわけで今回のブログのネタ猫画像を届けるSlack Appを作ってみました。

ざっくりとした仕様

Slack Appを作るにあたりGoogle Apps Scriptを使うのは決めていたので、以下のような仕様にしました。
・Google Apps Scriptのトリガ機能で一定時間ごとに猫宅配関数を呼ぶ
・猫宅配関数は猫チャンネルから画像URLをランダム取得
・そのあとmy分報チャンネルのわたし宛へ取得した画像を送信する

仕様も決まりましたので実際に作ってみることにします。

Slack側の準備

Slack Appの新規作成

まずはSlack APPの準備を行います。

1) Slack API: Applications | Slack ページを開きます

2) 「Create New App」を押下します

3) 「App Name」、「Development Slack Workspace」を設定し、「Create App」ボタンを押下します

4) 左側より「Basic Information」を選択し、「Permissions」を選択します

5) 必要な権限を追加して「Save Change」を押下します
・"Access user's public channel"(猫channelから履歴を取得するのに必要)を追加します

・"Send messages as delivery cat"(猫画像メッセージを送信するのに必要)を追加します

・両方追加したことを確認して「Save Changes」を押下します

6) 左側メニューより、「OAuth & Permissions」を選択し、「Install App to Workspace」を押下します。

7) 確認画面が表示されますので「許可する」を押下します

8) 左側メニューより、「OAuth & Permissions」を選択し、「OAuth Access Token」を確認します。
※後で使うのでコピーしておきます。

チャンネルIDの取得

猫チャンネルからのメッセージ履歴の取得とわたしの分報への送信には、
それぞれのチャンネルのIDが必要となります。

今回は手っ取り早い方法を使うことにします。

1) チャンネルを右クリック -> ポップアップにて「リンクをコピー」を選択

2) URLから最後の/以降の「xxxxxxxxx」がチャンネルIDとなります
https://~~~~~~.slack.com/messages/xxxxxxxxx

宅配先ユーザのメンバーIDを取得

猫宅配宛としてわたしのメンバーIDが必要となります。

1) Slackアプリの左上を押下、ポップアップから「プロフィール&アカウント」を選択します

2) 右側に表示されるので、「...」ボタンを押下し、ポップアップから「メンバーIDをコピー」を選択します

これで宅配先も取得できました。後はGoogle Apps Script側の実装となります。

Google Apps Scriptの準備

次に Google Apps Script側の準備を行います。

プロジェクトの作成

Google Driveを開き、「新規作成」を押下、「その他」から「Google Apps Script」を選択します。

※「Google Apps Script」が無い場合は、「アプリの追加から」で追加します

ソースの記述

コード.gsに以下のソースを貼り付け、保存します。

// 猫画像URLを返す
function _getImageURL(){
  // プロジェクトのプロパティからSlackのAccess Tokenを取得
  var accessToken = PropertiesService.getScriptProperties().getProperty('ACCESS_TOKEN');
  // 猫チャンネルのチャンネルIDを取得
  var channelid = PropertiesService.getScriptProperties().getProperty('CHANNEL_ID');

  // channels.history APIで猫チャンネルの履歴を取得
  var response = UrlFetchApp.fetch('https://slack.com/api/channels.history?token=' + accessToken + '&channel=' + channelid);
  // 戻り値をjsonに
  var json  = JSON.parse(response.getContentText());

  // 履歴からmessages.filesのあるメッセージを抽出
  var meslist = json.messages.filter(function(e){ return 'files' in e; });
  // ランダムで1つ
  var randnum = Math.floor( Math.random() * meslist.length );  

  console.log(meslist[randnum].files[0].permalink);
  // 猫画像URLを返す
  return meslist[randnum].files[0].permalink;
}

// 猫宅配関数
function sendPostEphemeral(){
  // プロジェクトのプロパティからSlackのAccess Tokenを取得
  var accessToken = PropertiesService.getScriptProperties().getProperty('ACCESS_TOKEN');
  // 宛先のチャンネルIDを取得
  var channelId = PropertiesService.getScriptProperties().getProperty('TIMES_CHANNEL_ID');
  // 宛先ユーザーのメンバーIDを取得
  var userId = PropertiesService.getScriptProperties().getProperty('USER_ID');
  // chat.postEphemeral APIの
  var url = "https://slack.com/api/chat.postEphemeral";
  
  // 猫画像URLを取得
  var imageUrl = _getImageURL();
  
  // 送信メッセージを作成
  var attachments = JSON.stringify([
        {
          color: '#77CEEB',
          text : '猫のお届けです',
          image_url: imageUrl
        }
    ]);
  var payload = {
    token : accessToken,
    channel : channelId,
    user: userId,
    as_users : false,
    username : 'cat delivary',
    attachments : attachments
  };
  var params = {
    method : 'post',
    payload : payload
  };

  // APIを呼ぶ  
  var response = UrlFetchApp.fetch(url, params)
  console.log(response);
}

保存時にはプロジェクト名を聞かれるので後でわかるように命名して保存します。

プロパティの設定

上記プログラムは、トークンやチャンネルIDなどプログラム中に埋め込みたくない値を、プロパティから取得しています。
ですので、プロパティ値を設定する必要があります。

(1) メニューの「ファイル」->「プロジェクトのプロパティ」を選択します

(2) 「プロジェクトのプロパティ」ダイアログにて「スクリプトのプロパティ」を選択します。

(3) +「行を追加」を押下してプロパティ設定欄を追加します。プロパティ名と値を登録します。

今回登録するプロパティ名と値は以下の通りです。

プロパティ名 プロパティ値
ACCESS_TOKEN Slack Appを作成した際にメモしたAccess Tokenの値
CHANNEL_ID データ取得元(猫チャンネル)のチャンネルID
TIMES_CHANNEL_ID メッセージ送信先にチャンネルID
USER_ID メッセージが見られるユーザのメンバーID

一通り登録したら「保存」で閉じます。

スコープの追加

channels.history API の利用には スコープの追加が必要となります。

手動で追加する場合の手順は以下の通りです。

(1) メニューより「表示」->「マニフェストファイルの表示」を選択します

(2) 左側の一覧にappsscript.jsonというファイルが追加されているので選択します

(3) スコープを追加します。 以下の記述を追記します。

"oauthScopes": ["https://www.googleapis.com/auth/script.external_request"]

(4) メニューの「ファイル」->「プロジェクトのプロパティ」でダイアログを表示し、「スコープ」を確認します
追加されていることを確認します。

デバッグ実行してみる

ここまでで一通り作成できましたので、動作確認をしたいと思います。

(1) デバッグ実行用にブレークポイントを設定する
ブレークポイントを設定することで、デバッグ実行時に処理をそこで止めることができます。
行番号あたりをクリックするとブレークポイントを設定した目印として赤い丸点が配置されます。

※再度クリックするとブレークポイントを削除できます

(2) デバッグ実行する
メニューより、「実行」->「関数をデバッグ」->「sendPostEphemeral」を選択します。

デバッグ実行するとブレークポイントまで実行されます。
画面下部には各変数の値が表示されます。
操作するには赤線のアイコンを押下します。
※左から、デバッグを続行、デバッグを一時停止、デバッグを停止、ステップイン、ステップオーバー、ステップアウト)

最後まで実行すると...
Slack上に表示されました。ねこかわいいですね。

トリガの設定

無事目的のチャンネルに投稿されたのを確認できたので、一定時間ごとに猫宅配関数を呼ぶようにトリガを設定します。
(1) 赤線の、時計アイコンをクリックします

(2) トリガ設定画面にて右下の「トリガーを追加」を選択します

(3) 「実行する関数を選択」では"sendPostEphemeral"を、「時間の間隔を選択(時間)」では"1時間おき"に選択し、「保存」を押下します

これで1時間ごとに猫画像が届くようになりました。

最後に

Google Apps Scriptでは他のスプレッドシートなども操作できるので、組み合わせれば色々便利なツールが作れそうですね。
それではまた。猫万歳!

参考文献

Slack API | Web API から Slack App 経由で チャンネル履歴を取得する - Qiita