🧘‍♀️

【GAS×Slack】GoogleFormで複数のイベントの参加者を募集し、自動でそれぞれのカレンダーに招待、Slackで確認DMを送付する

2022/11/10に公開

こんにちは。

aisaka(坂本愛)と申します。
普段、メルカリという会社のエンジニア組織で組織開発をしています。

私はエンジニアではないのですが、エンジニアリングへの理解を深めたり、単純に楽しくて、自分の業務の一部の自動化に取り組んでいます。

GoogleFormで複数のイベントの参加者を募集し、自動でそれぞれのカレンダーに招待、Slackで参加者に確認DMを送付するという社内システムを作ってみたので、紹介できればと思います。

この記事で書きたいこと

社内で勉強会やイベントをする際に、参加者を募りますよね。
Google formで参加者を公募するのが簡単で良いのですが、カレンダーへの招待や応募者の方への確認メッセージがちょっと手間だったりします。
本記事では、Google formで参加者を公募したときに下記のことを達成するためにやったことを記載していきます。

  • 応募者に自動でカレンダー招待を送付
  • 応募者にSlack Botを送付

社内イベントを主催される方や、SlackやGASを使ったOps自動化に興味がある人に読んでもらえたら嬉しいです。

手法

ツールは「Googleカレンダー」と「Googleフォーム」、「Slack」を利用します。
GAS(Google Apps Scriptの略)を使用することで簡単にGoogleカレンダーやフォーム、そして他のツールと連携できます。GASやAPIの基本知識があるとよいです。
また一度作ったら、テンプレ化してHRの方などnon-engineerの方も使えるように、なるべくシンプルに設計しています。

手順① - 応募者に自動でカレンダー招待を送付

まずは下記手順で、複数のイベントに応募者を招待できるようにします。

  • Googleフォームでイベントの応募フォームを作成する。
  • Googleカレンダーでイベントの予定を作成する。
  • Googleフォームからスクリプトエディタを開き、設定
  • コード(sendCalendar)を実行して、Formから応募者のカレンダー招待が自動でいくことを確認
  • 応募者がフォームに回答すると自動で該当の日時の複数イベントに招待される

Google formでイベントの応募フォームを作成

Google formでのイベント応募フォームはシンプルに下記のような形で作成しています。
※複数のセッションに応募できるように、チェックボックスにしています。

カレンダーでイベントの予定を作成

主催するイベントをGoogleカレンダーで予定を作成します。
※その際に、フォームのMeeting名とカレンダーのMeeting名は一致している必要があります。

Google formからリンクしたSpreadsheetを準備

作成したGoogle formからSpreadsheetを開きます。
自動でアップデートされる回答フォームとは別に、主催者用の情報をまとめるシートを用意します。
この主催者シートに変数をいれていきます。
例)

Apps Scriptを開き、設定

拡張機能からApps Scriptを開いて、下記コードをいれる。
上記のスクリーンショットの主催者情報を読み取れるように作っていますので、各自アレンジしてください。

function sendCalendar(e) {
  //参加者情報と参加希望イベントを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const participant_sheet= ss.getSheetByName('フォームの回答 1');
  const participant_lastRow = participant_sheet.getLastRow();
  const participant_email = participant_sheet.getRange(participant_lastRow,2).getValues();
  const event_values = participant_sheet.getRange(participant_lastRow,3).getValues();
  const event_name = event_values[0][0];
  
  //主催者のカレンダーIDを取得
  const organizer_sheet = ss.getSheetByName('Organizer_info');
  const organizerId = organizer_sheet.getRange(4,3).getValues();
  const calendar = CalendarApp.getCalendarById(organizerId[0]);

  //対象イベントの開催期間を指定
  const sDate = organizer_sheet.getRange(6,3).getValues(); // カレンダー取得開始日
  const eDate = organizer_sheet.getRange(7,3).getValues(); // カレンダー取得終了日
  
  //参加イベントを指定
  const splitEvent = event_name.split(",");
  
  for(i=0;i<splitEvent.length; i++){
    //console.log(splitEvent[i]);
    const searchEventName = splitEvent[i];
    //対象イベントのカレンダーへ参加登録者を追加
    const startDate = new Date(sDate);
    const endDate = new Date(eDate);
    const events = calendar.getEvents(startDate, endDate, {search:searchEventName}); // 対象イベントが存在する期間を指定
    const eventId = events[0].getId(); // 対象イベントのIDを取得
    const event = calendar.getEventById(eventId);
    event.addGuest(participant_email); //参加登録者をイベントへ追加
  }
}

左の方にある時計のマークから、トリガーを下記の通り設定します。
※これで、フォームが送付されたときにsendCalendarが実行されます。

カレンダーの自動送付の設定はこれで以上です!

手順② - 応募者にSlack Botを送付

GASからSlack APIをたたいて、DMのようなBotを送付する記事は他にもたくさんでているので、ぜひ探してみてください。

ここでは、下記手順で、応募者の方にSlack通知をする設定をいれていきます。

  • Slack appの準備
  • スクリプトエディタを開き、設定
  • 確認

Slack appの準備

BotからDMを送るという手法があるので、slack apiのページからアプリを選択 or 新規作成し、Tokenを払い出して、Auth & Permissionsを下記の通り設定します。

Apps Scriptを開き、設定

手順①で作ったスクリプトエディタに下記コードをいれる。
こちらも、主催者情報を読み取れるように作っていますので、各自アレンジしてください。

//TOKEN
const AuthToken = "払い出したトークンをいれる"

//参加者のEmail addressを読みとる
const ss = SpreadsheetApp.getActiveSpreadsheet();
const participant_sheet= ss.getSheetByName('フォームの回答 1');
const participant_lastRow = participant_sheet.getLastRow();
const participant_email_values = participant_sheet.getRange(participant_lastRow,2).getValues();
const participant_email = participant_email_values[0][0];

//参加者が申し込んだSessionを読み取る
const participant_session_values = participant_sheet.getRange(participant_lastRow,3).getValues();
const participant_session = participant_session_values[0][0];

//主催者がSlack botで流したいMessageを読み取り、作成
const message_sheet = ss.getSheetByName('Organizer_info');
const message1_values = message_sheet.getRange(9,2).getValues();
const message1 = message1_values[0][0];
const message1_period_values = message_sheet.getRange(10,2).getValues();
const message1_period = message1_period_values[0][0];
const message1_session_values = message_sheet.getRange(11,2).getValues();
const message1_session = message1_session_values[0][0];
const sDate = message_sheet.getRange(6,3).getValues(); // カレンダー取得開始日
const new_sDate = new Date (sDate);
const sDate_str = Utilities.formatDate(new_sDate, 'JST', 'yyyy/MM/dd');
const eDate = message_sheet.getRange(7,3).getValues(); // カレンダー取得終了日
const new_eDate = new Date (eDate);
const eDate_str = Utilities.formatDate(new_eDate, 'JST', 'yyyy/MM/dd');
const message_all =  message1 + '\n' + '*' + message1_period + '*' + '\n' + sDate_str +'-'+ eDate_str +'\n' + '*' + message1_session + '*' + '\n' + '```'+ participant_session+ '```';

function postDM() {
  const message = message_all;
  //チャンネルIDを取得
  const memberId = lookupByEmail(participant_email);
  const channel_id = getChannelID(memberId);
  
  //指定のチャンネルIDにDMを送信
  const message_options = {
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": AuthToken,
      "channel": channel_id,
      "text": message
    }
  };
  const message_url = 'https://slack.com/api/chat.postMessage';
  UrlFetchApp.fetch(message_url, message_options);
}

//Email addressからSlack IDを取り出す
function lookupByEmail(participant_email) {
  const options = {
    "method": "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload": {
      "token": AuthToken,
      "email": participant_email
      }
    };
  const url = 'https://slack.com/api/users.lookupByEmail';
  const response = UrlFetchApp.fetch(url, options);
  const result = JSON.parse(response);
  
  if(result.ok){
    console.log(result.user.id);
    return result.user.id;
  }else{
    console.log(result);
    return null;
  }
}

//Slack IDからDM用のIDをとりだす
function getChannelID(memberId) {
  const options = {
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": AuthToken,
      "users": memberId
    }
  };
  const url ='https://slack.com/api/conversations.open'
  const response = UrlFetchApp.fetch(url, options);
  const result = JSON.parse(response);
  
  if(result.ok){
    console.log(result.channel.id);
    return result.channel.id;
  }else{
    console.log(result);
    return null;
  }
}

左の方にある時計のマークから、またトリガーを下記の通り設定します。
※これで、フォームが送付されたときにpostDMが実行されます。

Slack Botの設定もこれで以上になります!
Formから応募が合った際に、Slack Botで通知がきて、カレンダー招待が自動できていたら成功です!

まとめ

職種に関わらず、業務の効率化をはかるためにテクノロジーを学んで活用することはとても大事なことです。
より簡単に、より効率よく、より快適に、仕事の質や生産性を高めることを目標にがんばります!

最後まで読んでいただきまして、ありがとうございました!
どなたかのお役に立てれば幸いです。

Discussion