ดูตัวอย่างลิงก์ที่มีชิปอัจฉริยะ (ตัวอย่างสําหรับนักพัฒนาซอฟต์แวร์)

หน้านี้จะอธิบายวิธีสร้างส่วนเสริม Google Workspace ที่ช่วยให้ผู้ใช้ Google เอกสารแสดงตัวอย่างลิงก์จากบริการของบุคคลที่สาม

ส่วนเสริมของ Google Workspace จะตรวจหาลิงก์ของบริการและแจ้งให้ผู้ใช้ Google เอกสารดูตัวอย่างได้ คุณกําหนดค่าส่วนเสริมเพื่อดูตัวอย่างรูปแบบ URL ต่างๆ ได้ เช่น ลิงก์ไปยังประวัติการช่วยเหลือ โอกาสในการขาย และโปรไฟล์พนักงาน

หากต้องการแสดงตัวอย่างลิงก์ในเอกสารของ Google เอกสาร ผู้ใช้จะต้องโต้ตอบกับชิปอัจฉริยะและการ์ดตามขั้นตอนต่อไปนี้

ผู้ใช้ดูตัวอย่างการ์ด

เมื่อผู้ใช้พิมพ์หรือวาง URL ลงในเอกสาร Google เอกสารจะแจ้งให้ผู้ใช้ใส่ลิงก์แทนชิปอัจฉริยะ ชิปอัจฉริยะจะแสดงไอคอน และชื่อย่อหรือคําอธิบายเนื้อหาของลิงก์ เมื่อผู้ใช้วางเมาส์เหนือชิป ก็จะเห็นอินเทอร์เฟซการ์ดที่แสดงตัวอย่างข้อมูลเพิ่มเติมเกี่ยวกับไฟล์หรือลิงก์ดังกล่าว

วิดีโอต่อไปนี้แสดงวิธีที่ผู้ใช้แปลงลิงก์เป็นชิปอัจฉริยะและแสดงตัวอย่างการ์ด

สิ่งที่ต้องดำเนินการก่อน

Apps Script

Node.js

Python

Java

ไม่บังคับ: ตั้งค่าการตรวจสอบสิทธิ์กับบริการของบุคคลที่สาม

หากส่วนเสริมเชื่อมต่อกับบริการที่ต้องมีการให้สิทธิ์ ผู้ใช้ต้องตรวจสอบสิทธิ์กับบริการเพื่อดูตัวอย่างลิงก์ ซึ่งหมายความว่าเมื่อผู้ใช้วางลิงก์จากบริการของคุณลงในเอกสาร Google เอกสารเป็นครั้งแรก ส่วนเสริมจะต้องเรียกใช้ขั้นตอนการให้สิทธิ์

หากต้องการตั้งค่าบริการ OAuth หรือข้อความแจ้งการให้สิทธิ์ที่กําหนดเอง โปรดดูหนึ่งในคําแนะนําต่อไปนี้

ส่วนนี้จะอธิบายวิธีการตั้งค่าตัวอย่างลิงก์สําหรับส่วนเสริมของคุณ ซึ่งประกอบด้วยขั้นตอนต่อไปนี้

  1. กําหนดค่าตัวอย่างลิงก์ในทรัพยากรการทําให้ใช้งานได้ของส่วนเสริมหรือไฟล์ Manifest
  2. สร้างชิปอัจฉริยะและอินเทอร์เฟซการ์ดสําหรับลิงก์ของคุณ

กําหนดค่าตัวอย่างลิงก์

หากต้องการกําหนดค่าตัวอย่างลิงก์ ให้ระบุส่วนและฟิลด์ต่อไปนี้ในไฟล์การทําให้ใช้งานได้ของส่วนเสริมหรือไฟล์ Manifest

  1. ในส่วน addOns ให้เพิ่มช่อง docs เพื่อขยาย Google เอกสาร
  2. ในช่อง docs ให้ใช้ทริกเกอร์ linkPreviewTriggers ที่มี runFunction (คุณกําหนดฟังก์ชันนี้ในส่วนสร้างชิปอัจฉริยะและการ์ด)

    โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับช่องที่คุณสามารถระบุในทริกเกอร์ linkPreviewTriggers ได้ที่เอกสารอ้างอิงเกี่ยวกับไฟล์ Manifest ของ Apps Script หรือแหล่งข้อมูลการทําให้ใช้งานได้สําหรับรันไทม์อื่นๆ

  3. ในช่อง oauthScopes ให้เพิ่มขอบเขตhttps://www.googleapis.com/auth/workspace.linkpreviewเพื่อให้ผู้ใช้ให้สิทธิ์ส่วนเสริมเพื่อดูตัวอย่างลิงก์ต่างๆ ในนามของตนเองได้

โปรดดูส่วน "oauthScopes" และ "addons" ของทรัพยากรในการทําให้ใช้งานได้ที่กําหนดค่าตัวอย่างลิงก์สําหรับบริการกรณีการสนับสนุน

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://www.example.com/images/company-logo.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "logoUrl": "https://www.example.com/images/support-icon.png",
          "localizedLabelText": {
            "es": "Caso de soporte"
          }
        }
      ]
    }
  }
}

ในตัวอย่างนี้ ตัวอย่างส่วนเสริมของ Google Workspace จะลิงก์ไปที่บริการกรณีการสนับสนุนของบริษัท ส่วนเสริมจะระบุรูปแบบ URL 3 รายการ เพื่อดูตัวอย่างลิงก์ เมื่อใดก็ตามที่ลิงก์ตรงกับรูปแบบ URL รูปแบบใดรูปแบบหนึ่งในเอกสารของ Google เอกสาร ฟังก์ชันเรียกกลับ caseLinkPreview จะสร้างและแสดงชิปอัจฉริยะและการ์ด

สร้างชิปและการ์ดอัจฉริยะ

หากต้องการส่งคืนชิปอัจฉริยะและการ์ดสําหรับลิงก์ คุณต้องใช้ฟังก์ชันใดก็ตามที่คุณระบุไว้ในออบเจ็กต์ linkPreviewTriggers

เมื่อผู้ใช้โต้ตอบกับลิงก์ที่ตรงกับรูปแบบ URL ที่ระบุ ทริกเกอร์ linkPreviewTriggers จะเริ่มทํางานแล้ว ฟังก์ชันเรียกกลับจะส่งออบเจ็กต์ออบเจ็กต์ docs.matchedUrl.url เป็นอาร์กิวเมนต์ คุณใช้เพย์โหลดของออบเจ็กต์เหตุการณ์นี้เพื่อสร้างชิปอัจฉริยะและการ์ดสําหรับตัวอย่างลิงก์

เช่น สําหรับส่วนเสริมที่ระบุรูปแบบ URL example.com/casesหากผู้ใช้ดูตัวอย่างลิงก์ https://www.example.com/cases/123456 ระบบจะแสดงผลเปย์โหลดกิจกรรมต่อไปนี้

JSON

{
  "docs": {
    "matchedUrl": {
        "url": "https://www.example.com/support/cases/123456"
    }
  }
}

ในการสร้างอินเทอร์เฟซการ์ด คุณต้องใช้วิดเจ็ตเพื่อแสดงข้อมูลเกี่ยวกับลิงก์ คุณยังสร้างการดําเนินการที่ให้ผู้ใช้เปิดลิงก์หรือแก้ไขเนื้อหาได้อีกด้วย ดูรายการวิดเจ็ตและการดําเนินการที่มีอยู่ได้ที่คอมโพเนนต์ที่รองรับการ์ดตัวอย่าง

วิธีสร้างชิปและการ์ดอัจฉริยะสําหรับตัวอย่างลิงก์

  1. ใช้ฟังก์ชันที่คุณระบุในส่วน linkPreviewTriggers ของทรัพยากรการทําให้ใช้งานได้ของส่วนเสริมหรือไฟล์ Manifest ดังนี้
    1. ฟังก์ชันต้องยอมรับออบเจ็กต์เหตุการณ์ที่มี docs.matchedUrl.url เป็นอาร์กิวเมนต์และส่งคืนออบเจ็กต์ Card รายการเดียว
    2. หากบริการของคุณต้องการการให้สิทธิ์ ฟังก์ชันนั้นจะต้องเรียกใช้ขั้นตอนการให้สิทธิ์ด้วย
  2. ในการ์ดการเรียกแต่ละการ์ด ให้ใช้ฟังก์ชันเรียกกลับที่ใช้เพื่อให้อินเทอร์แอ็กทีฟของวิดเจ็ตสําหรับอินเทอร์เฟซ ตัวอย่างเช่น หากคุณใส่ปุ่มในอินเทอร์เฟซ ปุ่มนั้นควรมี Action ที่แนบมา รวมถึงฟังก์ชันการเรียกกลับที่ทํางานเมื่อคลิกปุ่ม

โค้ดต่อไปนี้จะสร้างฟังก์ชันเรียกกลับ caseLinkPreview:

Apps Script

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // Returns the card.
    // Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(caseHeader)
      .addSection(CardService.newCardSection().addWidget(caseDescription))
      .build();
  }
}

Node.js

node/preview-links/index.js
/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}

Python

python/preview-links/main.py

def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
/**
 * Creates a case link preview card.
 *
 * @param url A URL.
 * @return A case link preview card.
 */
Card caseLinkPreview(String url) {
  String[] segments = url.split("/");
  String caseId = segments[segments.length - 1];

  CardHeader cardHeader = new CardHeader();
  cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

  TextParagraph textParagraph = new TextParagraph();
  textParagraph.setText("Customer can't view title on mobile device.");

  WidgetMarkup widget = new WidgetMarkup();
  widget.setTextParagraph(textParagraph);
  Section section = new Section();
  section.setWidgets(List.of(widget));

  Card card = new Card();
  card.setHeader(cardHeader);
  card.setSections(List.of(section));

  return card;
}

คอมโพเนนต์ที่รองรับการ์ดตัวอย่าง

ส่วนเสริมของ Google Workspace รองรับวิดเจ็ตและการดําเนินการต่อไปนี้สําหรับการ์ดตัวอย่างลิงก์

Apps Script

ช่องบริการการ์ด Type
TextParagraph วิดเจ็ต
DecoratedText วิดเจ็ต
Image วิดเจ็ต
IconImage วิดเจ็ต
ButtonSet วิดเจ็ต
TextButton วิดเจ็ต
ImageButton วิดเจ็ต
Grid วิดเจ็ต
Divider วิดเจ็ต
OpenLink แอ็กชัน
Navigation การดําเนินการ
รองรับเฉพาะเมธอด updateCard เท่านั้น

JSON

ช่องการ์ด (google.apps.card.v1) Type
TextParagraph วิดเจ็ต
DecoratedText วิดเจ็ต
Image วิดเจ็ต
Icon วิดเจ็ต
ButtonList วิดเจ็ต
Button วิดเจ็ต
Grid วิดเจ็ต
Divider วิดเจ็ต
OpenLink แอ็กชัน
Navigation การดําเนินการ
รองรับเฉพาะวิธี updateCard

ตัวอย่างที่สมบูรณ์: ส่วนเสริมของกรณีการสนับสนุน

ตัวอย่างต่อไปนี้มีส่วนเสริม Google Workspace ที่แสดงตัวอย่างลิงก์ไปยังประวัติการช่วยเหลือและโปรไฟล์ของพนักงาน

ตัวอย่างนี้

  • ตัวอย่างจะลิงก์ไปยังประวัติการช่วยเหลือ เช่น https://www.example.com/support/cases/1234 ชิปอัจฉริยะจะแสดงไอคอนการสนับสนุน และการ์ดตัวอย่างจะมีรหัสกรณีและคําอธิบาย
  • แสดงตัวอย่างลิงก์ไปยังตัวแทนกรณีการสนับสนุน เช่น https://www.example.com/people/rosario-cruz ชิปอัจฉริยะจะแสดงไอคอนบุคคล และการ์ดตัวอย่างจะประกอบด้วยชื่อ อีเมล ตําแหน่งงาน และรูปโปรไฟล์ของพนักงาน
  • หากตั้งค่าภาษาของผู้ใช้เป็นภาษาสเปน ชิปอัจฉริยะจะแปล labelText เป็นภาษาสเปน

แหล่งข้อมูลเพื่อการนําไปใช้งาน

Apps Script

{
  "timeZone": "America/New_York",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "peopleLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

JSON

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

รหัส

Apps Script

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // Returns the card.
    // Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(caseHeader)
      .addSection(CardService.newCardSection().addWidget(caseDescription))
      .build();
  }
}


/**
* Entry point for an employee profile link preview
*
* @param {!Object} event
* @return {!Card}
*/
function peopleLinkPreview(event) {

  // If the event object URL matches a specified pattern for employee profile links.
  if (event.docs.matchedUrl.url) {

    // Builds a preview card with an employee's name, title, email, and profile photo.
    const userHeader = CardService.newCardHeader().setTitle("Rosario Cruz");
    const userImage = CardService.newImage()
      .setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");
    const userInfo = CardService.newDecoratedText()
      .setText("rosario@example.com")
      .setBottomLabel("Case Manager")
      .setIcon(CardService.Icon.EMAIL);
    const userSection = CardService.newCardSection()
      .addWidget(userImage)
      .addWidget(userInfo);

    // Returns the card. Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(userHeader)
      .addSection(userSection)
      .build();
  }
}

Node.js

node/preview-links/index.js
const UrlParser = require('url');

/**
 * Responds to any HTTP request.
 *
 * @param {Object} req HTTP request context.
 * @param {Object} res HTTP response context.
 */
exports.createLinkPreview = (req, res) => {
  const event = req.body;
  if (event.docs.matchedUrl.url) {
    res.json(createCard(event.docs.matchedUrl.url));
  }
};

/**
 * Creates a preview link card for either a case link or people link.
 * 
 * @param {!String} url
 * @return {!Card}
 */
function createCard(url) {
  const parsedUrl = UrlParser.parse(url);
  if (parsedUrl.hostname === 'www.example.com') {
    if (parsedUrl.path.startsWith('/support/cases/')) {
      return caseLinkPreview(url);
    }

    if (parsedUrl.path.startsWith('/people/')) {
      return peopleLinkPreview();
    }
  }
}


/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}


/**
 * An employee profile link preview.
 *
 * @return {!Card}
 */
function peopleLinkPreview() {

  // Builds a preview card with an employee's name, title, email, and profile photo.
  // Returns the card. Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: "Rosario Cruz"
    },
    sections: [{
      widgets: [
        {
          image: {
            imageUrl: 'https://developers.google.com/workspace/add-ons/images/employee-profile.png'
          }
        }, {
          keyValue: {
            icon: "EMAIL",
            content: "rosario@example.com",
            bottomLabel: "Case Manager"
          }
        }
      ]
    }]
  };
}

Python

python/preview-links/main.py
from typing import Any, Mapping
from urllib.parse import urlparse

import flask
import functions_framework


@functions_framework.http
def create_link_preview(req: flask.Request):
    """Responds to any HTTP request.
    Args:
      req: HTTP request context.
    Returns:
      The response object.
    """
    event = req.get_json(silent=True)
    if event["docs"]["matchedUrl"]["url"]:
        return create_card(event["docs"]["matchedUrl"]["url"])


def create_card(url):
    """Creates a preview link card for either a case link or people link.
    Args:
      url: The matched url.
    Returns:
      A case link preview card or a people link preview card.
    """
    parsed_url = urlparse(url)
    if parsed_url.hostname != "www.example.com":
        return {}

    if parsed_url.path.startswith("/support/cases/"):
        return case_link_preview(url)

    if parsed_url.path.startswith("/people/"):
        return people_link_preview()

    return {}




def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }




def people_link_preview():
    """An employee profile link preview.
    Returns:
      A people link preview card.
    """

    # Builds a preview card with an employee's name, title, email, and profile photo.
    # Returns the card. Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": "Rosario Cruz"},
        "sections": [
            {
                "widgets": [
                    {
                        "image": {
                            "imageUrl": "https:#developers.google.com/workspace/add-ons/images/employee-profile.png"
                        }
                    },
                    {
                        "keyValue": {
                            "icon": "EMAIL",
                            "content": "rosario@example.com",
                            "bottomLabel": "Case Manager",
                        }
                    },
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
import com.google.api.services.chat.v1.model.Card;
import com.google.api.services.chat.v1.model.CardHeader;
import com.google.api.services.chat.v1.model.Image;
import com.google.api.services.chat.v1.model.KeyValue;
import com.google.api.services.chat.v1.model.Section;
import com.google.api.services.chat.v1.model.TextParagraph;
import com.google.api.services.chat.v1.model.WidgetMarkup;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class PreviewLink implements HttpFunction {
  private static final Gson gson = new Gson();

  /**
   * Responds to any HTTP request.
   *
   * @param request  An HTTP request context.
   * @param response An HTTP response context.
   */
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
    String url = body.getAsJsonObject("docs")
        .getAsJsonObject("matchedUrl")
        .get("url")
        .getAsString();

    response.getWriter().write(gson.toJson(createCard(url)));
  }

  /**
   * Creates a preview link card for either a case link or people link.
   *
   * @param url A URL.
   * @return A case link preview card or a people link preview card.
   */
  Card createCard(String url) throws MalformedURLException {
    URL parsedURL = new URL(url);

    if (!parsedURL.getHost().equals("www.example.com")) {
      return new Card();
    }

    if (parsedURL.getPath().startsWith("/support/cases/")) {
      return caseLinkPreview(url);
    }

    if (parsedURL.getPath().startsWith("/people/")) {
      return peopleLinkPreview();
    }

    return new Card();
  }


  /**
   * Creates a case link preview card.
   *
   * @param url A URL.
   * @return A case link preview card.
   */
  Card caseLinkPreview(String url) {
    String[] segments = url.split("/");
    String caseId = segments[segments.length - 1];

    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

    TextParagraph textParagraph = new TextParagraph();
    textParagraph.setText("Customer can't view title on mobile device.");

    WidgetMarkup widget = new WidgetMarkup();
    widget.setTextParagraph(textParagraph);
    Section section = new Section();
    section.setWidgets(List.of(widget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }


  /**
   * Creates a people link preview card.
   *
   * @return A people link preview card.
   */
  Card peopleLinkPreview() {
    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle("Rosario Cruz");

    Image image = new Image();
    image.setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");

    WidgetMarkup imageWidget = new WidgetMarkup();
    imageWidget.setImage(image);

    KeyValue keyValue = new KeyValue();
    keyValue.setIcon("EMAIL");
    keyValue.setContent("rosario@example.com");
    keyValue.setBottomLabel("Case Manager");

    WidgetMarkup keyValueWidget = new WidgetMarkup();
    keyValueWidget.setKeyValue(keyValue);

    Section section = new Section();
    section.setWidgets(List.of(imageWidget, keyValueWidget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }

}