创建第三方会议

您在脚本项目清单中定义的每个会议解决方案都有一个关联的 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 入口点。这些限制与 Google 日历 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;
}