กำลังซิงค์การเปลี่ยนแปลงการประชุมในปฏิทิน

ผู้ใช้สามารถอัปเดตหรือลบกิจกรรมใน Google ปฏิทินได้อย่างอิสระ หากผู้ใช้อัปเดตกิจกรรมหลังจากสร้างการประชุมสําหรับกิจกรรมนั้นไว้แล้ว ส่วนเสริมของคุณอาจต้องตอบสนองต่อการเปลี่ยนแปลงดังกล่าวด้วยการอัปเดตข้อมูลการประชุม หากระบบการประชุมของบุคคลที่สามต้องอาศัยการติดตามข้อมูลกิจกรรม การไม่อัปเดตการประชุมเมื่อมีการเปลี่ยนแปลงกิจกรรมอาจทำให้การประชุมใช้งานไม่ได้และส่งผลให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ไม่ดี

กระบวนการอัปเดตข้อมูลการประชุมตามการเปลี่ยนแปลงของกิจกรรมใน Google ปฏิทินเรียกว่าการซิงค์ คุณสามารถซิงค์การเปลี่ยนแปลงของกิจกรรมได้โดยการสร้าง Apps Scriptทริกเกอร์ที่ติดตั้งได้ซึ่งจะทำงานทุกครั้งที่มีการเปลี่ยนแปลงกิจกรรมในปฏิทินหนึ่งๆ ขออภัย เงื่อนไขเริ่มต้นจะไม่รายงานเหตุการณ์ที่มีการเปลี่ยนแปลง และคุณไม่สามารถจํากัดให้แสดงเฉพาะเหตุการณ์ที่มีการประชุมที่คุณสร้างขึ้น แต่คุณต้องขอรายการการเปลี่ยนแปลงทั้งหมดที่ทำกับปฏิทินนับตั้งแต่การซิงค์ครั้งล่าสุด กรองรายการกิจกรรม แล้วทำการอัปเดตตามความเหมาะสม

ขั้นตอนการซิงค์ทั่วไปมีดังนี้

  1. กระบวนการซิงค์จะเริ่มต้นขึ้นเมื่อผู้ใช้สร้างการประชุมเป็นครั้งแรก
  2. เมื่อใดก็ตามที่ผู้ใช้สร้าง อัปเดต หรือลบกิจกรรมในปฏิทิน เงื่อนไขเริ่มต้นจะเรียกใช้ฟังก์ชันทริกเกอร์ในโปรเจ็กต์ส่วนเสริม
  3. ฟังก์ชันทริกเกอร์จะตรวจสอบชุดการเปลี่ยนแปลงเหตุการณ์นับตั้งแต่การซิงค์ครั้งล่าสุด และพิจารณาว่าจำเป็นต้องอัปเดตการประชุมของบุคคลที่สามที่เกี่ยวข้องหรือไม่
  4. การอัปเดตที่จำเป็นสำหรับการประชุมจะดำเนินการโดยส่งคำขอ API ของบุคคลที่สาม
  5. ระบบจะจัดเก็บโทเค็นการซิงค์ใหม่เพื่อให้การเรียกใช้ทริกเกอร์ครั้งถัดไปต้องตรวจสอบการเปลี่ยนแปลงล่าสุดในปฏิทินเท่านั้น

เริ่มต้นการซิงค์

เมื่อส่วนเสริมสร้างการประชุมในระบบของบุคคลที่สามเรียบร้อยแล้ว ควรสร้างทริกเกอร์ที่ติดตั้งได้ซึ่งตอบสนองต่อการเปลี่ยนแปลงกิจกรรมในปฏิทินนี้ หากยังไม่มีทริกเกอร์ดังกล่าว

หลังจากสร้างทริกเกอร์แล้ว การสร้างข้อมูลควรเสร็จสมบูรณ์ด้วยการสร้างโทเค็นการซิงค์เริ่มต้น ซึ่งทำได้โดยเรียกใช้ฟังก์ชันทริกเกอร์โดยตรง

สร้างทริกเกอร์ปฏิทิน

หากต้องการซิงค์ ส่วนเสริมจะต้องตรวจหาเมื่อมีการเปลี่ยนแปลงกิจกรรมในปฏิทินที่มีการประชุมแนบอยู่ ซึ่งทำได้ด้วยการสร้างEventUpdated ทริกเกอร์ที่ติดตั้งได้ ส่วนเสริมของคุณต้องใช้ทริกเกอร์เพียงรายการเดียวสําหรับปฏิทินแต่ละรายการ และสามารถสร้างทริกเกอร์แบบเป็นโปรแกรมได้

เวลาที่เหมาะในการสร้างทริกเกอร์คือเมื่อผู้ใช้สร้างการประชุมครั้งแรก เนื่องจากเป็นช่วงที่ผู้ใช้เริ่มใช้ส่วนเสริม หลังจากสร้างการประชุมและยืนยันว่าไม่พบข้อผิดพลาดแล้ว ส่วนเสริมควรตรวจสอบว่ามีทริกเกอร์สำหรับผู้ใช้รายนี้หรือไม่ หากไม่มี ให้สร้าง

ใช้ฟังก์ชันทริกเกอร์การซิงค์

ระบบจะเรียกใช้ฟังก์ชันทริกเกอร์เมื่อ Apps Script ตรวจพบเงื่อนไขที่ทริกเกอร์ให้ทำงาน EventUpdated ทริกเกอร์ปฏิทินจะทํางานเมื่อผู้ใช้สร้าง แก้ไข หรือลบกิจกรรมในปฏิทินที่ระบุ

คุณต้องติดตั้งใช้งานฟังก์ชันทริกเกอร์ที่ส่วนเสริมใช้ ฟังก์ชันทริกเกอร์นี้ควรทําสิ่งต่อไปนี้

  1. โทรหาบริการขั้นสูงของปฏิทิน Calendar.Events.list() โดยใช้ syncToken เพื่อเรียกข้อมูลรายการกิจกรรมที่มีการเปลี่ยนแปลงนับตั้งแต่การซิงค์ครั้งล่าสุด การใช้โทเค็นการซิงค์จะช่วยลดจํานวนเหตุการณ์ที่ส่วนเสริมต้องตรวจสอบ

    เมื่อฟังก์ชันทริกเกอร์ทำงานโดยไม่มีโทเค็นการซิงค์ที่ถูกต้อง ระบบจะกลับไปใช้การซิงค์แบบเต็ม การซิงค์แบบเต็มจะพยายามดึงข้อมูลเหตุการณ์ทั้งหมดภายในกรอบเวลาที่กำหนดเพื่อสร้างโทเค็นการซิงค์ใหม่ที่ถูกต้อง

  2. ระบบจะตรวจสอบเหตุการณ์ที่แก้ไขแต่ละรายการเพื่อดูว่ามีการประชุมของบุคคลที่สามที่เกี่ยวข้องหรือไม่
  3. หากกิจกรรมมีการประชุม ระบบจะตรวจสอบเพื่อดูว่ามีอะไรเปลี่ยนแปลงไปบ้าง คุณอาจต้องแก้ไขการประชุมที่เกี่ยวข้อง ทั้งนี้ขึ้นอยู่กับการเปลี่ยนแปลง เช่น หากมีการลบกิจกรรม ส่วนเสริมก็น่าจะลบการประชุมด้วย
  4. การเปลี่ยนแปลงที่จำเป็นในการประชุมจะทำโดยการเรียก API ไปยังระบบของบุคคลที่สาม
  5. หลังจากทําการเปลี่ยนแปลงที่จําเป็นทั้งหมดแล้ว ให้จัดเก็บ nextSyncToken ที่แสดงผลโดยเมธอด Calendar.Events.list() โทเค็นการซิงค์นี้จะอยู่ในหน้าสุดท้ายของผลลัพธ์ที่การเรียกใช้ Calendar.Events.list() แสดง

การอัปเดตกิจกรรมใน Google ปฏิทิน

ในบางกรณี คุณอาจต้องการอัปเดตกิจกรรมใน Google ปฏิทินเมื่อทำการซิงค์ หากเลือกดำเนินการนี้ ให้อัปเดตกิจกรรมด้วยคําขอบริการขั้นสูงของ Google ปฏิทินที่เหมาะสม อย่าลืมใช้การอัปเดตแบบมีเงื่อนไขกับส่วนหัว If-Match ซึ่งจะช่วยป้องกันไม่ให้การเปลี่ยนแปลงของคุณเขียนทับการเปลี่ยนแปลงที่ผู้ใช้ทำในไคลเอ็นต์อื่นพร้อมกันโดยไม่ตั้งใจ

ตัวอย่าง

ตัวอย่างต่อไปนี้แสดงวิธีตั้งค่าการซิงค์สำหรับกิจกรรมในปฏิทินและการสัมมนาทางเว็บที่เกี่ยวข้อง

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

  }
}