LoginSignup
2
0

Googleカレンダーの予定をSlackに連携する with GAS

Posted at

やりたいこと

毎日特定の時間になったら、Googleカレンダーに登録されている当日の予定を取得し、指定のSlackチャネルに通知する。
予定が複数あった場合も、すべて表示する。

完成イメージ

スクリーンショット 2023-12-25 063305.png

悩んだところ

GASのSlackAppライブラリの問題

「GAS Slack 連携」で検索して出てくる多くの記事でSlackApp(M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO)というライブラリを使用する方法が紹介されています。
しかし2023/11/8時点では、既に使用できなくなっていました。(Slackに通知が飛ばない)

代替手段として、SlackのWebhookを使用する方法とSlack APIを使用する方法を検討した結果、以下の理由で最終的にSlack APIを使用しました。

Webhookの問題点

Webhookの方がSlack APIより簡易的に連携で来たのですが、Webhookの場合に以下のことが出来ませんでした。

複数行の引用ブロックができない

通常Slackでは、引用ブロックを複数行にしたい時にShift + Enterで実現出来ます。
しかしWebhookの場合は、これの実現手段がありません。
Slack APIでは>>>とすることにより、引用ブロック内での改行が実現出来ました。

URLをハイパーリンク化できない

WebhookではURLをそのまま送信しても、ただの文字列として扱われてしまいます。
Slack APIではURLを< >で囲むことにより、ハイパーリンクとして認識させることが出来ます。
例) <https://example.com>

実際のコード

function execute() {

  // Slackボットがメッセージを投稿するチャンネルを定義する
  const channelId = "XXXXXXXXXX"; // 通知したいSlackのチャンネルID

  // SlackAPIで登録したボットのトークンを設定する
  const token = 'xoxb-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
  const url = "https://slack.com/api/chat.postMessage";

  // 実行ユーザーのデフォルトであるGoogleカレンダーを取得する
  const myCalendar = CalendarApp.getDefaultCalendar();

  // Googleカレンダーの予定取得する日を設定する
  const calDate = new Date();

  // 今日1日のGoogleカレンダーのイベントを取得する
  const myEvent = myCalendar.getEventsForDay(calDate);

  // イベントがなかったら終了
  if (myEvent.length === 0) {
    console.info('イベント無し');
    return;
  }

  // Slackに通知するGoogleカレンダーの予定メッセージを作成
  const blocks = [];
  blocks.push(createMessage(`本日の予定です`));

  for(let i = 0; i < myEvent.length; i++){
    let startH = myEvent[i].getStartTime().getHours();
    let startM = myEvent[i].getStartTime().getMinutes();
    if(startM < 10) startM = '0' + startM;
    let endH = myEvent[i].getEndTime().getHours();
    let endM = myEvent[i].getEndTime().getMinutes();
    if(endM < 10) endM = '0' + endM;

    const timeString = `${myEvent[i].getStartTime().getMonth() + 1}/${myEvent[i].getStartTime().getDate()} ${startH}:${startM}${endH}:${endM}`;
    const locationString = myEvent[i].getLocation() ? `<https://www.google.com/maps/search/?api=1&query=${myEvent[i].getLocation()}|${myEvent[i].getLocation()}>` : '';

    blocks.push(createMessage(`
>>> *${myEvent[i].getTitle()}*
⏰ ${timeString}
📍 ${locationString}
📝 ${myEvent[i].getDescription()}
`
    ));
  }

  const headers = {
    "Content-Type": "application/json; charset=utf-8",
    "Authorization": "Bearer " + token
  };
  const payload = {
    "channel": channelId,
    "blocks": blocks
  };
  const params = {
    "method": "POST",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  UrlFetchApp.fetch(url, params);

  console.info('Success');
}

/* メッセージを作成 */
function createMessage(message) {
  return {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": message
      }
    };
}

チャンネルIDとAPIトークンの取得方法

それぞれ以下の記事を参考にして、取得してください。

  • チャンネルID

  • APIトークン

2
0
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
2
0