Предварительный просмотр ссылок в сообщениях Google Chat

Чтобы предотвратить переключение контекста, когда пользователи делятся ссылкой в ​​Google Chat, ваше приложение Chat может предварительно просмотреть ссылку, прикрепив к их сообщению карточку, которая дает дополнительную информацию и позволяет людям совершать действия прямо из Google Chat.

В Google Chat дополнения отображаются пользователям как приложения Google Chat. Дополнительную информацию см. в обзоре расширения Google Chat .

Например, представьте себе пространство Google Chat, включающее всех агентов по обслуживанию клиентов компании, а также приложение Chat под названием Case-y. Агенты часто делятся ссылками на обращения в службу поддержки клиентов в пространстве чата, и каждый раз, когда они это делают, их коллегам приходится открывать ссылку на обращение, чтобы просмотреть такие подробности, как правопреемник, статус и тема. Аналогично, если кто-то хочет взять на себя ответственность за обращение или изменить его статус, ему необходимо открыть ссылку.

Предварительный просмотр ссылки позволяет резидентному приложению чата пространства Case-y прикреплять карточку с указанием правопреемника, статуса и темы всякий раз, когда кто-то делится ссылкой на обращение. Кнопки на карточке позволяют агентам взять на себя ответственность за обращение и изменить статус непосредственно из потока чата.

Когда кто-то добавляет ссылку в свое сообщение, появляется метка, сообщающая ему, что приложение чата может просмотреть ссылку.

Чип, указывающий, что приложение Chat может предварительно просмотреть ссылку

После отправки сообщения ссылка отправляется в приложение «Чат», которое затем генерирует и прикрепляет карточку к сообщению пользователя.

Приложение чата просматривает ссылку, прикрепив карточку к сообщению

Помимо ссылки, карточка предоставляет дополнительную информацию о ссылке, включая интерактивные элементы, такие как кнопки. Ваше приложение Chat может обновлять прикрепленную карточку в ответ на действия пользователя, например нажатия кнопок.

Если кто-то не хочет, чтобы приложение Chat просматривало его ссылку, прикрепив карточку к сообщению, он может запретить предварительный просмотр, нажав на чипе предварительного просмотра. Пользователи могут удалить прикрепленную карту в любое время, нажав «Удалить предварительный просмотр» .

Предварительные условия

Node.js

Надстройка Google Workspace, расширяющая Google Chat. Чтобы создать его, выполните краткое руководство по HTTP .

Скрипт приложений

Надстройка Google Workspace, расширяющая Google Chat. Чтобы создать его, выполните краткое руководство по Apps Script .

Зарегистрируйте определенные ссылки, такие как example.com , support.example.com и support.example.com/cases/ , в качестве шаблонов URL-адресов на странице конфигурации вашего приложения Chat в консоли Google Cloud, чтобы ваше приложение Chat могло их просмотреть.

Меню конфигурации предварительного просмотра ссылок

  1. Откройте консоль Google Cloud .
  2. Рядом с надписью «Google Cloud» нажмите стрелку и откройте проект приложения Chat.
  3. В поле поиска введите Google Chat API и нажмите Google Chat API .
  4. Нажмите «Управление» > «Конфигурация» .
  5. В разделе «Предварительный просмотр ссылок» добавьте или измените шаблон URL-адреса.
    1. Чтобы настроить предварительный просмотр ссылок для нового шаблона URL-адреса, нажмите «Добавить шаблон URL-адреса» .
    2. Чтобы изменить конфигурацию существующего шаблона URL-адреса, нажмите стрелку вниз .
  6. В поле Шаблон хоста введите домен шаблона URL-адреса. Приложение Chat будет просматривать ссылки на этот домен.

    Чтобы иметь ссылки предварительного просмотра приложения Chat для определенного субдомена, например subdomain.example.com , включите субдомен.

    Чтобы иметь ссылки на предварительный просмотр приложения Chat для всего домена, укажите в качестве поддомена подстановочный знак со звездочкой (*). Например, *.example.com соответствует subdomain.example.com и any.number.of.subdomains.example.com .

  7. В поле Префикс пути введите путь для добавления к домену шаблона хоста.

    Чтобы сопоставить все URL-адреса в домене шаблона узла, оставьте префикс пути пустым.

    Например, если шаблон хоста — support.example.com , чтобы сопоставить URL-адреса обращений, размещенных по адресу support.example.com/cases/ , введите cases/ .

  8. Нажмите Готово .

  9. Нажмите Сохранить .

Теперь, когда кто-то добавляет ссылку, соответствующую шаблону URL-адреса предварительного просмотра ссылки, на сообщение в пространстве чата, включающем ваше приложение Chat, ваше приложение просматривает ссылку.

После того как вы настроите предварительный просмотр для конкретной ссылки, ваше приложение Chat сможет распознать и просмотреть ссылку, прикрепив к ней дополнительную информацию.

Внутри пространств Chat, включающих ваше приложение Chat, когда чье-либо сообщение содержит ссылку, соответствующую шаблону URL-адреса предварительного просмотра ссылки, ваше приложение Chat получает объект события с MessagePayload . В полезных данных объект message.matchedUrl содержит ссылку, которую пользователь включил в сообщение:

JSON

message: {
  matchedUrl: {
    url: "https://support.example.com/cases/case123"
  },
  ... // other message attributes redacted
}

Проверив наличие поля matchedUrl в полезных данных события MESSAGE , ваше приложение чата может добавить информацию в сообщение с предварительно просмотренной ссылкой. Ваше приложение чата может либо ответить обычным текстовым сообщением, либо прикрепить карточку.

Ответить текстовым сообщением

Для базовых ответов ваше приложение чата может предварительно просмотреть ссылку, ответив текстовым сообщением на ссылку. В этом примере прикрепляется сообщение, повторяющее URL-адрес ссылки, соответствующий шаблону URL-адреса предварительного просмотра ссылки.

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // If the Chat app does not detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // Reply with a text message for URLs of the subdomain "text"
  if (chatMessage.matchedUrl.url.includes("text.example.com")) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
    }}}}};
  }
}

Скрипт приложений

/**
 * Reply to messages that have links whose URLs match the pattern
 * "text.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // If the Chat app doesn't detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // Reply with a text message for URLs of the subdomain "text".
  if (chatMessage.matchedUrl.url.includes("text.example.com")) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
    }}}}};
  }
}

Чтобы прикрепить карточку к просматриваемой ссылке, верните действие DataActions с объектом ChatDataActionMarkup типа UpdateInlinePreviewAction .

В следующем примере приложение Chat добавляет карточку предварительного просмотра к сообщениям, содержащим шаблон URL-адреса support.example.com .

Приложение чата просматривает ссылку, прикрепив карточку к сообщению

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // Attach a card to the message for URLs of the subdomain "support"
  if (chatMessage.matchedUrl.url.includes("support.example.com")) {
    // A hard-coded card is used in this example. In a real-life scenario,
    // the case information would be fetched and used to build the card.
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case basics',
        },
        sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
        ]}]
      }
    }]}}}};
  }
}

Скрипт приложений

В этом примере отправляется карточное сообщение, возвращая card JSON . Вы также можете воспользоваться карточной службой Apps Script .

/**
 * Attach a card to messages that have links whose URLs match the pattern
 * "support.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // Attach a card to the message for URLs of the subdomain "support".
  if (chatMessage.matchedUrl.url.includes("support.example.com")) {
    // A hard-coded card is used in this example. In a real-life scenario,
    // the case information would be fetched and used to build the card.
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case summary',
        },
        sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // Clicking this button triggers the execution of the function
          // "assign" from the Apps Script project.
          onClick: { action: { function: 'assign'}}
        }]}}
        ]}]
      }
    }]}}}};
  }
}

Ваше приложение Chat может обновлять карточку предварительного просмотра ссылки, когда пользователи взаимодействуют с ней, например нажимают кнопку на карточке.

Чтобы обновить карточку, ваше приложение чата должно вернуть действие DataActions с одним из следующих объектов ChatDataActionMarkup :

  • Если пользователь отправил сообщение, верните объект UpdateMessageAction .
  • Если приложение Chat отправило сообщение, верните объект UpdateInlinePreviewAction .

Чтобы определить, кто отправил сообщение, используйте полезные данные события ( buttonClickedPayload ), чтобы проверить, установлен ли отправитель ( message.sender.type ) HUMAN (пользователь) или BOT (приложение чата).

В следующем примере показано, как приложение чата обновляет предварительный просмотр ссылки всякий раз, когда пользователь нажимает кнопку «Назначить мне» , обновляя поле «Назначенный» карты и отключая кнопку.

Приложение чата просматривает ссылку с обновленной версией карточки, прикрепленной к сообщению.

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to clicks by assigning user and updating the card that was attached to a
 * message with a previewed link.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Action response depending on the original message.
 */
function handleCardClick(chatMessage) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case basics',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
      ]}]
    }
  }]};

  // Checks whether the message event originated from a human or a Chat app
  // to return the adequate action response.
  if(chatMessage.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

Скрипт приложений

В этом примере отправляется карточное сообщение, возвращая card JSON . Вы также можете воспользоваться карточной службой Apps Script .

/**
 * Assigns and updates the card that's attached to a message with a
 * previewed link of the pattern "support.example.com".
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 *
 * @return {Object} Action response depending on the message author.
 */
function assign(event) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case summary',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          onClick: { action: { function: 'assign'}}
        }]}}
      ]}]
    }
  }]};

  // Use the adequate action response type. It depends on whether the message
  // the preview link card is attached to was created by a human or a Chat app.
  if(event.chat.buttonClickedPayload.message.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

Ограничения и соображения

При настройке предварительного просмотра ссылок для приложения Chat обратите внимание на следующие ограничения и рекомендации:

  • Каждое приложение чата поддерживает предварительный просмотр ссылок до 5 шаблонов URL-адресов.
  • Приложения чата просматривают одну ссылку на каждое сообщение. Если в одном сообщении присутствует несколько доступных для предварительного просмотра ссылок, отображается только первая доступная для предварительного просмотра ссылка.
  • Приложения чата просматривают только ссылки, начинающиеся с https:// , поэтому https://support.example.com/cases/ являются предварительным просмотром, а support.example.com/cases/ нет.
  • Если сообщение не содержит другую информацию, которая отправляется в приложение Chat, например косую черту , в приложение Chat при предварительном просмотре ссылки отправляется только URL-адрес ссылки.
  • Если пользователь публикует ссылку, приложение чата может обновить карточку предварительного просмотра ссылки только в том случае, если пользователи взаимодействуют с карточкой, например при нажатии кнопки. Вы не можете вызвать метод update() API Chat для ресурса Message , чтобы асинхронно обновить сообщение пользователя.
  • Приложения чата должны просматривать ссылки для всех в пространстве, поэтому в сообщении должно быть опущено поле privateMessageViewer .

При реализации предварительного просмотра ссылок вам может потребоваться отладка приложения Chat, прочитав журналы приложения. Чтобы прочитать журналы, посетите Logs Explorer в консоли Google Cloud.