GASを使ってドメイン内のすべてのGoogleグループ設定を出力する
定期的にGASでいろんなコードを書いているのですが、私の中でも書き方の流行り廃りが結構あったりします。
ドメイン内のすべてのGoogleグループ設定を出力する
というコードを最近書いたので、どういうコードを書いたのかを解説とセットで残しておこうかなと。
別にGoogleグループの設定なんて出力しないって方も、よりよいGASのコードを書きたいって方はぜひ見てってほしいです。(たぶん)参考になるところがあるはずです。
ちなみにGoogleグループ設定ってなに?そんなの気にしたことがない。って方は下記の吉田さんのnoteをみるとよいです。
Googleグループの設定と管理|吉田航|note
本記事で作るもの
こんな感じでサクッとGWS内の全てのグループ設定が出力できます。
事前準備
適当にスプレッドシートを作ってご自身のGWSのドメイン名のシートを作っといてください。
GASを作る
コード
下記のGASコードをコピペしてください。
const ACTIVE_USER_EMAIL = Session.getActiveUser().getEmail();
const DOMAIN_NAME = ACTIVE_USER_EMAIL.substring(ACTIVE_USER_EMAIL.indexOf('@') + 1);
const SHEET_HEADERS = [
'email',
'whoCanJoin',
'whoCanViewMembership',
'whoCanViewGroup',
'whoCanInvite',
'whoCanAdd',
'allowExternalMembers',
'whoCanPostMessage',
'allowWebPosting',
'primaryLanguage',
'maxMessageBytes',
'isArchived',
'archiveOnly',
'messageModerationLevel',
'spamModerationLevel',
'replyTo',
'includeCustomFooter',
'customFooterText',
'sendMessageDenyNotification',
'defaultMessageDenyNotificationText',
'showInGroupDirectory',
'allowGoogleCommunication',
'membersCanPostAsTheGroup',
'messageDisplayFont',
'includeInGlobalAddressList',
'whoCanLeaveGroup',
'whoCanContactOwner',
'whoCanAddReferences',
'whoCanAssignTopics',
'whoCanUnassignTopic',
'whoCanTakeTopics',
'whoCanMarkDuplicate',
'whoCanMarkNoResponseNeeded',
'whoCanMarkFavoriteReplyOnAnyTopic',
'whoCanMarkFavoriteReplyOnOwnTopic',
'whoCanUnmarkFavoriteReplyOnAnyTopic',
'whoCanEnterFreeFormTags',
'whoCanModifyTagsAndCategories',
'favoriteRepliesOnTop',
'whoCanApproveMembers',
'whoCanBanUsers',
'whoCanModifyMembers',
'whoCanApproveMessages',
'whoCanDeleteAnyPost',
'whoCanDeleteTopics',
'whoCanLockTopics',
'whoCanMoveTopicsIn',
'whoCanMoveTopicsOut',
'whoCanPostAnnouncements',
'whoCanHideAbuse',
'whoCanMakeTopicsSticky',
'whoCanModerateMembers',
'whoCanModerateContent',
'whoCanAssistContent',
'customRolesEnabledForSettingsToBeMerged',
'enableCollaborativeInbox',
'whoCanDiscoverGroup',
'defaultSender',
];
function onOpen() {
SpreadsheetApp.getUi().createMenu('Googleグループ設定出力')
.addItem('実行', 'writeGroupsSettingsList')
.addToUi();
}
function writeGroupsSettingsList() {
const sheet = SheetsService.getGroupsSheet({sheetName: DOMAIN_NAME});
SheetsService.clearSheet({sheet, headers: SHEET_HEADERS});
const allGroupsSettings = GroupService.listGoogleGroupSettings();
const rowValues = allGroupsSettings.map((gs) => {
const row = [];
SHEET_HEADERS.forEach(title => {
row.push(gs[title] || '');
})
return row;
});
const startRow = 2;
sheet.getRange(startRow, 1, rowValues.length, SHEET_HEADERS.length).setValues(rowValues);
}
class GroupService {
static listGoogleGroupSettings() {
const allGroupsSettings = [];
let pageToken = '';
let page;
do {
console.log('DOMAIN_NAME', DOMAIN_NAME);
// @see https://developers.google.com/apps-script/advanced/admin-sdk-directory
page = AdminDirectory.Groups.list({
domain: DOMAIN_NAME,
maxResults: 200,
pageToken,
});
page.groups.forEach((g) => {
console.log('groupKey', g.email);
// https://developers.google.com/apps-script/advanced/admin-sdk-groups-settings
// https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups
const groupSettings = AdminGroupsSettings.Groups.get(g.email);
allGroupsSettings.push(groupSettings);
});
pageToken = page.nextPageToken;
} while (pageToken);
return allGroupsSettings;
}
}
class SheetsService {
static clearSheet({sheet, headers}) {
sheet.clearContents();
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
};
static getGroupsSheet({sheetName}) {
return SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
}
}
サービスを有効化
下記の2つのサービスを追加してください。
- AdminDirectory
- AdminGroupsSettings
コードとサービスの有効化が終わると下記のような状態になります。
実行
スプレッドシートを再読込するとメニューに Googleグループ設定出力
がでているので、特権ユーザーで実行すればグループ設定が出力されます。
※ 最初の1回だけ認可だけが走るので、2回実行が必要になります
UIの調整
列や行の固定、交互の背景色等を設定してUIを調整すると良いでしょう。
実装時のポイント
実装時のポイントをいくつか解説します。
実行ユーザーをうまくつかってドメインを取る
const ACTIVE_USER_EMAIL = Session.getActiveUser().getEmail();
const DOMAIN_NAME = ACTIVE_USER_EMAIL.substring(ACTIVE_USER_EMAIL.indexOf('@') + 1);
Session.getActiveUser().getEmail()
でGASの実行ユーザーのメールアドレスが取れます。
複数GWS契約していても対応できますし、コードの可搬性を考えて、ドメインはベタ書きせずに動的にとると良いでしょう。
Web上では Session.getActiveUser().getUserLoginId()
を使ってメールアドレスを取得するコードが散見されますが、サポート終了していますので使わないように。
APIのキー名を利用してシートのヘッダーを定義
(こだわりがなければ)シートのヘッダーはGroups Settings APIで取得できる項目をそのまま使いましょう。
そうすることで、 group['key'] = 'value';
のように何度も値を入れる必要がなくなります。
const SHEET_HEADERS = [
'email',
'whoCanJoin',
...
ヘッダーの値を定義しておくことで、再実行時必要なシートのクリア処理で値を全部消す→ヘッダー行を設定、の流れをきれいに作れます。
また、シートのクリアを clearContents()
にしているのでシートの書式設定は残るようにしてあります。交互の背景色や、条件付き書式を作っても再実行でそのまま残せます。
class SheetsService {
static clearSheet({sheet, headers}) {
sheet.clearContents();
sheet.getRange(1, 1, 1, titles.length).setValues([headers]);
};
...
Classを使う
GroupService, SheetsService のようにClassを使っています。これはいろいろな理由があるのですが、特に重要な2点だけ解説しておきます。
1つめはファイル分割をしやすくする(依存関係を明確にする)ためです。
現状は大したコード量じゃないため1ファイルで書いていますが、コードが増えてくると可読性が下がっていきます。のちのちファイルを分けることを考慮して事前にClassを切って下地を作っておく、ということです。
2つめはグローバル定義された関数をへらすためです。
下記画像のように、手動実行時の関数リストはグローバルで定義された関数を引っ張ってきます。
直接実行する必要がない関数はClassを使って隠蔽しておくと、手動実行時にでてきませんし、トリガー設定時の候補にもでてきません。不要なものは隠すことでよりよいコードになります。
ちなみにFunction名の最後に _
をつけることでも隠すことができます。
classを作らずに隠したい場合は使うと良いと思います。
API実行はリファレンスのURLをコメントで残す
何をコメントに残すかは悩ましいですが、とりあえずコメントに絶対に残すべきなのはリファレンスのURLです。
※ @see
とかもつけてもいいかもしれません。
// https://developers.google.com/apps-script/advanced/admin-sdk-groups-settings
// https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups
const groupSettings = AdminGroupsSettings.Groups.get(g.email);
Discussion