Google Forms と Google Apps Script で Slack 匿名投稿機能を作る

Google Forms と Google Apps Script で Slack 匿名投稿機能を作る

過去のブログ記事で Cloudflare Workers を使った Slack への匿名投稿機能の作成手順を紹介したことがあります。

開発者ではない人によっても扱いやすいよう、今回は Google Forms と GAS (Google Apps Script) だけで Slack への匿名投稿機能を作成します。

完成したものがこちらです。

Slack App

では、さっそく作りましょう!

1. Google Forms を作成する #

Google Form を新規作成します。

Google Drive

下記画像のように「メッセージ」と「返信先メッセージのリンク」の2つの入力欄を設置してください。

  • メッセージ:長いテキストの入力フォーム。入力必須にします。
  • 返信先メッセージのリンク:短いテキストの入力フォーム。入力は任意にします。

それぞれの入力欄のタイトル(「メッセージ」「返信先メッセージのリンク」)は変えないでください。

*もし入力欄のタイトルを変えたい場合は、後述するコードの中身を微調整する必要があります。

Google Forms

最低限のフォームは上記で完成です。

あとはお好みで説明文章などを追加してください。

わたしの説明の文章と画像を追加して以下のようにしました。

Google Forms

2. Google Apps Script を作成する #

Google Form の右上のメニューから、Apps Script を選択します。

Google Apps Script

開いているファイル(Code.gs)に下記のコードをコピーして貼り付けます。そして保存しましょう。

このコードには Slack にメッセージを送る処理が書かれています。

Google Apps Script

/**
 * Google Form に送信 -> Apps Script(onFormSubmit) を実行 -> Slack 投稿
 *
 * 使い方
 * 1. Googleフォームに紐づく Apps Script にこのファイルを配置
 * 2. 「トリガー」から onFormSubmit を「フォーム送信時」で追加
 * 3. Script Properties の SLACK_INCOMING_WEBHOOK_URL に Slack の Incoming Webhook URL を設定
 */

const FORM_MESSAGE_FIELD_NAME = "メッセージ";
const FORM_REPLY_MESSAGE_LINK_FIELD_NAME = "返信先メッセージのリンク";

function onFormSubmit(e) {
  main(e);
}

function main(event) {
  const properties = PropertiesService.getScriptProperties();
  const SLACK_INCOMING_WEBHOOK_URL = properties.getProperty(
    "SLACK_INCOMING_WEBHOOK_URL",
  );
  if (!SLACK_INCOMING_WEBHOOK_URL) {
    throw new Error("SLACK_INCOMING_WEBHOOK_URL が設定されていません。");
  }

  const formInput = extractFormInput(event);
  const payload = {
    text: formInput.message,
    ...(formInput.threadTs ? { thread_ts: formInput.threadTs } : {}),
  };

  postSlackIncomingWebhook(SLACK_INCOMING_WEBHOOK_URL, payload);
}

/**
 * フォームの入力内容を抽出する
 */
function extractFormInput(event) {
  const itemResponses = event?.response?.getItemResponses();

  if (!itemResponses) {
    throw new Error("Googleフォームのサブミットイベントではありません。");
  }

  // { field title: field response }
  const answer = {};

  for (let i = 0; i < itemResponses.length; i++) {
    const itemResponse = itemResponses[i];
    const title = String(itemResponse.getItem().getTitle()).trim();
    answer[title] = String(itemResponse.getResponse() || "").trim();
  }

  const message = answer[FORM_MESSAGE_FIELD_NAME];
  const replyMessageLink = answer[FORM_REPLY_MESSAGE_LINK_FIELD_NAME];
  const threadTs = toThreadTs(replyMessageLink);

  return {
    message: message,
    threadTs: threadTs,
  };
}

/**
 * 返信先メッセージのリンクを thread_ts 形式へ変換
 * URL 形式以外が入力された場合も考慮する
 */
function toThreadTs(input) {
  const s = String(input).trim();

  // 例:https://hello.slack.com/archives/C**********/p1771908621666429
  const urlMatch = s.match(/\/p(\d{16,})/);
  if (urlMatch) {
    return messageIdToThreadTs(urlMatch[1]);
  }

  // 例:p1771908621666429
  const pMatch = s.match(/^p(\d{16,})$/);
  if (pMatch) {
    return messageIdToThreadTs(pMatch[1]);
  }

  // 例:1771908621.666429(すでに thread_ts 形式)
  const tsMatch = s.match(/^(\d{10})\.(\d{6})$/);
  if (tsMatch) {
    return s;
  }

  return null;
}

/**
 * Slack URL の p<16桁> を ts(秒.マイクロ秒) へ変換
 * 例: 1771908621666429 -> 1771908621.666429
 */
function messageIdToThreadTs(digits) {
  const seconds = digits.slice(0, 10);
  const micros = digits.slice(10);
  return `${seconds}.${micros}`;
}

/**
 * Slack の Incoming Webhook へ投稿する
 */
function postSlackIncomingWebhook(webhookUrl, payload) {
  const res = UrlFetchApp.fetch(webhookUrl, {
    method: "post",
    payload: JSON.stringify(payload),
    muteHttpExceptions: true,
  });

  const code = res.getResponseCode();
  const text = res.getContentText();
  if (code < 200 || code >= 300) {
    throw new Error(`Slack への投稿に失敗しました。HTTP ${code}: ${text}`);
  }
}

左のサイドバーメニューからトリガーのタブに移動します。

トリガーを追加のボタンを押してください。

Google Apps Script

以下のようにトリガーを登録します。

フォームが提出されたときにこの Google Apps Script が起動するようになります。

Google Apps Script

3. Slack App を作成する #

https://api.slack.com/apps を開きます。

Create an App を押してアプリを作成します。

Slack App

From scratch を選択します。

Slack App

アプリの名前を入力し、アプリを使うワークスペースを選択します。

Slack App

アプリが作成されたら、左のサイドバーメニューから Incoming Webhooks のタブに移動します。

Activate Incoming Webhooks を On にして有効化します。

Slack App

次に、左のサイドバーメニューから App Home のタブに移動します。

App Display Name の Edit を押します。

Slack App

アプリの表示名とユーザネームを入力して Add を押します。

Slack App

左のサイドバーメニューから Incoming Webhooks のタブに戻ります。

ページ下部の Add New Webhook を押します。

Slack App

追加するワークスペースとチャンネルを選択して、許可するを押します。

Slack App

生成された Webhook URL をコピーして控えておきます。

Slack App

4. Google Apps Script に Slack App の Webhook URL を設定する #

Google Apps Script に戻ります。

左のサイドバーメニューからプロジェクト設定のタブに移動します。

ページ下部のスクリプトプロパティの追加を押します。

Slack App

プロパティに SLACK_INCOMING_WEBHOOK_URL と入力します。

値には控えておいた Slack App の Webhook URL を貼り付けます。

その後プロパティを保存のボタンを押します。

Slack App

5. 動作確認 #

これで完成です。Google Forms から投稿してみましょう!

本記事冒頭のように動けば大成功です!