Skip to content

Instantly share code, notes, and snippets.

@prasann
Last active November 13, 2021 15:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prasann/a92c37c63e36d75630b9811b1dac272d to your computer and use it in GitHub Desktop.
Save prasann/a92c37c63e36d75630b9811b1dac272d to your computer and use it in GitHub Desktop.
Updates the calendar with a day long event when someone applies leave in leave planner
const leaveTag = "label-to-which-the-emails-are-marked";
const calendarId = "new-calendar-id";
const nameRegEx = /Leave plan for (?<name>.*) is as below/;
const leaveTypeRegEx = /Leave Type:\s*(?<type>(.)*)?/;
const startDateRegEx = /Start Date:\s*(?<leave>(?:.*)202.)(?:,\s)*(?:(Half-Day:\s*(.*)))?/;
const endDateRegEx = /End Date:\s*(?<leave>(?:.*)202.)(?:,\s)*(?:(Half-Day:\s*(.*)))?/;
function applyRegEx(regEx, key, messageBody){
const matches = regEx.exec(messageBody);
return matches?.groups && matches.groups[key] ? matches.groups[key] : undefined;
}
function parseLeaveDates(gmailMessage){
const messageBody = gmailMessage.getBody();
const name = applyRegEx(nameRegEx, 'name', messageBody);
const leaveType = applyRegEx(leaveTypeRegEx, 'type', messageBody);
const startDateStr = applyRegEx(startDateRegEx, 'leave', messageBody);
const endDateStr = applyRegEx(endDateRegEx, 'leave', messageBody);
return {
name,
leaveType,
startDateStr,
endDateStr
}
}
function getLeaveData(){
const leaveLabel = GmailApp.getUserLabelByName(leaveTag);
const unReadThreads = leaveLabel.getThreads().filter(thread => thread.isUnread());
return unReadThreads.reduce((acc, unReadThread) => {
unReadThread.markRead();
const gmailMessages = unReadThread.getMessages();
const leaveData = gmailMessages.map(gmailMessage => parseLeaveDates(gmailMessage));
return acc.concat(leaveData);
}, []);
}
function createACalendarEvent({name, leaveType, startDateStr, endDateStr}){
var calendar = CalendarApp.getCalendarById(calendarId);
const title = `${name} - ${leaveType}`
const startDate = new Date(startDateStr);
const endDate = new Date(endDateStr)
endDate.setDate(endDate.getDate() + 1)
calendar.createAllDayEvent(title,startDate,endDate)
}
// This is the main method that's triggered periodically
function leaveUpdater() {
const leaveData = getLeaveData();
Logger.log(leaveData);
leaveData.map(leave => {createACalendarEvent(leave)});
};
@arunvelsriram
Copy link

Sample metadata with oauth scopes:

{
  "timeZone": "Asia/Kolkata",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/gmail.labels", "https://www.googleapis.com/auth/gmail.modify", "https://mail.google.com/", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/calendar.readonly", "https://www.google.com/calendar/feeds"],
  "runtimeVersion": "V8",
  "gmail": {
    "name": "Leave Planner",
    "logoUrl": "https://www.gstatic.com/images/branding/googleg/1x/googleg_standard_color_64dp.png",
    "contextualTriggers": [{
      "unconditional": {
      },
      "onTriggerFunction": "leaveUpdater"
    }],
    "primaryColor": "#146b2e",
    "openLinkUrlPrefixes": ["https://developers.google.com/gmail"],
    "version": "TRUSTED_TESTER_V2"
  }
}

@arunvelsriram
Copy link

arunvelsriram commented Nov 13, 2021

fixed scheduling leaves for multiple days:

function createACalendarEvent({name, leaveType, startDateStr, endDateStr}){
  var calendar = CalendarApp.getCalendarById(calendarId);
  const title = `${name} - ${leaveType}`
  const startDate = new Date(startDateStr);
  const endDate = new Date(endDateStr)
  endDate.setDate(endDate.getDate() + 1)
  calendar.createAllDayEvent(title,startDate,endDate)
}

endDate is non-inclusive so added +1 to it.

@arunvelsriram
Copy link

Multiple leaves notifications sent as replies in a single email thread are not getting processed as we are considering only the first message in the thread. Sometimes the leave planner app sends the leaves notifications as replies in the same thread (happens when we submit multiple leave plans within a short period of time I guess).

Fix:

function parseLeaveDates(gmailMessage){
  const messageBody = gmailMessage.getBody();
  const name = applyRegEx(nameRegEx, 'name', messageBody);
  const leaveType = applyRegEx(leaveTypeRegEx, 'type', messageBody);
  const startDateStr = applyRegEx(startDateRegEx, 'leave', messageBody);
  const endDateStr = applyRegEx(endDateRegEx, 'leave', messageBody);
  return {
    name,
    leaveType,
    startDateStr,
    endDateStr
  }
}

function getLeaveData(){
  const leaveLabel = GmailApp.getUserLabelByName(leaveTag);
  const unReadThreads = leaveLabel.getThreads().filter(thread => thread.isUnread());
  return unReadThreads.reduce((acc, unReadThread) => {
    unReadThread.markRead();
    const gmailMessages = unReadThread.getMessages();
    const leaveData = gmailMessages.map(gmailMessage => parseLeaveDates(gmailMessage));
    return acc.concat(leaveData);
  }, []);
}

@prasann
Copy link
Author

prasann commented Nov 13, 2021

@arunvelsriram thanks ✌🏼, updated the gist with your snippets 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment