たのしい駆動開発

たのしいアウトプットの場所

GASを使ってSlackにスプレッドシートのグラフを送信する

Incoming WebhookのAbout的なことはここに書かれてます。 api.slack.com

前提

Incoming Webhook導入&設定済み

全体的なコード

var WEBHOOK_URL = "";
var DRIVE_FOLDER_ID = "";

function sender() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("");

  // テキスト送信
  var values = get_values(sheet);
  var text = generate_text(values[0], values[1], values[2]);
  var payload = JSON.stringify({ text: text });
  post(payload);

  // 画像送信
  var folder = DriveApp.getFolderById(DRIVE_FOLDER_ID);
  save_charts(sheet, folder);
  var image_ids = get_image_ids(folder);
  for (var i = 0; i < image_ids.length; i++) {
    payload = JSON.stringify({
      blocks: [
        {
          type: "image",
          image_url: "https://drive.google.com/uc?id=" + image_ids[i],
          alt_text: "chart_image",
        },
      ],
    });
    post(payload);
  }
}

function get_values(sheet) {
  // スプシからフィールドを取得。ここのコードの中身は気にしないでOK
  var l = sheet.getRange("").getDisplayValues();
  today = Utilities.formatDate(new Date(), "JST", "YYYY/M/d");
  for (var i = 0; i < l.length; i++) {
    if (l[i][0].match(today)) {
      return [l[i][0], l[i][1], l[i][3]];
    }
  }
}

function generate_text(v1, v2, v3) {
  // メッセージ作成
  var text = Utilities.formatString("%s, %s, %s", v1, v2, v3);
  return text;
}

function save_charts(sheet, folder) {
  // グラフ画像をGoogle Driveに保存
  var charts = sheet.getCharts();
  for (var i = 0; i < charts.length; i++) {
    var chart_image = charts[i]
      .getBlob()
      .getAs("image/png")
      .setName("chart" + i + ".png");
    file = folder.createFile(chart_image);
    // Slackで画像を送信するにはこの権限でないとエラーが起きる
    file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
  }
}

function get_image_ids(folder) {
  // Google Driveから画像のURLを取得
  var files = folder.getFiles();
  var ids = new Array();
  while (files.hasNext()) {
    var file = files.next();
    ids.push(file.getId());
  }
  return ids;
}

function post(payload) {
  // Slackに画像を投稿する
  var req = {
    method: "post",
    contentType: "application/json",
    payload: payload,
  };
  UrlFetchApp.fetch(WEBHOOK_URL, req);
}

function remover() {
  // imageのアクセス権限がリンクを知っている人なら誰でも見ることができるようになっている。
  // それがセキュリティ的によろしくないので、送信後画像をディレクトリから削除する
  var folder = DriveApp.getFolderById(DRIVE_FOLDER_ID);
  var image_ids = get_image_ids(folder);
  remove_files(image_ids);
}

function remove_files(image_ids) {
  // fileを削除
  for (var i = 0; i < image_ids.length; i++) {
    var file = DriveApp.getFileById(image_ids[i]);
    file.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.VIEW);
    file.setTrashed(true);
  }
}

Incoming Webhookの補足

画像の送信はこのようなJSONを送信する必要がある。

{
    method: "post",
    contentType: "application/json",
    payload: {
      blocks: [
        {
          type: "image",
          image_url: "https://drive.google.com/uc?id=" + image_ids[i],
          alt_text: "chart_image",
        },
      ],
    },
}

いつからか仕様が変わって、Blockというものになったらしい。画像を送信したいときは、以下のドキュメントに沿う必要がある。 api.slack.com

APIのテストはBlock Kit Builderからすることができる。 ここにJSONを貼り付けて、送信できるかどうか試してみるのもいいと思う。 それか、curlを使うのも全然ありではある。