forked from googleworkspace/apps-script-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvacationCalendar.gs
186 lines (178 loc) · 6.21 KB
/
vacationCalendar.gs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* Copyright Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// [START apps_script_calendar_vacation]
var TEAM_CALENDAR_ID = 'ENTER_TEAM_CALENDAR_ID_HERE';
var KEYWORDS = ['vacation', 'ooo', 'out of office'];
var MONTHS_IN_ADVANCE = 3;
// The maximum script run time under Apps Script Pro is 30 minutes; this setting
// will be used to report when the script is about to reach that limit.
var MAX_PRO_RUNTIME_MS = 29 * 60 * 1000;
/**
* Look through the domain users' public calendars and add any
* 'vacation' or 'out of office' events to the team calendar.
*/
function syncTeamVacationCalendar() {
// Define the calendar event date range to search.
var today = new Date();
var futureDate = new Date();
futureDate.setMonth(futureDate.getMonth() + MONTHS_IN_ADVANCE);
var lastRun = PropertiesService.getScriptProperties().getProperty('lastRun');
lastRun = lastRun ? new Date(lastRun) : null;
// Get the list of users in the domain.
var users = getDomainUsers();
// 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
// calendar.
var count = 0;
var timeout = false;
for (var i = 0; i < users.length; i++) {
if (isTimeUp(today, new Date())) {
timeout = true;
break;
}
var user = users[i];
var username = user.split('@')[0];
KEYWORDS.forEach(function(keyword) {
var events = findEvents(user, keyword, today, futureDate, lastRun);
events.forEach(function(event) {
event.summary = '[' + username + '] ' + event.summary;
event.organizer = {
id: TEAM_CALENDAR_ID
};
event.attendees = [];
Logger.log('Importing: %s', event.summary);
try {
Calendar.Events.import(event, TEAM_CALENDAR_ID);
count++;
} catch (e) {
Logger.log(
'Error attempting to import event: %s. Skipping.', e.toString());
}
});
});
}
PropertiesService.getScriptProperties().setProperty('lastRun', today);
Logger.log('Imported ' + count + ' events');
if (timeout) {
Logger.log('Execution time about to hit quota limit; execution stopped.');
}
var executionTime = ((new Date()).getTime() - today.getTime()) / 1000.0;
Logger.log('Total execution time (s) : ' + executionTime); ;
}
/**
* In a given user's calendar, look for occurrences of the given keyword
* in events within the specified date range and return any such events
* found.
* @param {string} user the user's primary email String.
* @param {string} keyword the keyword String to look for.
* @param {Date} start the starting Date of the range to examine.
* @param {Date} end the ending Date of the range to examine.
* @param {Date} opt_since a Date indicating the last time this script was run.
* @return {object[]} an array of calendar event Objects.
*/
function findEvents(user, keyword, start, end, opt_since) {
var params = {
q: keyword,
timeMin: formatDate(start),
timeMax: formatDate(end),
showDeleted: true
};
if (opt_since) {
// This prevents the script from examining events that have not been
// modified since the specified date (that is, the last time the
// script was run).
params['updatedMin'] = formatDate(opt_since);
}
var results = [];
try {
var response = Calendar.Events.list(user, params);
results = response.items.filter(function(item) {
// Filter out events where the keyword did not appear in the summary
// (that is, the keyword appeared in a different field, and are thus
// is not likely to be relevant).
if (item.summary.toLowerCase().indexOf(keyword) < 0) {
return false;
}
// If the event was created by someone other than the user, only include
// it if the user has marked it as 'accepted'.
if (item.organizer && item.organizer.email != user) {
if (!item.attendees) {
return false;
}
var matching = item.attendees.filter(function(attendee) {
return attendee.self;
});
return matching.length > 0 && matching[0].status == 'accepted';
}
return true;
});
} catch (e) {
Logger.log('Error retriving events for %s, %s: %s; skipping',
user, keyword, e.toString());
results = [];
}
return results;
}
/**
* Return a list of the primary emails of users in this domain.
* @return {string[]} An array of user email strings.
*/
function getDomainUsers() {
var pageToken;
var page;
var userEmails = [];
do {
page = AdminDirectory.Users.list({
customer: 'my_customer',
orderBy: 'givenName',
maxResults: 100,
pageToken: pageToken,
viewType: 'domain_public'
});
var users = page.users;
if (users) {
userEmails = userEmails.concat(users.map(function(user) {
return user.primaryEmail;
}));
} else {
Logger.log('No domain users found.');
}
pageToken = page.nextPageToken;
} while (pageToken);
return userEmails;
}
/**
* Return an RFC3339 formated date String corresponding to the given
* Date object.
* @param {Date} date a Date.
* @return {string} a formatted date string.
*/
function formatDate(date) {
return Utilities.formatDate(date, 'UTC', 'yyyy-MM-dd\'T\'HH:mm:ssZ');
}
/**
* Compares two Date objects and returns true if the difference
* between them is more than the maximum specified run time.
*
* @param {Date} start the first Date object.
* @param {Date} now the (later) Date object.
* @return {boolean} true if the time difference is greater than
* MAX_PROP_RUNTIME_MS (in milliseconds).
*/
function isTimeUp(start, now) {
return now.getTime() - start.getTime() > MAX_PRO_RUNTIME_MS;
}
// [END apps_script_calendar_vacation]