🐓
GAS:200件以上のGoogleグループ(メンバーや設定)の一覧を出力する をリファクタする
sawaさんのすんばらしいこちらの記事を参考に、リファクタしてみました。
すごく助かりました&勉強になりました。
ありがとうございます!
GAS
/**
* GoogleWorkSpaceで設定されているグループを取得しシートに書き出す関数
*
* @trigger{
* type: インストーラブルトリガー,
* user: XXXXX
* when: 毎日 午前0-1時
* }
*
* 参考URL
* https://zenn.dev/saawaa/articles/b03ee184685b64
*/
function exportGoogleGroup() {
// console.time('実行時間')
const ss = SpreadsheetApp.getActiveSpreadsheet();
//スプレッドシートの1つ目のシートを選択
const sheet = ss.getSheetByName("example.co.jp");
//対象ドメイン(example.co.jpの部分を置き換える)
const domain = 'example.co.jp';
//シートをクリア
sheet.clear();
//ヘッダー追加
const values = [];
values.push([
"メールアドレス",
"グループ名",
"説明",
"メンバー数",
"オーナー",//追加分
"マネージャー",//追加分
"メンバー",
"オーナーに連絡",
"メンバーを表示",
"会話を表示",
"投稿を公開",
"メンバーを管理",
"グループに参加できるユーザー",
"組織外のメンバーの許可",
]);
//オーナーに連絡の設定状況を日本語表示させる
const ownercontact = {
ALL_MANAGERS_CAN_CONTACT: 'グループの管理者',
ALL_MEMBERS_CAN_CONTACT: 'グループのメンバー',
ALL_IN_DOMAIN_CAN_CONTACT: '組織全体',
ANYONE_CAN_CONTACT: '外部'
};
//メンバーを表示と会話を表示の設定状況を日本語表示させる
const access = {
ALL_OWNERS_CAN_VIEW: 'グループのオーナー',
ALL_MANAGERS_CAN_VIEW: 'グループの管理者',
ALL_MEMBERS_CAN_VIEW: 'グループのメンバー',
ALL_IN_DOMAIN_CAN_VIEW: '組織全体',
ANYONE_CAN_VIEW: '外部'
};
//投稿を公開の設定状況を日本語表示させる
const post = {
NONE_CAN_POST: '投稿不可',
ALL_OWNERS_CAN_POST: 'グループのオーナー',
ALL_MANAGERS_CAN_POST: 'グループの管理者',
ALL_MEMBERS_CAN_POST: 'グループのメンバー',
ALL_IN_DOMAIN_CAN_POST: '組織全体',
ANYONE_CAN_POST: '外部'
};
//メンバーを管理の設定状況を日本語表示させる
const managemembers = {
OWNERS_ONLY: 'グループのオーナー',
OWNERS_AND_MANAGERS: 'グループの管理者',
ALL_MEMBERS: 'グループのメンバー'
};
//グループに参加できるユーザーの設定を日本語表示させる
const canjoin = {
ALL_IN_DOMAIN_CAN_JOIN: '組織内のすべてのユーザーが参加できる',
CAN_REQUEST_TO_JOIN: '組織内のすべてのユーザーがリクエストできる',
INVITED_CAN_JOIN: '招待されたユーザーのみ'
};
//組織外のメンバーの許可の設定を日本語表示させる
const allow = {
'false': '不可',
'true': '可'
};
let endFlag = false;
let token = '';
const groupsList = AdminDirectory.Groups.list({
domain: domain,
pageToken: token
});
//while文
while (!endFlag) {
try {
// console.time('実行時間AdminDirectory.Groups')
//グループ一覧の取得
// console.timeEnd('実行時間AdminDirectory.Groups')
// console.log(groupsList)
// return
for (let i = 0; i < groupsList.groups.length; i++) {
//グループの基本情報を取得
const value = [];
value.push(groupsList.groups[i].email); //メールアドレス
value.push(groupsList.groups[i].name); //グループ名
value.push(groupsList.groups[i].description); //説明
value.push(groupsList.groups[i].directMembersCount); //メンバー数
// console.time('実行時間AdminDirectory.Members')
//グループのメンバー情報の取得
const members = AdminDirectory.Members.list(groupsList.groups[i].email).members;
// console.timeEnd('実行時間AdminDirectory.Members')
// console.log(members)
//メンバー処理
if (members) {
//オーナ-データをセット
//members.role = "OWNER" ,"MANAGER","MEMBER" このうち、オーナの場合情報取得、いなければ空白を返す
//オーナーやマネージャは1名以上、2名とか3名の場合もある
//配列の中のオブジェクト、その中のmembers.role を取りたい
const owners = members.reduce((emails, member) => {
if (member.role === "OWNER") {
return emails += member.email + '\r\n';
} else {
return emails += '';
}
}, '')
// console.log(owners);
value.push(owners)
const manegers = members.reduce((emails, member) => {
if (member.role === "MANAGER") {
return emails += member.email + '\r\n';
} else {
return emails += '';
}
}, '')
// console.log(manegers);
value.push(manegers)
//メンバーデータをセット
let memberData = '';
for (let j = 0; j < members.length; j++) {
//memberData.push(members[j].email);
memberData += members[j].email + '\r\n';
}
value.push(memberData);
} else {
value.push(''); //オーナーなし
value.push(''); //マネージャーなし
value.push(''); //メンバーなし
}
//グループのプロパティを取得
const group = AdminGroupsSettings.Groups.get(groupsList.groups[i].email);
value.push(ownercontact[group.whoCanContactOwner]); //オーナーに連絡
value.push(access[group.whoCanViewMembership]); //メンバーを表示
value.push(access[group.whoCanViewGroup]); //会話を表示
value.push(post[group.whoCanPostMessage]); //投稿を公開
value.push(managemembers[group.whoCanModerateMembers]); //メンバーを管理
value.push(canjoin[group.whoCanJoin]); //グループに参加できるユーザー
value.push(allow[group.allowExternalMembers]); //組織外のメンバーの許可
// console.log(value.length)
// if (value.length == 12) {
// console.log(value)}
values.push(value);
}
if (groupsList["nextPageToken"] == null) {
console.log("Group nextPageToken null: " + groupsList["nextPageToken"])
endFlag = true;
} else {
token = groupsList["nextPageToken"];
}
} catch (error) {
console.log(error);
}
}
// console.log(values)
//取得したデータをスプレッドシートにセットする
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
//垂直方向の配置を指定する(上に配置:top, 真ん中に配置:middle, 下に配置:bottom)
// sheet.getRange(1, 1, values.length, 12).setVerticalAlignment('middle')
// console.timeEnd('実行時間')
}
改変した点
主な改変点は次の通りです。
- var宣言をconst・letに置き換えました。
- letはそれを使用している箇所の近くに置きました。
- const groupsList = AdminDirectory.Groups.list は反復処理の外に置きました。
- sheet.getRangeの第4引数を数字決めうちにせず、values[0].lengthとしました。
- グループのオーナとマネージャの情報も取るようにしました(これをやろうと思って色々手を出してしまった)
reduce
mapとかreduce苦手なんですよね。
reduceよりfilter mapや flatMap が見やすいという話もあり。
理解しやすいのを使ったら良いのではとのアドバイスでした。
taitoさんありがとう!
// 以下すべて同じ
// filterしてmap
members.filter(m => m.role === "OWNER").map(m => m.email);
// flatMap (mapしてflat()する)
members.flatMap(m => m.role == "OWNER" ? m.email : []);
// mapしてfilter
members.map(m => m.role == "OWNER" ? m.email : null).filter(Boolean);
// reduce
members.reduce((acc, m) => m.role === "OWNER" ? acc.concat(m.email) : acc, []);
未解決
未解決の事項は次の通りです。もう疲れたのでこの辺で勘弁してください。
- API複数回呼び出してるのをどうにかしたい。 const group = AdminGroupsSettings.Groups.get(groupsList.groups[i].email);
- value.push がいっぱいあるので、なんか上手くできそうな気がする。
- if/else でネストが深くなってる。
Discussion
使わせてもらいました!
一覧に出てきて感動しました〜。
使っていないと思われるグループの洗い出しが簡単になります。
ありがとうございました。ヽ(`・ω・´)ノ