当前位置: 首页 > 知识库问答 >
问题:

如何使用谷歌应用程序脚本同步日历?

韩照
2023-03-14

我想同步两个谷歌日历自动每当有一个更新到其中之一。请注意,这两个日历并不相同。我认为设置一个由日历触发的触发器就足够了。但谷歌文档称

这些触发器不会告诉您哪个事件发生了变化或它是如何变化的。相反,它们表示您的代码需要执行增量同步操作,以获取日历的最新更改。

所以我从谷歌找到了一个完全和增量同步的实现

我使用了上面链接中的函数LogSynceEvents()和getRelativeDate(),没有任何更改。然后我创建了两个函数

function fullSync(){
  var calendarId = 'myId'
  
  logSyncedEvents(calendarId, true)

}

function incrementalSync(){
  var calendarId = 'myID'
 
  logSyncedEvents(calendarId, false)

}

/**
 * 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) {
  var properties = PropertiesService.getUserProperties();
  var options = {
    maxResults: 100
  };
  var 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.
  var events;
  var 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;
      } else {
        throw new Error(e.message);
      }
    }

    if (events.items && events.items.length > 0) {
      for (var i = 0; i < events.items.length; i++) {
        var event = events.items[i];
        if (event.status === 'cancelled') {
          console.log('Event id %s was cancelled.', event.id);
        } else if (event.start.date) {
          // All-day event.
          var start = new Date(event.start.date);
          console.log('%s (%s)', event.summary, start.toLocaleDateString());
        } else {
          // Events that don't last all day; they have defined start times.
          var start = new Date(event.start.dateTime);
          console.log('%s (%s)', event.summary, start.toLocaleString());
        }
      }
    } else {
      console.log('No events found.');
    }

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

  properties.setProperty('syncToken', events.nextSyncToken);
}

然后我手动运行fullSync(),它找到了所有事件。然后我为今天创建了新事件并运行增量同步(),并期望脚本接收新事件。但是我得到了没有找到事件。

有人能帮我实现增量同步吗?

共有1个答案

燕禄
2023-03-14

我有一个旧的手动脚本,可以检查创建的辅助日历事件并将其同步到主日历。

我设法添加了一个触发器,对辅助日历执行的任何更改都将调用在主日历上创建事件的函数。

请随意测试它,如果这可以让您了解如何收集辅助日历的信息并更新主日历。

笔记:

  1. 它仅适用于基于小时的事件
  2. 它还可以跳过周末,您可以编辑或删除它
  3. 该脚本在主日历上创建事件,但使用默认名称(变量),您可能需要对其进行编辑或实现收集相同事件名称的方法
function callback() {

  var id="c_secondary@group.calendar.google.com"; // id of the secondary calendar to pull events from

  var today=new Date();
  var enddate=new Date();
  enddate.setDate(today.getDate()+7); // how many days in advance to monitor and block off time
  
  var secondaryCal=CalendarApp.getCalendarById(id);
  var secondaryEvents=secondaryCal.getEvents(today,enddate);
  
  var primaryCal=CalendarApp.getDefaultCalendar();
  var primaryEvents=primaryCal.getEvents(today,enddate); // all primary calendar events
  
  var primaryEventTitle="Testing the creation of the primary calendar"; // update this to the text you'd like to appear in the new events created in primary calendar
  
  var stat=1;
  var evi, existingEvent; 
  var primaryEventsFiltered = []; // to contain primary calendar events that were previously created from secondary calendar
  var primaryEventsUpdated = []; // to contain primary calendar events that were updated from secondary calendar
  var primaryEventsCreated = []; // to contain primary calendar events that were created from secondary calendar
  var primaryEventsDeleted = []; // to contain primary calendar events previously created that have been deleted from secondary calendar

  Logger.log('Number of primaryEvents: ' + primaryEvents.length);  
  Logger.log('Number of secondaryEvents: ' + secondaryEvents.length);
  
  // create filtered list of existing primary calendar events that were previously created from the secondary calendar
  for (pev in primaryEvents)
  {
    var pEvent = primaryEvents[pev];
    if (pEvent.getTitle() == primaryEventTitle)
    { primaryEventsFiltered.push(pEvent); }
  }
  
  // process all events in secondary calendar
  for (sev in secondaryEvents)
  {
    stat=1;
    evi=secondaryEvents[sev];
    
    // if the secondary event has already been blocked in the primary calendar, update it
    for (existingEvent in primaryEventsFiltered)
      {
        var pEvent = primaryEventsFiltered[existingEvent];
        var secondaryTitle = evi.getTitle();
        var secondaryDesc = evi.getDescription();
        if ((pEvent.getStartTime().getTime()==evi.getStartTime().getTime()) && (pEvent.getEndTime().getTime()==evi.getEndTime().getTime()))
        {
          stat=0;
          pEvent.setTitle(primaryEventTitle);
          pEvent.setDescription(secondaryTitle + '\n\n' + secondaryDesc);
          // event.setDescription(evi.getTitle() + '\n\n' + evi.getDescription());
          pEvent.setVisibility(CalendarApp.Visibility.PRIVATE); // set blocked time as private appointments in work calendar
          primaryEventsUpdated.push(pEvent.getId());
          Logger.log('PRIMARY EVENT UPDATED'
                     + '\nprimaryId: ' + pEvent.getId() + ' \nprimaryTitle: ' + pEvent.getTitle() + ' \nprimaryDesc: ' + pEvent.getDescription());
        } 
      }

    if (stat==0) continue;    
    
    var d = evi.getStartTime();
    var n = d.getDay();

    if (evi.isAllDayEvent())
    {
      continue; // Do nothing if the event is an all-day or multi-day event. This script only syncs hour-based events
    }
    else if (n==1 || n==2 || n==3 || n==4 || n==5) // skip weekends. Delete this if you want to include weekends
    // if the secondary event does not exist in the primary calendar, create it
    {
      var newEvent = primaryCal.createEvent(primaryEventTitle,evi.getStartTime(),evi.getEndTime()); // change the Booked text to whatever you would like your merged event titles to be
      // alternative version below that copies the exact secondary event information into the primary calendar event
      // var newEvent = primaryCal.createEvent(evi.getTitle(),evi.getStartTime(),evi.getEndTime(), {location: evi.getLocation(), description: evi.getDescription()});  
      newEvent.setDescription(evi.getTitle() + '\n\n' + evi.getDescription());
      newEvent.setVisibility(CalendarApp.Visibility.PRIVATE); // set blocked time as private appointments in work calendar
      newEvent.removeAllReminders(); // so you don't get double notifications. Delete this if you want to keep the default reminders for your newly created primary calendar events
      primaryEventsCreated.push(newEvent.getId());
      Logger.log('PRIMARY EVENT CREATED'
                 + '\nprimaryId: ' + newEvent.getId() + '\nprimaryTitle: ' + newEvent.getTitle() + '\nprimaryDesc ' + newEvent.getDescription() + '\n');
    }
  }

  // if a primary event previously created no longer exists in the secondary calendar, delete it
  for (pev in primaryEventsFiltered)
  {
    var pevIsUpdatedIndex = primaryEventsUpdated.indexOf(primaryEventsFiltered[pev].getId());
    if (pevIsUpdatedIndex == -1)
    { 
      var pevIdToDelete = primaryEventsFiltered[pev].getId();
      Logger.log(pevIdToDelete + ' deleted');
      primaryEventsDeleted.push(pevIdToDelete);
      primaryEventsFiltered[pev].deleteEvent();
    }
  }  

  Logger.log('Primary events previously created: ' + primaryEventsFiltered.length);
  Logger.log('Primary events updated: ' + primaryEventsUpdated.length);
  Logger.log('Primary events deleted: ' + primaryEventsDeleted.length);
  Logger.log('Primary events created: ' + primaryEventsCreated.length);

}  


function calendarTrigger() {
  var trigger = ScriptApp.newTrigger('callback')
  .forUserCalendar('c_secondary@group.calendar.google.com')
  .onEventUpdated()
  .create();
}
 类似资料:
  • 我想使用谷歌应用程序脚本更新谷歌电子表格,并在我拥有的一系列日历发生更改时使用Gmail API发送电子邮件。 Google日历推送通知是否可以与Google App Script一起使用,或者是否需要其他某种平台? 我愿意学习任何必要的东西。我知道需要一个域名来接收通知。 我感谢你的帮助!

  • 我正在构建谷歌应用程序脚本产品,当我部署GAS项目时,我只想让我的组织中的人可以访问该应用程序。当用户已经用我的组织电子邮件登录时,浏览器就可以了。但是我如何通过邮递员或终端访问部署的URL,我需要访问令牌或其他东西吗?欢迎提供任何建议! 欢迎提供任何建议!

  • 在继续使用GoogleApps脚本构建Google电子表格的过程中,我已经完成了获取Bittrex和Poloniex余额的工作,但无法使用Cryptopia。 下面是我与Bittrex将JSON对象数组映射到字符串的斗争的链接 以下是官方API链接:https://www.cryptopia.co.nz/Forum/Thread/256 以下是一些例子: https://www.cryptopia

  • 我使用一个简单的脚本来删除1天后所有标有“摄像头”的电子邮件。这已经奏效好几个月了。我没有改变它,但它突然停止工作。 该脚本仍有在我的Gmail上运行的权限,但已停止。 感谢任何建议。 脚本是; 谢了山姆

  • 我想每隔两分钟运行一次cron,0,2,4,6,8。。。。每个cron执行运行2分钟。 我用synchronized配置了cron schedule,如下所示。但我仍然看到调度程序的行为似乎是同步的,而不是给定的。 克朗被安排在 0-2第一个cron 4-6秒cron 8-10第三个cron Cron计划程序在最后一次执行Cron后等待2分钟。 如果我正确理解synchronized,那么添加它是

  • 有1个域分别有一个子域-school.com和students.school.com。 我已经为每个班级创建了谷歌课堂使用谷歌应用程序脚本。 运行函数时,出现此错误,