Sincronizando los cambios de la conferencia del calendario

Los usuarios pueden actualizar o borrar libremente los eventos del Calendario de Google. Si un usuario actualiza un evento después de crear una conferencia para él, es posible que el complemento responder al cambio actualizando los datos de la conferencia. Si el sistema de conferencias de terceros depende del seguimiento de los datos del evento, si no se actualiza la conferencia sobre un cambio en un evento, esta puede inutilizables y dar como resultado una mala experiencia del usuario.

El proceso de mantener actualizados los datos de la conferencia con los cambios en el El evento del Calendario de Google se llama sincronización. Puedes sincronizar los cambios en los eventos de las siguientes maneras: crear una secuencia de comandos de Apps Script activador instalable que se activa cada vez que cambian los eventos de un calendario determinado. Por desgracia, el activador no informar qué eventos cambiaron y no puedes limitarlo a solo eventos con conferencias que creaste. En su lugar, debes solicitar una lista de todos los cambios realizados en un calendario desde la última sincronización, filtra las en una lista de eventos y realizar las actualizaciones correspondientes.

El procedimiento de sincronización general es el siguiente:

  1. La primera vez que un usuario crea una conferencia, se inicializa el proceso de sincronización.
  2. Cuando el usuario crea, actualiza o borra uno de sus eventos de Calendario el activador ejecuta una función de activador en tu proyecto de complemento.
  3. La función del activador examina el conjunto de cambios del evento desde la última sincronizada y determina si se requiere la actualización de un tercero de Google Cloud.
  4. Todas las actualizaciones necesarias en las conferencias se hacen mediante la implementación Solicitudes a la API.
  5. Se almacena un nuevo token de sincronización para que la próxima ejecución del activador solo deba examinar los cambios más recientes en el calendario.

Inicializa la sincronización

Después de que el complemento haya creado correctamente una conferencia en un sistema de terceros, se debería crear un activador instalable que responda a cambios de eventos en este calendario, si el activador aún no existe.

Después de crear el activador, la inicialización debería terminar con la token de sincronización. Para ello, ejecuta directamente la función de activación.

Crea un activador de Calendario

Para sincronizar, tu complemento debe detectar si un evento de Calendario tiene un evento adjunto conferencia cambiante. Esto se logra creando un EventUpdated. activador instalable. Tu complemento solo necesita un activador para cada calendario y puede crearlos de manera programática.

Un buen momento para crear un activador es cuando el usuario crea su primera conferencia, ya que en ese momento el usuario comenzará a usar el complemento. Después del crear una conferencia y verificando que no haya errores, tu complemento debería comprobar si el ya existe para este usuario y, si no, crearlo.

Implementa una función de activador de sincronización

Las funciones de activación se ejecutan cuando Apps Script detecta una condición que causa que se active un activador. EventUpdated de activadores de Calendario se activa cuando un usuario crea, modifica o elimina cualquier evento en un evento calendario.

Debes implementar la función de activador que usa tu complemento. Esta función activadora debe hacer lo siguiente:

  1. Realizar una llamada a Calendar.Events.list() de servicio avanzado de Calendario con un syncToken para recuperar una lista de los eventos que cambiaron desde la última sincronizar. Al usar un token de sincronización, reduces la cantidad de eventos que que se debe examinar.

    Cuando la función de activación se ejecuta sin un token de sincronización válido, respalda una sincronización completa. Las sincronizaciones completas simplemente intentan recuperar todos los eventos dentro de un período prescrito para generar una sincronización nueva y válida token.

  2. Cada evento modificado se examina para determinar si tiene un de terceros.
  3. Si un evento tiene una conferencia, se examina para ver qué se modificó. Según el cambio, la modificación de la conferencia asociada puede ser necesarias. Por ejemplo, si se borró un evento, el complemento debería es probable que también elimines la conferencia.
  4. Cualquier cambio necesario en la conferencia se realiza a través de llamadas a la API a la de terceros.
  5. Después de realizar todos los cambios necesarios, almacena el nextSyncToken que muestra el método Calendar.Events.list() Este token de sincronización se encuentra en el último página de resultados que muestra la llamada a Calendar.Events.list()

Actualización del evento del Calendario de Google

En algunos casos, es posible que desees actualizar el evento del Calendario de Google al realizar una sincronización. Si decides hacerlo, actualiza el evento con las Servicio avanzado de Calendario de Google para cada solicitud. Asegúrate de usar actualización condicional con un encabezado If-Match. Esto evita que los cambios se hagan sobrescribir los cambios simultáneos que el usuario realizó en un cliente diferente

Ejemplo

En el siguiente ejemplo, se muestra cómo configurar la sincronización de los eventos del calendario y sus conferencias asociadas.

/**
 *  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.

  }
}