תצוגה מקדימה של הקישורים

כדי למנוע מעבר הקשר כשמשתמשים משתפים קישור ב-Google Chat, אפליקציית Chat יכולה להציג תצוגה מקדימה של הקישור על ידי צירוף כרטיס להודעה. הכרטיס יכלול מידע נוסף ויאפשר לאנשים לבצע פעולות ישירות מ-Google Chat.

לדוגמה, נניח שיש מרחב ב-Google Chat שכולל את כל נציגי שירות הלקוחות של חברה מסוימת, וגם אפליקציית Chat בשם Case-y. נציגי שירות לקוחות משתפים לעיתים קרובות קישורים לפנייות לשירות לקוחות במרחב הצ'אט, ובכל פעם שהם עושים זאת, הקולגות שלהם צריכים לפתוח את הקישור לפנייה כדי לראות פרטים כמו הנציג שאליו הוקצתה הפנייה, הסטטוס והנושא. באופן דומה, אם מישהו רוצה לקבל בעלות על פנייה או לשנות את הסטטוס שלה, הוא צריך לפתוח את הקישור.

התצוגה המקדימה של קישורים מאפשרת לאפליקציית Chat שפועלת במרחב, Case-y, לצרף כרטיס עם פרטים על המקרה, כמו המקצה, הסטטוס והנושא, בכל פעם שמישהו משתף קישור למקרה. הכפתורים בכרטיס מאפשרים לנציגים לקבל בעלות על הפנייה ולשנות את הסטטוס שלה ישירות מזרם הצ'אט.

כשמישהו מוסיף קישור להודעה שלו, מופיע צ'יפ שמודיע לו שאפליקציית Chat עשויה להציג תצוגה מקדימה של הקישור.

צ'יפ שמציין שאפליקציית Chat עשויה להציג תצוגה מקדימה של קישור

אחרי שליחת ההודעה, הקישור נשלח לאפליקציית Chat, שיוצרת ומצרפת את הכרטיס להודעה של המשתמש.

אפליקציית Chat מציגה תצוגה מקדימה של קישור על ידי צירוף כרטיס להודעה

בכרטיס מוצג מידע נוסף על הקישור, כולל רכיבים אינטראקטיביים כמו לחצנים. אפליקציית הצ'אט יכולה לעדכן את הכרטיס המצורף בתגובה לאינטראקציות של המשתמשים, כמו קליקים על לחצנים.

אם מישהו לא רוצה שאפליקציית Chat תציג תצוגה מקדימה של הקישור שלו על ידי צירוף כרטיס להודעה, הוא יכול למנוע את התצוגה המקדימה על ידי לחיצה על בצ'יפ התצוגה המקדימה. המשתמשים יכולים להסיר את הכרטיס המצורף מתי שרוצים על ידי לחיצה על הסרת התצוגה המקדימה.

דרישות מוקדמות

Node.js

אפליקציית Google Chat שמקבלת אירועי אינטראקציה ומגיבה להם. כדי ליצור אפליקציה אינטראקטיבית ל-Chat באמצעות שירות HTTP, צריך לפעול לפי המדריך למתחילים.

Python

אפליקציית Google Chat שמקבלת אירועי אינטראקציה ומגיבה להם. כדי ליצור אפליקציה אינטראקטיבית ל-Chat באמצעות שירות HTTP, צריך לפעול לפי המדריך למתחילים.

Java

אפליקציית Google Chat שמקבלת אירועי אינטראקציה ומגיבה להם. כדי ליצור אפליקציה אינטראקטיבית ל-Chat באמצעות שירות HTTP, צריך לפעול לפי המדריך למתחילים.

Apps Script

אפליקציית Google Chat שמקבלת אירועי אינטראקציה ומגיבה להם. כדי ליצור אפליקציה אינטראקטיבית ל-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. לוחצים על שמירה.

מעכשיו, בכל פעם שמישהו יכלול בהודעה במרחב ב-Chat שבו מותקנת אפליקציית Chat שלכם קישור שתואם לתבנית של כתובת URL לתצוגה מקדימה של קישור, האפליקציה שלכם תציג תצוגה מקדימה של הקישור.

אחרי שמגדירים תצוגה מקדימה של קישור מסוים, אפליקציית Chat יכולה לזהות את הקישור ולהציג אותו בתצוגה מקדימה על ידי הוספת מידע נוסף אליו.

במרחבים ב-Chat שכוללים את אפליקציית Chat שלכם, כשמישהו שולח הודעה שמכילה קישור שתואם לתבנית של כתובת URL לתצוגה מקדימה של קישור, אפליקציית Chat שלכם מקבלת אירוע אינטראקציה מסוג MESSAGE. מטען ה-JSON של אירוע האינטראקציה מכיל את השדה matchedUrl:

JSON

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

אפליקציית Chat יכולה להוסיף מידע להודעה עם הקישור שמוצגת לגביו תצוגה מקדימה, על ידי בדיקה אם השדה matchedUrl קיים במטען הייעודי (payload) של אירוע MESSAGE. אפליקציית Chat יכולה לענות באמצעות הודעת טקסט בסיסית או לצרף כרטיס.

איך עונים להודעות טקסט

כדי לקבל תשובות בסיסיות, אפליקציית Chat יכולה להציג תצוגה מקדימה של קישור על ידי שליחת תשובה עם הודעת טקסט פשוטה לקישור. בדוגמה הזו מצורפת הודעה שחוזרת על כתובת ה-URL של הקישור שתואמת לתבנית של כתובת URL של תצוגה מקדימה של קישור.

Node.js

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

כדי לצרף כרטיס לקישור שמוצגת לו תצוגה מקדימה, מחזירים ActionResponse מסוג UPDATE_USER_MESSAGE_CARDS. בדוגמה הזו מצורף כרטיס בסיסי.

אפליקציית Chat מציגה תצוגה מקדימה של קישור על ידי צירוף כרטיס להודעה

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

בדוגמה הזו נשלחת הודעה בכרטיס על ידי החזרת JSON של הכרטיס. אפשר גם להשתמש בשירות הכרטיסים של 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'}}
          }]}}
        ]}]
      }
    }]
  };
}

אפליקציית Chat יכולה לעדכן את כרטיס התצוגה המקדימה של הקישור כשמשתמשים מבצעים אינטראקציה עם הכרטיס, למשל לחיצה על לחצן בכרטיס.

כדי לעדכן את הכרטיס, אפליקציית Chat צריכה לטפל באירוע האינטראקציה CARD_CLICKED ולהחזיר actionResponse בהתאם למי ששלח את ההודעה שמכילה את התצוגה המקדימה של הקישור:

  • אם משתמש שלח את ההודעה, צריך להגדיר את הערך של actionResponse.type ל-UPDATE_USER_MESSAGE_CARDS.
  • אם האפליקציה של Chat שלחה את ההודעה, מגדירים את actionResponse.type ל-UPDATE_MESSAGE.

כדי לדעת מי שלח את ההודעה, אפשר להשתמש בשדה message.sender.type של אירוע האינטראקציה כדי לראות אם השולח היה משתמש HUMAN או BOT.

בדוגמה הבאה אפשר לראות איך אפליקציית Chat מעדכנת תצוגה מקדימה של קישור בכל פעם שמשתמש לוחץ על הלחצן הקצאה לי. האפליקציה מעדכנת את השדה מקבל ההקצאה בכרטיס ומשביתה את הלחצן.

תצוגה מקדימה של קישור באפליקציית Chat עם גרסה מעודכנת של כרטיס שמצורף להודעה

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

בדוגמה הזו נשלחת הודעה בכרטיס על ידי החזרת JSON של הכרטיס. אפשר גם להשתמש בשירות הכרטיסים של 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'}}
            }]}}
          ]}]
        }
      }]
    };
  }
}

מגבלות ושיקולים

כשמגדירים תצוגות מקדימות של קישורים לאפליקציית Chat, חשוב לשים לב למגבלות ולשיקולים הבאים:

  • כל אפליקציה ל-Chat תומכת בתצוגה מקדימה של קישורים לעד 5 תבניות של כתובות URL.
  • ב-Chat, מוצגת תצוגה מקדימה של קישור אחד לכל הודעה. אם יש כמה קישורים שאפשר לראות את התצוגה המקדימה שלהם בהודעה אחת, רק התצוגה המקדימה של הקישור הראשון תוצג.
  • באפליקציות צ'אט מוצגת תצוגה מקדימה רק לקישורים שמתחילים ב-https://, ולכן https://support.example.com/cases/ מוצגת תצוגה מקדימה, אבל support.example.com/cases/ לא.
  • אלא אם ההודעה כוללת מידע אחר שנשלח לאפליקציית Chat, כמו פקודת לוכסן, רק כתובת ה-URL של הקישור נשלחת לאפליקציית Chat בתצוגה מקדימה של קישור.
  • אם משתמש מפרסם את הקישור, אפליקציית Chat יכולה לעדכן את כרטיס התצוגה המקדימה של הקישור רק אם משתמשים מבצעים אינטראקציה עם הכרטיס, למשל לחיצה על לחצן. אי אפשר להפעיל את השיטה update() של Chat API במשאב Message כדי לעדכן הודעה של משתמש באופן אסינכרוני.
  • אפליקציות ל-Chat צריכות להציג תצוגה מקדימה של קישורים לכל המשתתפים במרחב, ולכן ההודעה לא יכולה לכלול את השדה privateMessageViewer.

במהלך ההטמעה של התצוגה המקדימה של הקישורים, יכול להיות שתצטרכו לנפות באגים באפליקציית Chat על ידי קריאת היומנים של האפליקציה. כדי לקרוא את היומנים, נכנסים אל Logs Explorer במסוף Google Cloud.