स्मार्ट चिप में मौजूद लिंक की झलक देखना

इस पेज पर, Google Workspace ऐड-ऑन बनाने का तरीका बताया गया है. इससे Google Docs के उपयोगकर्ता, तीसरे पक्ष की सेवा के लिंक की झलक देख सकते हैं.

Google Workspace ऐड-ऑन आपकी सेवा के लिंक का पता लगा सकता है और Google Docs के उपयोगकर्ताओं को, उनकी झलक देखने का अनुरोध कर सकता है. एक से ज़्यादा यूआरएल पैटर्न की झलक देखने के लिए, ऐड-ऑन को कॉन्फ़िगर किया जा सकता है. जैसे, सपोर्ट केस के लिंक, सेल्स लीड, और कर्मचारियों की प्रोफ़ाइल.

Google Docs दस्तावेज़ में लिंक की झलक देखने के लिए, उपयोगकर्ता स्मार्ट चिप और कार्ड का इस्तेमाल करते हैं:

उपयोगकर्ता किसी कार्ड की झलक देखता है

जब लोग किसी दस्तावेज़ में कोई यूआरएल टाइप या चिपकाते हैं, तो Google Docs उनसे लिंक को स्मार्ट चिप से बदलने के लिए कहता है. स्मार्ट चिप में एक आइकॉन और लिंक के कॉन्टेंट का छोटा टाइटल या ब्यौरा दिखता है. जब लोग चिप पर कर्सर घुमाते हैं, तो उन्हें एक कार्ड इंटरफ़ेस दिखता है, जिसमें फ़ाइल या लिंक के बारे में ज़्यादा जानकारी होती है.

नीचे दिए गए वीडियो में दिखाया गया है कि उपयोगकर्ता किसी लिंक को स्मार्ट चिप में कैसे बदलता है और कार्ड की झलक कैसे दिखाता है:

ज़रूरी शर्तें

Apps Script

Node.js

के तौर पर इस्तेमाल करने के लिए लिखे गए हैं

Python

Java

ज़रूरी नहीं: तीसरे पक्ष की सेवा के लिए पुष्टि करने की सुविधा सेट अप करना

अगर आपका ऐड-ऑन किसी ऐसी सेवा से कनेक्ट होता है जिसके लिए अनुमति की ज़रूरत है, तो लिंक की झलक देखने के लिए उपयोगकर्ताओं को सेवा की पुष्टि करनी होगी. इसका मतलब है कि जब उपयोगकर्ता पहली बार Google Docs दस्तावेज़ में आपकी सेवा का कोई लिंक चिपकाते हैं, तो आपके ऐड-ऑन को ऑथराइज़ेशन फ़्लो शुरू करना होगा.

OAuth सेवा या कस्टम ऑथराइज़ेशन प्रॉम्प्ट सेट अप करने के लिए, इनमें से कोई एक गाइड देखें:

इस सेक्शन में अपने ऐड-ऑन के लिए लिंक की झलक सेट अप करने का तरीका बताया गया है. इसमें, ये चरण शामिल हैं:

  1. अपने ऐड-ऑन के डिप्लॉयमेंट संसाधन या मेनिफ़ेस्ट फ़ाइल में लिंक की झलक कॉन्फ़िगर करने का तरीका अपनाएं.
  2. अपने लिंक के लिए, स्मार्ट चिप और कार्ड का इंटरफ़ेस बनाएं.

लिंक की झलक कॉन्फ़िगर करें

लिंक की झलक कॉन्फ़िगर करने के लिए, अपने ऐड-ऑन के डिप्लॉयमेंट संसाधन या मेनिफ़ेस्ट फ़ाइल में ये सेक्शन और फ़ील्ड तय करें:

  1. addOns सेक्शन में जाकर, Google Docs को बड़ा करने के लिए docs फ़ील्ड जोड़ें.
  2. docs फ़ील्ड में, linkPreviewTriggers ट्रिगर लागू करें जिसमें runFunction शामिल हो. इस फ़ंक्शन के बारे में नीचे दिए गए सेक्शन स्मार्ट चिप और कार्ड बनाएं में बताया गया है.

    linkPreviewTriggers ट्रिगर में कौनसे फ़ील्ड तय किए जा सकते हैं, इस बारे में जानने के लिए, 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 ऐड-ऑन की झलक दिखाने वाले लिंक. लिंक की झलक देखने के लिए, ऐड-ऑन तीन यूआरएल पैटर्न के बारे में बताता है. जब भी कोई लिंक, Google Docs दस्तावेज़ में मौजूद किसी भी यूआरएल पैटर्न से मेल खाता है, तो कॉलबैक फ़ंक्शन caseLinkPreview, स्मार्ट चिप और कार्ड बनाता है और दिखाता है.

स्मार्ट चिप और कार्ड बनाना

किसी लिंक का स्मार्ट चिप और कार्ड दिखाने के लिए, आपको वे सभी फ़ंक्शन लागू करने होंगे जिन्हें आपने linkPreviewTriggers ऑब्जेक्ट में बताया है.

जब कोई उपयोगकर्ता, दिए गए यूआरएल पैटर्न से मैच करने वाले लिंक के साथ इंटरैक्ट करता है, तो linkPreviewTriggers ट्रिगर फ़ायर होता है और उसका कॉलबैक फ़ंक्शन, इवेंट ऑब्जेक्ट docs.matchedUrl.url को आर्ग्युमेंट के तौर पर पास करता है. इस इवेंट ऑब्जेक्ट के पेलोड का इस्तेमाल, लिंक की झलक के लिए स्मार्ट चिप और कार्ड बनाने में किया जाता है.

उदाहरण के लिए, example.com/cases यूआरएल पैटर्न के बारे में बताने वाले ऐड-ऑन के लिए, अगर उपयोगकर्ता लिंक https://www.example.com/cases/123456 की झलक दिखाता है, तो नीचे दिया गया इवेंट पेलोड दिखाया जाता है:

JSON

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

कार्ड का इंटरफ़ेस बनाने के लिए, लिंक के बारे में जानकारी दिखाने के लिए विजेट का इस्तेमाल किया जाता है. ऐसी कार्रवाइयां भी बनाई जा सकती हैं जो उपयोगकर्ताओं को लिंक खोलने या उसके कॉन्टेंट में बदलाव करने की सुविधा दें. उपलब्ध विजेट और कार्रवाइयों की सूची के लिए, झलक कार्ड के लिए इस्तेमाल किए जा सकने वाले कॉम्पोनेंट देखें.

लिंक की झलक के लिए स्मार्ट चिप और कार्ड बनाने के लिए:

  1. वह फ़ंक्शन लागू करें जो आपने अपने ऐड-ऑन के डिप्लॉयमेंट रिसॉर्स के linkPreviewTriggers सेक्शन में या मेनिफ़ेस्ट फ़ाइल में बताया है:
    1. फ़ंक्शन को एक ऐसे इवेंट ऑब्जेक्ट को स्वीकार करना होगा जिसमें docs.matchedUrl.url एक तर्क के तौर पर हो और एक ही Card ऑब्जेक्ट दिखाया जाए.
    2. अगर आपकी सेवा के लिए अनुमति की ज़रूरत है, तो फ़ंक्शन को ऑथराइज़ेशन फ़्लो को भी शुरू करना चाहिए.
  2. हर प्रीव्यू कार्ड के लिए, इंटरफ़ेस के लिए विजेट इंटरैक्टिविटी की सुविधा देने वाला कोई भी कॉलबैक फ़ंक्शन लागू करें. उदाहरण के लिए, अगर आपने "लिंक देखें" बटन शामिल किया है, तो लिंक को नई विंडो में खोलने के लिए, कॉलबैक फ़ंक्शन के बारे में बताने वाली कार्रवाई बनाएं. विजेट इंटरैक्शन के बारे में ज़्यादा जानने के लिए, ऐड-ऑन कार्रवाइयां देखें.

यहां दिया गया कोड, कॉलबैक फ़ंक्शन caseLinkPreview बनाता है:

Apps Script

app-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

कार्ड सेवा फ़ील्ड टाइप
TextParagraph विजेट
DecoratedText विजेट
Image विजेट
IconImage विजेट
ButtonSet विजेट
TextButton विजेट
ImageButton विजेट
Grid विजेट
Divider विजेट
OpenLink कार्रवाई
Navigation
कार्रवाई के लिए, सिर्फ़ updateCard वाला तरीका इस्तेमाल किया जा सकता है.

JSON

कार्ड (google.apps.card.v1) फ़ील्ड टाइप
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

apps-script/preview-links/appsscript.json
{
  "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

app-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;
  }

}