יצירה ועדכון של כרטיסים אינטראקטיביים

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

יצירה ועדכון של כרטיסים שימושיים כשרוצים:

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

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

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

Node.js

Python

Java

Apps Script

יצירת מפתח API כדי לגשת לתכונות של תצוגה מקדימה למפתחים

כדי לקרוא ל-method של API בגרסת תצוגה מקדימה למפתחים, צריך להשתמש בגרסה לא ציבורית של מסמך גילוי ה-API. כדי לאמת את הבקשה, צריך להעביר מפתח API.

כדי ליצור את מפתח ה-API, פותחים את פרויקט Google Cloud של האפליקציה ומבצעים את הפעולות הבאות:

  1. במסוף Google Cloud, לוחצים על סמל התפריט > APIs & Services > Credentials.

    כניסה לדף Credentials

  2. לוחצים על Create credentials > API key.
  3. מפתח ה-API החדש מוצג.
    • לוחצים על סמל ההעתקה כדי להעתיק את מפתח ה-API לשימוש בקוד של האפליקציה. מפתח ה-API מופיע גם בקטע API Keys (מפתחות API) בפרטי הכניסה של הפרויקט.
    • כדי למנוע שימוש לא מורשה, מומלץ להגביל את המקומות שבהם אפשר להשתמש במפתח ה-API ואת ממשקי ה-API שאפשר להשתמש בו עבורם. פרטים נוספים זמינים במאמר בנושא הוספת הגבלות על ממשקי API.

יצירת הודעה בכרטיס מטעם משתמש

כדי ליצור הודעה עם כרטיסים בשם משתמש, צריך להשתמש באימות משתמש.

כדי ליצור את ההודעה, מציינים את הפרטים הבאים בבקשה:

  • היקף ההרשאה chat.messages.create או chat.messages.
  • השדה cardsV2 במשאב Message, שמכיל את נתוני הכרטיס.
  • הפרמטר cardId בכל כרטיס, שנדרש לעדכונים אסינכרוניים.

בדוגמה הבאה מוצג איך יוצרים הודעה עם כרטיס בשם משתמש:

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 with Developer Preview labels
  const chat = await google.discoverAPI(
    'https://chat.googleapis.com/$discovery/rest?version=v1&labels=DEVELOPER_PREVIEW&key=API_KEY'
  );

  // 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 with Developer Preview labels.
    service = build(
        'chat',
        'v1',
        credentials=credentials,
        discoveryServiceUrl='https://chat.googleapis.com/$discovery/rest?version=v1&labels=DEVELOPER_PREVIEW&key=API_KEY'
    )

    # 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);
  }
}

עדכון כרטיסים באופן אסינכרוני

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

כדי לעדכן את הכרטיסים, קוראים לשיטה replaceCards עם הפרטים הבאים:

  • היקף ההרשאה chat.bot.
  • ה-name של ההודעה לעדכון.
  • הרשימה החדשה cardsV2. הפעולה הזו תחליף את כל הכרטיסים הקיימים בהודעה. אם מספקים רשימה ריקה, הכרטיסים מוסרים.

בדוגמה הבאה אפשר לראות איך מעדכנים את הכרטיסים של הודעה:

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 with Developer Preview labels
  const chat = await google.discoverAPI(
    'https://chat.googleapis.com/$discovery/rest?version=v1&labels=DEVELOPER_PREVIEW&key=API_KEY'
  );

  // 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 with Developer Preview labels.
    service = build(
        'chat',
        'v1',
        credentials=credentials,
        discoveryServiceUrl='https://chat.googleapis.com/$discovery/rest?version=v1&labels=DEVELOPER_PREVIEW&key=API_KEY'
    )

    # 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);
  }
}

מגבלות

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

    הדרישה הזו שונה מדרישות של ממשקי API אחרים שמשתמשים באימות משתמשים, שבדרך כלל לא מחייבים שהאפליקציה תהיה חברה במרחב.

  • בשיטה replaceCards אפשר להחליף כרטיסים ולהסיר אותם, ואפשר להוסיף כרטיסים נוספים תוך כדי החלפה, אבל אי אפשר להוסיף כרטיסים להודעה שכבר אין בה כרטיסים.

  • אפליקציית צ'אט יכולה להחליף רק כרטיסים שהיא צירפה להודעה, ולא כרטיסים שאפליקציות צ'אט אחרות צירפו.

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