创建第三方会议

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

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

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

检索事件信息

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

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

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 脚本中都可用。

处理错误

在某些情况下,由于第三方会议系统返回错误,无法完成会议创建。在这些情况下,您的插件应构建并返回包含 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;
}