Важно ! Это краткое руководство предназначено только для поставщиков веб-конференций.
Следующее краткое руководство по дополнению Google Workspace расширяет возможности Календаря Google для синхронизации с вымышленной службой веб-конференций под названием My Web Conferencing. При редактировании событий календаря надстройка позволяет пользователям видеть «Мою веб-конференцию» в качестве опции конференц-связи.
В кратком руководстве показано создание конференции и синхронизация событий, но оно не работает, пока вы не подключите его к API решения для конференц-связи.
Цели
- Настройте свою среду.
- Настройте сценарий.
- Запустите сценарий.
Предварительные условия
- Веб-браузер с доступом в Интернет.
- Аккаунт Google Workspace (вам может потребоваться одобрение администратора).
- Проект Google Cloud .
Настройте свою среду
Откройте свой облачный проект в консоли Google Cloud.
Если он еще не открыт, откройте проект Cloud, который вы собираетесь использовать для этого примера:
- В консоли Google Cloud перейдите на страницу «Выбор проекта» .
- Выберите проект Google Cloud, который вы хотите использовать. Или нажмите «Создать проект» и следуйте инструкциям на экране. Если вы создаете проект Google Cloud, вам может потребоваться включить для него оплату .
Включите API календаря
В этом кратком руководстве используется расширенная служба календаря, которая обращается к API календаря.
Прежде чем использовать API Google, вам необходимо включить их в проекте Google Cloud. Вы можете включить один или несколько API в одном проекте Google Cloud.В своем проекте Google Cloud включите API календаря.
Настройка экрана согласия OAuth
Для надстроек Google Workspace требуется настройка экрана согласия. Настройка экрана согласия OAuth в надстройке Google Workspace определяет, что Google отображает пользователям.
- В консоли Google Cloud выберите > API и службы > Экран согласия OAuth .
- В качестве типа пользователя выберите «Внутренний» , затем нажмите «Создать» .
- Заполните форму регистрации приложения, затем нажмите « Сохранить и продолжить» .
На данный момент вы можете пропустить добавление областей и нажать « Сохранить и продолжить» . В будущем, когда вы создадите приложение для использования за пределами вашей организации Google Workspace, вам необходимо изменить тип пользователя на Внешний , а затем добавить области авторизации, необходимые вашему приложению.
- Просмотрите сводку регистрации приложения. Чтобы внести изменения, нажмите «Изменить» . Если регистрация приложения выглядит нормально, нажмите «Вернуться на панель управления» .
Настройте сценарий
Создайте проект скрипта приложений.
- Чтобы создать новый проект Apps Script, перейдите по адресу script.new .
- Нажмите «Проект без названия» .
- Переименуйте надстройку «Конференция» проекта Apps Script и нажмите «Переименовать» .
- Рядом с файлом
Code.gs
нажмите Еще > Переименовать . Назовите файлCreateConf
. - Нажмите « > «Скрипт» . файл»
- Назовите файл
Syncing
». Замените содержимое каждого файла следующим соответствующим кодом:
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; }
Синхронизация.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. } }
Нажмите «Настройки проекта». .
Установите флажок «Показывать файл манифеста «appsscript.json» в поле редактора» .
Нажмите
редактора» .Откройте файл
appsscript.json
и замените его содержимое следующим кодом, затем нажмите «Сохранить». .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" ] }
Скопируйте номер облачного проекта
- В консоли Google Cloud выберите > IAM и администрирование > Настройки .
- В поле Номер проекта скопируйте значение.
Установите облачный проект проекта Apps Script.
- В проекте Apps Script нажмите «Настройки проекта» . .
- В разделе «Проект Google Cloud Platform (GCP)» нажмите « Изменить проект» .
- В поле «Номер проекта GCP» вставьте номер проекта Google Cloud.
- Нажмите Установить проект .
Установите тестовое развертывание
- В проекте Apps Script нажмите редактора» .
- Откройте файл
CreateConf.gs
и нажмите «Выполнить» . При появлении запроса авторизуйте сценарий. - Щелкните Развертывание > Тестовые развертывания .
- Нажмите «Установить» > «Готово» .
Запустите сценарий
- Перейдите на сайт Calendar.google.com .
- Создайте новое событие или откройте существующее.
- Рядом с пунктом «Добавить видеоконференцию Google Meet» нажмите стрелку > Моя веб-конференция . Отображается ошибка «Не удалось создать конференцию», поскольку надстройка не подключена к реальному стороннему решению для проведения конференций.
Следующие шаги
- Расширьте Google Workspace с помощью дополнений
- Создание дополнений для Google Workspace
- Опубликовать приложение