লিঙ্কের প্রিভিউ

Google Chat-এ ব্যবহারকারীরা কোনও লিঙ্ক শেয়ার করলে, প্রসঙ্গ পরিবর্তন হওয়া আটকাতে, আপনার Chat অ্যাপ তাদের মেসেজে একটি কার্ড অ্যাটাচ করে লিঙ্কটি প্রিভিউ করতে পারে। এর ফলে আরও তথ্য পাওয়া যায় এবং লোকজন Google Chat থেকেই অ্যাকশন নিতে পারেন।

যেমন, কোনও কোম্পানির কাস্টমার পরিষেবা এজেন্টদের সাথে Case-y নামের একটি Chat অ্যাপ আছে এমন একটি Google Chat স্পেসের কথা ভাবুন। এজেন্টরা প্রায়ই চ্যাট স্পেসে গ্রাহক পরিষেবা সংক্রান্ত কেসের লিঙ্ক শেয়ার করেন এবং প্রত্যেকবার তারা এটি করলে, তাদের সহকর্মীদের অবশ্যই কেসের লিঙ্ক খুলে অ্যাসাইনি, স্ট্যাটাস ও বিষয়ের মতো বিবরণ দেখতে হবে। একইভাবে, কেউ যদি কোনও কেসের মালিকানা নিতে বা স্ট্যাটাস পরিবর্তন করতে চান, তাহলে তাকে লিঙ্কটি খুলতে হবে।

লিঙ্ক প্রিভিউ করার সুবিধা চালু থাকলে, স্পেসের রেসিডেন্ট Chat অ্যাপ, কেসি, অ্যাসাইনি, স্ট্যাটাস ও বিষয় সহ একটি কার্ড অ্যাটাচ করতে পারে, যখনই কেউ কেস লিঙ্ক শেয়ার করেন। কার্ডে থাকা বোতামের সাহায্যে এজেন্টরা কেসের দায়িত্ব নিতে এবং চ্যাট স্ট্রিম থেকে সরাসরি স্ট্যাটাস পরিবর্তন করতে পারেন।

কেউ তার মেসেজে কোনও লিঙ্ক যোগ করলে, একটি চিপ দেখা যায় যা তাকে জানায় যে Chat অ্যাপ লিঙ্কটির প্রিভিউ দেখাতে পারে।

চিপ থেকে বোঝা যায় যে Chat অ্যাপ কোনও লিঙ্কের প্রিভিউ দেখাতে পারে

মেসেজ পাঠানোর পরে, লিঙ্কটি Chat অ্যাপে পাঠানো হয়, যা তারপরে ব্যবহারকারীর মেসেজে কার্ড জেনারেট করে অ্যাটাচ করে।

মেসেজে কার্ড অ্যাটাচ করে চ্যাট অ্যাপের মাধ্যমে লিঙ্কের প্রিভিউ দেখানো

লিঙ্কের পাশাপাশি, কার্ডটি লিঙ্ক সম্পর্কে অতিরিক্ত তথ্য প্রদান করে, যার মধ্যে বোতামের মতো ইন্ট্যার‍্যাক্টিভ এলিমেন্ট অন্তর্ভুক্ত। আপনার Chat অ্যাপ, বোতামে ক্লিক করার মতো ব্যবহারকারীর ইন্টার‍্যাকশনের উত্তরে অ্যাটাচ করা কার্ড আপডেট করতে পারে।

কেউ যদি চান যে Chat অ্যাপ তার মেসেজে কার্ড অ্যাটাচ করে তার লিঙ্কের প্রিভিউ না দেখাক, তাহলে তিনি প্রিভিউ চিপে আইকনে ক্লিক করে প্রিভিউ দেখানো আটকাতে পারেন। ব্যবহারকারী প্রিভিউ সরান বিকল্পে ক্লিক করে যেকোনও সময় অ্যাটাচ করা কার্ড সরিয়ে দিতে পারবেন।

পূর্বশর্ত

HTTP

Google Chat অ্যাপ যা ব্যবহারকারীর ইন্টার‍্যাকশন গ্রহণ করে এবং উত্তর দেয়। এটি তৈরি করতে, HTTP কুইকস্টার্ট সম্পূর্ণ করুন।

Apps Script

Google Chat অ্যাপ যা ব্যবহারকারীর ইন্টার‍্যাকশন গ্রহণ করে এবং উত্তর দেয়। এটি তৈরি করতে, অ্যাপ স্ক্রিপ্ট কুইকস্টার্ট সম্পূর্ণ করুন।

নির্দিষ্ট লিঙ্ক - যেমন example.com, support.example.com এবং support.example.com/cases/ - আপনার Chat অ্যাপের কনফিগারেশন পৃষ্ঠায় URL প্যাটার্ন হিসেবে Google Cloud কনসোলে রেজিস্টার করুন, যাতে আপনার Chat অ্যাপ সেগুলির প্রিভিউ দেখতে পায়।

লিঙ্ক প্রিভিউ কনফিগারেশন মেনু

  1. Google Cloud Console খুলুন।
  2. "Google Cloud" বিকল্পের পাশে, নিচের দিকের তীরচিহ্ন আইকনে ক্লিক করুন এবং আপনার Chat অ্যাপের প্রোজেক্ট খুলুন।
  3. সার্চ ফিল্ডে Google Chat API টাইপ করে Google Chat API বিকল্পে ক্লিক করুন।
  4. ম্যানেজ করুন > কনফিগারেশন বিকল্পে ক্লিক করুন।
  5. লিঙ্ক প্রিভিউয়ের মধ্যে, URL প্যাটার্ন যোগ করুন বা এডিট করুন।
    1. নতুন URL প্যাটার্নের জন্য লিঙ্কের প্রিভিউ কনফিগার করতে, URL প্যাটার্ন যোগ করুন বিকল্পে ক্লিক করুন।
    2. আগে থেকে থাকা URL প্যাটার্নের কনফিগারেশন এডিট করতে, নিম্নমুখী তীরচিহ্নে ক্লিক করুন।
  6. হোস্ট প্যাটার্ন ফিল্ডে, URL প্যাটার্নের ডোমেন লিখুন। Chat অ্যাপ এই ডোমেনের লিঙ্ক প্রিভিউ করবে।

    নির্দিষ্ট সাবডোমেনের জন্য Chat অ্যাপের প্রিভিউ লিঙ্ক পেতে, যেমন subdomain.example.com, সাবডোমেন অন্তর্ভুক্ত করুন।

    সম্পূর্ণ ডোমেনের জন্য Chat অ্যাপের প্রিভিউ লিঙ্ক পেতে, সাবডোমেন হিসেবে অ্যাস্টেরিস্ক (*) সহ ওয়াইল্ডকার্ড ক্যারেক্টার নির্দিষ্ট করুন। যেমন, *.example.com, subdomain.example.com এবং any.number.of.subdomains.example.com-এর সাথে ম্যাচ করে।

  7. পাথ প্রিফিক্স ফিল্ডে, হোস্ট প্যাটার্ন ডোমেনে যোগ করার জন্য একটি পাথ লিখুন।

    হোস্ট প্যাটার্ন ডোমেনের সব URL ম্যাচ করাতে, পাথ প্রিফিক্স খালি রাখুন।

    যেমন, হোস্ট প্যাটার্ন support.example.com হলে, support.example.com/cases/-এ হোস্ট করা কেসের URL-এর সাথে ম্যাচ করাতে, cases/ লিখুন।

  8. হয়ে গেছে বিকল্পে ক্লিক করুন।

  9. সেভ করুন বিকল্পে ক্লিক করুন।

এখন, কেউ যদি Chat স্পেসে এমন কোনও মেসেজ লেখেন যাতে আপনার Chat অ্যাপ আছে এবং সেই মেসেজে এমন কোনও লিঙ্ক যোগ করেন যা লিঙ্ক প্রিভিউ URL প্যাটার্নের সাথে ম্যাচ করে, তাহলে আপনার অ্যাপ সেই লিঙ্কটির প্রিভিউ দেখাবে।

কোনও লিঙ্কের জন্য লিঙ্ক প্রিভিউ কনফিগার করার পরে, আপনার Chat অ্যাপ সেটিতে আরও তথ্য যোগ করে লিঙ্কটি চিনতে ও প্রিভিউ করতে পারবে।

আপনার Chat অ্যাপ সহ Chat স্পেসের মধ্যে, কোনও ব্যক্তির মেসেজে যদি এমন লিঙ্ক থাকে যা লিঙ্ক প্রিভিউ URL প্যাটার্নের সাথে ম্যাচ করে, তাহলে আপনার Chat অ্যাপ MessagePayload সহ একটি ইভেন্ট অবজেক্ট পায়। পে-লোডে, message.matchedUrl (chat.messagePayload.message.matchedUrl.url) অবজেক্টে সেই লিঙ্ক থাকে যা ব্যবহারকারী মেসেজে যোগ করেছেন:

JSON

message: {
  matchedUrl: {
    url: "https://support.example.com/cases/case123"
  },
  ... // other message attributes redacted
}

MESSAGE ইভেন্টের পে-লোড (chat.messagePayload.message.matchedUrl.url)-এ matchedUrl ফিল্ড আছে কিনা তা চেক করে, আপনার চ্যাট অ্যাপ প্রিভিউ করা লিঙ্কের সাথে মেসেজে তথ্য যোগ করতে পারে। আপনার Chat অ্যাপ একটি সাধারণ টেক্সট মেসেজ দিয়ে উত্তর দিতে পারে অথবা একটি কার্ড অ্যাটাচ করতে পারে।

টেক্সট মেসেজের মাধ্যমে উত্তর দিন

সাধারণ উত্তরের ক্ষেত্রে, আপনার Chat অ্যাপ কোনও লিঙ্কে সাধারণ টেক্সট মেসেজ দিয়ে উত্তর দেওয়ার মাধ্যমে লিঙ্কের প্রিভিউ দেখাতে পারে। এই উদাহরণে এমন একটি মেসেজ অ্যাটাচ করা হয়েছে যা লিঙ্ক URL-কে রিপিট করে এবং লিঙ্ক প্রিভিউ URL প্যাটার্নের সাথে ম্যাচ করে।

Node.js

node/chat/preview-link/index.js
// Reply with a text message for URLs of the subdomain "text"
if (chatMessage.matchedUrl.url.includes("text.example.com")) {
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
  }}}}};
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Python

python/chat/preview-link/main.py
# Reply with a text message for URLs of the subdomain "text"
if "text.example.com" in chatMessage.get('matchedUrl').get('url'):
  return { 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': { 'message': {
    'text': 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.get('matchedUrl').get('url')
  }}}}}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Java

java/chat/preview-link/src/main/java/com/google/chat/previewLink/App.java
// Reply with a text message for URLs of the subdomain "text"
if (chatMessage.at("/matchedUrl/url").asText().contains("text.example.com")) {
  return new GenericJson() {{
    put("hostAppDataAction", new GenericJson() {{
      put("chatDataAction", new GenericJson() {{
        put("createMessageAction", new GenericJson() {{
          put("message", new Message()
            .setText("event.chat.messagePayload.message.matchedUrl.url: " + chatMessage.at("/matchedUrl/url").asText()));
        }});
      }});
    }});
  }};
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Apps Script

apps-script/chat/preview-link/preview-link.gs
// Reply with a text message for URLs of the subdomain "text".
if (chatMessage.matchedUrl.url.includes("text.example.com")) {
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    text: 'event.chat.messagePayload.message.matchedUrl.url: ' + chatMessage.matchedUrl.url
  }}}}};
}

প্রিভিউ করা লিঙ্কে কার্ড অ্যাটাচ করতে, DataActions অ্যাকশনটি ChatDataActionMarkup অবজেক্টের ধরন UpdateInlinePreviewAction সহ রিটার্ন করুন।

নিচের উদাহরণে, Chat অ্যাপ এমন মেসেজে প্রিভিউ কার্ড যোগ করে যাতে support.example.com URL প্যাটার্ন থাকে।

মেসেজে কার্ড অ্যাটাচ করে চ্যাট অ্যাপের মাধ্যমে লিঙ্কের প্রিভিউ দেখানো

Node.js

node/chat/preview-link/index.js
// Attach a card to the message for URLs of the subdomain "support"
if (chatMessage.matchedUrl.url.includes("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case basics',
      },
      sections: [{ widgets: [
      { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
      { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
      { decoratedText: { topLabel: 'Status', text: 'Open'}},
      { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
      { buttonList: { buttons: [{
        text: 'OPEN CASE',
        onClick: { openLink: {
          url: 'https://support.example.com/orders/case123'
        }},
      }, {
        text: 'RESOLVE CASE',
        onClick: { openLink: {
          url: 'https://support.example.com/orders/case123?resolved=y',
        }},
      }, {
        text: 'ASSIGN TO ME',
        onClick: { action: { function: FUNCTION_URL }}
      }]}}
      ]}]
    }
  }]}}}};
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Python

python/chat/preview-link/main.py
# Attach a card to the message for URLs of the subdomain "support"
if "support.example.com" in chatMessage.get('matchedUrl').get('url'):
  # A hard-coded card is used in this example. In a real-life scenario,
  # the case information would be fetched and used to build the card.
  return { 'hostAppDataAction': { 'chatDataAction': { 'updateInlinePreviewAction': { 'cardsV2': [{
    'cardId': 'attachCard',
    'card': {
      'header': {
        'title': 'Example Customer Service Case',
        'subtitle': 'Case basics',
      },
      'sections': [{ 'widgets': [
      { 'decoratedText': { 'topLabel': 'Case ID', 'text': 'case123'}},
      { 'decoratedText': { 'topLabel': 'Assignee', 'text': 'Charlie'}},
      { 'decoratedText': { 'topLabel': 'Status', 'text': 'Open'}},
      { 'decoratedText': { 'topLabel': 'Subject', 'text': 'It won\'t turn on...' }},
      { 'buttonList': { 'buttons': [{
        'text': 'OPEN CASE',
        'onClick': { 'openLink': {
          'url': 'https://support.example.com/orders/case123'
        }},
      }, {
        'text': 'RESOLVE CASE',
        'onClick': { 'openLink': {
          'url': 'https://support.example.com/orders/case123?resolved=y',
        }},
      }, {
        'text': 'ASSIGN TO ME',
        'onClick': { 'action': { 'function': FUNCTION_URL }}
      }]}}
      ]}]
    }
  }]}}}}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Java

java/chat/preview-link/src/main/java/com/google/chat/previewLink/App.java
// Attach a card to the message for URLs of the subdomain "support"
if (chatMessage.at("/matchedUrl/url").asText().contains("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  CardWithId cardV2 = new CardWithId()
    .setCardId("attachCard")
    .setCard(new GoogleAppsCardV1Card()
      .setHeader(new GoogleAppsCardV1CardHeader()
        .setTitle("Example Customer Service Case")
        .setSubtitle("Case basics"))
      .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Case ID")
          .setText("case123")),
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Assignee")
          .setText("Charlie")),
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Status")
          .setText("Open")),
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Subject")
          .setText("It won't turn on...")),
        new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList()
          .setButtons(List.of(
            new GoogleAppsCardV1Button()
              .setText("OPEN CASE")
            .setOnClick(new GoogleAppsCardV1OnClick()
                .setOpenLink(new GoogleAppsCardV1OpenLink()
                  .setUrl("https://support.example.com/orders/case123"))),
            new GoogleAppsCardV1Button()
              .setText("RESOLVE CASE")
            .setOnClick(new GoogleAppsCardV1OnClick()
                .setOpenLink(new GoogleAppsCardV1OpenLink()
                  .setUrl("https://support.example.com/orders/case123?resolved=y"))),
            new GoogleAppsCardV1Button()
              .setText("ASSIGN TO ME")
              .setOnClick(new GoogleAppsCardV1OnClick()
                .setAction(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL)))
          ))
        )
      ))))
    );

  return new GenericJson() {{
    put("hostAppDataAction", new GenericJson() {{
      put("chatDataAction", new GenericJson() {{
        put("updateInlinePreviewAction", new GenericJson() {{
          put("cardsV2", List.of(cardV2));
        }});
      }});
    }});
  }};
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Apps Script

apps-script/chat/preview-link/preview-link.gs
// Attach a card to the message for URLs of the subdomain "support".
if (chatMessage.matchedUrl.url.includes("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case summary',
      },
      sections: [{ widgets: [
      { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
      { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
      { decoratedText: { topLabel: 'Status', text: 'Open'}},
      { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
      { buttonList: { buttons: [{
        text: 'OPEN CASE',
        onClick: { openLink: {
          url: 'https://support.example.com/orders/case123'
        }},
      }, {
        text: 'RESOLVE CASE',
        onClick: { openLink: {
          url: 'https://support.example.com/orders/case123?resolved=y',
        }},
      }, {
        text: 'ASSIGN TO ME',
        // Clicking this button triggers the execution of the function
        // "assign" from the Apps Script project.
        onClick: { action: { function: 'assign'}}
      }]}}
      ]}]
    }
  }]}}}};
}

আপনার Chat অ্যাপ লিঙ্ক প্রিভিউ কার্ড আপডেট করতে পারে, যখন ব্যবহারকারীরা সেটির সাথে ইন্টার‍্যাক্ট করেন, যেমন কার্ডের কোনও বোতামে ক্লিক করা।

কার্ড আপডেট করতে, আপনার Chat অ্যাপকে নিম্নলিখিত ChatDataActionMarkup অবজেক্টের একটি সহ DataActions অ্যাকশন রিটার্ন করতে হবে:

  • কোনও ব্যবহারকারী মেসেজ পাঠালে, একটি UpdateMessageAction অবজেক্ট ফেরত দাও।
  • Chat অ্যাপ মেসেজটি পাঠিয়ে থাকলে, একটি UpdateInlinePreviewAction অবজেক্ট রিটার্ন করুন।

কে মেসেজ পাঠিয়েছেন তা নির্ধারণ করতে, ইভেন্ট পেলোড ব্যবহার করুন (buttonClickedPayload) এবং দেখুন যে প্রেরক (message.sender.type) HUMAN (ব্যবহারকারী) অথবা BOT (চ্যাট অ্যাপ) হিসেবে সেট করা আছে কিনা।

নিচের উদাহরণে দেখানো হয়েছে যে কীভাবে কোনও ব্যবহারকারী আমাকে অ্যাসাইন করুন বোতামে ক্লিক করলে, কার্ডের Assignee ফিল্ড আপডেট করে এবং বোতামটি বন্ধ করে, Chat অ্যাপ একটি লিঙ্ক প্রিভিউ আপডেট করে।

মেসেজে অ্যাটাচ করা কার্ডের আপডেট করা ভার্সন সহ চ্যাট অ্যাপে লিঙ্কের প্রিভিউ দেখা

Node.js

node/chat/preview-link/index.js
/**
 * Respond to clicks by assigning and updating the card that's attached to a
 * message previewed link of the pattern "support.example.com".
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Action response depending on the message author.
 */
function handleCardClick(chatMessage) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case basics',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          onClick: { action: { function: FUNCTION_URL }}
        }]}}
      ]}]
    }
  }]};

  // Use the adequate action response type. It depends on whether the message
  // the preview link card is attached to was created by a human or a Chat app.
  if(chatMessage.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Python

python/chat/preview-link/main.py
def handle_card_click(chatMessage: dict) -> dict:
  """Respond to clicks by assigning and updating the card that's attached to a
  message previewed link of the pattern "support.example.com".

  - Reply with text messages that echo "text.example.com" link URLs in messages.
  - Attach cards to messages with "support.example.com" link URLs.

  Args:
      chatMessage (Mapping[str, Any]): The chat message object from Google Workspace Add On event.

  Returns:
      Mapping[str, Any]: Action response depending on the message author.
  """
  # Creates the updated card that displays "You" for the assignee
  # and that disables the button.
  #
  # A hard-coded card is used in this example. In a real-life scenario,
  # an actual assign action would be performed before building the card.
  message = { 'cardsV2': [{
    'cardId': 'attachCard',
    'card': {
      'header': {
        'title': 'Example Customer Service Case',
        'subtitle': 'Case basics',
      },
      'sections': [{ 'widgets': [
      { 'decoratedText': { 'topLabel': 'Case ID', 'text': 'case123'}},
      # The assignee is now "You"
      { 'decoratedText': { 'topLabel': 'Assignee', 'text': 'You'}},
      { 'decoratedText': { 'topLabel': 'Status', 'text': 'Open'}},
      { 'decoratedText': { 'topLabel': 'Subject', 'text': 'It won\'t turn on...' }},
      { 'buttonList': { 'buttons': [{
        'text': 'OPEN CASE',
        'onClick': { 'openLink': {
          'url': 'https://support.example.com/orders/case123'
        }},
      }, {
        'text': 'RESOLVE CASE',
        'onClick': { 'openLink': {
          'url': 'https://support.example.com/orders/case123?resolved=y',
        }},
      }, {
        'text': 'ASSIGN TO ME',
        # The button is now disabled
        'disabled': True,
        'onClick': { 'action': { 'function': FUNCTION_URL }}
      }]}}
      ]}]
    }
  }]}

  # Use the adequate action response type. It depends on whether the message
  # the preview link card is attached to was created by a human or a Chat app.
  if chatMessage.get('sender').get('type') == 'HUMAN':
    return { 'hostAppDataAction': { 'chatDataAction': { 'updateInlinePreviewAction': message }}}
  else:
    return { 'hostAppDataAction': { 'chatDataAction': { 'updateMessageAction': message }}}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Java

java/chat/preview-link/src/main/java/com/google/chat/previewLink/App.java
/**
 * Respond to clicks by assigning and updating the card that's attached to a
 * message previewed link of the pattern "support.example.com".
 *
 * @param chatMessage The chat message object from Google Workspace Add On event.
 * @return Action response depending on the message author.
 */
GenericJson handleCardClick(JsonNode chatMessage) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  Message message = new Message().setCardsV2(List.of(new CardWithId()
    .setCardId("attachCard")
    .setCard(new GoogleAppsCardV1Card()
      .setHeader(new GoogleAppsCardV1CardHeader()
        .setTitle("Example Customer Service Case")
        .setSubtitle("Case basics"))
      .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Case ID")
          .setText("case123")),
        // The assignee is now "You"
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Assignee")
          .setText("You")),
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Status")
          .setText("Open")),
        new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
          .setTopLabel("Subject")
          .setText("It won't turn on...")),
        new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList()
          .setButtons(List.of(
            new GoogleAppsCardV1Button()
              .setText("OPEN CASE")
              .setOnClick(new GoogleAppsCardV1OnClick()
                .setOpenLink(new GoogleAppsCardV1OpenLink()
                  .setUrl("https://support.example.com/orders/case123"))),
            new GoogleAppsCardV1Button()
              .setText("RESOLVE CASE")
              .setOnClick(new GoogleAppsCardV1OnClick()
                .setOpenLink(new GoogleAppsCardV1OpenLink()
                  .setUrl("https://support.example.com/orders/case123?resolved=y"))),
            new GoogleAppsCardV1Button()
              .setText("ASSIGN TO ME")
              // The button is now disabled
              .setDisabled(true)
              .setOnClick(new GoogleAppsCardV1OnClick()
                .setAction(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL)))
          ))
        )
      ))))
    )
  ));

  // Use the adequate action response type. It depends on whether the message
  // the preview link card is attached to was created by a human or a Chat app.
  if("HUMAN".equals(chatMessage.at("/sender/type").asText())) {
    return new GenericJson() {{
      put("hostAppDataAction", new GenericJson() {{
        put("chatDataAction", new GenericJson() {{
          put("updateInlinePreviewAction", message);
        }});
      }});
    }};
  } else {
    return new GenericJson() {{
      put("hostAppDataAction", new GenericJson() {{
        put("chatDataAction", new GenericJson() {{
          put("updateMessageAction", message);
        }});
      }});
    }};
  }
}

FUNCTION_URL-এর পরিবর্তে HTTP এন্ডপয়েন্ট লিখুন যা বোতামে ক্লিক করা ম্যানেজ করে।

Apps Script

apps-script/chat/preview-link/preview-link.gs
/**
 * Assigns and updates the card that's attached to a message with a
 * previewed link of the pattern "support.example.com".
 *
 * @param {Object} event The event object from the Google Workspace add-on.
 * @return {Object} Action response depending on the message author.
 */
function assign(event) {
  // Creates the updated card that displays "You" for the assignee
  // and that disables the button.
  //
  // A hard-coded card is used in this example. In a real-life scenario,
  // an actual assign action would be performed before building the card.
  const message = { cardsV2: [{
    cardId: 'attachCard',
    card: {
      header: {
        title: 'Example Customer Service Case',
        subtitle: 'Case summary',
      },
      sections: [{ widgets: [
        { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
        // The assignee is now "You"
        { decoratedText: { topLabel: 'Assignee', text: 'You'}},
        { decoratedText: { topLabel: 'Status', text: 'Open'}},
        { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
        { buttonList: { buttons: [{
          text: 'OPEN CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123'
          }},
        }, {
          text: 'RESOLVE CASE',
          onClick: { openLink: {
            url: 'https://support.example.com/orders/case123?resolved=y',
          }},
        }, {
          text: 'ASSIGN TO ME',
          // The button is now disabled
          disabled: true,
          onClick: { action: { function: 'assign'}}
        }]}}
      ]}]
    }
  }]};

  // Use the adequate action response type. It depends on whether the message
  // the preview link card is attached to was created by a human or a Chat app.
  if(event.chat.buttonClickedPayload.message.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

সীমা ও বিবেচ্য বিষয়

আপনার Chat অ্যাপের জন্য লিঙ্ক প্রিভিউ কনফিগার করার সময়, এইসব সীমা ও বিবেচ্য বিষয়গুলি মনে রাখবেন:

  • প্রতিটি Chat অ্যাপে সর্বাধিক ৫টি URL প্যাটার্নের জন্য লিঙ্ক প্রিভিউ কাজ করে।
  • চ্যাট অ্যাপ, প্রতিটি মেসেজে একটি করে লিঙ্ক প্রিভিউ করে। একটি মেসেজে একাধিক প্রিভিউ করা যায় এমন লিঙ্ক থাকলে, শুধুমাত্র প্রথম প্রিভিউ করা যায় এমন লিঙ্কটি প্রিভিউ করা হয়।
  • চ্যাট অ্যাপ শুধুমাত্র https:// দিয়ে শুরু হওয়া লিঙ্ক প্রিভিউ করে, তাই https://support.example.com/cases/ প্রিভিউ করে, কিন্তু support.example.com/cases/ করে না।
  • মেসেজে যদি অন্য কোনও তথ্য না থাকে যা Chat অ্যাপে পাঠানো হয়, যেমন স্ল্যাশ কমান্ড, তাহলে শুধু লিঙ্কের URL, লিঙ্ক প্রিভিউয়ের মাধ্যমে Chat অ্যাপে পাঠানো হয়।
  • কোনও ব্যবহারকারী লিঙ্ক পোস্ট করলে, কোনও চ্যাট অ্যাপ শুধুমাত্র তখনই লিঙ্ক প্রিভিউ কার্ড আপডেট করতে পারে যদি ব্যবহারকারী কার্ডের সাথে ইন্টার‍্যাক্ট করেন, যেমন কোনও বোতামে ক্লিক করে। ব্যবহারকারীর মেসেজ অ্যাসিঙ্ক্রোনাসভাবে আপডেট করতে, আপনি Chat API-এর update() মেথডকে Message রিসোর্সে কল করতে পারবেন না।
  • চ্যাট অ্যাপকে স্পেসের সকলের জন্য লিঙ্কের প্রিভিউ দেখাতে হবে, তাই মেসেজে privateMessageViewer ফিল্ডটি বাদ দিতে হবে।

লিঙ্ক প্রিভিউ প্রয়োগ করার সময়, অ্যাপের লগ পড়ে আপনাকে হয়ত নিজের Chat অ্যাপ ডিবাগ করতে হবে। লগ পড়তে, Google Cloud Console-এ Logs Explorer দেখুন।

Google Workspace অ্যাড-অন নয় এমন Chat অ্যাপের ক্ষেত্রে নিম্নলিখিত ডকুমেন্টেশন প্রযোজ্য। অ্যাড-অন নয় এমন Chat অ্যাপ মাইগ্রেট করতে, Google Chat অ্যাপকে Google Workspace অ্যাড-অনে কনভার্ট করুন দেখুন।

অ্যাড-অন নয় এমন চ্যাট অ্যাপ সহ Chat স্পেসের মধ্যে, কারও মেসেজে এমন লিঙ্ক থাকলে যা লিঙ্ক প্রিভিউ URL প্যাটার্নের সাথে ম্যাচ করে, তাহলে চ্যাট অ্যাপ একটি MESSAGE ইন্টার‍্যাকশন ইভেন্ট পায়। ইন্টার‍্যাকশন ইভেন্টের JSON পে-লোডে matchedUrl ফিল্ড থাকে:

JSON

message: {
  matchedUrl: {
    url: "https://support.example.com/cases/case123"
  },
  ... // other message attributes redacted
}

MESSAGE ইভেন্টের পে-লোডে matchedUrl ফিল্ড আছে কিনা তা চেক করে, অ্যাড-অন নয় এমন কোনও চ্যাট অ্যাপ প্রিভিউ করা লিঙ্ক সহ মেসেজে তথ্য যোগ করতে পারে।

টেক্সট মেসেজের মাধ্যমে উত্তর দিন

সাধারণ উত্তরের ক্ষেত্রে, অ্যাড-অন নয় এমন কোনও Chat অ্যাপ লিঙ্কে সাধারণ টেক্সট মেসেজ দিয়ে উত্তর দিয়ে কোনও লিঙ্কের প্রিভিউ দেখাতে পারে। এই উদাহরণে এমন একটি মেসেজ অ্যাটাচ করা হয়েছে যা লিঙ্ক প্রিভিউ URL প্যাটার্নের সাথে ম্যাচ করে এমন লিঙ্ক URL রিপিট করে:

Node.js

node/preview-link/index.js
// Reply with a text message for URLs of the subdomain "text"
if (event.message.matchedUrl.url.includes("text.example.com")) {
  return {
    text: 'event.message.matchedUrl.url: ' + event.message.matchedUrl.url
  };
}

Python

python/preview-link/main.py
# Reply with a text message for URLs of the subdomain "text"
if 'text.example.com' in event.get('message').get('matchedUrl').get('url'):
  return {
    'text': 'event.message.matchedUrl.url: ' +
            event.get('message').get('matchedUrl').get('url')
  }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Reply with a text message for URLs of the subdomain "text"
if (event.at("/message/matchedUrl/url").asText().contains("text.example.com")) {
  return new Message().setText("event.message.matchedUrl.url: " +
    event.at("/message/matchedUrl/url").asText());
}

Apps Script

apps-script/preview-link/preview-link.gs
// Reply with a text message for URLs of the subdomain "text"
if (event.message.matchedUrl.url.includes("text.example.com")) {
  return {
    text: 'event.message.matchedUrl.url: ' + event.message.matchedUrl.url
  };
}

এমন একটি কার্ড অ্যাটাচ করুন যা লিঙ্কের প্রিভিউ দেখায়

অ্যাড-অন নয় এমন Chat অ্যাপে প্রিভিউ করা লিঙ্কে কার্ড অ্যাটাচ করতে, UPDATE_USER_MESSAGE_CARDS টাইপের ActionResponse রিটার্ন করুন। এই উদাহরণে একটি সাধারণ কার্ড অ্যাটাচ করা হয়েছে:

Node.js

node/preview-link/index.js
// Attach a card to the message for URLs of the subdomain "support"
if (event.message.matchedUrl.url.includes("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  return {
    actionResponse: { type: 'UPDATE_USER_MESSAGE_CARDS' },
    cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case basics',
        },
        sections: [{ widgets: [
          { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
          { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
          { decoratedText: { topLabel: 'Status', text: 'Open'}},
          { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
          { buttonList: { buttons: [{
            text: 'OPEN CASE',
            onClick: { openLink: {
              url: 'https://support.example.com/orders/case123'
            }},
          }, {
            text: 'RESOLVE CASE',
            onClick: { openLink: {
              url: 'https://support.example.com/orders/case123?resolved=y',
            }},
          }, {
            text: 'ASSIGN TO ME',
            onClick: { action: { function: 'assign'}}
          }]}}
        ]}]
      }
    }]
  };
}

Python

python/preview-link/main.py
# Attach a card to the message for URLs of the subdomain "support"
if 'support.example.com' in event.get('message').get('matchedUrl').get('url'):
  # A hard-coded card is used in this example. In a real-life scenario,
  # the case information would be fetched and used to build the card.
  return {
    'actionResponse': { 'type': 'UPDATE_USER_MESSAGE_CARDS' },
    'cardsV2': [{
      'cardId': 'attachCard',
      'card': {
        'header': {
          'title': 'Example Customer Service Case',
          'subtitle': 'Case basics',
        },
        'sections': [{ 'widgets': [
          { 'decoratedText': { 'topLabel': 'Case ID', 'text': 'case123'}},
          { 'decoratedText': { 'topLabel': 'Assignee', 'text': 'Charlie'}},
          { 'decoratedText': { 'topLabel': 'Status', 'text': 'Open'}},
          { 'decoratedText': { 'topLabel': 'Subject', 'text': 'It won\'t turn on...' }},
          { 'buttonList': { 'buttons': [{
            'text': 'OPEN CASE',
            'onClick': { 'openLink': {
              'url': 'https://support.example.com/orders/case123'
            }},
          }, {
            'text': 'RESOLVE CASE',
            'onClick': { 'openLink': {
              'url': 'https://support.example.com/orders/case123?resolved=y',
            }},
          }, {
            'text': 'ASSIGN TO ME',
            'onClick': { 'action': { 'function': 'assign'}}
          }]}}
        ]}]
      }
    }]
  }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Attach a card to the message for URLs of the subdomain "support"
if (event.at("/message/matchedUrl/url").asText().contains("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  return new Message()
    .setActionResponse(new ActionResponse()
      .setType("UPDATE_USER_MESSAGE_CARDS"))
    .setCardsV2(List.of(new CardWithId()
      .setCardId("attachCard")
      .setCard(new GoogleAppsCardV1Card()
        .setHeader(new GoogleAppsCardV1CardHeader()
          .setTitle("Example Customer Service Case")
          .setSubtitle("Case basics"))
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Case ID")
            .setText("case123")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Assignee")
            .setText("Charlie")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Status")
            .setText("Open")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Subject")
            .setText("It won't turn on...")),
          new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(
              new GoogleAppsCardV1Button()
                .setText("OPEN CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123"))),
              new GoogleAppsCardV1Button()
                .setText("RESOLVE CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123?resolved=y"))),
              new GoogleAppsCardV1Button()
                .setText("ASSIGN TO ME")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setAction(new GoogleAppsCardV1Action().setFunction("assign")))))))))))));
}

Apps Script

এই উদাহরণটি কার্ড JSON রিটার্ন করে একটি কার্ড মেসেজ পাঠায়। এছাড়াও, আপনি Apps স্ক্রিপ্ট কার্ড পরিষেবা ব্যবহার করতে পারবেন।

apps-script/preview-link/preview-link.gs
// Attach a card to the message for URLs of the subdomain "support"
if (event.message.matchedUrl.url.includes("support.example.com")) {
  // A hard-coded card is used in this example. In a real-life scenario,
  // the case information would be fetched and used to build the card.
  return {
    actionResponse: { type: 'UPDATE_USER_MESSAGE_CARDS' },
    cardsV2: [{
      cardId: 'attachCard',
      card: {
        header: {
          title: 'Example Customer Service Case',
          subtitle: 'Case basics',
        },
        sections: [{ widgets: [
          { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
          { decoratedText: { topLabel: 'Assignee', text: 'Charlie'}},
          { decoratedText: { topLabel: 'Status', text: 'Open'}},
          { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
          { buttonList: { buttons: [{
            text: 'OPEN CASE',
            onClick: { openLink: {
              url: 'https://support.example.com/orders/case123'
            }},
          }, {
            text: 'RESOLVE CASE',
            onClick: { openLink: {
              url: 'https://support.example.com/orders/case123?resolved=y',
            }},
          }, {
            text: 'ASSIGN TO ME',
            onClick: { action: { function: 'assign'}}
          }]}}
        ]}]
      }
    }]
  };
}

লিঙ্ক প্রিভিউ কার্ড আপডেট করা

Chat অ্যাপে কোনও লিঙ্ক প্রিভিউ কার্ড আপডেট করতে যা কোনও অ্যাড-অন নয়, CARD_CLICKED ইন্টার‍্যাকশন ইভেন্ট হ্যান্ডেল করুন এবং actionResponse ফেরত দিন। এটি সেই ব্যক্তির উপর ভিত্তি করে করা হয় যিনি লিঙ্ক প্রিভিউ সহ মেসেজ পাঠিয়েছেন:

  • ব্যবহারকারী মেসেজটি পাঠিয়ে থাকলে, actionResponse.type-এর মান UPDATE_USER_MESSAGE_CARDS হিসেবে সেট করুন।
  • Chat অ্যাপ মেসেজ পাঠালে, actionResponse.type-এর মান UPDATE_MESSAGE হিসেবে সেট করুন।

কে মেসেজ পাঠিয়েছে তা নির্ধারণ করতে, ইন্ট্যার‍্যাকশন ইভেন্টের message.sender.type ফিল্ড ব্যবহার করে দেখুন যে প্রেরক HUMAN ব্যবহারকারী নাকি BOT।

নিচের উদাহরণে দেখানো হয়েছে যে কীভাবে কোনও চ্যাট অ্যাপ যা অ্যাড-অন নয়, সেটি কোনও ব্যবহারকারী আমাকে অ্যাসাইন করুন বোতামে ক্লিক করলে কার্ডের অ্যাসাইনি ফিল্ড আপডেট করে এবং বোতামটি বন্ধ করে লিঙ্ক প্রিভিউ আপডেট করে:

Node.js

node/preview-link/index.js
/**
 * Updates a card that was attached to a message with a previewed link.
 *
 * @param {Object} event The event object from Chat.
 *
 * @return {Object} Response from the Chat app. Either a new card attached to
 * the message with the previewed link, or an update to an existing card.
 */
function onCardClick(event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.action.actionMethodName === 'assign') {
    // A hard-coded card is used in this example. In a real-life scenario,
    // an actual assign action would be performed before building the card.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    const actionResponseType = event.message.sender.type === 'HUMAN' ?
      'UPDATE_USER_MESSAGE_CARDS' :
      'UPDATE_MESSAGE';

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return {
      actionResponse: { type: actionResponseType },
      cardsV2: [{
        cardId: 'attachCard',
        card: {
          header: {
            title: 'Example Customer Service Case',
            subtitle: 'Case basics',
          },
          sections: [{ widgets: [
            { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
            // The assignee is now "You"
            { decoratedText: { topLabel: 'Assignee', text: 'You'}},
            { decoratedText: { topLabel: 'Status', text: 'Open'}},
            { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
            { buttonList: { buttons: [{
              text: 'OPEN CASE',
              onClick: { openLink: {
                url: 'https://support.example.com/orders/case123'
              }},
            }, {
              text: 'RESOLVE CASE',
              onClick: { openLink: {
                url: 'https://support.example.com/orders/case123?resolved=y',
              }},
            }, {
              text: 'ASSIGN TO ME',
              // The button is now disabled
              disabled: true,
              onClick: { action: { function: 'assign'}}
            }]}}
          ]}]
        }
      }]
    };
  }
}

Python

python/preview-link/main.py
def on_card_click(event: dict) -> dict:
  """Updates a card that was attached to a message with a previewed link."""
  # To respond to the correct button, checks the button's actionMethodName.
  if 'assign' == event.get('action').get('actionMethodName'):
    # A hard-coded card is used in this example. In a real-life scenario,
    # an actual assign action would be performed before building the card.

    # Checks whether the message event originated from a human or a Chat app
    # and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    # "UPDATE_MESSAGE" if Chat app.
    actionResponseType = 'UPDATE_USER_MESSAGE_CARDS' if \
      event.get('message').get('sender').get('type') == 'HUMAN' else \
      'UPDATE_MESSAGE'

    # Returns the updated card that displays "You" for the assignee
    # and that disables the button.
    return {
      'actionResponse': { 'type': actionResponseType },
      'cardsV2': [{
        'cardId': 'attachCard',
        'card': {
          'header': {
            'title': 'Example Customer Service Case',
            'subtitle': 'Case basics',
          },
          'sections': [{ 'widgets': [
            { 'decoratedText': { 'topLabel': 'Case ID', 'text': 'case123'}},
            # The assignee is now "You"
            { 'decoratedText': { 'topLabel': 'Assignee', 'text': 'You'}},
            { 'decoratedText': { 'topLabel': 'Status', 'text': 'Open'}},
            { 'decoratedText': { 'topLabel': 'Subject', 'text': 'It won\'t turn on...' }},
            { 'buttonList': { 'buttons': [{
              'text': 'OPEN CASE',
              'onClick': { 'openLink': {
                'url': 'https://support.example.com/orders/case123'
              }},
            }, {
              'text': 'RESOLVE CASE',
              'onClick': { 'openLink': {
                'url': 'https://support.example.com/orders/case123?resolved=y',
              }},
            }, {
              'text': 'ASSIGN TO ME',
              # The button is now disabled
              'disabled': True,
              'onClick': { 'action': { 'function': 'assign'}}
            }]}}
          ]}]
        }
      }]
    }

Java

java/preview-link/src/main/java/com/google/chat/preview/App.java
// Updates a card that was attached to a message with a previewed link.
Message onCardClick(JsonNode event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.at("/action/actionMethodName").asText().equals("assign")) {
    // A hard-coded card is used in this example. In a real-life scenario,
    // an actual assign action would be performed before building the card.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    String actionResponseType =
      event.at("/message/sender/type").asText().equals("HUMAN")
      ? "UPDATE_USER_MESSAGE_CARDS" : "UPDATE_MESSAGE";

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return new Message()
    .setActionResponse(new ActionResponse()
      .setType(actionResponseType))
    .setCardsV2(List.of(new CardWithId()
      .setCardId("attachCard")
      .setCard(new GoogleAppsCardV1Card()
        .setHeader(new GoogleAppsCardV1CardHeader()
          .setTitle("Example Customer Service Case")
          .setSubtitle("Case basics"))
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Case ID")
            .setText("case123")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Assignee")
            // The assignee is now "You"
            .setText("You")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Status")
            .setText("Open")),
          new GoogleAppsCardV1Widget().setDecoratedText(new GoogleAppsCardV1DecoratedText()
            .setTopLabel("Subject")
            .setText("It won't turn on...")),
          new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(
              new GoogleAppsCardV1Button()
                .setText("OPEN CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123"))),
              new GoogleAppsCardV1Button()
                .setText("RESOLVE CASE")
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setOpenLink(new GoogleAppsCardV1OpenLink()
                    .setUrl("https://support.example.com/orders/case123?resolved=y"))),
              new GoogleAppsCardV1Button()
                .setText("ASSIGN TO ME")
                // The button is now disabled
                .setDisabled(true)
                .setOnClick(new GoogleAppsCardV1OnClick()
                  .setAction(new GoogleAppsCardV1Action().setFunction("assign")))))))))))));
  }
  return null;
}

Apps Script

এই উদাহরণটি কার্ড JSON রিটার্ন করে একটি কার্ড মেসেজ পাঠায়। এছাড়াও, আপনি Apps স্ক্রিপ্ট কার্ড পরিষেবা ব্যবহার করতে পারবেন।

apps-script/preview-link/preview-link.gs
/**
 * Updates a card that was attached to a message with a previewed link.
 *
 * @param {Object} event The event object from Chat.
 *
 * @return {Object} Response from the Chat app. Either a new card attached to
 * the message with the previewed link, or an update to an existing card.
 */
function onCardClick(event) {
  // To respond to the correct button, checks the button's actionMethodName.
  if (event.action.actionMethodName === 'assign') {
    // A hard-coded card is used in this example. In a real-life scenario,
    // an actual assign action would be performed before building the card.

    // Checks whether the message event originated from a human or a Chat app
    // and sets actionResponse.type to "UPDATE_USER_MESSAGE_CARDS if human or
    // "UPDATE_MESSAGE" if Chat app.
    const actionResponseType = event.message.sender.type === 'HUMAN' ?
      'UPDATE_USER_MESSAGE_CARDS' :
      'UPDATE_MESSAGE';

    // Returns the updated card that displays "You" for the assignee
    // and that disables the button.
    return {
      actionResponse: { type: actionResponseType },
      cardsV2: [{
        cardId: 'attachCard',
        card: {
          header: {
            title: 'Example Customer Service Case',
            subtitle: 'Case basics',
          },
          sections: [{ widgets: [
            { decoratedText: { topLabel: 'Case ID', text: 'case123'}},
            // The assignee is now "You"
            { decoratedText: { topLabel: 'Assignee', text: 'You'}},
            { decoratedText: { topLabel: 'Status', text: 'Open'}},
            { decoratedText: { topLabel: 'Subject', text: 'It won\'t turn on...' }},
            { buttonList: { buttons: [{
              text: 'OPEN CASE',
              onClick: { openLink: {
                url: 'https://support.example.com/orders/case123'
              }},
            }, {
              text: 'RESOLVE CASE',
              onClick: { openLink: {
                url: 'https://support.example.com/orders/case123?resolved=y',
              }},
            }, {
              text: 'ASSIGN TO ME',
              // The button is now disabled
              disabled: true,
              onClick: { action: { function: 'assign'}}
            }]}}
          ]}]
        }
      }]
    };
  }
}