0

I'm trying to trigger a function calendarScan() when changes are made to my Google Calendar events using the code below.

ScriptApp.newTrigger('calendarScan')
  .forUserCalendar(Session.getActiveUser().getEmail())
  .onEventUpdated()
  .create();

I can't figure out why the trigger isn't working. The script is standalone. The calendarScan() functions runs fine manually.

Your help is sincerely appreciated.

tehhowch
  • 9,645
  • 4
  • 24
  • 42
Brandon Pillay
  • 986
  • 1
  • 12
  • 28
  • sorry i made mistake earlier, it isn't working. the trigger shows up under 'current project's triggers' but simply doesn't run. – Brandon Pillay Oct 03 '18 at 20:15
  • The sheet the function is linked to has a bound script. Could that affect it? – Brandon Pillay Oct 03 '18 at 20:19
  • 1
    What does `Session.getActiveUser().getEmail()` display? – tehhowch Oct 03 '18 at 20:19
  • brandon007pillay@gmail.com my email address that's linked to the calendar that I edit. – Brandon Pillay Oct 03 '18 at 20:25
  • 1
    I can't reproduce. When I create a calendar trigger for a function, that function is run when i add/edit/delete an event in my calendar. What do you mean by **"The script is standalone"** and **"the sheet the function is linked to"** - is `calendarScan` not in the same Script Project as the function that creates the given trigger? – tehhowch Oct 03 '18 at 20:28
  • I'm using Google Sheets in the function, the Google sheet has an App Script bound to the Google Sheet. I have functions there that work fine. The function and trigger is in a different project referencing the same sheet. Does that make sense? Also, I just noticed the curly brackets for the function are red but the script runs fine. – Brandon Pillay Oct 03 '18 at 20:39
  • This what I'm referring to : https://stackoverflow.com/questions/13711260/why-does-google-script-editor-stop-paren-matching-after-100-lines-in-a-function – Brandon Pillay Oct 03 '18 at 20:48
  • 1
    **"The function and trigger is in a different project"** You can't create a trigger for a function that is not in the same Script Project as the function creating the trigger. To create a calendar event trigger for the function `calendarScan`, `function calendarScan() {...}` must be in the same project as the code that uses `ScriptApp.createTrigger("calendarScan")` – tehhowch Oct 03 '18 at 20:53
  • 1
    That isn't the issue, I found the problem. The trigger can only run if changes are made to the PRIMARY calendar. Do you know how I can extend the trigger to allow a trigger if changes are made to the secondary calendars? – Brandon Pillay Oct 03 '18 at 21:02
  • 1
    I imagine you would need to create the trigger for the appropriate calendar ID, rather than the primary calendar associated with the user's email. – tehhowch Oct 03 '18 at 21:08

1 Answers1

3

To create a Calendar Event trigger for all calendars a user owns, the Calendar API can be used (once enabled):

function getOwnedCalendars_() {
  const options = {
    minAccessLevel: "owner", // freeBusyReader, reader, writer
    fields: "nextPageToken, items(id,summary,description)"
  };

  const cals = [];
  do {
    var search = Calendar.CalendarList.list(options);
    options.pageToken = search.nextPageToken;
    if (search.items && search.items.length)
      Array.prototype.push.apply(cals, search.items);
  } while (options.pageToken);
  return cals;
}
function giveMeTheTrigger(e) {
  console.log(e);
}
function makeTriggers() {
  getOwnedCalendars_().forEach(function (cal) {
    var t = ScriptApp.newTrigger("giveMeTheTrigger")
         .forUserCalendar(cal.id)
         .onEventUpdated()
         .create();
    console.log({message: "Created event trigger for calendar '" + cal.summary + "'",
                 desc: cal.description, id: cal.id, triggerId: t.getUniqueId()});
  });
}

Given that you're expected to be using the Calendar API to effectively use this Event Updated trigger, this shouldn't be too much extra overhead.

tehhowch
  • 9,645
  • 4
  • 24
  • 42
  • Thank you tehhowch. I've only ever used the Calendar Service in Google App Script so I only know the classes for the GAS Calendar service. Do you know where I can find references and documentation that entail 'minAccessLevel' and 'pageToken'? – Brandon Pillay Oct 04 '18 at 19:11
  • 1
    @Brandon I linked the API reference documentation of the method, `CalendarList::list`. It explains what each of these (optional) input parameters mean. You can always also review the relevant "______ Resource" page within the API reference - generally you will find a description of whatever resource's properties exist. The names are generally not meant to be obscure, either - `minAccessLevel` -> minimum access level (of the requesting user) -> owner -> "show only calendars the requesting user is an owner of." I'll let you intuit what `pageToken` and `nextPageToken` do, given my code above. – tehhowch Oct 04 '18 at 20:11
  • It should be `ScriptApp.newTrigger(functionName)` – Suhail Ansari Nov 10 '18 at 15:43
  • Thanks @tehhowch, this is really useful! The Google documentation is somewhat skimpy: are such triggers "persistent", or do you need to reset them each time they trigger? – Jean-Rene Bouvier Sep 09 '20 at 10:42
  • @jean these triggers should continue to fire after triggering. You can verify this with the code in my example: authorize it, run the `makeTriggers` method, and then update an event in an owned calendar a few times. You should see logs of the triggered events in stackdriver. Note that any new calendars you become the owner of will not have a trigger registered automatically, so you should delete existing triggers before running the function action, to avoid duplicating triggers. – tehhowch Sep 10 '20 at 12:37