From dcdd9a17fa5a0c00f9f4debac04be08394eb7dcd Mon Sep 17 00:00:00 2001 From: Eric Koleda Date: Thu, 22 Aug 2019 10:40:37 -0400 Subject: [PATCH 1/3] Add support for nested groups. --- vacation-calendar/src/Code.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/vacation-calendar/src/Code.js b/vacation-calendar/src/Code.js index e44935de..4c8fb72d 100644 --- a/vacation-calendar/src/Code.js +++ b/vacation-calendar/src/Code.js @@ -36,7 +36,8 @@ function sync() { lastRun = lastRun ? new Date(lastRun) : null; // Get the list of users in the Google Group. - var users = GroupsApp.getGroupByEmail(GROUP_EMAIL).getUsers(); + var group = GroupsApp.getGroupByEmail(GROUP_EMAIL); + var users = getAllUsers(group); // For each user, find events having one or more of the keywords in the event // summary in the specified date range. Import each of those to the team @@ -57,6 +58,37 @@ function sync() { console.log('Imported ' + count + ' events'); } +/** + * Gets all the users that are members of a Google Group, including indirect + * members (for groups that contain other groups). + * @param {GroupsApp.Group} group The group to get the users for. + * @param {Number} optMaxDepth The maximum depth of sub-groups that should be + * searched. + * @return {Session.User[]} The users within the group. + */ +function getAllUsers(group, optMaxDepth) { + var maxDepth = optMaxDepth; + if (isNaN(parseInt(optMaxDepth))) { + maxDepth = Number.MAX_VALUE; + } + var users = group.getUsers(); + if (maxDepth > 0) { + group.getGroups().forEach(function(childGroup) { + users = users.concat(getAllUsers(childGroup, maxDepth - 1)); + }) + } + // Remove duplicates. + var emailsSeen = {}; + users = users.reduce(function(result, user) { + if (!emailsSeen[user.getEmail()]) { + emailsSeen[user.getEmail()] = true; + result.push(user); + } + return result; + }, []); + return users; +} + /** * Imports the given event from the user's calendar into the shared team * calendar. From 0ecceefeb0357b1e7581bb93bf8e2f649967e776 Mon Sep 17 00:00:00 2001 From: Eric Koleda Date: Thu, 22 Aug 2019 11:43:07 -0400 Subject: [PATCH 2/3] Only remove duplicates once. --- vacation-calendar/src/Code.js | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/vacation-calendar/src/Code.js b/vacation-calendar/src/Code.js index 4c8fb72d..2d6d7197 100644 --- a/vacation-calendar/src/Code.js +++ b/vacation-calendar/src/Code.js @@ -61,31 +61,34 @@ function sync() { /** * Gets all the users that are members of a Google Group, including indirect * members (for groups that contain other groups). - * @param {GroupsApp.Group} group The group to get the users for. + * @param {GoogleAppsScript.GroupsApp.Group} group The group to get the users + * for. * @param {Number} optMaxDepth The maximum depth of sub-groups that should be - * searched. - * @return {Session.User[]} The users within the group. + * searched. The default is not to limit the depth. + * @param {boolean} optRemoveDuplicates Whether or not to remove duplicate users + * in the results. The default is true. + * @return {GoogleAppsScript.User[]} The users within the group. */ -function getAllUsers(group, optMaxDepth) { - var maxDepth = optMaxDepth; - if (isNaN(parseInt(optMaxDepth))) { - maxDepth = Number.MAX_VALUE; - } +function getAllUsers(group, optMaxDepth, optRemoveDuplicates) { + var maxDepth = optMaxDepth != null ? optMaxDepth : Number.MAX_VALUE; + var removeDuplicates = optRemoveDuplicates != null ? + optRemoveDuplicates : true; var users = group.getUsers(); if (maxDepth > 0) { group.getGroups().forEach(function(childGroup) { - users = users.concat(getAllUsers(childGroup, maxDepth - 1)); + users = users.concat(getAllUsers(childGroup, maxDepth - 1, false)); }) } - // Remove duplicates. - var emailsSeen = {}; - users = users.reduce(function(result, user) { - if (!emailsSeen[user.getEmail()]) { - emailsSeen[user.getEmail()] = true; - result.push(user); - } - return result; - }, []); + if (removeDuplicates) { + var contains = {}; + users = users.reduce(function(result, user) { + if (!contains[user.getEmail()]) { + contains[user.getEmail()] = true; + result.push(user); + } + return result; + }, []); + } return users; } From a7bc591674586e58ef880fb5b06eea05e1779999 Mon Sep 17 00:00:00 2001 From: Eric Koleda Date: Thu, 22 Aug 2019 16:42:23 -0400 Subject: [PATCH 3/3] Use iterative approach to avoid repeating paths. --- vacation-calendar/src/Code.js | 45 ++++++++++++++--------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/vacation-calendar/src/Code.js b/vacation-calendar/src/Code.js index 2d6d7197..485462c3 100644 --- a/vacation-calendar/src/Code.js +++ b/vacation-calendar/src/Code.js @@ -61,35 +61,26 @@ function sync() { /** * Gets all the users that are members of a Google Group, including indirect * members (for groups that contain other groups). - * @param {GoogleAppsScript.GroupsApp.Group} group The group to get the users - * for. - * @param {Number} optMaxDepth The maximum depth of sub-groups that should be - * searched. The default is not to limit the depth. - * @param {boolean} optRemoveDuplicates Whether or not to remove duplicate users - * in the results. The default is true. - * @return {GoogleAppsScript.User[]} The users within the group. + * @param {GoogleAppsScript.GroupsApp.Group} group The target group. + * @return {GoogleAppsScript.User[]} All users within the group. */ -function getAllUsers(group, optMaxDepth, optRemoveDuplicates) { - var maxDepth = optMaxDepth != null ? optMaxDepth : Number.MAX_VALUE; - var removeDuplicates = optRemoveDuplicates != null ? - optRemoveDuplicates : true; - var users = group.getUsers(); - if (maxDepth > 0) { - group.getGroups().forEach(function(childGroup) { - users = users.concat(getAllUsers(childGroup, maxDepth - 1, false)); - }) +function getAllUsers(group) { + var users = {}; + var queue = [group]; + var visited = {}; + var current; + while (current = queue.pop()) { + var key = current.getEmail(); + if (visited[key]) continue; + current.getUsers().forEach(function(user) { + users[user.getEmail()] = user; + }); + queue = queue.concat(current.getGroups()); + visited[key] = true; } - if (removeDuplicates) { - var contains = {}; - users = users.reduce(function(result, user) { - if (!contains[user.getEmail()]) { - contains[user.getEmail()] = true; - result.push(user); - } - return result; - }, []); - } - return users; + return Object.keys(users).map(function(email) { + return users[email]; + }); } /**