【问题标题】:Update attendees when editing a Google calendar event with Google apps script使用 Google 应用程序脚本编辑 Google 日历活动时更新与会者
【发布时间】:2014-04-06 21:07:45
【问题描述】:

情况

我有一个日历,上面有很多活动(员工评估)。

我进行了大量修改(更改活动的长度等),但邀请函将发给拥有 Lotus Notes 日历的人(穷人)。

这意味着除非我触发所谓的“发送通知?”在鼠标点击版本的事物中,他们无法知道事件已更新。

(Similar Q)

在此示例中,我尝试触发的事件与 Send Update? 模式被 send 接受时触发的事件相同。

代码

这是一些示例代码,用于获取 Appraisals 日历上的所有事件并将它们的位置更改为“月亮”。

function fixInvitations(){
  //get the callendar named "Appraisals"
  var cApp = CalendarApp.getCalendarsByName("Appraisals")[0];
  var events = cApp.getEvents(new Date(), new Date("Dec 30 2014"));

  for (eIndex in events){
    var event = events[eIndex];
    event.setLocation("the moon");
  }
}

问题

如何为受邀参加活动的所有各方触发更新,以便将更改反映在他们的日历中?

目前这些活动已在月球上发布,但更新并未告知非 Google 日历上的人有关更改的信息。

有用,但不是那么有用的事实

手动触发发送的更新邮件包含.ics文件(Gist of the contents)。这包含一个 VCALENDAR 和一个 VEVENT。来自Wikipedia page on VEVENTs

对于发送事件的更新,UID 应该与原始 UID 匹配。另一个要设置的组件属性是:

SEQUENCE:<Num of Update>

即,对于第一次更新:

SEQUENCE:1

因此,如果有一种方法可以手动构建带有.ics 附件的电子邮件,它会解决问题,但这感觉就像是大材小用。 This is mentioned here 但未解决。

【问题讨论】:

  • 你能提供一些代码来展示你目前正在使用的东西吗?
  • 我添加了一些示例代码。
  • 我有一个想法,将日历链接到电子表格(将日历事件导入电子表格),然后使用脚本复制事件,但更改属性(在这种情况下,位置为月亮),并向所有参与者发送一封电子邮件,告知活动详细信息已更改。我认为这很容易做到。根据我的研究,向与会者发送电子邮件爆炸可能不是内置功能,但可能会进行“结束”以到达相同的目的地。
  • 使用 'getX' 方法查找事件非常简单,然后我可以向所有人发送一封电子邮件,说明事件的变化情况,但这不是 更新 到现有事件。如果我这样做,那么他们的日历中有一个不正确的事件,我也可以从这些值中创建一个新事件,但这会导致重复。当您手动更改事件时,它会触发某种“发送更新电子邮件”事件;我想从我的代码中触发。
  • 另一种解决方案是从原始事件中获取 .getGuests,将该数组传递给具有 MailApp 方法的函数,以向所有客人发送电子邮件,让他们知道详细信息已更改。明天晚上我可能会尝试把它放在一起作为替代方案。我认为没有办法从脚本触发通知。我阅读了所有相关的类文档,但什么也没看到。我添加了我的答案,它仍然需要一些修改来修复我与 onEdit 事件中断的 createNewEvent,所以如果你想等到我修复它之前接受答案,我理解。

标签: google-apps-script google-calendar-api icalendar


【解决方案1】:

我在这方面有点挣扎,并从 ekoleda+devrel@google.com 获得了一些帮助:Calendar 能够向通过 addGuest http://code.google.com/p/google-apps-script-issues/issues/detail?id=574 添加的用户发送电子邮件邀请

希望能为人们节省一些时间的几点建议:

请注意,CalendarApp 和 Advanced Calendar 服务使用不同的 事件 ID 格式:

  • CalendarApp 返回以“@google.com”结尾的事件 ID。 b3gv...a5jrs@google.com
  • 高级日历服务/日历 API 需要一个不包含 @google.com 的事件 ID。 b3gv...a5jrs

这是一些工作代码:

function sendInvite(calendarId, eventId, email) {
  var event = Calendar.Events.get(calendarId, eventId);
  if(event.attendees) {
    event.attendees.push({
      email: email
    });
  } else {
    event.attendees = new Array({email: email});
  }
  event = Calendar.Events.patch(event, calendarId, eventId, {
    sendNotifications: true
  });
}

最后请注意,如果您是活动所有者并且尝试添加自己的电子邮件地址,您将不会收到电子邮件通知。这在日历世界中是有意义的,因为您不会进入自己的日历活动,将自己添加为与会者,并期望系统提示您是否要通知自己。但是,这可能是人们尝试和测试事物的常用方法(我没有域测试帐户,而且我不能总是用我的个人 gmail 帐户可靠地测试事物)。因此,如果您使用自己的帐户进行测试并认为事情不正常,请记住这一点。一旦您尝试使用非活动所有者帐户进行操作,邀请将通过电子邮件发送。

【讨论】:

    【解决方案2】:

    我今天收到了来自 Google 的电子邮件,说他们已在应用脚本中添加了一项功能,使这成为可能。

    更新: 状态:已修复 所有者:ekoleda+devrel@google.com 标签:-Priority-Medium

    ekoleda+devrel@google.com 对问题 574 的评论 #11:日历能够向通过 addGuest 添加的用户发送电子邮件邀请 http://code.google.com/p/google-apps-script-issues/issues/detail?id=574

    现在可以使用高级日历服务:

    https://developers.google.com/apps-script/advanced/calendar

    您可以使用 Calendar.Events.patch() 添加与会者,如果您将可选参数 sendNotifications 设置为“true”,与会者将收到邀请。

    https://developers.google.com/google-apps/calendar/v3/reference/events/patch

    我今天将尝试解决此问题,然后编辑此回复以反映这一点。

    【讨论】:

    • 这从未更新过答案。你能记得如果你解决了这个问题吗? :)
    【解决方案3】:

    Google 日历 API 支持用于事件更新的标志 sendNotifications: https://developers.google.com/google-apps/calendar/v3/reference/events/update

    我会为 App Script 提交功能请求以公开标志,同时直接使用日历 API 来更新事件,就像外部 API 一样: https://developers.google.com/apps-script/guides/services/external

    【解决方案4】:

    我认为一种解决方案是创建一个包含列标题的电子表格:事件 ID、事件名称、描述、开始时间、结束时间、位置、来宾列表,然后将此脚本添加到电子表格中。 calendarImport() 将导入所有日历事件并将它们写入工作表。然后,您可以修改电子表格行中的事件(将位置更改为月球),并运行 calendarCreateEvent 根据您所做的更改创建一个新事件。它将自动向所有旧与会者发送通知以接受新活动,因为这是一个新邀请。

    我非常接近该解决方案,但现在我在访问日历以创建新事件时遇到了问题。我认为这是因为我从 onEdit 事件函数中调用它。已经很晚了,但是如果您重写脚本的第三部分以获取事件数据范围,然后使用 for/if 循环来检查添加日期与修改日期,那么您应该能够创建一个新事件,并删除旧的事件。这会将事件详细信息更改的通知推送给已经接受旧事件的每个人。

    我认为,鉴于您一开始提供的代码示例,您可能已经知道如何做到这一点,但如果您不知道,我可能会在明天晚上拼凑一些东西来搜索已重新创建的旧事件并删除它们。

    Here's my spreadsheet and code in action.

    function calendarImport(){
      //http://www.google.com/google-d-s/scripts/class_calendar.html#getEvents
      // The code below will retrieve events between 2 dates for the user's default calendar and
      // display the events the current spreadsheet
      var cal = CalendarApp.getDefaultCalendar();
      var calId = cal.getId();
      var sheet = SpreadsheetApp.getActiveSheet();
      var sheetName = SpreadsheetApp.getActiveSheet().setName(calId +" Calendar Data");
      var events = cal.getEvents(new Date("March 9, 2014"), new Date("March 14, 2014"));
      for (var i=0;i<events.length;i++) {
        //http://www.google.com/google-d-s/scripts/class_calendarevent.html
        Logger.log(events);
        var details=[[events[i].getId(),events[i].getTitle(), events[i].getDescription(), events[i].getStartTime(), events[i].getEndTime(),events[i].getLocation()]];
        var guestList = events[i].getGuestList();
        var guestArray = [];
        for (var n in guestList){
          var guestEmail = (guestList[n].getEmail());
          guestArray.push(guestEmail);
          Logger.log(guestArray);
    
        }
    
        var row=i+1;
        var range=sheet.getRange(row+1,1,1,6);
        range.setValues(details);
        var guestRange = sheet.getRange(row+1,7,1,1);
        guestRange.setValues([guestArray]);
        var dateAdded = Utilities.formatDate(new Date(), "GMT-6","MM/dd/yy HH:mm:ss");
        var dateAddedRange = sheet.getRange(row+1,8,1,1);
        dateAddedRange.setValue(dateAdded);
      }
    }
    
    function onEdit(event){
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var calId = CalendarApp.getDefaultCalendar().getId();
      var sh = ss.getSheetByName(sheetName);
      var actSht = event.source.getActiveSheet();
      var actRng = event.source.getActiveRange();
      var index = actRng.getRowIndex();
      Logger.log(index);
      var dateCol = actSht.getLastColumn();
      var calId
      var lastCell = actSht.getRange(index,dateCol);
      var date = Utilities.formatDate(new Date(), "GMT-6", "MM/dd/yyyy HH:mm:ss");
      lastCell.setValue(date);
      var modifiedRow = sh.getRange(index,1,1,ss.getLastColumn()).getValues();
      Logger.log(modifiedRow[0][7])
      if (modifiedRow[0][7] < modifiedRow[0][8]){
        var firstAdded = modifiedRow[0][7];
        var dateModified = modifiedRow[0][8];
        calendarCreateEvent(index,firstAdded,dateModified,calId);
      }
    
    
    }
    
    function calendarCreateEvent(index,firstAdded,dateModified,calId){
      var sheet = SpreadsheetApp.getActiveSheet();
      var added = firstAdded;
      var modified = dateModified;
      var startRow = index;  // First row of data to process
      var calId = calId;
      Logger.log(calId);
      Logger.log(startRow);
      Logger.log(added);
      Logger.log(modified);
      if (modified - added > "0"){
        var numRows = 1;   // Number of rows to process
        var dataRange = sheet.getRange(startRow, 1, numRows, 9);
        var data = dataRange.getValues();
        var cal = CalendarApp.getCalendarById(calId);
        for (i in data) {
          var row = data[i];
          var eventId = row[0]
          var title = row[1];  // First column
          var desc = row[2];       // Second column
          var tstart = row[3];
          var tstop = row[4];
          var loc = row[5];
          var guests = row[6];
          //cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
          var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc, guests:guests});//.addGuest(guests);
          var newEventId = newEvent.getId();
          Logger.log(newEventId);
    
        }
      }
    }
    

    【讨论】:

    • 太酷了!虽然它不能解决我想要更新现有事件的问题。如果我这样做,它会在人们的日历上乱扔不再真实的事件。我想我可以获取事件的详细信息,删除它并使用新属性重新创建它,但不能保证它实际上会发送有关已删除事件的更新。
    • 其实那是我的计划,只是还没来得及完成。如果您注意到,我将事件 ID 添加到跟踪中,因此一旦您创建了新事件,您就可以返回并使用另一个函数删除旧事件。另外,我破坏了我的代码,试图用它做一些更复杂的操作,所以不要再去测试站点了,它被破坏了。根据我的研究,您无法使用脚本触发发送通知(没有方法)。另一种选择是修改活动,获取客人列表,并使用 MailApp 发送更新以通知客人活动详细信息已更改(可能更容易)。
    • 如果您在编辑后创建新活动,它会像新活动一样自动弹出到与会者日历上(我建议更改活动标题或描述以表明新活动是修改后的版本旧事件。)但是,您将首先创建新事件(使用新属性),然后删除旧事件,而不通知与会者旧事件已被删除。由于它使用您的旧来宾列表创建了一个新活动(并且您可以过滤掉“未参加”,您可以通过监视新的“是”响应来确保每个人都知道该活动已更改。
    • ..如果您使用的是 Google 日历,则可以使用,但我的与会者都使用非 Google 日历。使用 Google 唯一的解决方案,只需更新事件就会改变它,但是一旦你出去,你需要触发更新。
    • 使用其他日历的人是否会通过电子邮件收到邀请,这些邀请会自动添加到他们的日历中?还是他们必须手动添加它们?我不熟悉有多少日历工作(我想你提到了 Lotus)。如果他们这样做了,那么您可以在创建新事件时发送一封通知电子邮件,如文档developers.google.com/apps-script/reference/calendar/… 中所述。
    猜你喜欢
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 2023-03-09
    • 2014-06-30
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多