7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

共有してるGoogleスプレッドシートに変更があったか1時間に1回確認してDiscordへ通知を送る

Last updated at Posted at 2023-05-16

やりたいこと

  • 他人と共有してるGoogleスプレッドシートに対して、誰かが編集したときにその変更通知をDiscordで受け取りたい。
    • スプシを共有してるメンバーが居るDiscordサーバーのチャンネルに通知すれば、互いの変更を知れてハッピーになれる。
  • 通知は1時間に1回程度の頻度にしたい。
    • 即時通知だとうるさい。逆に変更を躊躇してしまう。
  • 特定のシートの変更内容だけ受け取りたい。
  • どこが変更されたかをちょっとくらいは通知内容に載せたい。

Discord側の設定

  1. 通知を飛ばしたい先のチャンネルの :gear: 歯車アイコンを押す(あるいはサーバー設定)。
  2. 「ウェブフックを作成」ボタンを押す。
  3. 「ウェブフックURLをコピー」ボタンを押して、URLをコピーしておく。

Webhookの作成には相応の権限が必要なので注意。

Googleスプレッドシート側の設定

GASを開く

  1. Google Driveの対象スプレッドシートを開く。
  2. 上部メニューの「拡張機能」を選択
  3. 「App Script」を選択
  4. 別窓でApp Scriptの編集画面が開かれる。

ソースコード

以下をコピペ。
加えて、下記のソースコード内に ★★★ が付いているコメント部分(3箇所)を編集する。

コード.gs
////////////////////////////////////////////////////////////////////////////////
// 編集時に発行されるイベント
////////////////////////////////////////////////////////////////////////////////
function recordToProperty(e) {
  // 変更されたのが指定したシートの場合のみ有効
  // ★★★編集を監視したいシート名に置き換える
  if (e.source.getSheetName() != 'シート1') {
    return;
  }

  // 変更時刻
  const time = new Date().getTime();

  // メッセージに変更された範囲、新しい値を入れる
  const message = [e.range.getA1Notation(), e.value];

  // 変更があったことをスクリプトプロパティに追加。keyは変更時刻
  const script_property = PropertiesService.getScriptProperties();
  script_property.setProperty(time, JSON.stringify(message));
}

////////////////////////////////////////////////////////////////////////////////
// 定期実行されるイベント
////////////////////////////////////////////////////////////////////////////////
function notifyToDiscord(e) {
  // スクリプトプロパティの変更をチェック。
  const script_property = PropertiesService.getScriptProperties();
  const properties = script_property.getProperties();
  const array = Object.entries(properties);

  // スクリプトプロパティに1件もなければ、この期間に変更なしと見なす。
  if (array.length == 0) {
    return;
  }

  // プロパティがあったので変更あり。Webhookを送信する。
  const WEBHOOK_URL = 'https://discord.com/api/webhooks/xxxxxx/xxxxxx';  // ★★★DiscordのWebhook URL

  // メッセージを作成
  let message_body = 'シートに変更があったよ!!\n';
  let embeds = {
    fields: [],
  };

  array.forEach((prop) => {
    const key = prop[0];              // time
    const val = JSON.parse(prop[1]);  // message
    embeds.fields.push({
      name: 'セル: ' + val[0],
      value: '変更後の内容: ' + val[1],
    });
  });

  const payload = {
    'username': /* ★★★投稿時のユーザー名。指定しない(デフォのままで良い)場合は、行ごと削除する */,
    'content': message_body,
    'tts': false,
    'embeds': [embeds],
  }

  const param = {
    'method': 'POST',
    'headers': {
        'Content-type': 'application/json'
      },
    'payload': JSON.stringify(payload)
  }
  UrlFetchApp.fetch(WEBHOOK_URL, param);

  // 送信成功後、プロパティを全削除
  script_property.deleteAllProperties();
}

トリガー設定1:編集した即時反応

編集するたびに実行される処理にトリガーを設定する。
こちらの関数では通知を行わず、スクリプトプロパティに貯めるだけ。

左メニューの時計アイコンを押して、「トリガーを追加」ボタンを押す。
以下のように設定する。

項目 設定値
実行する関数 recordToProperty
実行するデプロイ HEAD(デフォルト)
イベントのソース スプレッドシートから
イベントの種類 編集時
エラー通知設定 任意

なお、操作中にアクセス権限を求める警告が出た場合は、適宜「許可(Allow)」する。

トリガー設定2:定期実行

定期実行するトリガーを設定する。
スクリプトプロパティが1件でもあればDiscordに通知する。

上記と同様に、以下のように設定する。

項目 設定値
実行する関数 notifyToDiscord
実行するデプロイ HEAD(デフォルト)
イベントのソース 時間主導型
時間ベースのトリガーのタイプ 時間ベースのタイマー
時間の間隔 1時間おき
エラー通知設定 任意

通知頻度を変えたい場合は、時間の間隔をイイ感じに調整する。

動作確認

  1. スプレッドシートを編集する
  2. notifyToDiscord 関数を手動で「実行」する

これでDiscordの指定したチャンネルへBotの書き込みが投稿されれば :ok:

参考記事

License

MIT License

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?