Synchroniser les modifications apportées à la conférence Agenda

Les utilisateurs peuvent modifier ou supprimer leurs événements Google Agenda. Si un utilisateur modifie un événement après avoir créé une visioconférence pour celui-ci, votre module complémentaire Google Workspace devra peut-être répondre à la modification en mettant à jour les données de la visioconférence. Si votre système de visioconférence tiers dépend du suivi des données d'événement, le fait de ne pas mettre à jour la visioconférence en cas de modification d'un événement peut la rendre inutilisable.

Le processus qui consiste à mettre à jour les données de la conférence en fonction des modifications apportées à l'événement Agenda s'appelle la synchronisation. Synchronisez les modifications apportées aux événements en créant un déclencheur installable Google Apps Script qui se déclenche chaque fois que des événements sont modifiés dans un agenda donné. Le déclencheur n'indique pas les événements qui ont été modifiés et vous ne pouvez pas le limiter aux événements avec des conférences que vous avez créées. Demandez la liste de toutes les modifications apportées à un agenda depuis la dernière synchronisation, filtrez la liste des événements et apportez les modifications nécessaires.

Voici la procédure générale de synchronisation :

  1. La première fois qu'un utilisateur crée une conférence, le processus de synchronisation est initialisé.
  2. Chaque fois que l'utilisateur crée, modifie ou supprime l'un de ses événements d'agenda, le déclencheur exécute une fonction de déclencheur dans le projet de votre module complémentaire.
  3. La fonction de déclencheur examine l'ensemble des modifications d'événements depuis la dernière synchronisation et détermine si l'une d'elles nécessite la mise à jour d'une conférence tierce associée.
  4. Les mises à jour requises sont apportées aux conférences en effectuant des requêtes d'API tierces.
  5. Un nouveau jeton de synchronisation est stocké afin que la prochaine exécution du déclencheur n'examine que les modifications les plus récentes apportées à l'agenda.

Initialiser la synchronisation

Le processus d'initialisation garantit que votre module complémentaire est prêt à répondre aux modifications apportées à l'agenda. Une fois que le module complémentaire a créé une conférence sur un système tiers, il doit créer un déclencheur installable qui répond aux modifications d'événements dans cet agenda, si le déclencheur n'existe pas déjà.

Une fois le déclencheur créé, l'initialisation devrait se terminer en créant le jeton de synchronisation initial. Pour ce faire, exécutez directement la fonction de déclencheur.

Créer un déclencheur d'agenda

Pour la synchronisation, votre module complémentaire doit détecter lorsqu'un événement Agenda auquel une conférence est associée est modifié. Pour ce faire, vous devez créer un déclencheur installable EventUpdated. Votre module complémentaire n'a besoin que d'un déclencheur pour chaque agenda et peut les créer de manière programmatique.

Il est recommandé de créer un déclencheur lorsque l'utilisateur crée sa première conférence, car c'est à ce moment-là qu'il commence à utiliser le module complémentaire. Après avoir créé une conférence et vérifié qu'il n'y a pas d'erreur, votre module complémentaire doit vérifier si le déclencheur existe pour cet utilisateur et, si ce n'est pas le cas, le créer.

Pour créer des déclencheurs, le module complémentaire doit disposer des scopes https://www.googleapis.com/auth/calendar.readonly et https://www.googleapis.com/auth/script.scriptapp.

Implémenter une fonction de déclencheur de synchronisation

Les fonctions de déclencheur sont exécutées lorsqu'Apps Script détecte une condition qui déclenche un déclencheur. Les déclencheurs Agenda EventUpdated se déclenchent lorsqu'un utilisateur crée, modifie ou supprime un événement dans un agenda spécifié.

Implémentez la fonction de déclencheur utilisée par votre module complémentaire. Cette fonction de déclencheur doit effectuer les opérations suivantes :

  1. Effectuez un appel de service avancé Calendar.Events.list de l'agenda à l'aide d'un syncToken pour récupérer la liste des événements qui ont été modifiés depuis la dernière synchronisation. En utilisant un jeton de synchronisation, vous réduisez le nombre d'événements que votre module complémentaire doit examiner.

    Lorsque la fonction de déclencheur s'exécute sans jeton de synchronisation valide, elle revient à une synchronisation complète. Les synchronisations complètes tentent de récupérer tous les événements dans une période prédéfinie afin de générer un nouveau jeton de synchronisation valide.

  2. Chaque événement modifié est examiné pour déterminer s'il est associé à une conférence tierce.

  3. Si un événement comporte une conférence, les modifications apportées sont examinées. Selon la modification, il peut être nécessaire de modifier la conférence associée. Par exemple, si un événement a été supprimé, le module complémentaire doit supprimer la conférence.

  4. Toute modification nécessaire de la conférence est effectuée en appelant l'API du système tiers.

  5. Après avoir apporté toutes les modifications nécessaires, stockez le nextSyncToken renvoyé par la méthode Calendar.Events.list. Ce jeton de synchronisation se trouve sur la dernière page de résultats renvoyée par l'appel Calendar.Events.list.

Modifier l'événement d'agenda

Dans certains cas, vous pouvez mettre à jour l'événement d'agenda lors de la synchronisation. Si vous choisissez cette option, mettez à jour l'événement avec la requête Service avancé Agenda appropriée. Veillez à utiliser la mise à jour conditionnelle avec un en-tête If-Match. Cela empêche vos modifications d'écraser celles apportées simultanément par l'utilisateur dans un autre client.

Exemple

L'exemple suivant montre comment configurer la synchronisation des événements d'agenda et de leurs visioconférences associées.

/**
 *  Initializes syncing of conference data by creating a sync trigger and
 *  sync token if either does not exist yet.
 *
 *  @param {String} calendarId The ID of the Google Calendar.
 */
function initializeSyncing(calendarId) {
  // Create a syncing trigger if it doesn't exist yet.
  createSyncTrigger(calendarId);

  // Perform an event sync to create the initial sync token.
  syncEvents({'calendarId': calendarId});
}

/**
 *  Creates a sync trigger if it does not exist yet.
 *
 *  @param {String} calendarId The ID of the Google Calendar.
 */
function createSyncTrigger(calendarId) {
  // Check to see if the trigger already exists; if does, return.
  var allTriggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < allTriggers.length; i++) {
    var trigger = allTriggers[i];
    if (trigger.getTriggerSourceId() == calendarId) {
      return;
    }
  }

  // Trigger does not exist, so create it. The trigger calls the
  // 'syncEvents()' trigger function when it fires.
  var trigger = ScriptApp.newTrigger('syncEvents')
      .forUserCalendar(calendarId)
      .onEventUpdated()
      .create();
}

/**
 *  Sync events for the given calendar; this is the syncing trigger
 *  function. If a sync token already exists, this retrieves all events
 *  that have been modified since the last sync, then checks each to see
 *  if an associated conference needs to be updated and makes any required
 *  changes. If the sync token does not exist or is invalid, this
 *  retrieves future events modified in the last 24 hours instead. In
 *  either case, a new sync token is created and stored.
 *
 *  @param {Object} e If called by a event updated trigger, this object
 *      contains the Google Calendar ID, authorization mode, and
 *      calling trigger ID. Only the calendar ID is actually used here,
 *      however.
 */
function syncEvents(e) {
  var calendarId = e.calendarId;
  var properties = PropertiesService.getUserProperties();
  var syncToken = properties.getProperty('syncToken');

  var options;
  if (syncToken) {
    // There's an existing sync token, so configure the following event
    // retrieval request to only get events that have been modified
    // since the last sync.
    options = {
      syncToken: syncToken
    };
  } else {
    // No sync token, so configure to do a 'full' sync instead. In this
    // example only recently updated events are retrieved in a full sync.
    // A larger time window can be examined during a full sync, but this
    // slows down the script execution. Consider the trade-offs while
    // designing your add-on.
    var now = new Date();
    var yesterday = new Date();
    yesterday.setDate(now.getDate() - 1);
    options = {
      timeMin: now.toISOString(),          // Events that start after now...
      updatedMin: yesterday.toISOString(), // ...and were modified recently
      maxResults: 50,   // Max. number of results per page of responses
      orderBy: 'updated'
    }
  }

  // Examine the list of updated events since last sync (or all events
  // modified after yesterday if the sync token is missing or invalid), and
  // update any associated conferences as required.
  var events;
  var pageToken;
  do {
    try {
      options.pageToken = pageToken;
      events = Calendar.Events.list(calendarId, options);
    } catch (err) {
      // Check to see if the sync token was invalidated by the server;
      // if so, perform a full sync instead.
      if (err.message ===
            "Sync token is no longer valid, a full sync is required.") {
        properties.deleteProperty('syncToken');
        syncEvents(e);
        return;
      } else {
        throw new Error(err.message);
      }
    }

    // Read through the list of returned events looking for conferences
    // to update.
    if (events.items && events.items.length > 0) {
      for (var i = 0; i < events.items.length; i++) {
         var calEvent = events.items[i];
         // Check to see if there is a record of this event has a
         // conference that needs updating.
         if (eventHasConference(calEvent)) {
           updateConference(calEvent, calEvent.conferenceData.conferenceId);
         }
      }
    }

    pageToken = events.nextPageToken;
  } while (pageToken);

  // Record the new sync token.
  if (events.nextSyncToken) {
    properties.setProperty('syncToken', events.nextSyncToken);
  }
}

/**
 *  Returns true if the specified event has an associated conference
 *  of the type managed by this add-on; retuns false otherwise.
 *
 *  @param {Object} calEvent The Google Calendar event object, as defined by
 *      the Calendar API.
 *  @return {boolean}
 */
function eventHasConference(calEvent) {
  var name = calEvent.conferenceData.conferenceSolution.name || null;

  // This version checks if the conference data solution name matches the
  // one of the solution names used by the add-on. Alternatively you could
  // check the solution's entry point URIs or other solution-specific
  // information.
  if (name) {
    if (name === "My Web Conference" ||
        name === "My Recorded Web Conference") {
      return true;
    }
  }
  return false;
}

/**
 *  Update a conference based on new Google Calendar event information.
 *  The exact implementation of this function is highly dependant on the
 *  details of the third-party conferencing system, so only a rough outline
 *  is shown here.
 *
 *  @param {Object} calEvent The Google Calendar event object, as defined by
 *      the Calendar API.
 *  @param {String} conferenceId The ID used to identify the conference on
 *      the third-party conferencing system.
 */
function updateConference(calEvent, conferenceId) {
  // Check edge case: the event was cancelled
  if (calEvent.status === 'cancelled' || eventHasConference(calEvent)) {
    // Use the third-party API to delete the conference too.


  } else {
    // Extract any necessary information from the event object, then
    // make the appropriate third-party API requests to update the
    // conference with that information.

  }
}