创建第三方会议

您在脚本项目清单中定义的每个会议解决方案都有一个关联的 onCreateFunction。每当用户尝试选择该会议解决方案作为活动时,该插件都会调用此函数,以创建一个会议。

您必须实现插件清单中所述的每个 onCreateFunction。一般来说,这些函数必须执行以下操作:

  1. 检索第三方会议系统创建会议可能需要的任何 Google 日历活动信息,例如活动 ID 或参加者列表。
  2. 连接到第三方会议服务,然后使用 Google 日历活动信息在该服务中创建新的会议。
  3. 如果会议创建请求因某种原因而失败,请使用错误信息构建并返回包含 ConferenceErrorConferenceData 对象。否则,请完成以下步骤。
    1. 初始化会议同步
    2. 使用第三方会议服务返回的信息构建并返回新的 ConferenceData 对象。

检索活动信息

如需创建第三方会议,需要有关相应 Google 日历活动的某些信息。所需的确切活动信息因第三方会议系统而异,但通常包括活动开始时间、结束时间、摘要、参加者名单和 ID。

调用时,系统会向您定义的每个 onCreateFunction 传递一个包含日历 ID 和活动 ID 的参数。您可以使用这些 ID 通过 Google 日历高级服务检索完整的活动信息。

Google 日历可能会在活动存在之前为其添加会议详细信息。在这种情况下,Google 日历会向 onCreateFunction 传递有效的 eventId,但对 Calendar.Events.get() 的后续调用可能会导致错误响应,其中指出相应活动不存在。在这些情况下,最好使用占位数据创建第三方会议;在活动下次同步时,这些数据会被替换。

创建第三方会议

onCreateFunction 检索到必要的事件数据后,必须连接到第三方会议系统才能创建会议。通常情况下,这通过发出第三方会议系统支持的 API 请求来实现。请查看第三方会议解决方案的文档,确定您可以使用哪些 API 请求创建会议。

在 Apps 脚本中,处理发出外部 API 请求的最简单方法是使用适用于 Apps 脚本的 OAuth2适用于 Apps 脚本的 OAuth1 开源库。您还可以使用 UrlFetch 服务连接到外部 API,但这需要您明确处理授权详细信息。

请求创建会议后,您可能需要发出其他请求以检索新的会议详细信息。

初始化会议同步

插件在第三方系统上成功创建会议后,应该执行几个步骤来启用同步,以便在会议中反映对 Google 日历活动的更改。

如需详细了解如何在创建会议后设置同步,请参阅同步日历更改

构建会议数据响应

然后,onCreateFunction 必须使用第三方服务返回的会议信息构建并返回 ConferenceData 对象;会议数据部分介绍了此对象的内容。Google 日历会利用这些信息,在会议开始后将用户定向到会议。

构建 ConferenceData 对象时,请注意字段长度、入口点 URI 的格式和允许的入口点组合有一些限制。例如,一个 ConferenceData 中最多只能有一个 VIDEO 入口点。这些限制与 Calendar API 事件中针对相应 conferenceData 字段所述的限制相同,但其中并非所有 API 事件字段都适用于 Apps Script。

处理错误

在某些情况下,由于第三方会议系统返回的错误,会议创建无法完成。在这些情况下,您的插件应通过构建并返回包含 ConferenceError 详细信息的 ConferenceData 对象来稳健地处理错误情况,以便 Google 日历可以相应地采取行动。

构建 ConferenceData 对象以报告错误时,除了 ConferenceError 对象之外,您无需添加任何 ConferenceData 组件。ConferenceErrors 可以包含 ConferenceErrorType、错误消息,以及在出现身份验证问题时,包含允许用户登录第三方会议系统的网址。

示例

以下是 onCreateFunction 的示例(请注意,函数的名称可以是任何名称;您只需在插件项目清单中定义该名称即可)。

函数 create3rdPartyConference() 会与第三方系统联系以在其中创建会议,而 getAuthenticationUrl() 函数会创建第三方系统身份验证网址。这些功能并未在此处完全实现,因为它们在很大程度上依赖于第三方系统详细信息。

函数 initializeSyncing() 在此处未显示;它会处理同步所需的任何初步工作。如需了解详情,请参阅同步日历更改

/**
 *  Creates a conference, then builds and returns a ConferenceData object
 *  with the corresponding conference information. This method is called
 *  when a user selects a conference solution defined by the add-on that
 *  uses this function as its 'onCreateFunction' in the add-on manifest.
 *
 *  @param {Object} arg The default argument passed to a 'onCreateFunction';
 *      it carries information about the Google Calendar event.
 *  @return {ConferenceData}
 */
function createConference(arg) {
  const eventData = arg.eventData;
  const calendarId = eventData.calendarId;
  const eventId = eventData.eventId;

  // Retrieve the Calendar event information using the Calendar
  // Advanced service.
  var calendarEvent;
  try {
    calendarEvent = Calendar.Events.get(calendarId, eventId);
  } catch (err) {
    // The calendar event does not exist just yet; just proceed with the
    // given event ID and allow the event details to sync later.
    console.log(err);
    calendarEvent = {
      id: eventId,
    };
  }

  // Create a conference on the third-party service and return the
  // conference data or errors in a custom JSON object.
  var conferenceInfo = create3rdPartyConference(calendarEvent);

  // Build and return a ConferenceData object, either with conference or
  // error information.
  var dataBuilder = ConferenceDataService.newConferenceDataBuilder();

  if (!conferenceInfo.error) {
    // No error, so build the ConferenceData object from the
    // returned conference info.

    var phoneEntryPoint = ConferenceDataService.newEntryPoint()
        .setEntryPointType(ConferenceDataService.EntryPointType.PHONE)
        .setUri('tel:+' + conferenceInfo.phoneNumber)
        .setPin(conferenceInfo.phonePin);

    var adminEmailParameter = ConferenceDataService.newConferenceParameter()
        .setKey('adminEmail')
        .setValue(conferenceInfo.adminEmail);

    dataBuilder.setConferenceId(conferenceInfo.id)
        .addEntryPoint(phoneEntryPoint)
        .addConferenceParameter(adminEmailParameter)
        .setNotes(conferenceInfo.conferenceLegalNotice);

    if (conferenceInfo.videoUri) {
      var videoEntryPoint = ConferenceDataService.newEntryPoint()
          .setEntryPointType(ConferenceDataService.EntryPointType.VIDEO)
          .setUri(conferenceInfo.videoUri)
          .setPasscode(conferenceInfo.videoPasscode);
      dataBuilder.addEntryPoint(videoEntryPoint);
    }

    // Since the conference creation request succeeded, make sure that
    // syncing has been enabled.
    initializeSyncing(calendarId, eventId, conferenceInfo.id);

  } else if (conferenceInfo.error === 'AUTH') {
    // Authenentication error. Implement a function to build the correct
    // authenication URL for the third-party conferencing system.
    var authenticationUrl = getAuthenticationUrl();
    var error = ConferenceDataService.newConferenceError()
        .setConferenceErrorType(
            ConferenceDataService.ConferenceErrorType.AUTHENTICATION)
        .setAuthenticationUrl(authenticationUrl);
    dataBuilder.setError(error);

  } else {
    // Other error type;
    var error = ConferenceDataService.newConferenceError()
        .setConferenceErrorType(
            ConferenceDataService.ConferenceErrorType.TEMPORARY);
    dataBuilder.setError(error);
  }

  // Don't forget to build the ConferenceData object.
  return dataBuilder.build();
}


/**
 *  Contact the third-party conferencing system to create a conference there,
 *  using the provided calendar event information. Collects and retuns the
 *  conference data returned by the third-party system in a custom JSON object
 *  with the following fields:
 *
 *    data.adminEmail - the conference administrator's email
 *    data.conferenceLegalNotice - the conference legal notice text
 *    data.error - Only present if there was an error during
 *         conference creation. Equal to 'AUTH' if the add-on user needs to
 *         authorize on the third-party system.
 *    data.id - the conference ID
 *    data.phoneNumber - the conference phone entry point phone number
 *    data.phonePin - the conference phone entry point PIN
 *    data.videoPasscode - the conference video entry point passcode
 *    data.videoUri - the conference video entry point URI
 *
 *  The above fields are specific to this example; which conference information
 *  your add-on needs is dependent on the third-party conferencing system
 *  requirements.
 *
 * @param {Object} calendarEvent A Calendar Event resource object returned by
 *     the Google Calendar API.
 * @return {Object}
 */
function create3rdPartyConference(calendarEvent) {
  var data = {};

  // Implementation details dependent on the third-party system API.
  // Typically one or more API calls are made to create the conference and
  // acquire its relevant data, which is then put in to the returned JSON
  // object.

  return data;
}

/**
 *  Return the URL used to authenticate the user with the third-party
 *  conferencing system.
 *
 *  @return {String}
 */
function getAuthenticationUrl() {
  var url;
  // Implementation details dependent on the third-party system.

  return url;
}