Bắt đầu nhanh về hội nghị truyền hình

Lưu ý quan trọng: Hướng dẫn bắt đầu nhanh này chỉ dành cho các nhà cung cấp dịch vụ hội nghị truyền hình trên web.

Tính năng bắt đầu nhanh Tiện ích bổ sung của Google Workspace sau đây giúp mở rộng Lịch Google để đồng bộ hoá với một dịch vụ hội nghị truyền hình hư cấu trên web có tên là Hội nghị truyền hình trên web của tôi. Khi chỉnh sửa sự kiện trên Lịch, tiện ích bổ sung này cho phép người dùng xem Hội nghị truyền hình trên web của tôi dưới dạng một chế độ hội nghị truyền hình.

Tính năng bắt đầu nhanh cho thấy tính năng tạo hội nghị và đồng bộ hoá sự kiện, nhưng không hoạt động cho đến khi bạn kết nối tính năng này với API giải pháp hội nghị truyền hình.

Mục tiêu

  • Thiết lập môi trường.
  • Thiết lập tập lệnh.
  • Chạy tập lệnh.

Điều kiện tiên quyết

Thiết lập môi trường

Mở dự án Cloud trong bảng điều khiển Google Cloud

Nếu chưa mở, hãy mở dự án Cloud mà bạn định sử dụng cho mẫu này:

  1. Trong bảng điều khiển Google Cloud, hãy chuyển đến trang Chọn dự án.

    Chọn một dự án trên Google Cloud

  2. Chọn dự án Google Cloud mà bạn muốn sử dụng. Hoặc nhấp vào Tạo dự án rồi làm theo hướng dẫn trên màn hình. Nếu tạo một dự án trên Google Cloud, có thể bạn sẽ phải bật tính năng thanh toán cho dự án đó.

Bật API Lịch

Bước bắt đầu nhanh này sử dụng dịch vụ nâng cao của Lịch, vốn truy cập vào API Lịch.

Trước khi sử dụng các API của Google, bạn cần bật các API này trong một dự án trên Google Cloud. Bạn có thể bật một hoặc nhiều API trong một dự án Google Cloud.

    Trong dự án trên Google Cloud, hãy bật API Lịch.

    Bật API

Tiện ích bổ sung của Google Workspace cần bạn thiết lập màn hình đồng ý. Việc định cấu hình màn hình xin phép bằng OAuth cho Tiện ích bổ sung của Google Workspace sẽ xác định nội dung mà Google sẽ hiển thị cho người dùng.

  1. Trong bảng điều khiển Google Cloud, hãy chuyển đến Trình đơn > API và Dịch vụ > màn hình xin phép bằng OAuth.

    Chuyển đến màn hình xin phép bằng OAuth

  2. Đối với Loại người dùng, hãy chọn Nội bộ, rồi nhấp vào Tạo.
  3. Hoàn tất biểu mẫu đăng ký ứng dụng, sau đó nhấp vào Lưu và tiếp tục.
  4. Hiện tại, bạn có thể bỏ qua bước thêm phạm vi rồi nhấp vào Lưu và tiếp tục. Trong tương lai, khi tạo một ứng dụng để sử dụng bên ngoài tổ chức Google Workspace, bạn phải thay đổi Loại người dùng thành Bên ngoài, sau đó thêm phạm vi uỷ quyền mà ứng dụng yêu cầu.

  5. Xem lại bản tóm tắt về gói đăng ký ứng dụng của bạn. Để chỉnh sửa, hãy nhấp vào Chỉnh sửa. Nếu quá trình đăng ký ứng dụng có vẻ ổn, hãy nhấp vào Back to Dashboard (Quay lại trang tổng quan).

Thiết lập tập lệnh

Tạo dự án Apps Script

  1. Để tạo một dự án Apps Script mới, hãy truy cập vào script.new.
  2. Nhấp vào Dự án không có tiêu đề.
  3. Đổi tên dự án Apps Script thành tiện ích bổ sung Hội nghị rồi nhấp vào Đổi tên.
  4. Bên cạnh tệp Code.gs, hãy nhấp vào biểu tượng Tuỳ chọn khác > Đổi tên. Đặt tên cho tệp CreateConf.
  5. Nhấp vào Thêm tệp > Tập lệnh.
  6. Đặt tên Syncing cho tệp.
  7. Thay thế nội dung của từng tệp bằng mã tương ứng sau:

    CreateConf.gs

    /**
     *  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;
    }
    
    

    Syncing.gs

    /**
     *  Initializes syncing of conference data by creating a sync trigger and
     *  sync token if either does not exist yet.
     *
     *  @param {String} calendarId The ID of the Google Calendar.
     */
    function initializeSyncing(calendarId) {
      // Create a syncing trigger if it doesn't exist yet.
      createSyncTrigger(calendarId);
    
      // Perform an event sync to create the initial sync token.
      syncEvents({'calendarId': calendarId});
    }
    
    /**
     *  Creates a sync trigger if it does not exist yet.
     *
     *  @param {String} calendarId The ID of the Google Calendar.
     */
    function createSyncTrigger(calendarId) {
      // Check to see if the trigger already exists; if does, return.
      var allTriggers = ScriptApp.getProjectTriggers();
      for (var i = 0; i < allTriggers.length; i++) {
        var trigger = allTriggers[i];
        if (trigger.getTriggerSourceId() == calendarId) {
          return;
        }
      }
    
      // Trigger does not exist, so create it. The trigger calls the
      // 'syncEvents()' trigger function when it fires.
      var trigger = ScriptApp.newTrigger('syncEvents')
          .forUserCalendar(calendarId)
          .onEventUpdated()
          .create();
    }
    
    /**
     *  Sync events for the given calendar; this is the syncing trigger
     *  function. If a sync token already exists, this retrieves all events
     *  that have been modified since the last sync, then checks each to see
     *  if an associated conference needs to be updated and makes any required
     *  changes. If the sync token does not exist or is invalid, this
     *  retrieves future events modified in the last 24 hours instead. In
     *  either case, a new sync token is created and stored.
     *
     *  @param {Object} e If called by a event updated trigger, this object
     *      contains the Google Calendar ID, authorization mode, and
     *      calling trigger ID. Only the calendar ID is actually used here,
     *      however.
     */
    function syncEvents(e) {
      var calendarId = e.calendarId;
      var properties = PropertiesService.getUserProperties();
      var syncToken = properties.getProperty('syncToken');
    
      var options;
      if (syncToken) {
        // There's an existing sync token, so configure the following event
        // retrieval request to only get events that have been modified
        // since the last sync.
        options = {
          syncToken: syncToken
        };
      } else {
        // No sync token, so configure to do a 'full' sync instead. In this
        // example only recently updated events are retrieved in a full sync.
        // A larger time window can be examined during a full sync, but this
        // slows down the script execution. Consider the trade-offs while
        // designing your add-on.
        var now = new Date();
        var yesterday = new Date();
        yesterday.setDate(now.getDate() - 1);
        options = {
          timeMin: now.toISOString(),          // Events that start after now...
          updatedMin: yesterday.toISOString(), // ...and were modified recently
          maxResults: 50,   // Max. number of results per page of responses
          orderBy: 'updated'
        }
      }
    
      // Examine the list of updated events since last sync (or all events
      // modified after yesterday if the sync token is missing or invalid), and
      // update any associated conferences as required.
      var events;
      var pageToken;
      do {
        try {
          options.pageToken = pageToken;
          events = Calendar.Events.list(calendarId, options);
        } catch (err) {
          // Check to see if the sync token was invalidated by the server;
          // if so, perform a full sync instead.
          if (err.message ===
                "Sync token is no longer valid, a full sync is required.") {
            properties.deleteProperty('syncToken');
            syncEvents(e);
            return;
          } else {
            throw new Error(err.message);
          }
        }
    
        // Read through the list of returned events looking for conferences
        // to update.
        if (events.items && events.items.length > 0) {
          for (var i = 0; i < events.items.length; i++) {
             var calEvent = events.items[i];
             // Check to see if there is a record of this event has a
             // conference that needs updating.
             if (eventHasConference(calEvent)) {
               updateConference(calEvent, calEvent.conferenceData.conferenceId);
             }
          }
        }
    
        pageToken = events.nextPageToken;
      } while (pageToken);
    
      // Record the new sync token.
      if (events.nextSyncToken) {
        properties.setProperty('syncToken', events.nextSyncToken);
      }
    }
    
    /**
     *  Returns true if the specified event has an associated conference
     *  of the type managed by this add-on; retuns false otherwise.
     *
     *  @param {Object} calEvent The Google Calendar event object, as defined by
     *      the Calendar API.
     *  @return {boolean}
     */
    function eventHasConference(calEvent) {
      var name = calEvent.conferenceData.conferenceSolution.name || null;
    
      // This version checks if the conference data solution name matches the
      // one of the solution names used by the add-on. Alternatively you could
      // check the solution's entry point URIs or other solution-specific
      // information.
      if (name) {
        if (name === "My Web Conference" ||
            name === "My Recorded Web Conference") {
          return true;
        }
      }
      return false;
    }
    
    /**
     *  Update a conference based on new Google Calendar event information.
     *  The exact implementation of this function is highly dependant on the
     *  details of the third-party conferencing system, so only a rough outline
     *  is shown here.
     *
     *  @param {Object} calEvent The Google Calendar event object, as defined by
     *      the Calendar API.
     *  @param {String} conferenceId The ID used to identify the conference on
     *      the third-party conferencing system.
     */
    function updateConference(calEvent, conferenceId) {
      // Check edge case: the event was cancelled
      if (calEvent.status === 'cancelled' || eventHasConference(calEvent)) {
        // Use the third-party API to delete the conference too.
    
    
      } else {
        // Extract any necessary information from the event object, then
        // make the appropriate third-party API requests to update the
        // conference with that information.
    
      }
    }
    
    
  8. Nhấp vào biểu tượng Cài đặt dự án Biểu tượng cho phần cài đặt dự án.

  9. Đánh dấu vào hộp Show "appsscript.json" in editor (Hiển thị tệp kê khai "appsscript.json" trong trình chỉnh sửa).

  10. Nhấp vào biểu tượng Trình chỉnh sửa .

  11. Mở tệp appsscript.json và thay thế nội dung bằng mã sau, sau đó nhấp vào Lưu Biểu tượng Lưu.

    appsscript.json

    {
      "addOns": {
        "calendar": {
          "conferenceSolution": [{
            "id": 1,
            "name": "My Web Conference",
            "logoUrl": "https://lh3.googleusercontent.com/...",
            "onCreateFunction": "createConference"
          }],
          "currentEventAccess": "READ_WRITE"
        },
        "common": {
          "homepageTrigger": {
            "enabled": false
          },
          "logoUrl": "https://lh3.googleusercontent.com/...",
          "name": "My Web Conferencing"
        }
      },
      "timeZone": "America/New_York",
      "dependencies": {
        "enabledAdvancedServices": [
        {
          "userSymbol": "Calendar",
          "serviceId": "calendar",
          "version": "v3"
        }
        ]
      },
      "webapp": {
        "access": "ANYONE",
        "executeAs": "USER_ACCESSING"
      },
      "exceptionLogging": "STACKDRIVER",
      "oauthScopes": [
        "https://www.googleapis.com/auth/calendar.addons.execute",
        "https://www.googleapis.com/auth/calendar.events.readonly",
        "https://www.googleapis.com/auth/calendar.addons.current.event.read",
        "https://www.googleapis.com/auth/calendar.addons.current.event.write",
        "https://www.googleapis.com/auth/script.external_request",
        "https://www.googleapis.com/auth/script.scriptapp"
      ]
    }
    
    

Sao chép số dự án trên đám mây

  1. Trong bảng điều khiển Google Cloud, hãy chuyển đến Trình đơn > IAM và Quản trị viên > Cài đặt.

    Chuyển đến phần Cài đặt quản trị và quản lý danh tính và quyền truy cập (IAM)

  2. Trong trường Project number (Số dự án), hãy sao chép giá trị.

Đặt dự án trên đám mây của dự án Apps Script

  1. Trong dự án Apps Script, hãy nhấp vào biểu tượng Project Settings (Cài đặt dự án) Biểu tượng cho phần cài đặt dự án.
  2. Trong mục Dự án Google Cloud Platform (GCP), hãy nhấp vào Thay đổi dự án.
  3. Trong mục Số dự án GCP, hãy dán số dự án trên Google Cloud.
  4. Nhấp vào Đặt dự án.

Cài đặt hoạt động triển khai thử nghiệm

  1. Trong dự án Apps Script, hãy nhấp vào biểu tượng Editor (Trình chỉnh sửa) .
  2. Mở tệp CreateConf.gs rồi nhấp vào Run (Chạy). Khi được nhắc, hãy cho phép tập lệnh này.
  3. Nhấp vào Triển khai > Kiểm thử các bản triển khai.
  4. Nhấp vào Cài đặt > Xong.

Chạy tập lệnh

  1. Truy cập vào calendar.google.com.
  2. Tạo sự kiện mới hoặc mở sự kiện hiện cóCreate a new event or open an existing one.
  3. Bên cạnh mục Thêm hội nghị truyền hình trên Google Meet, hãy nhấp vào biểu tượng Mũi tên xuống > Hội nghị truyền hình trên web của tôi. Lỗi Không tạo được hội nghị truyền hình xuất hiện vì tiện ích bổ sung không được kết nối với một giải pháp hội nghị truyền hình thực sự của bên thứ ba.

Các bước tiếp theo