Akıllı çiplerle bağlantı önizleme (Geliştirici Önizlemesi)

Bu sayfada, Google Dokümanlar kullanıcılarının üçüncü taraf bir hizmetten gelen bağlantıları önizleyebilmesini sağlayan bir Google Workspace Eklentisinin nasıl oluşturulacağı açıklanmaktadır.

Bir Google Workspace eklentisi, hizmetinizin bağlantılarını algılayabilir ve Google Dokümanlar kullanıcılarından bunları önizlemelerini isteyebilir. Destek kayıtları, olası satışlar ve çalışan profillerine bağlantılar gibi birden fazla URL kalıbını önizlemek için bir eklenti yapılandırabilirsiniz.

Bir Google Dokümanlar dokümanındaki bağlantıları önizlemek için kullanıcılar akıllı çipler ve kartlarla etkileşime geçer:

Kullanıcı bir kartı önizler

Google Dokümanlar, kullanıcılar bir URL yazdığında veya dokümana yapıştırdığında, bağlantıyı akıllı çiple değiştirmelerini ister. Akıllı çip, bağlantı içeriğinin bir simgesini ve kısa başlığını veya açıklamasını gösterir. Kullanıcı fareyle çipin üzerine geldiğinde, dosya veya bağlantı hakkında daha fazla bilgiyi önizleyen bir kart arayüzü görür.

Aşağıdaki videoda bir kullanıcının bir bağlantıyı akıllı çipe dönüştürme ve bir kartın önizlemesini görüntüleme yöntemi gösterilmektedir:

Ön koşullar

Apps Komut Dosyası

Node.js

olarak çalışacak şekilde yazılmıştır.

Python

Java

İsteğe bağlı: Üçüncü taraf bir hizmet için kimlik doğrulamayı ayarlayın

Eklentiniz, yetkilendirme gerektiren bir hizmete bağlanırsa kullanıcıların, bağlantıları önizlemek için hizmette kimlik doğrulaması yapmaları gerekir. Diğer bir deyişle, kullanıcılar hizmetinizden bir bağlantıyı ilk kez bir Google Dokümanlar dokümanına yapıştırdığında eklentiniz yetkilendirme akışını çağırmalıdır.

Bir OAuth hizmeti veya özel yetkilendirme istemi oluşturmak için aşağıdaki kılavuzlardan birine bakın:

Bu bölümde, eklentiniz için aşağıdaki adımları içeren bağlantı önizlemelerinin nasıl ayarlanacağı açıklanmaktadır:

  1. Eklentinizin dağıtım kaynağında veya manifest dosyasında bağlantı önizlemelerini yapılandırın.
  2. Bağlantılarınız için akıllı çip ve kart arayüzünü oluşturun.

Bağlantı önizlemelerini yapılandırma

Bağlantı önizlemelerini yapılandırmak için eklentinizin dağıtım kaynağında veya manifest dosyasında aşağıdaki bölümleri ve alanları belirtin:

  1. Google Dokümanlar'ı genişletmek için addOns bölümüne docs alanını ekleyin.
  2. docs alanına, runFunction içeren linkPreviewTriggers tetikleyicisini uygulayın (Bu işlevi, Akıllı çipi ve kartı oluşturma başlıklı bölümde tanımlarsınız).

    linkPreviewTriggers tetikleyicisinde hangi alanları belirtebileceğiniz hakkında bilgi edinmek için Apps Komut Dosyası manifest dosyaları veya diğer çalışma zamanları için dağıtım kaynakları ile ilgili referans belgelere bakın.

  3. Kullanıcıların kendi adlarına bağlantıları önizlemesi için eklentiyi yetkilendirebilmek için oauthScopes alanına https://www.googleapis.com/auth/workspace.linkpreview kapsamını ekleyin.

Örneğin, bir destek kaydı hizmetinin bağlantı önizlemelerini yapılandıran bir dağıtım kaynağının oauthScopes ve addons bölümüne göz atın:

{
  "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"
          }
        }
      ]
    }
  }
}

Bu örnekte, Google Workspace eklentisi bir şirketin destek kaydı hizmetinin bağlantılarını önizler. Eklenti, bağlantıları önizlemek için üç URL kalıbı belirtir. Bir bağlantı bir Google Dokümanlar dokümanındaki URL kalıplarından biriyle her eşleştiğinde caseLinkPreview geri çağırma işlevi, akıllı bir çip ve kart oluşturup görüntüler.

Akıllı çipi ve kartı oluşturma

Bir bağlantı için akıllı çip ve kart döndürmek amacıyla linkPreviewTriggers nesnesinde belirttiğiniz tüm işlevleri uygulamanız gerekir.

Bir kullanıcı, belirtilen URL kalıbıyla eşleşen bir bağlantıyla etkileşim kurduğunda linkPreviewTriggers tetikleyicisi tetiklenir ve geri çağırma işlevi docs.matchedUrl.url etkinlik nesnesini bağımsız değişken olarak geçirir. Bağlantınızın önizlemesi için akıllı çip ve kart oluşturmak üzere bu etkinlik nesnesinin yükünü kullanırsınız.

Örneğin, example.com/cases URL kalıbını belirten bir eklenti için kullanıcı https://www.example.com/cases/123456 bağlantısını önizlerse aşağıdaki etkinlik yükü döndürülür:

JSON

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

Kart arayüzünü oluşturmak için widget'ları kullanarak bağlantıyla ilgili bilgileri görüntüleyebilirsiniz. Ayrıca, kullanıcıların bağlantıyı açmasına veya içeriğini değiştirmesine izin veren işlemler de oluşturabilirsiniz. Kullanılabilir widget ve işlemlerin listesi için Önizleme kartları için desteklenen bileşenler başlıklı makaleyi inceleyin.

Bağlantı önizlemesi için akıllı çip ve kart oluşturmak üzere:

  1. Eklentinizin dağıtım kaynağının veya manifest dosyasının linkPreviewTriggers bölümünde belirttiğiniz işlevi uygulayın:
    1. İşlev, bağımsız değişken olarak docs.matchedUrl.url içeren bir etkinlik nesnesini kabul etmeli ve tek bir Card nesnesi döndürmelidir.
    2. Hizmetiniz için yetkilendirme gerekiyorsa işlev, yetkilendirme akışını da çağırmalıdır.
  2. Her önizleme kartına, arayüz için widget etkileşimi sağlamak üzere kullanılan geri çağırma işlevlerini uygulayın. Örneğin, arayüze bir düğme eklerseniz bu düğme ekli bir Action ve bu düğme tıklandığında çalıştırılan bir geri çağırma işlevi içermelidir.

Aşağıdaki kod, caseLinkPreview geri çağırma işlevini oluşturur:

Apps Komut Dosyası

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

düğüm/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;
}

Önizleme kartları için desteklenen bileşenler

Google Workspace eklentileri, bağlantı önizleme kartları için aşağıdaki widget'ları ve işlemleri destekler:

Apps Komut Dosyası

Kart Hizmeti alanı Type
TextParagraph Widget
DecoratedText Widget
Image Widget
IconImage Widget
ButtonSet Widget
TextButton Widget
ImageButton Widget
Grid Widget
Divider Widget
OpenLink İşlem
Navigation
işlemi yalnızca updateCard yöntemi desteklenir.

JSON

Kart (google.apps.card.v1) alanı Type
TextParagraph Widget
DecoratedText Widget
Image Widget
Icon Widget
ButtonList Widget
Button Widget
Grid Widget
Divider Widget
OpenLink İşlem
Navigation
işlemi yalnızca updateCard yöntemi desteklenir.

Tam örnek: Destek kaydı eklentisi

Aşağıdaki örnekte bir şirketin destek kayıtları ve çalışan profillerine bağlantıları önizleyen bir Google Workspace eklentisi bulunmaktadır.

Örnekte aşağıdaki işlemler gerçekleştirilir:

  • Önizlemeler, https://www.example.com/support/cases/1234 gibi destek kayıtlarına bağlantı verir. Akıllı çip bir destek simgesi gösterir ve önizleme kartı, yazışma kimliğini ve açıklamasını içerir.
  • Destek ekibi aracılarının bağlantılarını (ör. https://www.example.com/people/rosario-cruz) önizler. Akıllı çip bir kişi simgesi gösteriyor. Önizleme kartı da çalışanın adını, e-posta adresini, iş unvanını ve profil fotoğrafını içeriyor.
  • Kullanıcının yerel ayarı İspanyolcaya ayarlanmışsa akıllı çip, labelText dilini İspanyolcaya yerelleştirir.

Dağıtım kaynağı

Apps Komut Dosyası

{
  "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"
        }
      ]
    }
  }
}

Kod

Apps Komut Dosyası

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

düğüm/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;
  }

}