سرویس تقویم پیشرفته

سرویس پیشرفته تقویم به شما امکان می‌دهد از API عمومی تقویم گوگل در Apps Script استفاده کنید. این API بسیار شبیه به سرویس تقویم داخلی Apps Script است و به اسکریپت‌ها اجازه می‌دهد تا به تقویم گوگل کاربر، از جمله تقویم‌های اضافی که کاربر در آنها مشترک شده است، دسترسی داشته باشند و آنها را تغییر دهند. در بیشتر موارد، استفاده از سرویس داخلی آسان‌تر است، اما این سرویس پیشرفته چند ویژگی اضافی از جمله تنظیم رنگ پس‌زمینه برای رویدادهای فردی را ارائه می‌دهد.

مرجع

برای اطلاعات دقیق در مورد این سرویس، به مستندات مرجع برای API عمومی تقویم گوگل مراجعه کنید. مانند تمام سرویس‌های پیشرفته در Apps Script، سرویس پیشرفته تقویم از همان اشیاء، متدها و پارامترهای API عمومی استفاده می‌کند. برای اطلاعات بیشتر، به بخش «نحوه تعیین امضاهای متد» مراجعه کنید.

برای گزارش مشکلات و یافتن پشتیبانی‌های دیگر، به راهنمای پشتیبانی تقویم مراجعه کنید.

هدرهای درخواست HTTP

سرویس تقویم پیشرفته می‌تواند هدرهای درخواست HTTP شامل If-Match و If-None-Match را بپذیرد. برای جزئیات بیشتر، به مستندات مرجع مراجعه کنید.

کد نمونه

کد نمونه زیر از نسخه ۳ این API استفاده می‌کند.

ایجاد رویدادها

مثال زیر نحوه ایجاد یک رویداد در تقویم پیش‌فرض کاربر را نشان می‌دهد.

پیشرفته/تقویم.gs
/**
 * Creates an event in the user's default calendar.
 * @see https://developers.google.com/calendar/api/v3/reference/events/insert
 */
function createEvent() {
  const calendarId = 'primary';
  const start = getRelativeDate(1, 12);
  const end = getRelativeDate(1, 13);
  // event details for creating event.
  let event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString()
    },
    end: {
      dateTime: end.toISOString()
    },
    attendees: [
      {email: 'gduser1@workspacesample.dev'},
      {email: 'gduser2@workspacesample.dev'}
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11
  };
  try {
    // call method to insert/create new event in provided calandar
    event = Calendar.Events.insert(event, calendarId);
    console.log('Event ID: ' + event.id);
  } catch (err) {
    console.log('Failed with error %s', err.message);
  }
}

/**
 * Helper function to get a new Date object relative to the current date.
 * @param {number} daysOffset The number of days in the future for the new date.
 * @param {number} hour The hour of the day for the new date, in the time zone
 *     of the script.
 * @return {Date} The new date.
 */
function getRelativeDate(daysOffset, hour) {
  const date = new Date();
  date.setDate(date.getDate() + daysOffset);
  date.setHours(hour);
  date.setMinutes(0);
  date.setSeconds(0);
  date.setMilliseconds(0);
  return date;
}

تقویم‌های فهرست‌بندی

مثال زیر نحوه بازیابی جزئیات مربوط به تقویم‌های نمایش داده شده در لیست تقویم‌های کاربر را نشان می‌دهد.

پیشرفته/تقویم.gs
/**
 * Lists the calendars shown in the user's calendar list.
 * @see https://developers.google.com/calendar/api/v3/reference/calendarList/list
 */
function listCalendars() {
  let calendars;
  let pageToken;
  do {
    calendars = Calendar.CalendarList.list({
      maxResults: 100,
      pageToken: pageToken

    });
    if (!calendars.items || calendars.items.length === 0) {
      console.log('No calendars found.');
      return;
    }
    // Print the calendar id and calendar summary
    for (const calendar of calendars.items) {
      console.log('%s (ID: %s)', calendar.summary, calendar.id);
    }
    pageToken = calendars.nextPageToken;
  } while (pageToken);
}

رویدادهای فهرست‌شده

مثال زیر نحوه فهرست کردن 10 رویداد آینده در تقویم پیش‌فرض کاربر را نشان می‌دهد.

پیشرفته/تقویم.gs
/**
 * Lists the next 10 upcoming events in the user's default calendar.
 * @see https://developers.google.com/calendar/api/v3/reference/events/list
 */
function listNext10Events() {
  const calendarId = 'primary';
  const now = new Date();
  const events = Calendar.Events.list(calendarId, {
    timeMin: now.toISOString(),
    singleEvents: true,
    orderBy: 'startTime',
    maxResults: 10
  });
  if (!events.items || events.items.length === 0) {
    console.log('No events found.');
    return;
  }
  for (const event of events.items) {
    if (event.start.date) {
      // All-day event.
      const start = new Date(event.start.date);
      console.log('%s (%s)', event.summary, start.toLocaleDateString());
      continue;
    }
    const start = new Date(event.start.dateTime);
    console.log('%s (%s)', event.summary, start.toLocaleString());
  }
}

اصلاح مشروط یک رویداد

مثال زیر نحوه به‌روزرسانی مشروط یک رویداد تقویم را با استفاده از هدر If-Match نشان می‌دهد. اسکریپت یک رویداد جدید ایجاد می‌کند، 30 ثانیه صبر می‌کند، سپس رویداد را تنها در صورتی به‌روزرسانی می‌کند که هیچ جزئیات رویدادی از زمان ایجاد رویداد تغییر نکرده باشد.

پیشرفته/تقویم.gs
/**
 * Creates an event in the user's default calendar, waits 30 seconds, then
 * attempts to update the event's location, on the condition that the event
 * has not been changed since it was created.  If the event is changed during
 * the 30-second wait, then the subsequent update will throw a 'Precondition
 * Failed' error.
 *
 * The conditional update is accomplished by setting the 'If-Match' header
 * to the etag of the new event when it was created.
 */
function conditionalUpdate() {
  const calendarId = 'primary';
  const start = getRelativeDate(1, 12);
  const end = getRelativeDate(1, 13);
  let event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString()
    },
    end: {
      dateTime: end.toISOString()
    },
    attendees: [
      {email: 'gduser1@workspacesample.dev'},
      {email: 'gduser2@workspacesample.dev'}
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11
  };
  event = Calendar.Events.insert(event, calendarId);
  console.log('Event ID: ' + event.getId());
  // Wait 30 seconds to see if the event has been updated outside this script.
  Utilities.sleep(30 * 1000);
  // Try to update the event, on the condition that the event state has not
  // changed since the event was created.
  event.location = 'The Coffee Shop';
  try {
    event = Calendar.Events.update(
        event,
        calendarId,
        event.id,
        {},
        {'If-Match': event.etag}
    );
    console.log('Successfully updated event: ' + event.id);
  } catch (e) {
    console.log('Fetch threw an exception: ' + e);
  }
}

بازیابی مشروط یک رویداد

مثال زیر نحوه‌ی واکشی مشروط یک رویداد تقویم را با استفاده از هدر If-None-Match نشان می‌دهد. اسکریپت یک رویداد جدید ایجاد می‌کند، سپس به مدت 30 ثانیه تغییرات رویداد را بررسی می‌کند. هر زمان که رویداد تغییر کند، نسخه‌ی جدید واکشی می‌شود.

پیشرفته/تقویم.gs
/**
 * Creates an event in the user's default calendar, then re-fetches the event
 * every second, on the condition that the event has changed since the last
 * fetch.
 *
 * The conditional fetch is accomplished by setting the 'If-None-Match' header
 * to the etag of the last known state of the event.
 */
function conditionalFetch() {
  const calendarId = 'primary';
  const start = getRelativeDate(1, 12);
  const end = getRelativeDate(1, 13);
  let event = {
    summary: 'Lunch Meeting',
    location: 'The Deli',
    description: 'To discuss our plans for the presentation next week.',
    start: {
      dateTime: start.toISOString()
    },
    end: {
      dateTime: end.toISOString()
    },
    attendees: [
      {email: 'gduser1@workspacesample.dev'},
      {email: 'gduser2@workspacesample.dev'}
    ],
    // Red background. Use Calendar.Colors.get() for the full list.
    colorId: 11
  };
  try {
    // insert event
    event = Calendar.Events.insert(event, calendarId);
    console.log('Event ID: ' + event.getId());
    // Re-fetch the event each second, but only get a result if it has changed.
    for (let i = 0; i < 30; i++) {
      Utilities.sleep(1000);
      event = Calendar.Events.get(calendarId, event.id, {}, {'If-None-Match': event.etag});
      console.log('New event description: ' + event.start.dateTime);
    }
  } catch (e) {
    console.log('Fetch threw an exception: ' + e);
  }
}

همگام‌سازی رویدادها

مثال زیر نحوه بازیابی رویدادها با استفاده از توکن‌های همگام‌سازی را نشان می‌دهد. هنگامی که یک توکن همگام‌سازی را در درخواست سرویس پیشرفته تقویم قرار می‌دهید، پاسخ حاصل فقط شامل مواردی است که از زمان تولید آن توکن تغییر کرده‌اند و امکان پردازش کارآمدتر را فراهم می‌کند. برای جزئیات بیشتر در مورد فرآیند همگام‌سازی، به بخش «همگام‌سازی کارآمد منابع» مراجعه کنید.

مثال زیر از همان متد getRelativeDate(daysOffset, hour) که در مثال‌های بالا تعریف شده است، استفاده می‌کند.

پیشرفته/تقویم.gs
/**
 * Retrieve and log events from the given calendar that have been modified
 * since the last sync. If the sync token is missing or invalid, log all
 * events from up to a month ago (a full sync).
 *
 * @param {string} calendarId The ID of the calender to retrieve events from.
 * @param {boolean} fullSync If true, throw out any existing sync token and
 *        perform a full sync; if false, use the existing sync token if possible.
 */
function logSyncedEvents(calendarId, fullSync) {
  const properties = PropertiesService.getUserProperties();
  const options = {
    maxResults: 100
  };
  const syncToken = properties.getProperty('syncToken');
  if (syncToken && !fullSync) {
    options.syncToken = syncToken;
  } else {
    // Sync events up to thirty days in the past.
    options.timeMin = getRelativeDate(-30, 0).toISOString();
  }
  // Retrieve events one page at a time.
  let events;
  let pageToken;
  do {
    try {
      options.pageToken = pageToken;
      events = Calendar.Events.list(calendarId, options);
    } catch (e) {
      // Check to see if the sync token was invalidated by the server;
      // if so, perform a full sync instead.
      if (e.message === 'Sync token is no longer valid, a full sync is required.') {
        properties.deleteProperty('syncToken');
        logSyncedEvents(calendarId, true);
        return;
      }
      throw new Error(e.message);
    }
    if (events.items && events.items.length === 0) {
      console.log('No events found.');
      return;
    }
    for (const event of events.items) {
      if (event.status === 'cancelled') {
        console.log('Event id %s was cancelled.', event.id);
        return;
      }
      if (event.start.date) {
        const start = new Date(event.start.date);
        console.log('%s (%s)', event.summary, start.toLocaleDateString());
        return;
      }
      // Events that don't last all day; they have defined start times.
      const start = new Date(event.start.dateTime);
      console.log('%s (%s)', event.summary, start.toLocaleString());
    }
    pageToken = events.nextPageToken;
  } while (pageToken);
  properties.setProperty('syncToken', events.nextSyncToken);
}