Xem trước đường liên kết

Để ngăn việc chuyển đổi ngữ cảnh khi người dùng chia sẻ đường liên kết trong Google Chat, ứng dụng Chat có thể xem trước đường liên kết đó bằng cách đính kèm một thẻ vào tin nhắn của họ để cung cấp thêm thông tin và cho phép mọi người thực hiện hành động ngay trong Google Chat.

Ví dụ: hãy tưởng tượng một không gian trong Google Chat bao gồm tất cả nhân viên dịch vụ khách hàng của một công ty và một ứng dụng Chat có tên làCase-y. Nhân viên thường xuyên chia sẻ đường liên kết đến các trường hợp dịch vụ khách hàng trong không gian Chat. Mỗi khi họ chia sẻ, các đồng nghiệp phải mở đường liên kết đến trường hợp đó để xem thông tin chi tiết như người được giao, trạng thái và tiêu đề. Tương tự như vậy, nếu người dùng muốn sở hữu một yêu cầu hoặc thay đổi trạng thái, thì họ cần mở đường liên kết.

Tính năng xem trước đường liên kết cho phép ứng dụng Chat nội bộ của không gian, Case-y, đính kèm một thẻ cho biết người được giao, trạng thái và tiêu đề bất cứ khi nào ai đó chia sẻ đường liên kết đến trường hợp. Các nút trên thẻ cho phép nhân viên hỗ trợ nhận quyền sở hữu trường hợp và thay đổi trạng thái ngay trong luồng trò chuyện.

Khi có người thêm đường liên kết vào tin nhắn, một khối sẽ xuất hiện cho biết ứng dụng Chat có thể xem trước đường liên kết đó.

Khối cho biết ứng dụng Chat có thể xem trước đường liên kết

Sau khi gửi tin nhắn, đường liên kết sẽ được gửi đến ứng dụng Chat. Sau đó, ứng dụng này sẽ tạo và đính kèm thẻ vào tin nhắn của người dùng.

Ứng dụng trò chuyện xem trước đường liên kết bằng cách đính kèm thẻ vào tin nhắn

Bên cạnh đường liên kết, thẻ này còn cung cấp thêm thông tin về đường liên kết, bao gồm cả các thành phần tương tác như nút. Ứng dụng Chat của bạn có thể cập nhật thẻ đính kèm để phản hồi các lượt tương tác của người dùng, chẳng hạn như lượt nhấp vào nút.

Nếu không muốn ứng dụng Chat xem trước đường liên kết bằng cách đính kèm thẻ vào tin nhắn, người dùng có thể ngăn việc xem trước bằng cách nhấp vào trên khối xem trước. Người dùng có thể xoá thẻ đính kèm bất cứ lúc nào bằng cách nhấp vào Xoá bản xem trước.

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

Node.js

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn thành phần bắt đầu nhanh này.

Python

Một ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn thành phần bắt đầu nhanh này.

Java

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn tất hướng dẫn bắt đầu nhanh này.

Apps Script

Một ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat có thể tương tác trong Apps Script, hãy hoàn thành hướng dẫn nhanh này.

Đăng ký các đường liên kết cụ thể (chẳng hạn như example.com, support.example.comsupport.example.com/cases/) dưới dạng mẫu URL trên trang cấu hình của ứng dụng Chat trong Google Cloud Console để ứng dụng Chat có thể xem trước các đường liên kết đó.

Trình đơn cấu hình bản xem trước đường liên kết

  1. Mở Google Cloud Console.
  2. Bên cạnh "Google Cloud", hãy nhấp vào biểu tượng Mũi tên xuống rồi mở dự án của ứng dụng Chat.
  3. Trong trường tìm kiếm, hãy nhập Google Chat API rồi nhấp vào Google Chat API.
  4. Nhấp vào Quản lý > Cấu hình.
  5. Trong phần Bản xem trước đường liên kết, hãy thêm hoặc chỉnh sửa một mẫu URL.
    1. Để định cấu hình bản xem trước đường liên kết cho một mẫu URL mới, hãy nhấp vào Thêm mẫu URL.
    2. Để chỉnh sửa cấu hình cho một mẫu URL hiện có, hãy nhấp vào biểu tượng Mũi tên xuống .
  6. Trong trường Mẫu máy chủ lưu trữ, hãy nhập miền của mẫu URL. Ứng dụng Chat sẽ xem trước các đường liên kết đến miền này.

    Để ứng dụng Chat xem trước đường liên kết cho một miền con cụ thể, chẳng hạn như subdomain.example.com, hãy thêm miền con đó.

    Để ứng dụng Chat xem trước các đường liên kết cho toàn bộ miền, hãy chỉ định một ký tự đại diện có dấu hoa thị (*) làm miền con. Ví dụ: *.example.com khớp với subdomain.example.comany.number.of.subdomains.example.com.

  7. Trong trường Tiền tố đường dẫn, nhập đường dẫn để thêm vào miền mẫu máy chủ lưu trữ.

    Để so khớp tất cả URL trong miền mẫu máy chủ, hãy để trống Tiền tố đường dẫn.

    Ví dụ: nếu mẫu Máy chủ lưu trữ là support.example.com, thì để khớp với URL cho các trường hợp được lưu trữ tại support.example.com/cases/, hãy nhập cases/.

  8. Nhấp vào Xong.

  9. Nhấp vào Lưu.

Giờ đây, mỗi khi có người đưa đường liên kết khớp với mẫu URL xem trước đường liên kết vào tin nhắn trong phòng Chat có ứng dụng Chat, ứng dụng của bạn sẽ xem trước đường liên kết đó.

Sau khi bạn định cấu hình tính năng xem trước đường liên kết cho một đường liên kết nhất định, ứng dụng Chat có thể nhận dạng và xem trước đường liên kết đó bằng cách đính kèm thêm thông tin vào đường liên kết đó.

Bên trong không gian Chat có ứng dụng Chat, khi tin nhắn của một người chứa đường liên kết khớp với mẫu URL xem trước đường liên kết, ứng dụng Chat sẽ nhận được sự kiện tương tác MESSAGE. Tải trọng JSON cho sự kiện tương tác chứa trường matchedUrl:

JSON

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

Bằng cách kiểm tra sự hiện diện của trường matchedUrl trong tải trọng sự kiện MESSAGE, ứng dụng Chat của bạn có thể thêm thông tin vào thông báo bằng đường liên kết đã xem trước. Ứng dụng Chat có thể trả lời bằng tin nhắn văn bản cơ bản hoặc đính kèm thẻ.

Trả lời bằng tin nhắn văn bản

Đối với các câu trả lời cơ bản, ứng dụng Chat có thể xem trước một đường liên kết bằng cách trả lời bằng tin nhắn văn bản đơn giản về đường liên kết đó. Ví dụ này đính kèm một thông báo lặp lại URL của đường liên kết khớp với mẫu URL của bản xem trước đường liên kết.

Node.js

nút/preview-link/index.js
// Reply with a text message for URLs of the subdomain "text"
if (event.message.matchedUrl.url.includes("text.example.com")) {
  return {
    text: 'event.message.matchedUrl.url: ' + event.message.matchedUrl.url
  };
}

Python

python/preview-link/main.py
# Reply with a text message for URLs of the subdomain "text"
if 'text.example.com' in event.get('message').get('matchedUrl').get('url'):
  return {
    'text': 'event.message.matchedUrl.url: ' +
            event.get('message').get('matchedUrl').get('url')
  }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Reply with a text message for URLs of the subdomain "text"
if (event.at("/message/matchedUrl/url").asText().contains("text.example.com")) {
  return new Message().setText("event.message.matchedUrl.url: " +
    event.at("/message/matchedUrl/url").asText());
}

Apps Script

apps-script/preview-link/preview-link.gs
// Reply with a text message for URLs of the subdomain "text"
if (event.message.matchedUrl.url.includes("text.example.com")) {
  return {
    text: 'event.message.matchedUrl.url: ' + event.message.matchedUrl.url
  };
}

Để đính kèm một thẻ vào đường liên kết đã xem trước, hãy trả về một ActionResponse thuộc loại UPDATE_USER_MESSAGE_CARDS. Ví dụ này đính kèm một thẻ cơ bản.

Ứng dụng trò chuyện xem trước đường liên kết bằng cách đính kèm thẻ vào tin nhắn

Node.js

node/preview-link/index.js
// Attach a card to the message for URLs of the subdomain "support"
if (event.message.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 {
    actionResponse: { type: 'UPDATE_USER_MESSAGE_CARDS' },
    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',
            onClick: { action: { function: 'assign'}}
          }]}}
        ]}]
      }
    }]
  };
}

Python

python/preview-link/main.py
# Attach a card to the message for URLs of the subdomain "support"
if 'support.example.com' in event.get('message').get('matchedUrl').get('url'):
  # 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 {
    'actionResponse': { 'type': 'UPDATE_USER_MESSAGE_CARDS' },
    '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',
            'onClick': { 'action': { 'function': 'assign'}}
          }]}}
        ]}]
      }
    }]
  }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Attach a card to the message for URLs of the subdomain "support"
if (event.at("/message/matchedUrl/url").asText().contains("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 new Message()
    .setActionResponse(new ActionResponse()
      .setType("UPDATE_USER_MESSAGE_CARDS"))
    .setCardsV2(List.of(new CardWithId()
      .setCardId("attachCard")
      .setCard(new GoogleAppsCardV1Card()
        .setHeader(new GoogleAppsCardV1CardHeader()
          .setTitle("Example Customer Service Case")
          .setSubtitle("Case basics"))
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Case ID")
            .setText("case123")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Assignee")
            .setText("Charlie")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Status")
            .setText("Open")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Subject")
            .setText("It won't turn on...")),
          new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(
              new GoogleAppsCardV1Button()
                .setText("OPEN CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123"))),
              new GoogleAppsCardV1Button()
                .setText("RESOLVE CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123?resolved=y"))),
              new GoogleAppsCardV1Button()
                .setText("ASSIGN TO ME")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setAction(new GoogleAppsCardV1Action().setFunction("assign")))))))))))));
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/preview-link/preview-link.gs
// Attach a card to the message for URLs of the subdomain "support"
if (event.message.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 {
    actionResponse: { type: 'UPDATE_USER_MESSAGE_CARDS' },
    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',
            onClick: { action: { function: 'assign'}}
          }]}}
        ]}]
      }
    }]
  };
}

Ứng dụng Chat của bạn có thể cập nhật thẻ xem trước đường liên kết khi người dùng tương tác với thẻ đó, chẳng hạn như nhấp vào một nút trên thẻ.

Để cập nhật thẻ, ứng dụng Chat của bạn phải xử lý sự kiện tương tác CARD_CLICKED và trả về actionResponse dựa trên người đã gửi tin nhắn chứa bản xem trước đường liên kết:

  • Nếu người dùng gửi thông báo, hãy đặt actionResponse.type thành UPDATE_USER_MESSAGE_CARDS.
  • Nếu ứng dụng Chat đã gửi tin nhắn, hãy đặt actionResponse.type thành UPDATE_MESSAGE.

Để xác định người gửi thư, bạn có thể sử dụng trường message.sender.type của sự kiện tương tác để xem người gửi là người dùng HUMAN hay BOT.

Ví dụ sau đây cho thấy cách một ứng dụng Chat cập nhật bản xem trước đường liên kết bất cứ khi nào người dùng nhấp vào nút Gán cho tôi bằng cách cập nhật trường Người được giao của thẻ và tắt nút này.

Ứng dụng trò chuyện xem trước một đường liên kết có phiên bản thẻ mới cập nhật được đính kèm vào một tin nhắn

Node.js

node/preview-link/index.js
/**
 * Updates a card that was attached to a message with a previewed link.
 *
 * @param {Object} event The event object from Chat.
 *
 * @return {Object} Response from the Chat app. Either a new card attached to
 * the message with the previewed link, or an update to an existing card.
 */
function onCardClick(event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.action.actionMethodName === 'assign') {
    // 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.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    const actionResponseType = event.message.sender.type === 'HUMAN' ?
      'UPDATE_USER_MESSAGE_CARDS' :
      'UPDATE_MESSAGE';

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return {
      actionResponse: { type: actionResponseType },
      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,
              onClick: { action: { function: 'assign'}}
            }]}}
          ]}]
        }
      }]
    };
  }
}

Python

python/preview-link/main.py
def on_card_click(event: dict) -> dict:
  """Updates a card that was attached to a message with a previewed link."""
  # To respond to the correct button, checks the button's actionMethodName.
  if 'assign' == event.get('action').get('actionMethodName'):
    # 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.

    # Checks whether the message event originated from a human or a Chat app
    # and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    # "UPDATE_MESSAGE" if Chat app.
    actionResponseType = 'UPDATE_USER_MESSAGE_CARDS' if \
      event.get('message').get('sender').get('type') == 'HUMAN' else \
      'UPDATE_MESSAGE'

    # Returns the updated card that displays "You" for the assignee
    # and that disables the button.
    return {
      'actionResponse': { 'type': actionResponseType },
      '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,
              'onClick': { 'action': { 'function': 'assign'}}
            }]}}
          ]}]
        }
      }]
    }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Updates a card that was attached to a message with a previewed link.
Message onCardClick(JsonNode event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.at("/action/actionMethodName").asText().equals("assign")) {
    // 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.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    String actionResponseType =
      event.at("/message/sender/type").asText().equals("HUMAN")
      ? "UPDATE_USER_MESSAGE_CARDS" : "UPDATE_MESSAGE";

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return new Message()
    .setActionResponse(new ActionResponse()
      .setType(actionResponseType))
    .setCardsV2(List.of(new CardWithId()
      .setCardId("attachCard")
      .setCard(new GoogleAppsCardV1Card()
        .setHeader(new GoogleAppsCardV1CardHeader()
          .setTitle("Example Customer Service Case")
          .setSubtitle("Case basics"))
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Case ID")
            .setText("case123")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Assignee")
            // The assignee is now "You"
            .setText("You")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Status")
            .setText("Open")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Subject")
            .setText("It won't turn on...")),
          new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(
              new GoogleAppsCardV1Button()
                .setText("OPEN CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123"))),
              new GoogleAppsCardV1Button()
                .setText("RESOLVE CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123?resolved=y"))),
              new GoogleAppsCardV1Button()
                .setText("ASSIGN TO ME")
                // The button is now disabled
                .setDisabled(true)
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setAction(new GoogleAppsCardV1Action().setFunction("assign")))))))))))));
  }
  return null;
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/preview-link/preview-link.gs
/**
 * Updates a card that was attached to a message with a previewed link.
 *
 * @param {Object} event The event object from Chat.
 *
 * @return {Object} Response from the Chat app. Either a new card attached to
 * the message with the previewed link, or an update to an existing card.
 */
function onCardClick(event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.action.actionMethodName === 'assign') {
    // 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.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    const actionResponseType = event.message.sender.type === 'HUMAN' ?
      'UPDATE_USER_MESSAGE_CARDS' :
      'UPDATE_MESSAGE';

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return {
      actionResponse: { type: actionResponseType },
      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,
              onClick: { action: { function: 'assign'}}
            }]}}
          ]}]
        }
      }]
    };
  }
}

Giới hạn và cân nhắc

Khi bạn định cấu hình bản xem trước đường liên kết cho ứng dụng Chat, hãy lưu ý những giới hạn và điều cần cân nhắc sau:

  • Mỗi ứng dụng Chat hỗ trợ bản xem trước đường liên kết cho tối đa 5 mẫu URL.
  • Các ứng dụng nhắn tin sẽ xem trước một đường liên kết cho mỗi tin nhắn. Nếu một tin nhắn có nhiều đường liên kết có thể xem trước, thì chỉ đường liên kết có thể xem trước đầu tiên mới xem trước.
  • Các ứng dụng nhắn tin chỉ xem trước đường liên kết bắt đầu bằng https://, vì vậy, https://support.example.com/cases/ sẽ xem trước còn support.example.com/cases/ thì không.
  • Trừ phi tin nhắn bao gồm các thông tin khác được gửi đến ứng dụng Chat, chẳng hạn như lệnh dấu gạch chéo, chỉ có URL liên kết được gửi đến ứng dụng Chat bằng bản xem trước đường liên kết.
  • Nếu người dùng đăng đường liên kết, thì ứng dụng Chat chỉ có thể cập nhật thẻ xem trước đường liên kết nếu người dùng tương tác với thẻ đó, chẳng hạn như bằng một lượt nhấp vào nút. Bạn không thể gọi phương thức update() của API Chat trên tài nguyên Message để cập nhật thông báo của người dùng một cách không đồng bộ.
  • Các ứng dụng nhắn tin phải xem trước đường liên kết cho mọi người trong không gian, vì vậy, tin nhắn phải bỏ qua trường privateMessageViewer.

Khi triển khai bản xem trước đường liên kết, bạn có thể cần gỡ lỗi ứng dụng Chat bằng cách đọc nhật ký của ứng dụng. Để đọc nhật ký, hãy truy cập vào Trình khám phá nhật ký trên Google Cloud Console.