はじめに
20卒新卒エンジニアです.コロナの影響で入社式も延期になり,4ヶ月たった今ですら,出社できない状況です.
ついには内定式以来,リアルで同期全員と会ったことがありません...
そこで,強制的にコミュニケーションを取る場を作ろうと,今回シャッフルランチ(リモート)を企画しました!
同期のカレンダーに勝手にランチイベントを突っ込む極悪非道の企画です
この記事では,オンラインシャッフルランチの企画を支える技術としてGASを使って,自動的にGoogle Meetを有効にした状態でGoogleカレンダーにランチイベントを登録する方法を紹介します.
やりたいこと
参加メンバーをシャッフルして3人グループを作る
※ オンラインで話すなら,これぐらいが程よかったので1グループ3人としました.
グループごとにGoogleカレンダーにランチイベントを登録
Googleカレンダーから直接Google Meetにアクセスできるようにする
考えるべきこと
余る人がでた場合
3人で1グループ作るとすると,余りが1人または2人でる可能性があります
このような場合,以下のようにグループを再編することでボッチを回避しました.
- 1人余る場合は,4人グループを1つ作成
- 2人余る場合は,4人グループを2つ作成
メンバー情報の取得方法
カレンダー登録するためには,メンバーのメールアドレスが必要です.
新卒同期が参加する共有カレンダーを作っているので,そこからメンバー情報(メールアドレス)が取得できないか検討しましたが,直接は無理そうでした.
なので,今回はスプレッドシートにメンバーリストを記載して,そこから取得するようにしました.
詳細は後述します.
準備
コーディングを行う前に,いくつか用意することがあります.
このセクションでは,準備事項について詳細に説明します.
カレンダーID
GASからカレンダーを操作するために,カレンダーIDが必要です.
取得方法は,Google Calendarから歯車マーク -> 設定 -> 参加している共有カレンダーを選択すると,ページ下に赤枠で囲ったカレンダーIDが表示されます.これを使うのでコピーしておきます.
スプレッドシート
スプレッドシートの作成
Google Driveの任意の場所にスプレッドシートを作成します.
メールアドレスとカレンダーIDを記載
シート名を「test」として,
- 1列目に参加するユーザのメールアドレス
- 2列目には,先程コピーしたカレンダーID
Calendar API
スプレッドシートのタブからツール -> スクリプトエディタを選択すると,GASエディタが表示されます.
ここで,Calendar APIを利用するために,タブからリソース -> Googleの拡張サービスを選択し,Calendar APIをONにします.
以上で,準備が整いました.
コーディング
このセクションでは,作成したコードについてそれぞれ詳細に説明します.
スプレッドシートの操作
メールアドレス一覧の取得
スプレッドシートから情報を取得するために,インスタンスを作成しています.
メールアドレスは,getRangeで2行1列を始点,getLastRowで終点を指定してgetValuesで配列としてすべてのメールアドレスを取得します.
// シートオブジェクトを作成
const ss = SpreadsheetApp.getActiveSpreadsheet();
// 操作するシートのオブジェクトを取得
const sheet = ss.getSheetByName('test');
// ユーザのEmailアドレスをシートから取得
const emails = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues();
配列のフォーマット
取得したメールアドレス一覧が格納された配列の中身は以下のようになっています.
[['xxx@example.com'], ['xxx@example.com'], ['xxx@example.com']]
後述するカレンダー登録でユーザを指定するためには,以下のような形式にフォーマットする必要があります.
[{'email': 'xxx@example.com'}, {'email': 'xxx@example.com'}, ... , {'email': 'xxx@example.com'}]
そのためのコードは以下のようになります.
// Calendar API用にフォーマット
const formatedEmails = shuffle(emails).map(email => ({'email': email[0]}));
カレンダーIDの取得
スプレッドシートの2行2列目にあるカレンダーIDを取得します.
// 共有カレンダーのIDをシートから取得
const calendarId = sheet.getRange(2, 2).getValue();
シャッフル
配列の要素をランダムに並び替えるコードは以下のようになります.
// 配列の要素をシャッフル
function shuffle(array){
var result = [];
for(i = array.length; i > 0; i--){
var index = Math.floor(Math.random() * i);
var val = array.splice(index, 1)[0];
result.push(val);
}
return result;
}
グループの作成
基本的には,3人で1グループを作成します.
グループは以下のように配列にネストした形で表現しています.
[
[
{'email': 'xxx@example.com'},
{'email': 'xxx@example.com'},
{'email': 'xxx@example.com'}
],
[
{'email': 'xxx@example.com'},
{'email': 'xxx@example.com'},
{'email': 'xxx@example.com'}
]
]
余りがでた場合は前述したとおり,4人グループを作成します.
Switch文ではその処理をおこなっています.
そもそも人数が少ない場合(5人以下)は,グループ化せずそのまま返すようにします.
// グループ作成
function createLunchGroups(array) {
const arrayLen = array.length;
// 作成できるグループ数
const groupNum = Math.floor(arrayLen / 3);
var result = [];
// グループ数が2つ未満だった場合、グループ分けを行わない
if (groupNum < 2) {
result.push(array)
return result;
}
// 3人一組でグループ分けを行う
switch (arrayLen % 3) {
// 1人余る場合: 4人グループを1つ作る
case 1:
// 4人グループを1つ作成
result.push(array.slice(0, 4));
// 3人グループを作成
for (i = 2; i <= groupNum; i++) {
result.push(array.slice(i*3-2, i*3+1));
}
break;
// 2人余る場合
case 2:
// 4人グループを2つ作成
for (i = 0; i < 2; i++) {
result.push(array.slice(i*4, i*4+4))
}
// 3人グループ作成
for (i = 3; i <= groupNum; i++) {
result.push(array.slice(i*3-1, i*3+2));
}
break;
// 3人ちょうどで作れる場合
default:
for (i = 1; i <= groupNum; i++) {
result.push(array.slice(i*3-3, i*3))
}
break;
}
return result;
}
Googleカレンダーへの登録
カレンダーにイベントを登録をするには「Calendar.Events.insert」を使います.
引数には,イベントの詳細情報をパラメータとして渡すことで細かい制御が可能です.
今回は,
- タイトルおよびイベントの説明
- 場所
- 開始日時および終了日時
- Google Meetの設定
- attendsで招待するユーザを指定
をパラメータとして渡しています.
特にGoogle Meetを有効化するには,「conferenceDataVersion」の値として1を指定し,「conferenceData」をパラメータで渡す必要があります.
// イベント登録
function createEvent(calendarId, users) {
// リクエストIDをランダムに生成
const requestId = Utilities.formatString("shuffle#%d", Math.random()*100);
// イベントの詳細設定
const detail = {
summary: 'シャッフルランチ',
location: 'リモート',
description: '同期との交流を目的としたランチ会です!',
start: {
dateTime: new Date('2020/8/3 12:00:00').toISOString()
},
end: {
dateTime: new Date('2020/8/3 12:30:00').toISOString()
},
conferenceData: {
createRequest: {
conferenceSolutionKey: {
type: "hangoutsMeet"
},
requestId: requestId
}
},
attendees: users
};
// イベントの登録
const event = Calendar.Events.insert(detail, calendarId, { conferenceDataVersion: 1 });
Logger.log('Event ID: ' + JSON.stringify(event));
}
実行
メイン関数としてmainProcessを定義したので,これを実行します.
function mainProcess() {
// シートオブジェクトを作成
const ss = SpreadsheetApp.getActiveSpreadsheet();
// 操作するシートのオブジェクトを取得
const sheet = ss.getSheetByName('test');
// ユーザのEmailアドレスをシートから取得
const emails = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues();
// Calendar API用にフォーマット
const formatedEmails = shuffle(emails).map(email => ({'email': email[0]}));
// グループの作成
const lunchGroups = createLunchGroups(formatedEmails);
// カレンダーIDをシートから取得
const calendarId = sheet.getRange(2, 2).getValue();
// グループごとにイベント登録
lunchGroups.map(group => createEvent(calendarId, group));
}
スクリプトは「Ctrl + R」で実行できます.
実行すると,反映されるまで多少時間かかりますが,30秒ほどでカレンダーにイベント登録がされていると思います.
おわりに
リモートシャッフルランチをいい感じに登録するスクリプトを紹介しました.
なかなかリアルではコミュニケーションが取りづらい状況なので,少しでもオンライン・ランチのハードルが下がり,誰でも気軽に企画できるようになればと思います.