ساختن برنامه Google Chat در پشت دیوار آتش با Pub/Sub

این صفحه نحوه ایجاد برنامه Chat را که بااستفاده از Pub/Sub رویدادها را از Chat دریافت می‌کند توضیح می‌دهد. این نوع معماری برای برنامه Chat درصورتی مفید است که سازمانتان دیوار آتش داشته باشد، که می‌تواند مانع از ارسال پیام‌های Chat به برنامه Chat شما شود، یا اگر می‌خواهید رویدادهایی درباره فضای Chat یا کاربر با Google Workspace Events API ارسال یا دریافت کنید. بااین‌حال، این معماری به‌دلیل اینکه این برنامه‌های Chat فقط می‌توانند پیام‌های ناهم‌زمان ارسال و دریافت کنند، محدودیت‌های زیر را دارد:

  • نمی‌توانید از کادرهای گفتگو در پیام‌ها استفاده کنید. درعوض، از پیام کارت استفاده کنید.
  • نمی‌توان کارت‌های تکی را با پاسخ هم‌زمان به‌روز کرد. درعوض، با فراخوانی روش patch کل پیام را به‌روز کنید.

نمودار زیر معماری برنامه Chat ساخته‌شده با Pub/Sub را نشان می‌دهد:

معماری برنامه Chat پیاده‌سازی‌شده با Pub/Sub.

در نمودار قبلی، کاربری که با برنامه گپ Pub/Sub تعامل می‌کند جریان اطلاعات زیر را دارد:

  1. کاربر با برنامه Chat تعامل برقرار می‌کند، برای نمونه، پیامی برای آن ارسال می‌کند، فرمانی صادر می‌کند، یا آن را به فضای Chat اضافه یا از آن حذف می‌کند، یا رویدادی در فضای Chat رخ می‌دهد که برنامه Chat برای آن اشتراک فعال دارد.

  2. ‫Chat پیام را به موضوع Pub/Sub ارسال می‌کند.

  3. کارساز برنامه، که یا سیستم ابری است یا سیستم در محل، که منطق برنامه Chat را دربرمی‌گیرد، در موضوع Pub/Sub مشترک می‌شود تا پیام را ازطریق دیوار آتش دریافت کند.

  4. به‌صورت اختیاری، برنامه Chat می‌تواند «میانای برنامه‌سازی کاربردی Chat» را برای پست کردن ناهمزمان پیام‌ها یا انجام عملیات دیگر فراخوانی کند.

پیش‌نیازها

Node.js

  • حساب «کسب‌وکار» یا «سازمانی» Google Workspace با دسترسی به Google Chat.
  • پروژه Google Cloud با صورت‌حساب فعال. برای بررسی اینکه صورت‌حساب برای پروژه موجود فعال است یا نه، به درستی‌سنجی وضعیت صورت‌حساب پروژه‌ها مراجعه کنید. برای ایجاد پروژه و راه‌اندازی صورت‌حساب، به ایجاد پروژه Google Cloud مراجعه کنید.
  • ‫Node.js 14 یا بالاتر
  • ابزار مدیریت بسته npm
  • پروژه Node.js اولیه. برای مقداردهی اولیه یک پروژه جدید، پوشه جدیدی ایجاد کنید و به آن بروید، سپس فرمان زیر را در رابط خط فرمان اجرا کنید:
    npm init

Python

جاوا

راه‌اندازی محیط

قبل‌از استفاده از «میاناهای برنامه‌سازی کاربردی Google»، باید آن‌ها را در پروژه Google Cloud روشن کنید. می‌توانید یک یا چند API را در یک پروژه Google Cloud روشن کنید.

راه‌اندازی Pub/Sub

  1. موضوع Pub/Sub ایجاد کنید که Chat API بتواند به آن پیام ارسال کند. توصیه می‌کنیم برای هر برنامه Chat از یک موضوع استفاده کنید.

  2. حساب خدماتی ایجاد کنید تا برنامه Chat با Pub/Sub و Chat مجاز شود و فایل کلید خصوصی را در فهرست راهنمای کاری‌تان ذخیره کنید.

  3. اشتراک کششی برای موضوع ایجاد کنید.

  4. «نقش مشترک Pub/Sub» را در اشتراک برای حساب خدماتی که قبلاً ایجاد کرده‌اید اختصاص دهید.

نوشتن دستورگان

در این بخش، منطق برنامه را برای برنامه Chat خودتان تعریف می‌کنید. برنامه‌ای می‌نویسید که با Google Cloud اصالت‌سنجی می‌کند و در موضوع Pub/Sub مشترک می‌شود تا رویدادهای Chat را دریافت کند، مثلاً وقتی کاربری به برنامه Chat شما پیام ارسال می‌کند.

وقتی این دستورگان پیامی دریافت می‌کند، داده‌های رویداد را پردازش می‌کند و از Google Chat API برای پست کردن پاسخ به کاربر یا فضا استفاده می‌کند. این راه‌اندازی به برنامه Chat شما امکان می‌دهد در پشت دیوار آتش کار کند و درعین‌حال با کاربران Chat تعامل داشته باشد.

Node.js

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام package.json ایجاد کنید.

  5. در فایل package.json، کد زیر را جای‌گذاری کنید:

    {
      "name": "pub-sub-app",
      "version": "1.0.0",
      "description": "Google Chat App that listens for messages via Cloud Pub/Sub",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "dependencies": {
        "@google-apps/chat": "^0.4.0",
        "@google-cloud/pubsub": "^4.5.0"
      },
      "license": "Apache-2.0"
    }
    
  6. در فهرست راهنمای کاری‌تان، فایلی به‌نام index.js ایجاد کنید.

  7. در index.js، کد زیر را جای‌گذاری کنید:

    const {ChatServiceClient} = require('@google-apps/chat');
    const {MessageReplyOption} = require('@google-apps/chat').protos.google.chat.v1.CreateMessageRequest;
    const {PubSub} = require('@google-cloud/pubsub');
    const {SubscriberClient} = require('@google-cloud/pubsub/build/src/v1');
    
    // Receives messages from a pull subscription.
    function receiveMessages() {
      const chat = new ChatServiceClient({
        keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS,
        scopes: ['https://www.googleapis.com/auth/chat.bot'],
      });
    
      const subscriptionPath = new SubscriberClient()
        .subscriptionPath(process.env.PROJECT_ID, process.env.SUBSCRIPTION_ID)
      const subscription = new PubSub()
        .subscription(subscriptionPath);
    
      // Handle incoming message, then acknowledge the received message
      const messageHandler = message => {
        console.log(`Id : ${message.id}`);
        const event = JSON.parse(message.data);
        console.log(`Data : ${JSON.stringify(event)}`);
    
        // Post the response to Google Chat.
        const request = formatRequest(event);
        if (request != null) {
          chat.createMessage(request);
        }
    
        // Acknowledge the message.
        message.ack();
      }
    
      subscription.on('message', messageHandler);
      console.log(`Listening for messages on ${subscriptionPath}`);
    
      // Keep main thread from exiting while waiting for messages
      setTimeout(() => {
        subscription.removeListener('message', messageHandler);
        console.log(`Stopped listening for messages.`);
      }, 60 * 1000);
    }
    
    // Send message to Google Chat based on the type of event
    function formatRequest(event) {
      const chatEvent = event.chat || {};
    
      // If the app was removed, we don't respond.
      if (chatEvent.removedFromSpacePayload) {
        console.log(`App removed from space.`);
        return null;
      }
    
      const payload = chatEvent.messagePayload || chatEvent.addedToSpacePayload;
      const spaceName = payload?.space?.name;
    
      if (!spaceName) {
        console.log('No space name in event.');
        return null;
      }
    
      if (chatEvent.addedToSpacePayload) {
        // An app can also be added to a space by @mentioning it in a
        // message. In that case, we fall through to the message case
        // and let the app respond. If the app was added using the
        // invite flow, we just post a thank you message in the space.
        return {
          parent: spaceName,
          message: { text: 'Thank you for adding me!' },
        };
      } else if (chatEvent.messagePayload) {
        // In case of message, post the response in the same thread.
        const message = chatEvent.messagePayload.message;
        return {
          parent: spaceName,
          messageReplyOption: MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD,
          message: {
            text: 'You said: `' + message.text + '`',
            thread: { name: message.thread.name },
          },
        };
      }
    }
    
    if (!process.env.PROJECT_ID) {
      console.log('Missing PROJECT_ID env var.');
      process.exit(1);
    }
    if (!process.env.SUBSCRIPTION_ID) {
      console.log('Missing SUBSCRIPTION_ID env var.');
      process.exit(1);
    }
    if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) {
      console.log('Missing GOOGLE_APPLICATION_CREDENTIALS env var.');
      process.exit(1);
    }
    
    receiveMessages();
    

Python

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام requirements.txt ایجاد کنید.

  5. در فایل requirements.txt، کد زیر را جای‌گذاری کنید:

    google-cloud-pubsub>=2.23.0
    google-apps-chat==0.1.9
    
  6. در فهرست راهنمای کاری‌تان، فایلی به‌نام app.py ایجاد کنید.

  7. در app.py، کد زیر را جای‌گذاری کنید:

    import json
    import logging
    import os
    import sys
    import time
    from google.apps import chat_v1 as google_chat
    from google.cloud import pubsub_v1
    from google.oauth2.service_account import Credentials
    
    def receive_messages():
      """Receives messages from a pull subscription."""
    
      scopes = ['https://www.googleapis.com/auth/chat.bot']
      service_account_key_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')
      creds = Credentials.from_service_account_file(service_account_key_path)
      chat = google_chat.ChatServiceClient(
          credentials=creds, client_options={'scopes': scopes}
      )
    
      project_id = os.environ.get('PROJECT_ID')
      subscription_id = os.environ.get('SUBSCRIPTION_ID')
      subscriber = pubsub_v1.SubscriberClient()
      subscription_path = subscriber.subscription_path(project_id, subscription_id)
    
      # Handle incoming message, then acknowledge the received message
      def callback(message):
        event = json.loads(message.data)
        logging.info('Data : %s', event)
    
        # Post the response to Google Chat.
        request = format_request(event)
        if request is not None:
          chat.create_message(request)
    
        # Acknowledge the message.
        message.ack()
    
      subscriber.subscribe(subscription_path, callback = callback)
      logging.info('Listening for messages on %s', subscription_path)
    
      # Keep main thread from exiting while waiting for messages
      while True:
        time.sleep(60)
    
    def format_request(event):
      """Send message to Google Chat based on the type of event.
      Args:
        event: A dictionary with the event data.
      """
      chat_event = event.get('chat', {})
    
      # If the app was removed, we don't respond.
      if 'removedFromSpacePayload' in chat_event:
        logging.info('App removed from space.')
        return
    
      payload = chat_event.get('messagePayload') or chat_event.get(
          'addedToSpacePayload'
      )
      space_name = payload.get('space', {}).get('name') if payload else None
    
      if not space_name:
        logging.warning('No space name in event.')
        return
    
      if 'addedToSpacePayload' in chat_event:
        # An app can also be added to a space by @mentioning it in a
        # message. In that case, we fall through to the message case
        # and let the app respond. If the app was added using the
        # invite flow, we just post a thank you message in the space.
        return google_chat.CreateMessageRequest(
            parent = space_name,
            message = {
              'text': 'Thank you for adding me!'
            }
        )
      elif 'messagePayload' in chat_event:
        # In case of message, post the response in the same thread.
        message = chat_event['messagePayload']['message']
        return google_chat.CreateMessageRequest(
            parent = space_name,
            message_reply_option = google_chat.CreateMessageRequest.MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD,
            message = {
              'text': 'You said: `' + message['text'] + '`',
              'thread': {
                'name': message['thread']['name']
              }
            }
        )
    
    if __name__ == '__main__':
      if 'PROJECT_ID' not in os.environ:
        logging.error('Missing PROJECT_ID env var.')
        sys.exit(1)
    
      if 'SUBSCRIPTION_ID' not in os.environ:
        logging.error('Missing SUBSCRIPTION_ID env var.')
        sys.exit(1)
    
      if 'GOOGLE_APPLICATION_CREDENTIALS' not in os.environ:
        logging.error('Missing GOOGLE_APPLICATION_CREDENTIALS env var.')
        sys.exit(1)
    
      logging.basicConfig(
          level=logging.INFO,
          style='{',
          format='{levelname:.1}{asctime} {filename}:{lineno}] {message}')
      receive_messages()
    

جاوا

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام pom.xml ایجاد کنید.

  5. در فایل pom.xml، کد زیر را جای‌گذاری کنید:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
    
     <groupId>com.google.chat.addon</groupId>
     <artifactId>pubsub-addon-chat-app</artifactId>
     <version>0.1.0</version>
    
     <name>pubsub-addon-chat-app-java</name>
    
     <properties>
       <maven.compiler.release>11</maven.compiler.release>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
    
     <dependencyManagement>
       <dependencies>
         <dependency>
           <groupId>com.google.cloud</groupId>
           <artifactId>libraries-bom</artifactId>
           <version>26.41.0</version> <!-- Use a recent BOM version -->
           <type>pom</type>
           <scope>import</scope>
         </dependency>
       </dependencies>
     </dependencyManagement>
    
     <dependencies>
       <!-- Google Chat GAPIC library -->
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-chat</artifactId>
       </dependency>
       <!-- Google Cloud Pub/Sub library -->
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-pubsub</artifactId>
       </dependency>
       <!-- Google Apps Add-ons Event Object -->
       <dependency>
         <groupId>com.google.apps.addons.v1</groupId>
         <artifactId>google-apps-addons-v1-java</artifactId>
         <version>0.2.0</version> <!-- Check for latest version -->
       </dependency>
       <!-- Protobuf JSON utility -->
       <dependency>
         <groupId>com.google.protobuf</groupId>
         <artifactId>protobuf-java-util</artifactId>
       </dependency>
       <!-- Google Auth Library -->
       <dependency>
         <groupId>com.google.auth</groupId>
         <artifactId>google-auth-library-oauth2-http</artifactId>
       </dependency>
       <dependency>
         <groupId>com.google.api</groupId>
         <artifactId>gax</artifactId>
       </dependency>
       <!-- JSON utilities for PubSub message (if needed, though protobuf-java-util is primary for EventObject) -->
       <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
         <version>2.14.2</version>
       </dependency>
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-jdk14</artifactId>
         <version>1.7.36</version>
         <scope>runtime</scope>
       </dependency>
     </dependencies>
    
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.13.0</version>
           <configuration>
             <source>11</source>
             <target>11</target>
           </configuration>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>exec-maven-plugin</artifactId>
           <version>3.3.0</version>
           <configuration>
             <mainClass>Main</mainClass>
           </configuration>
         </plugin>
       </plugins>
     </build>
    </project>
    
  6. در فهرست راهنمای کارتان، ساختار فهرست راهنمای src/main/java را ایجاد کنید.

  7. در دایرکتوری src/main/java، فایلی با نام Main.java ایجاد کنید.

  8. در Main.java، کد زیر را جای‌گذاری کنید:

    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.chat.v1.ChatServiceClient;
    import com.google.chat.v1.ChatServiceSettings;
    import com.google.chat.v1.CreateMessageRequest;
    import com.google.chat.v1.CreateMessageRequest.MessageReplyOption;
    import com.google.chat.v1.Message;
    import com.google.chat.v1.Thread;
    import com.google.cloud.pubsub.v1.AckReplyConsumer;
    import com.google.cloud.pubsub.v1.MessageReceiver;
    import com.google.cloud.pubsub.v1.Subscriber;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.pubsub.v1.PubsubMessage;
    import java.io.FileInputStream;
    import java.util.Collections;
    
    public class Main {
    
      public static final String PROJECT_ID_ENV_PROPERTY = "PROJECT_ID";
      public static final String SUBSCRIPTION_ID_ENV_PROPERTY = "SUBSCRIPTION_ID";
      public static final String CREDENTIALS_PATH_ENV_PROPERTY = "GOOGLE_APPLICATION_CREDENTIALS";
    
      public static void main(String[] args) throws Exception {
        ProjectSubscriptionName subscriptionName =
            ProjectSubscriptionName.of(
                System.getenv(Main.PROJECT_ID_ENV_PROPERTY),
                System.getenv(Main.SUBSCRIPTION_ID_ENV_PROPERTY));
    
        // Instantiate app, which implements an asynchronous message receiver.
        EchoApp echoApp = new EchoApp();
    
        // Create a subscriber for <var>SUBSCRIPTION_ID</var> bound to the message receiver
        final Subscriber subscriber = Subscriber.newBuilder(subscriptionName, echoApp).build();
        System.out.println("Subscriber is listening to events...");
        subscriber.startAsync();
    
        // Wait for termination
        subscriber.awaitTerminated();
      }
    }
    
    /**
     * A demo app which implements {@link MessageReceiver} to receive messages.
     * It echoes incoming messages.
     */
    class EchoApp implements MessageReceiver {
    
      // Path to the private key JSON file of the service account to be used for posting response
      // messages to Google Chat.
      // In this demo, we are using the same service account for authorizing with Cloud Pub/Sub to
      // receive messages and authorizing with Google Chat to post messages. If you are using
      // different service accounts, set the path to the private key JSON file of the service
      // account used to post messages to Google Chat here.
      private static final String SERVICE_ACCOUNT_KEY_PATH =
        System.getenv(Main.CREDENTIALS_PATH_ENV_PROPERTY);
    
      // Developer code for Google Chat API scope.
      private static final String GOOGLE_CHAT_API_SCOPE = "https://www.googleapis.com/auth/chat.bot";
    
      private static final String ADDED_RESPONSE = "Thank you for adding me!";
    
      ChatServiceClient chatServiceClient;
    
      EchoApp() throws Exception {
        GoogleCredentials credential =
            GoogleCredentials.fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH))
                .createScoped(Collections.singleton(GOOGLE_CHAT_API_SCOPE));
    
        // Create the ChatServiceSettings with the app credentials
        ChatServiceSettings chatServiceSettings =
            ChatServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();
    
        // Set the Chat service client
        chatServiceClient = ChatServiceClient.create(chatServiceSettings);
      }
    
      // Called when a message is received by the subscriber.
      @Override
      public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer consumer) {
        System.out.println("Id : " + pubsubMessage.getMessageId());
        // Handle incoming message, then acknowledge the received message
        try {
          ObjectMapper mapper = new ObjectMapper();
          JsonNode dataJson = mapper.readTree(pubsubMessage.getData().toStringUtf8());
          System.out.println("Data : " + dataJson.toString());
          handle(dataJson);
          consumer.ack();
        } catch (Exception e) {
          System.out.println(e);
          // Negative acknowledgement makes Pub/Sub redeliver the message.
          consumer.nack();
        }
      }
    
      // Send message to Google Chat based on the type of event.
      public void handle(JsonNode eventJson) throws Exception {
        // Google Chat events for add-ons are wrapped in a 'chat' object.
        if (!eventJson.has("chat")) {
          System.out.println("Ignored: Not a Chat event (missing 'chat' field).");
          return;
        }
    
        JsonNode chatNode = eventJson.get("chat");
        CreateMessageRequest createMessageRequest = null;
    
        if (chatNode.has("messagePayload")) {
          // HANDLE MESSAGE
          JsonNode messagePayload = chatNode.get("messagePayload");
          JsonNode message = messagePayload.get("message");
          JsonNode space = messagePayload.get("space");
    
          String spaceName = space.get("name").asText();
          String userText = message.has("text") ? message.get("text").asText() : "";
          String threadName = message.has("thread") ? message.get("thread").get("name").asText() : "";
    
          System.out.println("Received message in " + spaceName + ": " + userText);
    
          createMessageRequest =
              CreateMessageRequest.newBuilder()
                  .setParent(spaceName)
                  .setMessageReplyOption(MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD)
                  .setMessage(
                      Message.newBuilder()
                          .setText("You said: `" + userText + "`")
                          .setThread(Thread.newBuilder().setName(threadName).build())
                          .build())
                  .build();
    
        } else if (chatNode.has("addedToSpacePayload")) {
          // HANDLE ADDED TO SPACE
          JsonNode addedPayload = chatNode.get("addedToSpacePayload");
          JsonNode space = addedPayload.get("space");
          String spaceName = space.get("name").asText();
    
          System.out.println("Added to space: " + spaceName);
    
          createMessageRequest =
              CreateMessageRequest.newBuilder()
                  .setParent(spaceName)
                  .setMessage(Message.newBuilder().setText(ADDED_RESPONSE).build())
                  .build();
    
        } else if (chatNode.has("removedFromSpacePayload")) {
          System.out.println("Removed from space.");
          return;
        } else {
          System.out.println("Ignored: Unhandled Chat event type.");
          return;
        }
    
        if (createMessageRequest != null) {
          // Post the response to Google Chat.
          chatServiceClient.createMessage(createMessageRequest);
          System.out.println("Sent reply.");
        }
      }
    }
    

پیکربندی برنامه Chat

برنامه Chat را در کنسول Google Cloud پیکربندی کنید تا جزئیاتی مانند نام و چهرک آن را ارائه دهید و اتصال به موضوع Pub/Sub را راه‌اندازی کنید.

با متصل شدن به موضوع Pub/Sub، به Chat اجازه می‌دهید رویدادها را به برنامه‌تان ارسال کند. سپس نوشتار شما که در موضوع مشترک شده است می‌تواند این رویدادها را دریافت کند و به کاربران پاسخ دهد.

  1. در کنسول Google Cloud، به منو > «میاناهای برنامه‌سازی کاربردی و سرویس‌ها» > «میاناهای برنامه‌سازی کاربردی و سرویس‌های فعال» > Google Chat API > «پیکربندی» بروید.

    رفتن به پیکربندی Chat API

  2. پیکربندی برنامه Chat برای Pub/Sub:

    1. در نام برنامه، Quickstart App را وارد کنید.
    2. در نشانی وب چهرک، https://developers.google.com/workspace/chat/images/quickstart-app-avatar.png را وارد کنید.
    3. در شرح، Quickstart app را وارد کنید.
    4. در بخش عملکرد، گزینه پیوستن به فضاها و مکالمه‌های گروهی را انتخاب کنید.
    5. در بخش تنظیمات اتصال، Cloud Pub/Sub را انتخاب کنید و نام موضوع Pub/Sub را که قبلاً ساخته‌اید جای‌گذاری کنید.
    6. در بخش رؤیت‌پذیری، گزینه این برنامه Google Chat را برای افراد و گروه‌های خاصی در دامنه‌تان دردسترس قرار دهید و نشانی ایمیلتان را وارد کنید.
    7. در بخش گزارش‌ها، خطاهای گزارش به «گزارش‌گیری» را انتخاب کنید.
  3. روی ذخیره کلیک کنید.

اکنون که برنامه Chat را پیکربندی کرده‌اید، باید پیکربندی Pub/Sub را به‌روز کنید.

  1. در صفحه پیکربندی Chat API، در بخش تنظیمات اتصال، ایمیل حساب سرویس را کپی کنید. این ایمیل ایمیل یکتایی است که برای پروژه Google Cloud شما تولید شده است.
  2. با اختصاص نقش ناشر Pub/Sub به ایمیل حساب سرویس که قبلاً کپی کرده‌اید، به Chat اجازه دهید در موضوع منتشر کند.

برنامه آماده دریافت و پاسخ دادن به پیام‌ها در Chat است.

اجرای دستورگان

در یک CLI، به دایرکتوری کاری خود بروید و اسکریپت را اجرا کنید:

Node.js

npm install
npm start

Python

python -m venv env
source env/bin/activate
pip install -r requirements.txt -U
python app.py

جاوا

mvn compile exec:java -Dexec.mainClass=Main

وقتی کد را اجرا می‌کنید، برنامه شروع به گوش دادن به پیام‌های منتشرشده در موضوع Pub/Sub می‌کند.

آزمایش کردن برنامه Chat

برای آزمایش برنامه Chat، فضای پیام مستقیمی را با برنامه Chat باز کنید و پیامی ارسال کنید:

  1. بااستفاده از حساب Google Workspace که هنگام اضافه کردن خودتان به‌عنوان آزمایش‌کننده معتمد ارائه کردید، Google Chat را باز کنید.

    رفتن به Google Chat

  2. روی گپ جدید کلیک کنید.
  3. در فیلد افزودن ۱ یا چند نفر، نام برنامه Chat خود را تایپ کنید.
  4. برنامه Chat را از نتایج انتخاب کنید. پیام مستقیمی باز می‌شود.

  5. در پیام مستقیم جدید با برنامه، Hello را تایپ کنید و enter را فشار دهید.

برای افزودن آزمایش‌گران مطمئن و کسب اطلاعات بیشتر درباره آزمایش ویژگی‌های تعاملی، به آزمایش ویژگی‌های تعاملی برای برنامه‌های Google Chat مراجعه کنید.

عیب‌یابی

وقتی برنامه یا کارت Google Chat خطایی برمی‌گرداند، میانای Chat پیامی را نشان می‌دهد که می‌گوید «مشکلی پیش آمد». یا «نمی‌توانیم درخواستتان را پردازش کنیم.» گاهی‌اوقات «میانای کاربری Chat» هیچ پیام خطایی نمایش نمی‌دهد، اما برنامه Chat یا کارت نتیجه غیرمنتظره‌ای تولید می‌کند؛ برای مثال، ممکن است پیام کارت ظاهر نشود.

اگرچه ممکن است پیام خطا در واسط کاربر Chat نمایش داده نشود، پیام‌های خطای توصیفی و داده‌های گزارش برای کمک به شما در رفع خطاها وقتی گزارش خطا برای برنامه‌های Chat روشن باشد دردسترس است. برای دریافت راهنمایی درباره مشاهده، اشکال‌زدایی، و رفع خطاها، عیب‌یابی و رفع خطاهای Google Chat را ببینید.

مرتب‌سازی

برای اینکه هزینه منابع استفاده‌شده در این آموزش به حساب Google Cloud شما اضافه نشود، توصیه می‌کنیم پروژه Cloud را حذف کنید.

  1. در کنسول Google Cloud، به صفحه مدیریت منابع بروید. روی منو > IAM و سرپرست > مدیریت منابع کلیک کنید.

    به «مدیر منابع» بروید

  2. در فهرست پروژه، پروژه‌ای را که می‌خواهید حذف کنید انتخاب کنید و سپس روی حذف کلیک کنید.
  3. در چارگوش گفتگو، شناسه پروژه را تایپ کنید و سپس روی خاموش کردن کلیک کنید تا پروژه حذف شود.

برنامه‌های Chat که برافزا نیستند: ساختن برنامه Google Chat با Pub/Sub

برای ساختن برنامه Chat که برافزای Google Workspace نیست با Pub/Sub، این مراحل را برای اعطای اجازه‌های انتشار Pub/Sub، نوشتن نوشتار، و پیکربندی برنامه Chat که برافزا نیست دنبال کنید.

به Chat اجازه دهید در موضوع منتشر کند

با اختصاص نقش ناشر Pub/Sub به حساب سرویس زیر، به Chat اجازه دهید در موضوع Pub/Sub منتشر کند

chat-api-push@system.gserviceaccount.com

نوشتن دستورگان برای برنامه Chat که برافزا نیست

Node.js

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام package.json ایجاد کنید.

  5. در فایل package.json، کد زیر را جای‌گذاری کنید:

    node/pub-sub-app/package.json
    {
      "name": "pub-sub-app",
      "version": "1.0.0",
      "description": "Google Chat App that listens for messages via Cloud Pub/Sub",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "dependencies": {
        "@google-apps/chat": "^0.4.0",
        "@google-cloud/pubsub": "^4.5.0"
      },
      "license": "Apache-2.0"
    }
  6. در فهرست راهنمای کاری‌تان، فایلی به‌نام index.js ایجاد کنید.

  7. در index.js، کد زیر را جای‌گذاری کنید:

    node/pub-sub-app/index.js
    const {ChatServiceClient} = require('@google-apps/chat');
    const {MessageReplyOption} = require('@google-apps/chat').protos.google.chat.v1.CreateMessageRequest;
    const {PubSub} = require('@google-cloud/pubsub');
    const {SubscriberClient} = require('@google-cloud/pubsub/build/src/v1');
    
    // Receives messages from a pull subscription.
    function receiveMessages() {
      const chat = new ChatServiceClient({
        keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS,
        scopes: ['https://www.googleapis.com/auth/chat.bot'],
      });
    
      const subscriptionPath = new SubscriberClient()
        .subscriptionPath(process.env.PROJECT_ID, process.env.SUBSCRIPTION_ID)
      const subscription = new PubSub()
        .subscription(subscriptionPath);
    
      // Handle incoming message, then ack/nack the received message
      const messageHandler = message => {
        console.log(`Id : ${message.id}`);
        const event = JSON.parse(message.data);
        console.log(`Data : ${JSON.stringify(event)}`);
    
        // Post the response to Google Chat.
        const request = formatRequest(event);
        if (request != null) {
          chat.createMessage(request);
        }
    
        // Ack the message.
        message.ack();
      }
    
      subscription.on('message', messageHandler);
      console.log(`Listening for messages on ${subscriptionPath}`);
    
      // Keep main thread from exiting while waiting for messages
      setTimeout(() => {
        subscription.removeListener('message', messageHandler);
        console.log(`Stopped listening for messages.`);
      }, 60 * 1000);
    }
    
    // Send message to Google Chat based on the type of event
    function formatRequest(event) {
      const spaceName = event.space.name;
      const eventType = event.type;
    
      // If the app was removed, we don't respond.
      if (event.type == 'REMOVED_FROM_SPACE') {
        console.log(`App removed rom space ${spaceName}`);
        return null;
      } else if (eventType == 'ADDED_TO_SPACE' && !eventType.message) {
        // An app can also be added to a space by @mentioning it in a
        // message. In that case, we fall through to the message case
        // and let the app respond. If the app was added using the
        // invite flow, we just post a thank you message in the space.
        return {
          parent: spaceName,
          message: { text: 'Thank you for adding me!' }
        };
      } else if (eventType == 'ADDED_TO_SPACE' || eventType == 'MESSAGE') {
        // In case of message, post the response in the same thread.
        return {
          parent: spaceName,
          messageReplyOption: MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD,
          message: {
            text: 'You said: `' + event.message.text + '`',
            thread: { name: event.message.thread.name }
          }
        };
      }
    }
    
    if (!process.env.PROJECT_ID) {
      console.log('Missing PROJECT_ID env var.');
      process.exit(1);
    }
    if (!process.env.SUBSCRIPTION_ID) {
      console.log('Missing SUBSCRIPTION_ID env var.');
      process.exit(1);
    }
    if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) {
      console.log('Missing GOOGLE_APPLICATION_CREDENTIALS env var.');
      process.exit(1);
    }
    
    receiveMessages();

Python

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام requirements.txt ایجاد کنید.

  5. در فایل requirements.txt، کد زیر را جای‌گذاری کنید:

    python/pub-sub-app/requirements.txt
    google-cloud-pubsub>=2.23.0
    google-apps-chat==0.1.9
  6. در فهرست راهنمای کاری‌تان، فایلی به‌نام app.py ایجاد کنید.

  7. در app.py، کد زیر را جای‌گذاری کنید:

    python/pub-sub-app/app.py
    import json
    import logging
    import os
    import sys
    import time
    from google.apps import chat_v1 as google_chat
    from google.cloud import pubsub_v1
    from google.oauth2.service_account import Credentials
    
    
    def receive_messages():
      """Receives messages from a pull subscription."""
    
      scopes = ['https://www.googleapis.com/auth/chat.bot']
      service_account_key_path = os.environ.get(
        'GOOGLE_APPLICATION_CREDENTIALS')
      creds = Credentials.from_service_account_file(
        service_account_key_path)
      chat = google_chat.ChatServiceClient(
        credentials = creds,
        client_options = {
          "scopes": scopes
        })
    
      project_id = os.environ.get('PROJECT_ID')
      subscription_id = os.environ.get('SUBSCRIPTION_ID')
      subscriber = pubsub_v1.SubscriberClient()
      subscription_path = subscriber.subscription_path(
          project_id, subscription_id)
    
      # Handle incoming message, then ack/nack the received message
      def callback(message):
        event = json.loads(message.data)
        logging.info('Data : %s', event)
        space_name = event['space']['name']
    
        # Post the response to Google Chat.
        request = format_request(event)
        if request is not None:
          chat.create_message(request)
    
        # Ack the message.
        message.ack()
    
      subscriber.subscribe(subscription_path, callback = callback)
      logging.info('Listening for messages on %s', subscription_path)
    
      # Keep main thread from exiting while waiting for messages
      while True:
        time.sleep(60)
    
    
    def format_request(event):
      """Send message to Google Chat based on the type of event.
      Args:
        event: A dictionary with the event data.
      """
      space_name = event['space']['name']
      event_type = event['type']
    
      # If the app was removed, we don't respond.
      if event['type'] == 'REMOVED_FROM_SPACE':
        logging.info('App removed rom space %s', space_name)
        return
      elif event_type == 'ADDED_TO_SPACE' and 'message' not in event:
        # An app can also be added to a space by @mentioning it in a
        # message. In that case, we fall through to the message case
        # and let the app respond. If the app was added using the
        # invite flow, we just post a thank you message in the space.
        return google_chat.CreateMessageRequest(
            parent = space_name,
            message = {
              'text': 'Thank you for adding me!'
            }
        )
      elif event_type in ['ADDED_TO_SPACE', 'MESSAGE']:
        # In case of message, post the response in the same thread.
        return google_chat.CreateMessageRequest(
            parent = space_name,
            message_reply_option = google_chat.CreateMessageRequest.MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD,
            message = {
              'text': 'You said: `' + event['message']['text'] + '`',
              'thread': {
                'name': event['message']['thread']['name']
              }
            }
        )
    
    
    if __name__ == '__main__':
      if 'PROJECT_ID' not in os.environ:
        logging.error('Missing PROJECT_ID env var.')
        sys.exit(1)
    
      if 'SUBSCRIPTION_ID' not in os.environ:
        logging.error('Missing SUBSCRIPTION_ID env var.')
        sys.exit(1)
    
      if 'GOOGLE_APPLICATION_CREDENTIALS' not in os.environ:
        logging.error('Missing GOOGLE_APPLICATION_CREDENTIALS env var.')
        sys.exit(1)
    
      logging.basicConfig(
          level=logging.INFO,
          style='{',
          format='{levelname:.1}{asctime} {filename}:{lineno}] {message}')
      receive_messages()

جاوا

  1. در یک CLI، اطلاعات اعتباری حساب سرویس را ارائه دهید:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. در یک CLI، شناسه پروژه Google Cloud را ارائه دهید:

    export PROJECT_ID=PROJECT_ID
    
  3. در CLI، شناسه اشتراک را برای اشتراک Pub/Sub که قبلاً ایجاد کرده‌اید ارائه دهید:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. در فهرست راهنمای کاری‌تان، فایلی به‌نام pom.xml ایجاد کنید.

  5. در فایل pom.xml، کد زیر را جای‌گذاری کنید:

    java/pub-sub-app/pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.google.chat</groupId>
      <artifactId>pub-sub-app</artifactId>
      <version>0.1.0</version>
    
      <name>pub-sub-app-java</name>
    
      <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
    
      <dependencies>
        <!-- Google Chat GAPIC library -->
        <dependency>
          <groupId>com.google.api.grpc</groupId>
          <artifactId>proto-google-cloud-chat-v1</artifactId>
          <version>0.8.0</version>
        </dependency>
        <dependency>
          <groupId>com.google.api</groupId>
          <artifactId>gax</artifactId>
          <version>2.48.1</version>
        </dependency>
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>google-cloud-chat</artifactId>
          <version>0.1.0</version>
        </dependency>
        <!-- Google Cloud Pub/Sub library -->
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>google-cloud-pubsub</artifactId>
        <version>1.125.8</version>
        </dependency>
        <!-- JSON utilities -->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.14.2</version>
        </dependency>
      </dependencies>
    
    </project>
  6. در فهرست راهنمای کارتان، ساختار فهرست راهنمای src/main/java را ایجاد کنید.

  7. در دایرکتوری src/main/java، فایلی با نام Main.java ایجاد کنید.

  8. در Main.java، کد زیر را جای‌گذاری کنید:

    java/pub-sub-app/src/main/java/Main.java
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.chat.v1.ChatServiceClient;
    import com.google.chat.v1.ChatServiceSettings;
    import com.google.chat.v1.CreateMessageRequest;
    import com.google.chat.v1.CreateMessageRequest.MessageReplyOption;
    import com.google.chat.v1.Message;
    import com.google.chat.v1.Thread;
    import com.google.cloud.pubsub.v1.AckReplyConsumer;
    import com.google.cloud.pubsub.v1.MessageReceiver;
    import com.google.cloud.pubsub.v1.Subscriber;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.pubsub.v1.PubsubMessage;
    import java.io.FileInputStream;
    import java.util.Collections;
    
    public class Main {
    
      public static final String PROJECT_ID_ENV_PROPERTY = "PROJECT_ID";
      public static final String SUBSCRIPTION_ID_ENV_PROPERTY = "SUBSCRIPTION_ID";
      public static final String CREDENTIALS_PATH_ENV_PROPERTY = "GOOGLE_APPLICATION_CREDENTIALS";
    
      public static void main(String[] args) throws Exception {
        ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of(
          System.getenv(Main.PROJECT_ID_ENV_PROPERTY),
          System.getenv(Main.SUBSCRIPTION_ID_ENV_PROPERTY));
    
        // Instantiate app, which implements an asynchronous message receiver.
        EchoApp echoApp = new EchoApp();
    
        // Create a subscriber for <var>SUBSCRIPTION_ID</var> bound to the message receiver
        final Subscriber subscriber = Subscriber.newBuilder(subscriptionName, echoApp).build();
        System.out.println("Subscriber is listening to events...");
        subscriber.startAsync();
    
        // Wait for termination
        subscriber.awaitTerminated();
      }
    }
    
    /**
     * A demo app which implements {@link MessageReceiver} to receive messages. It simply echoes the
     * incoming messages.
     */
    class EchoApp implements MessageReceiver {
    
      // Path to the private key JSON file of the service account to be used for posting response
      // messages to Google Chat.
      // In this demo, we are using the same service account for authorizing with Cloud Pub/Sub to
      // receive messages and authorizing with Google Chat to post messages. If you are using
      // different service accounts, please set the path to the private key JSON file of the service
      // account used to post messages to Google Chat here.
      private static final String SERVICE_ACCOUNT_KEY_PATH =
        System.getenv(Main.CREDENTIALS_PATH_ENV_PROPERTY);
    
      // Developer code for Google Chat API scope.
      private static final String GOOGLE_CHAT_API_SCOPE = "https://www.googleapis.com/auth/chat.bot";
    
      private static final String ADDED_RESPONSE = "Thank you for adding me!";
    
      ChatServiceClient chatServiceClient;
    
      EchoApp() throws Exception {
        GoogleCredentials credential = GoogleCredentials
          .fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH))
          .createScoped(Collections.singleton(GOOGLE_CHAT_API_SCOPE));
    
        // Create the ChatServiceSettings with the app credentials
        ChatServiceSettings chatServiceSettings = ChatServiceSettings.newBuilder()
          .setCredentialsProvider(FixedCredentialsProvider.create(credential)).build();
    
        // Set the Chat service client
        chatServiceClient = ChatServiceClient.create(chatServiceSettings);
      }
    
      // Called when a message is received by the subscriber.
      @Override
      public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer consumer) {
        System.out.println("Id : " + pubsubMessage.getMessageId());
        // Handle incoming message, then ack/nack the received message
        try {
          ObjectMapper mapper = new ObjectMapper();
          JsonNode dataJson = mapper.readTree(pubsubMessage.getData().toStringUtf8());
          System.out.println("Data : " + dataJson.toString());
          handle(dataJson);
          consumer.ack();
        } catch (Exception e) {
          System.out.println(e);
          consumer.nack();
        }
      }
    
      // Send message to Google Chat based on the type of event.
      public void handle(JsonNode eventJson) throws Exception {
        CreateMessageRequest createMessageRequest;
        switch (eventJson.get("type").asText()) {
          case "ADDED_TO_SPACE":
            // An app can also be added to a space by @mentioning it in a message. In that case, we fall
            // through to the MESSAGE case and let the app respond. If the app was added using the
            // invite flow, we just post a thank you message in the space.
            if (!eventJson.has("message")) {
              createMessageRequest = CreateMessageRequest.newBuilder()
                .setParent(eventJson.get("space").get("name").asText())
                .setMessage(Message.newBuilder().setText(ADDED_RESPONSE).build()).build();
              break;
            }
          case "MESSAGE":
            // In case of message, post the response in the same thread.
            createMessageRequest = CreateMessageRequest.newBuilder()
              .setParent(eventJson.get("space").get("name").asText())
              .setMessageReplyOption(MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD)
              .setMessage(Message.newBuilder()
                .setText("You said: `" + eventJson.get("message").get("text").asText() + "`")
                .setThread(Thread.newBuilder()
                  .setName(eventJson.get("message").get("thread").get("name").asText())
                  .build()).build()).build();
            break;
          case "REMOVED_FROM_SPACE":
          default:
            // Do nothing
            return;
        }
    
        // Post the response to Google Chat.
        chatServiceClient.createMessage(createMessageRequest);
      }
    }

پیکربندی برنامه Chat که برافزا نیست

  1. در کنسول Google Cloud، به منو > «میاناهای برنامه‌سازی کاربردی و سرویس‌ها» > «میاناهای برنامه‌سازی کاربردی و سرویس‌های فعال» > Google Chat API > «پیکربندی» بروید.

    رفتن به «پیکربندی»

  2. برنامه Chat را که برافزا برای Pub/Sub نیست پیکربندی کنید:

    1. ساخت این برنامه Chat به‌عنوان برافزای Google Workspace را لغو انتخاب کنید. کادر گفتگویی باز می‌شود که از شما می‌خواهد تأیید کنید. در چارگوش گفتگو، روی غیرفعال کردن کلیک کنید.
    2. در نام برنامه، Quickstart App را وارد کنید.
    3. در نشانی وب چهرک، https://developers.google.com/workspace/chat/images/quickstart-app-avatar.png را وارد کنید.
    4. در شرح، Quickstart app را وارد کنید.
    5. در بخش عملکرد، گزینه پیوستن به فضاها و مکالمه‌های گروهی را انتخاب کنید.
    6. در بخش تنظیمات اتصال، Cloud Pub/Sub را انتخاب کنید و نام موضوع Pub/Sub را که قبلاً ساخته‌اید جای‌گذاری کنید.
    7. در بخش رؤیت‌پذیری، گزینه این برنامه Google Chat را برای افراد و گروه‌های خاصی در دامنه‌تان دردسترس قرار دهید و نشانی ایمیلتان را وارد کنید.
    8. در بخش گزارش‌ها، خطاهای گزارش به «گزارش‌گیری» را انتخاب کنید.
  3. روی ذخیره کلیک کنید.