Lucy
Lucy

Reputation: 11

Inviting guests to a "Quick Add" Google Calendar event

I am trying to improve the functionality of the "Quick Add" feature in Google Calendar. Quick Add is the feature that is normally accessed by going to Google Calendar and clicking the down arrow next to the red "Create" button (see image: http://s2.postimg.org/95zxshivt/calendar_screenshot.png).

The functionality I am trying to achieve is to allow the user to invite guests to the newly created Calendar event using keywords in what they type in the Quick Add box. For example, if the user uses the Quick Add box to add an event by entering the text Eat pizza tomorrow at 3pm with [email protected] and [email protected], Google Calendar adds a new event with the title Eat pizza with [email protected] and [email protected] at 3pm the next day, like it is supposed to. I want to go a step further by having Google also send out two Calendar invites to the newly created event: one for [email protected] and the other to [email protected].

I appreciate your advice on this topic. I am trying to understand what the best approach is:

Please let me know what you think. I would greatly appreciate your ideas.

Lucy

Upvotes: 1

Views: 1901

Answers (1)

Serge insas
Serge insas

Reputation: 46792

As you probably know, there is not trigger source linked to the creation of an event from the Calendar Ui.

You have indeed 2 possibilities :

  • encode the event using a dedicated Ui (a chrome extension or a standalone webapp) that would take care of sending the invitations but that would probably not meet the initial requirement you described as "expanding the capabilities os the quickAdd features"
  • Find a way to detect an event creation and automatically send invitations from its content.

This last possibility is perfectly doable using a timer trigger that monitors your calendar and detects any new event (by comparing a list stored somewhere to the actual calendar content).

I have made such an app for a different purpose and it works nicely but there are a few difficulties you should be aware of.

When storing the events in scriptProperties (it's probably the best place to go) you have a limited amount of storage size available so you must know how much event you will be able to handle.

Any change in an event like adding a detail or rectifying a typo will re-trigger the invitation process and send the invitation again. Although this can probably be avoided but it would be quite complex.

When the script runs right after an event end, the comparison detects an change because one event is missing (from the script pov) so it could send a mail to cancel the event (if you had chosen to implement that functionality of course but I guess it's a "must have"). It might be a bit tricky to handle that situation... (compare event end time to actual time when the trigger fires the script, could be a matter of milliseconds ;-).

Apart from these difficulties, the general idea is as follow :

  • create a timer trigger to run every hour or so
  • store every event in this calendar in script Properties (or eventually in a spreadsheet) starting from the present date and ending in a few days (not too far ahead because it wouldn't make sense to send invites for an event happening next year)
  • compare the list with the calendar content
  • grab every "new" events and extract email address from the description (using regex for example or string manipulation)
  • send the invitations (that's the easy part)

This workflow works but it might be a bit fragile in the comparison and in the email detection.


EDIT

Since this was an interesting subject (IMHO) and that I thought I could use efficiently (now that I switched to english in my calendar UI ;-D) I wrote a code to achieve it...

I embedded the code in a spreadsheet to simplify the processsing and the storage of the events in the many calendars I own.

This spreadsheet is viewable here and if you make a copy of it you'll be able to run the code.

I setup a timer trigger that runs the autoCheckAllCal function every hour and it seems to work without any issue.

Tell me what you think.

The full code is reproduced below, it gets data from the calendar, checks if the event has guests and if not it checks the title for any valid email address (one or more) and sends the invitations automatically.

I used a regex to extract emails from the title string (this regex was borrowed from an answer on SO since I'm not good enough at this !)

note : setup an onOpen trigger for myOnOpen (because of global var declaration using SS service)

// update the ID below to your copy ID and run the Callist() function to get the calendars ID on first sheet.
//set up an onOpen trigger for the myOnOpen function
var ss = SpreadsheetApp.openById('1xDOaoSl3HbkS95cj8Jl-82rdiui7G0sFz96PIO6iVF4');// this spreadsheet
var calNamesSheet = ss.getSheetByName('calNames');
var calList = calNamesSheet.getDataRange().getValues();

function MyOnOpen() {
  var menuEntries = [ {name: "Lauch autoTest", functionName: "autoCheckAllCals"},
                      {name: "delete created sheets", functionName: "delsheets"}
                     ];
  ss.addMenu("Tracking utilities",menuEntries);//
}

function autoCheckAllCals(){
  var today =  new Date(); // now
  var startDate = new Date(today.setHours(0,0,0,0));// today @ 0 AM
  var endDate = new Date(new Date(startDate).setDate(startDate.getDate()+7)); // adjust time frame to read here = 7 days
  for(var nn=0;nn<calList.length;nn++){
    var logArray = new Array();
    logArray.push(['Calendar + Title','Description','Start','End','Location','Creators','Date Created','Duration','Guests']);
    var calName = calList[nn][0];
    var calId = calList[nn][1];   
    var Calendar = CalendarApp.getCalendarById(calId);
    var events = Calendar.getEvents(startDate , endDate);
    if (events[0]) {
      for (var i = 0; i < events.length; i++) {
        var row = new Array();
        row.push(calName +' : '+events[i].getTitle());
        row.push(events[i].getDescription());      
        row.push(Utilities.formatDate(events[i].getStartTime(), Session.getScriptTimeZone(), "MMM-dd-yy")+' @ ' +Utilities.formatDate(events[i].getStartTime(), Session.getScriptTimeZone(), "HH:mm"));
        row.push(Utilities.formatDate(events[i].getEndTime(), Session.getScriptTimeZone(), "MMM-dd-yy")+' @ ' +Utilities.formatDate(events[i].getEndTime(), Session.getScriptTimeZone(), "HH:mm"));
        row.push(events[i].getLocation());      
        row.push(events[i].getCreators().join());
        row.push('on '+Utilities.formatDate(events[i].getLastUpdated(), Session.getScriptTimeZone(), "MMM-dd-yyyy"));
        row.push(((events[i].getEndTime() - events[i].getStartTime()) / 3600000)+' hours');//duration
        var inviteList = checkInvites(events[i]);
        if (inviteList.length==0){ // if guests were found in checkInvites() then don't read it from event since checkInvites() added them to the cal but this event is not yet updated
          var list = events[i].getGuestList();
          for(n=0;n<list.length;++n){inviteList.push(list[n].getEmail())};
        }else{
          for(var n in inviteList){
            events[i].addGuest(inviteList[n]);
          }
        }
        row.push(inviteList.join(', '));
        logArray.push(row);
      }
    }    
//    Logger.log(logArray);
    if(logArray.length==0){continue};
    try{
      var sheetToWrite = ss.insertSheet(calName,ss.getNumSheets());// create sheet if doesn't exist
    }catch(err){
      var sheetToWrite = ss.getSheetByName(calName);// else open it
      }
    sheetToWrite.getRange(1,1,logArray.length,logArray[0].length).setValues(logArray).setHorizontalAlignment('left'); // enhance formating
    sheetToWrite.getRange(1,1,1,logArray[0].length).setBackground('#EEA').setBorder(true,true,true,true,true,true).setHorizontalAlignment('left').setFontSize(12);
    for(var w in logArray[0]){
      sheetToWrite.setColumnWidth(Number(w)+1,180);
    }
  }
}

function checkInvites(event){
  var email = []
  var title = event.getTitle();
  if(title.indexOf('@')==-1){return email};
  email = title.match(/([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/g);
  Logger.log('email var = '+email);
  return email;
}

function delsheets(){
  var numbofsheet = ss.getNumSheets();// check how many sheets in the spreadsheet
  for (var pa=numbofsheet-1;pa>0;pa--){ 
    ss.setActiveSheet(ss.getSheets()[pa]);
    if(ss.getSheets()[pa].getSheetName()!='calNames'){
      ss.deleteActiveSheet(); // delete sheets begining with the last one
      Utilities.sleep(400);
    }
  }
  SpreadsheetApp.flush();
}

// This small function is to get the list of calendar names & Ids that you have access to, please edit the calNames sheet to keep only the ones you want to monitor (without empty rows).
function Callist(){
  calNamesSheet.getDataRange().clearContent();                      
  var list = new Array();
  var store = new Array();
  list = CalendarApp.getAllCalendars()
  for (n=0;n<list.length;++n){
    var name = list[n].getName() ;                     
    var id = list[n].getId() ;                     
    store.push( [name,id])
  }        
  calNamesSheet.getRange(1,1,store.length,store[0].length).setValues(store);  
}

// Serge insas - 08-2014

Upvotes: 1

Related Questions