Skip to content

Commit 738570f

Browse files
FoxtrotSierra6829jonas0b1011001
authored andcommitted
feat: Comprehensive email summary (#339)
* feat: comprehensive email summary * feat: custom email subject * feat: custom date format * refactor: add back line break * docs: add function documentation
1 parent 11d730f commit 738570f

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-7
lines changed

Code.gs

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ var addTasks = false;
4949

5050
var emailSummary = false; // Will email you when an event is added/modified/removed to your calendar
5151
var email = ""; // OPTIONAL: If "emailSummary" is set to true or you want to receive update notifications, you will need to provide your email address
52+
var customEmailSubject = ""; // OPTIONAL: If you want to change the email subject, provide a custom one here. Default: "GAS-ICS-Sync Execution Summary"
53+
var dateFormat = "YYYY-MM-DD" // date format in the email summary (e.g. "YYYY-MM-DD", "DD.MM.YYYY", "MM/DD/YYYY". separators are ".", "-" and "/")
5254

5355
/*
5456
*=========================================

Helpers.gs

+82-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,54 @@
1+
/**
2+
* Formats the date and time according to the format specified in the configuration.
3+
*
4+
* @param {string} date The date to be formatted.
5+
* @return {string} The formatted date string.
6+
*/
7+
function formatDate(date) {
8+
const year = date.slice(0,4);
9+
const month = date.slice(5,7);
10+
const day = date.slice(8,10);
11+
let formattedDate;
12+
13+
if (dateFormat == "YYYY/MM/DD") {
14+
formattedDate = year + "/" + month + "/" + day
15+
}
16+
else if (dateFormat == "DD/MM/YYYY") {
17+
formattedDate = day + "/" + month + "/" + year
18+
}
19+
else if (dateFormat == "MM/DD/YYYY") {
20+
formattedDate = month + "/" + day + "/" + year
21+
}
22+
else if (dateFormat == "YYYY-MM-DD") {
23+
formattedDate = year + "-" + month + "-" + day
24+
}
25+
else if (dateFormat == "DD-MM-YYYY") {
26+
formattedDate = day + "-" + month + "-" + year
27+
}
28+
else if (dateFormat == "MM-DD-YYYY") {
29+
formattedDate = month + "-" + day + "-" + year
30+
}
31+
else if (dateFormat == "YYYY.MM.DD") {
32+
formattedDate = year + "." + month + "." + day
33+
}
34+
else if (dateFormat == "DD.MM.YYYY") {
35+
formattedDate = day + "." + month + "." + year
36+
}
37+
else if (dateFormat == "MM.DD.YYYY") {
38+
formattedDate = month + "." + day + "." + year
39+
}
40+
41+
if (date.length < 11) {
42+
return formattedDate
43+
}
44+
45+
const time = date.slice(11,16)
46+
const timeZone = date.slice(19)
47+
48+
return formattedDate + " at " + time + " (UTC" + (timeZone == "Z" ? "": timeZone) + ")"
49+
}
50+
51+
152
/**
253
* Takes an intended frequency in minutes and adjusts it to be the closest
354
* acceptable value to use Google "everyMinutes" trigger setting (i.e. one of
@@ -486,12 +537,13 @@ function processEvent(event, calendarTz){
486537
//------------------------ Send event object to gcal ------------------------
487538
if (needsUpdate){
488539
if (modifyExistingEvents){
540+
oldEvent = calendarEvents[index]
489541
Logger.log("Updating existing event " + newEvent.extendedProperties.private["id"]);
490542
newEvent = callWithBackoff(function(){
491543
return Calendar.Events.update(newEvent, targetCalendarId, calendarEvents[index].id);
492544
}, defaultMaxRetries);
493545
if (newEvent != null && emailSummary){
494-
modifiedEvents.push([[newEvent.summary, newEvent.start.date||newEvent.start.dateTime], targetCalendarName]);
546+
modifiedEvents.push([[oldEvent.summary, newEvent.summary, oldEvent.start.date||oldEvent.start.dateTime, newEvent.start.date||newEvent.start.dateTime, oldEvent.end.date||oldEvent.end.dateTime, newEvent.end.date||newEvent.end.dateTime, oldEvent.location, newEvent.location, oldEvent.description, newEvent.description], targetCalendarName]);
495547
}
496548
}
497549
}
@@ -502,7 +554,7 @@ function processEvent(event, calendarTz){
502554
return Calendar.Events.insert(newEvent, targetCalendarId);
503555
}, defaultMaxRetries);
504556
if (newEvent != null && emailSummary){
505-
addedEvents.push([[newEvent.summary, newEvent.start.date||newEvent.start.dateTime], targetCalendarName]);
557+
addedEvents.push([[newEvent.summary, newEvent.start.date||newEvent.start.dateTime, newEvent.end.date||newEvent.end.dateTime, newEvent.location, newEvent.description], targetCalendarName]);
506558
}
507559
}
508560
}
@@ -943,7 +995,7 @@ function processEventCleanup(){
943995
}, defaultMaxRetries);
944996

945997
if (emailSummary){
946-
removedEvents.push([[calendarEvents[i].summary, calendarEvents[i].start.date||calendarEvents[i].start.dateTime], targetCalendarName]);
998+
removedEvents.push([[calendarEvents[i].summary, calendarEvents[i].start.date||calendarEvents[i].start.dateTime, calendarEvents[i].end.date||calendarEvents[i].end.dateTime, calendarEvents[i].location, calendarEvents[i].description], targetCalendarName]);
947999
}
9481000
}
9491001
}
@@ -1161,7 +1213,7 @@ function sendSummary() {
11611213
var subject;
11621214
var body;
11631215

1164-
var subject = `GAS-ICS-Sync Execution Summary: ${addedEvents.length} new, ${modifiedEvents.length} modified, ${removedEvents.length} deleted`;
1216+
var subject = `${customEmailSubject ? customEmailSubject : "GAS-ICS-Sync Execution Summary"}: ${addedEvents.length} new, ${modifiedEvents.length} modified, ${removedEvents.length} deleted`;
11651217
addedEvents = condenseCalendarMap(addedEvents);
11661218
modifiedEvents = condenseCalendarMap(modifiedEvents);
11671219
removedEvents = condenseCalendarMap(removedEvents);
@@ -1170,23 +1222,46 @@ function sendSummary() {
11701222
for (var tgtCal of addedEvents){
11711223
body += `<br/>${tgtCal[0]}: ${tgtCal[1].length} added events<br/><ul>`;
11721224
for (var addedEvent of tgtCal[1]){
1173-
body += "<li>" + addedEvent[0][0] + " at " + addedEvent[0][1] + "</li>";
1225+
body += "<li>"
1226+
+ "Name: " + addedEvent[0][0] + "<br/>"
1227+
+ "Start: " + formatDate(addedEvent[0][1]) + "<br/>"
1228+
+ "End: " + formatDate(addedEvent[0][2]) + "<br/>"
1229+
+ (addedEvent[0][3] ? ("Location: " + addedEvent[0][3] + "<br/>") : "")
1230+
+ (addedEvent[0][4] ? ("Description: " + addedEvent[0][4] + "<br/>") : "")
1231+
+ "</li>";
11741232
}
11751233
body += "</ul>";
11761234
}
11771235

11781236
for (var tgtCal of modifiedEvents){
11791237
body += `<br/>${tgtCal[0]}: ${tgtCal[1].length} modified events<br/><ul>`;
11801238
for (var modifiedEvent of tgtCal[1]){
1181-
body += "<li>" + modifiedEvent[0][0] + " at " + modifiedEvent[0][1] + "</li>";
1239+
body += "<li>"
1240+
+ (modifiedEvent[0][0] != modifiedEvent[0][1] ? ("<del>Name: " + modifiedEvent[0][0] + "</del><br/>") : "")
1241+
+ "Name: " + modifiedEvent[0][1] + "<br/>"
1242+
+ (modifiedEvent[0][2] != modifiedEvent[0][3] ? ("<del>Start: " + formatDate(modifiedEvent[0][2]) + "</del><br/>") : "")
1243+
+ " Start: " + formatDate(modifiedEvent[0][3]) + "<br/>"
1244+
+ (modifiedEvent[0][4] != modifiedEvent[0][5] ? ("<del>End: " + formatDate(modifiedEvent[0][4]) + "</del><br/>") : "")
1245+
+ " End: " + formatDate(modifiedEvent[0][5]) + "<br/>"
1246+
+ (modifiedEvent[0][6] != modifiedEvent[0][7] ? ("<del>Location: " + (modifiedEvent[0][6] ? modifiedEvent[0][6] : "") + "</del><br/>") : "")
1247+
+ (modifiedEvent[0][7] ? (" Location: " + modifiedEvent[0][7] + "<br/>") : "")
1248+
+ (modifiedEvent[0][8] != modifiedEvent[0][9] ? ("<del>Description: " + (modifiedEvent[0][8] ? modifiedEvent[0][8] : "") + "</del><br/>") : "")
1249+
+ (modifiedEvent[0][9] ? (" Description: " + modifiedEvent[0][9] + "<br/>") : "")
1250+
+ "</li>";
11821251
}
11831252
body += "</ul>";
11841253
}
11851254

11861255
for (var tgtCal of removedEvents){
11871256
body += `<br/>${tgtCal[0]}: ${tgtCal[1].length} removed events<br/><ul>`;
11881257
for (var removedEvent of tgtCal[1]){
1189-
body += "<li>" + removedEvent[0][0] + " at " + removedEvent[0][1] + "</li>";
1258+
body += "<li>"
1259+
+ "<del>Name: " + removedEvent[0][0] + "</del><br/>"
1260+
+ "<del>Start: " + formatDate(removedEvent[0][1]) + "</del><br/>"
1261+
+ "<del>End: " + formatDate(removedEvent[0][2]) + "</del><br/>"
1262+
+ (removedEvent[0][3] ? ("<del>Location: " + removedEvent[0][3] + "</del><br/>") : "")
1263+
+ (removedEvent[0][4] ? ("<del>Description: " + removedEvent[0][4] + "</del><br/>") : "")
1264+
+ "</li>";
11901265
}
11911266
body += "</ul>";
11921267
}

0 commit comments

Comments
 (0)