Membuat dan memperbarui kartu interaktif

Panduan ini menjelaskan cara menggunakan Google Chat API untuk membuat pesan yang berisi kartu interaktif atas nama pengguna, melampirkan kartu ke pesan yang ada, dan memperbarui kartu tersebut secara asinkron.

Membuat dan memperbarui kartu berguna saat Anda ingin melakukan hal berikut:

  • Memposting kartu yang merepresentasikan tugas atau resource eksternal atas nama pengguna.
  • Lampirkan kartu ke pesan pengguna yang ada untuk memberikan konteks atau alur kerja interaktif.
  • Perbarui status kartu (misalnya, "Sedang Berlangsung" menjadi "Selesai") berdasarkan peristiwa eksternal, tanpa menunggu interaksi pengguna.
  • Memperbarui konten kartu pada pesan pengguna, seperti pratinjau link.

Prasyarat

Node.js

Python

Java

Apps Script

Membuat pesan kartu atas nama pengguna

Untuk membuat pesan dengan kartu atas nama pengguna, gunakan autentikasi pengguna.

Untuk membuat pesan, tentukan hal berikut dalam permintaan Anda:

  • Cakupan otorisasi chat.messages.create atau chat.messages.
  • Kolom cardsV2 di resource Message, yang berisi data kartu.
  • cardId untuk setiap kartu, yang diperlukan untuk update asinkron.

Contoh berikut menunjukkan cara membuat pesan dengan kartu atas nama pengguna:

Node.js

/**
 * This sample shows how to create a message with a card on behalf of a user.
 */
const {google} = require('googleapis');
const {auth} = require('google-auth-library');

async function main() {
  // Create a client
  const authClient = await auth.getClient({
    scopes: ['https://www.googleapis.com/auth/chat.messages.create']
  });
  google.options({auth: authClient});

  // Initialize the Chat API
  const chat = google.chat({version: 'v1'});

  // The space to create the message in.
  const parent = 'spaces/SPACE_NAME';

  // Create the request
  const request = {
    parent: parent,
    requestBody: {
      text: 'Here is a card created on my behalf:',
      cardsV2: [{
        cardId: 'unique-card-id',
        card: {
          header: {
            title: 'Card Title',
            subtitle: 'Card Subtitle'
          },
          sections: [{
            widgets: [{
              textParagraph: {
                text: 'This card is attached to a user message.'
              }
            }]
          }]
        }
      }]
    }
  };

  // Call the API
  const response = await chat.spaces.messages.create(request);

  // Handle the response
  console.log(response.data);
}

main().catch(console.error);

Python

"""
This sample shows how to create a message with a card on behalf of a user.
"""
from google.oauth2 import service_account
from googleapiclient.discovery import build
import google.auth

def create_message_with_card():
    # Create a client
    scopes = ["https://www.googleapis.com/auth/chat.messages.create"]
    credentials, _ = google.auth.default(scopes=scopes)

    # Build the service endpoint for Chat API.
    service = build('chat', 'v1', credentials=credentials)

    # The space to create the message in.
    parent = "spaces/SPACE_NAME"

    # Create the request
    result = service.spaces().messages().create(
        parent=parent,
        body={
            'text': 'Here is a card created on my behalf:',
            'cardsV2': [{
                'cardId': 'unique-card-id',
                'card': {
                    'header': {
                        'title': 'Card Title',
                        'subtitle': 'Card Subtitle'
                    },
                    'sections': [{
                        'widgets': [{
                            'textParagraph': {
                                'text': 'This card is attached to a user message.'
                            }
                        }]
                    }]
                }
            }]
        }
    ).execute()

    print(result)

if __name__ == "__main__":
    create_message_with_card()

Java

/**
 * This sample shows how to create a message with a card on behalf of a user.
 */
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class CreateMessageWithCard {
  public static void main(String[] args) throws Exception {
    HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
    GsonFactory jsonFactory = GsonFactory.getDefaultInstance();

    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.messages.create"));
    HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));

    String parent = "spaces/SPACE_NAME";
    GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + parent + "/messages");

    // Construct the message body
    Map<String, Object> message = new HashMap<>();
    message.put("text", "Here is a card created on my behalf:");

    Map<String, Object> header = new HashMap<>();
    header.put("title", "Card Title");
    header.put("subtitle", "Card Subtitle");

    Map<String, Object> textParagraph = new HashMap<>();
    textParagraph.put("text", "This card is attached to a user message.");

    Map<String, Object> widget = new HashMap<>();
    widget.put("textParagraph", textParagraph);

    Map<String, Object> section = new HashMap<>();
    section.put("widgets", Collections.singletonList(widget));

    Map<String, Object> card = new HashMap<>();
    card.put("header", header);
    card.put("sections", Collections.singletonList(section));

    Map<String, Object> cardWithId = new HashMap<>();
    cardWithId.put("cardId", "unique-card-id");
    cardWithId.put("card", card);

    message.put("cardsV2", Collections.singletonList(cardWithId));

    HttpRequest request = requestFactory.buildPostRequest(url, new JsonHttpContent(jsonFactory, message));
    System.out.println(request.execute().parseAsString());
  }
}

Apps Script

/**
 * This sample shows how to create a message with a card on behalf of a user.
 */
function createMessageWithCard() {
  const parent = 'spaces/SPACE_NAME';
  const url = `https://chat.googleapis.com/v1/${parent}/messages`;

  const message = {
    text: 'Here is a card created on my behalf:',
    cardsV2: [{
      cardId: 'unique-card-id',
      card: {
        header: {
          title: 'Card Title',
          subtitle: 'Card Subtitle'
        },
        sections: [{
          widgets: [{
            textParagraph: {
              text: 'This card is attached to a user message.'
            }
          }]
        }]
      }
    }]
  };

  const options = {
    method: 'post',
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
    },
    contentType: 'application/json',
    payload: JSON.stringify(message),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    console.log(response.getContentText());
  } catch (err) {
    console.log('Failed to create message: ' + err.message);
  }
}

Melampirkan kartu ke pesan yang ada atas nama pengguna

Untuk melampirkan kartu ke pesan yang ada atas nama pengguna, panggil metode patch menggunakan autentikasi pengguna.

Untuk melampirkan kartu ke pesan, tentukan hal berikut dalam permintaan Anda:

  • Cakupan otorisasi chat.messages.
  • name pesan yang akan diperbarui, dalam format spaces/{space}/messages/{message}.
  • updateMask disetel ke cards_v2. Saat memperbarui pesan dengan autentikasi pengguna, cards_v2 harus menjadi satu-satunya kolom dalam mask pembaruan. Anda tidak dapat memperbarui pesan text dan cards_v2 dalam permintaan yang sama.
  • Kolom cardsV2 di resource Message, yang berisi data kartu.
  • cardId untuk setiap kartu, yang diperlukan untuk update asinkron berikutnya.

Contoh berikut menunjukkan cara melampirkan kartu ke pesan yang ada atas nama pengguna:

Node.js

/**
 * This sample shows how to attach a card to an existing message on behalf of a user.
 */
const {google} = require('googleapis');
const {auth} = require('google-auth-library');

async function main() {
  // Create a client with user credentials
  const authClient = await auth.getClient({
    scopes: ['https://www.googleapis.com/auth/chat.messages']
  });
  google.options({auth: authClient});

  // Initialize the Chat API
  const chat = google.chat({version: 'v1'});

  // The message to update.
  const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';

  // Create the request
  const request = {
    name: messageName,
    updateMask: 'cards_v2',
    requestBody: {
      cardsV2: [{
        cardId: 'unique-card-id',
        card: {
          header: {
            title: 'Card Title',
            subtitle: 'Card Subtitle'
          },
          sections: [{
            widgets: [{
              textParagraph: {
                text: 'This card was attached to an existing user message.'
              }
            }]
          }]
        }
      }]
    }
  };

  // Call the API
  const response = await chat.spaces.messages.patch(request);

  // Handle the response
  console.log(response.data);
}

main().catch(console.error);

Python

"""
This sample shows how to attach a card to an existing message on behalf of a user.
"""
from googleapiclient.discovery import build
import google.auth

def attach_card_to_message():
    # Create a client with user credentials
    scopes = ["https://www.googleapis.com/auth/chat.messages"]
    credentials, _ = google.auth.default(scopes=scopes)

    # Build the service endpoint for Chat API.
    service = build('chat', 'v1', credentials=credentials)

    # The message to update.
    message_name = "spaces/SPACE_NAME/messages/MESSAGE_ID"

    # Create the request
    result = service.spaces().messages().patch(
        name=message_name,
        updateMask="cards_v2",
        body={
            'cardsV2': [{
                'cardId': 'unique-card-id',
                'card': {
                    'header': {
                        'title': 'Card Title',
                        'subtitle': 'Card Subtitle'
                    },
                    'sections': [{
                        'widgets': [{
                            'textParagraph': {
                                'text': 'This card was attached to an existing user message.'
                            }
                        }]
                    }]
                }
            }]
        }
    ).execute()

    print(result)

if __name__ == "__main__":
    attach_card_to_message()

Java

/**
 * This sample shows how to attach a card to an existing message on behalf of a user.
 */
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class AttachCardToMessage {
  public static void main(String[] args) throws Exception {
    HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
    GsonFactory jsonFactory = GsonFactory.getDefaultInstance();

    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.messages"));
    HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));

    String messageName = "spaces/SPACE_NAME/messages/MESSAGE_ID";
    GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + messageName + "?updateMask=cards_v2");

    // Construct the card body
    Map<String, Object> header = new HashMap<>();
    header.put("title", "Card Title");
    header.put("subtitle", "Card Subtitle");

    Map<String, Object> textParagraph = new HashMap<>();
    textParagraph.put("text", "This card was attached to an existing user message.");

    Map<String, Object> widget = new HashMap<>();
    widget.put("textParagraph", textParagraph);

    Map<String, Object> section = new HashMap<>();
    section.put("widgets", Collections.singletonList(widget));

    Map<String, Object> card = new HashMap<>();
    card.put("header", header);
    card.put("sections", Collections.singletonList(section));

    Map<String, Object> cardWithId = new HashMap<>();
    cardWithId.put("cardId", "unique-card-id");
    cardWithId.put("card", card);

    Map<String, Object> message = new HashMap<>();
    message.put("cardsV2", Collections.singletonList(cardWithId));

    HttpRequest request = requestFactory.buildPatchRequest(url, new JsonHttpContent(jsonFactory, message));
    System.out.println(request.execute().parseAsString());
  }
}

Apps Script

/**
 * This sample shows how to attach a card to an existing message on behalf of a user.
 */
function attachCardToMessage() {
  const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
  const url = `https://chat.googleapis.com/v1/${messageName}?updateMask=cards_v2`;

  const message = {
    cardsV2: [{
      cardId: 'unique-card-id',
      card: {
        header: {
          title: 'Card Title',
          subtitle: 'Card Subtitle'
        },
        sections: [{
          widgets: [{
            textParagraph: {
              text: 'This card was attached to an existing user message.'
            }
          }]
        }]
      }
    }]
  };

  const options = {
    method: 'patch',
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
    },
    contentType: 'application/json',
    payload: JSON.stringify(message),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    console.log(response.getContentText());
  } catch (err) {
    console.log('Failed to attach card: ' + err.message);
  }
}

Memperbarui kartu secara asinkron

Setelah membuat pesan dengan kartu atau melampirkan kartu ke pesan yang ada, Anda dapat memperbarui kartu secara asinkron menggunakan autentikasi aplikasi. Hal ini memungkinkan aplikasi Anda memuat ulang konten kartu tanpa memerlukan interaksi pengguna. Hanya aplikasi Chat yang menambahkan kartu ke pesan pengguna yang dapat menggantinya. Jika pengguna mengedit teks pesan, kartu milik aplikasi akan dihapus, dan aplikasi Anda tidak dapat lagi memperbaruinya.

Saat kartu diperbarui secara asinkron, Google Chat akan menampilkan indikator Diedit di samping atribusi kartu untuk memberi tahu pengguna bahwa konten kartu diperbarui secara terpisah dari pesan.

Untuk memperbarui kartu, panggil metode replaceCards dengan:

  • Cakupan otorisasi chat.bot.
  • name pesan yang akan diperbarui.
  • Daftar cardsV2 baru. Tindakan ini akan menggantikan semua kartu yang ada dalam pesan. Jika Anda memberikan daftar kosong, kartu akan dihapus. Jika Anda menghapus semua kartu, Anda tidak dapat menggunakan replaceCards untuk menambahkannya kembali; sebagai gantinya, gunakan UpdateMessage dengan autentikasi pengguna untuk melampirkan kartu baru.

Contoh berikut menunjukkan cara memperbarui kartu pesan:

Node.js

/**
 * This sample shows how to update cards on a message.
 */
const {google} = require('googleapis');
const {auth} = require('google-auth-library');

async function main() {
  // Create a client with app credentials
  const authClient = await auth.getClient({
    scopes: ['https://www.googleapis.com/auth/chat.bot']
  });
  google.options({auth: authClient});

  // Initialize the Chat API
  const chat = google.chat({version: 'v1'});

  // The message to update.
  const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';

  // Create the request
  const request = {
    name: messageName,
    requestBody: {
      cardsV2: [{
        cardId: 'unique-card-id',
        card: {
          header: {
            title: 'Updated Card Title',
            subtitle: 'Updated Card Subtitle'
          },
          sections: [{
            widgets: [{
              textParagraph: {
                text: 'The card content has been updated asynchronously.'
              }
            }]
          }]
        }
      }]
    }
  };

  // Call the API
  await chat.spaces.messages.replaceCards(request);
  console.log('Cards updated.');
}

main().catch(console.error);

Python

"""
This sample shows how to update cards on a message.
"""
from google.oauth2 import service_account
from googleapiclient.discovery import build
import google.auth

def replace_message_cards():
    # Create a client with app credentials
    scopes = ["https://www.googleapis.com/auth/chat.bot"]
    credentials, _ = google.auth.default(scopes=scopes)

    # Build the service endpoint for Chat API.
    service = build('chat', 'v1', credentials=credentials)

    # The message to update.
    message_name = "spaces/SPACE_NAME/messages/MESSAGE_ID"

    # Create the request
    result = service.spaces().messages().replaceCards(
        name=message_name,
        body={
            'cardsV2': [{
                'cardId': 'unique-card-id',
                'card': {
                    'header': {
                        'title': 'Updated Card Title',
                        'subtitle': 'Updated Card Subtitle'
                    },
                    'sections': [{
                        'widgets': [{
                            'textParagraph': {
                                'text': 'The card content has been updated asynchronously.'
                            }
                        }]
                    }]
                }
            }]
        }
    ).execute()

    print("Cards updated.")

if __name__ == "__main__":
    replace_message_cards()

Java

/**
 * This sample shows how to update cards on a message.
 */
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ReplaceMessageCards {
  public static void main(String[] args) throws Exception {
    HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
    GsonFactory jsonFactory = GsonFactory.getDefaultInstance();

    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.bot"));
    HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));

    String messageName = "spaces/SPACE_NAME/messages/MESSAGE_ID";
    GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + messageName + ":replaceCards");

    // Construct the body
    Map<String, Object> header = new HashMap<>();
    header.put("title", "Updated Card Title");
    header.put("subtitle", "Updated Card Subtitle");

    Map<String, Object> textParagraph = new HashMap<>();
    textParagraph.put("text", "The card content has been updated asynchronously.");

    Map<String, Object> widget = new HashMap<>();
    widget.put("textParagraph", textParagraph);

    Map<String, Object> section = new HashMap<>();
    section.put("widgets", Collections.singletonList(widget));

    Map<String, Object> card = new HashMap<>();
    card.put("header", header);
    card.put("sections", Collections.singletonList(section));

    Map<String, Object> cardWithId = new HashMap<>();
    cardWithId.put("cardId", "unique-card-id");
    cardWithId.put("card", card);

    Map<String, Object> body = new HashMap<>();
    body.put("cardsV2", Collections.singletonList(cardWithId));

    HttpRequest request = requestFactory.buildPostRequest(url, new JsonHttpContent(jsonFactory, body));
    request.execute();
    System.out.println("Cards updated.");
  }
}

Apps Script

/**
 * This sample shows how to update cards on a message.
 */
function replaceMessageCards() {
  const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
  const url = `https://chat.googleapis.com/v1/${messageName}:replaceCards`;

  const request = {
    cardsV2: [{
      cardId: 'unique-card-id',
      card: {
        header: {
          title: 'Updated Card Title',
          subtitle: 'Updated Card Subtitle'
        },
        sections: [{
          widgets: [{
            textParagraph: {
              text: 'The card content has been updated asynchronously.'
            }
          }]
        }]
      }
    }]
  };

  const options = {
    method: 'post',
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
    },
    contentType: 'application/json',
    payload: JSON.stringify(request),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    console.log('Cards updated.');
  } catch (err) {
    console.log('Failed to update cards: ' + err.message);
  }
}

Batasan

  • Saat membuat pesan dengan kartu atas nama pengguna atau memperbarui kartu, aplikasi Chat harus menjadi anggota ruang. Persyaratan ini berlaku saat:

    Persyaratan ini berbeda dengan API lain yang menggunakan autentikasi pengguna, yang biasanya tidak mengharuskan aplikasi menjadi anggota ruang.

  • Saat memperbarui pesan dengan autentikasi pengguna, jika cards_v2 ditentukan dalam updateMask, tidak ada kolom lain (seperti text) yang dapat diperbarui dalam permintaan yang sama.

  • Metode replaceCards mendukung penggantian dan penghapusan kartu, dan Anda dapat menambahkan kartu lain saat menggantinya, tetapi Anda tidak dapat menambahkan kartu ke pesan yang belum memiliki kartu. Untuk melampirkan kartu ke pesan yang tidak memiliki kartu, gunakan UpdateMessage dengan autentikasi pengguna.

  • Atribusi dan kepemilikan kartu:

    • Kartu yang dilampirkan ke pesan pengguna diatribusikan dan dimiliki oleh aplikasi Chat yang melampirkannya, seperti yang ditunjukkan oleh kolom CardWithId.owner hanya output.
    • Aplikasi Chat hanya dapat mengganti kartu yang dilampirkan ke pesan, bukan kartu yang dilampirkan oleh aplikasi Chat lain.
  • Jika pengguna mengedit teks pesan, kartu yang dimiliki aplikasi Chat akan dihapus, dan Anda tidak dapat memperbaruinya lagi.