معاينة الروابط في رسائل Google Chat

لمنع تبديل السياق عندما يشارك المستخدمون رابطًا في Google Chat، يمكن لتطبيق Chat معاينة الرابط من خلال إرفاق ملف ملتحم برسالته يقدّم المزيد من المعلومات ويسمح للمستخدمين باتخاذ إجراء مباشرةً من Google Chat.

في Google Chat، تظهر الإضافات للمستخدمين على أنّها تطبيقات Google Chat. لمزيد من المعلومات، راجِع نظرة عامة على توسيع نطاق Google Chat.

على سبيل المثال، تخيل مساحة في Google Chat تتضمّن جميع موظّفي خدمة عملاء الشركة بالإضافة إلى تطبيق Chat باسم "Casey". يشارك موظّفو الدعم غالبًا روابط لطلبات خدمة العملاء في مساحة Chat، ويجب على زملاء موظّفي الدعم فتح رابط الطلب في كل مرة لعرض تفاصيل مثل المُسنَد إليه والحالة والموضوع. وبالمثل، إذا أراد أحد المستخدمين الحصول على ملكية طلب أو تغيير حالته، عليه فتح الرابط.

تتيح ميزة "معاينة الروابط" لتطبيق Chat المقيم في المساحة، وهو Case-y، إرفاق بطاقة تعرض المُسنَد إليه والحالة والموضوع عندما يشارك أحد المستخدمين رابط طلب الدعم. تتيح الأزرار على البطاقة لموظّفي الدعم اكتساب ملكية القضية وتغيير الحالة مباشرةً من بث المحادثة.

عندما يضيف مستخدم رابطًا إلى رسالته، تظهر شريحة تُعلمه بأنّ تطبيق Chat قد يُجري معاينة للرابط.

شريحة تشير إلى أنّ تطبيق Chat قد يعرض معاينة لرابط

بعد إرسال الرسالة، يتم إرسال الرابط إلى تطبيق Chat الذي ينشئ العبارة ويرفقها برسالة المستخدم.

تطبيق Chat يُعاين رابطًا من خلال إرفاق بطاقة بالرسالة

إلى جانب الرابط، تقدّم البطاقة معلومات إضافية عنه، بما في ذلك العناصر التفاعلية مثل الأزرار. يمكن لتطبيق Chat تعديل البطاقة المرفقة استجابةً لتفاعلات المستخدِم، مثل النقرات على الأزرار.

إذا لم يكن المستخدم يريد أن يعرِض تطبيق Chat مقتطفًا من الرابط من خلال إرفاق بطاقة برسالته، يمكنه منع المعاينة من خلال النقر على في شريحة المعاينة. يمكن للمستخدمين إزالة البطاقة المرفقة في أي وقت من خلال النقر على إزالة المعاينة.

المتطلبات الأساسية

Node.js

إضافة Google Workspace التي توفّر ميزات إضافية في Google Chat لإنشاء تطبيق، أكمِل البدء السريع لاستخدام بروتوكول HTTP.

برمجة تطبيقات

إضافة Google Workspace التي توفّر ميزات إضافية في Google Chat لإنشاء تطبيق، أكمِل الخطوات الأساسية لبدء استخدام Apps Script.

سجِّل روابط معيّنة، مثل example.com وsupport.example.com و support.example.com/cases/، كنماذج عناوين URL في صفحة ضبط تطبيق Chat في وحدة تحكّم 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، لإقران عناوين URL للحالات المستضافة على support.example.com/cases/، أدخِل cases/.

  8. انقر على تم.

  9. انقر على حفظ.

الآن، عندما يُدرِج أحد المستخدمين رابطًا يتطابق مع نمط عنوان URL لمعاينة الرابط في رسالة في مساحة Chat تتضمّن تطبيق Chat، يُعاين تطبيقك الرابط.

بعد ضبط إعدادات معاينة الرابط لرابط معيّن، يمكن لتطبيق Chat التعرّف على الرابط ومعاينته من خلال إرفاق المزيد من المعلومات به.

داخل مساحات Chat التي تتضمّن تطبيق Chat، عندما تحتوي رسالة أحد المستخدمين على رابط يتطابق مع نمط عنوان URL لمعاينة الرابط، يتلقّى تطبيق Chatعنصر حدث مع MessagePayload. في الحمولة، يحتوي العنصر message.matchedUrl على الرابط الذي أدرجه المستخدم في الرسالة:

JSON

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

من خلال التحقّق من توفّر حقل matchedUrl في حمولة حدث MESSAGE، يمكن لتطبيق Chat إضافة معلومات إلى الرسالة التي تتضمّن الرابط الذي تمت معاينته. يمكن لتطبيق Chat إرسال ردّ باستخدام رسالة نصية أساسية أو إرفاق بطاقة.

الردّ برسالة نصية

بالنسبة إلى الردود الأساسية، يمكن لتطبيق Chat معاينة رابط من خلال الردّ على رابط باستخدام رسالة نصية. يُرفِق هذا المثال رسالة تُكرّر عنوان URL للرابط الذي يتطابق مع نمط عنوان URL لمعاينة الرابط.

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // If the Chat app does not detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // 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
    }}}}};
  }
}

برمجة تطبيقات

/**
 * Reply to messages that have links whose URLs match the pattern
 * "text.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // If the Chat app doesn't detect a link preview URL pattern, reply
  // with a text message that says so.
  if (!chatMessage.matchedUrl) {
    return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
      text: 'No matchedUrl detected.'
    }}}}};
  }

  // 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 بطاقة معاينة إلى الرسائل التي تحتوي على نمط عنوان URL support.example.com.

تطبيق Chat يُعاين رابطًا من خلال إرفاق بطاقة بالرسالة

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to messages that have links whose URLs match URL patterns configured
 * for link previewing.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Response to send back depending on the matched URL.
 */
function handlePreviewLink(chatMessage) {
  // 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',
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
        ]}]
      }
    }]}}}};
  }
}

برمجة تطبيقات

يُرسِل هذا المثال رسالة بطاقة من خلال عرض ملف JSON للبطاقة. يمكنك أيضًا استخدام خدمة بطاقات Apps Script.

/**
 * Attach a card to messages that have links whose URLs match the pattern
 * "support.example.com" configured for link previewing.
 *
 * @param {Object} event The event object from Google Workspace Add-on.
 *
 * @return {Object} The action response.
 */
function onMessage(event) {
  // Stores the Google Chat event as a variable.
  const chatMessage = event.chat.messagePayload.message;

  // 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 الإجراء DataActions مع أحد عناصر ChatDataActionMarkup التالية:

لتحديد مُرسِل الرسالة، استخدِم الحمولة البرمجية للحدث (buttonClickedPayload) للتحقّق مما إذا كان المُرسِل (message.sender.type) قد تم ضبطه على HUMAN (مستخدم) أو BOT (تطبيق Chat).

يوضّح المثال التالي كيفية تعديل تطبيق Chat لمعاينة الرابط كلما نقر مستخدم على الزر إسناد إليّ من خلال تعديل حقل المُسنَد إليه في البطاقة وإيقاف الزر.

تطبيق Chat يعاين رابطًا يحتوي على نسخة معدَّلة من بطاقة مرفقة برسالة

Node.js

/**
 * Google Cloud Function that handles messages that have links whose
 * URLs match URL patterns configured for link previewing.
 *
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.previewLinks = function previewLinks(req, res) {
  const chatEvent = req.body.chat;

  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handlePreviewLink(chatEvent.messagePayload.message));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    return res.send(handleCardClick(chatEvent.buttonClickedPayload.message));
  }
};

/**
 * Respond to clicks by assigning user and updating the card that was attached to a
 * message with a previewed link.
 *
 * @param {Object} chatMessage The chat message object from Google Workspace Add On event.
 * @return {Object} Action response depending on the original message.
 */
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,
          // Use runtime environment variable set with self URL
          onClick: { action: { function: process.env.BASE_URL }}
        }]}}
      ]}]
    }
  }]};

  // Checks whether the message event originated from a human or a Chat app
  // to return the adequate action response.
  if(chatMessage.sender.type === 'HUMAN') {
    return { hostAppDataAction: { chatDataAction: { updateInlinePreviewAction: message }}};
  } else {
    return { hostAppDataAction: { chatDataAction: { updateMessageAction: message }}};
  }
}

برمجة تطبيقات

يُرسِل هذا المثال رسالة بطاقة من خلال عرض ملف JSON للبطاقة. يمكنك أيضًا استخدام خدمة بطاقات Apps Script.

/**
 * 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 معاينات الروابط لما يصل إلى 5 نماذج لعناوين URL.
  • تعرض تطبيقات Chat معاينة لرابط واحد في كل رسالة. إذا كانت هناك عدة روابط قابلة للمعاينة في رسالة واحدة، لن تتم معاينة سوى الرابط الأول القابل للمعاينة.
  • لا تعرض تطبيقات Chat سوى معاينات للروابط التي تبدأ بالرمز https://، لذا يتم عرض معاينات لتطبيق https://support.example.com/cases/، ولكن لا يتم عرض معاينات لتطبيق support.example.com/cases/.
  • ما لم تتضمّن الرسالة معلومات أخرى يتم إرسالها إلى تطبيق Chat، مثل أمر الشرطة المائلة، يتم إرسال عنوان URL للرابط فقط إلى تطبيق Chat من خلال معاينات الروابط.
  • إذا نشر مستخدم الرابط، لا يمكن لتطبيق Chat تعديل بطاقة معاينة الرابط إلا إذا تفاعل المستخدمون مع البطاقة، مثلاً من خلال هُمسة زر. لا يمكنك استدعاء طريقة update() في Chat API على مورد Message لتعديل رسالة مستخدم بشكل غير متزامن.
  • يجب أن تُعاين تطبيقات المحادثة الروابط لجميع المستخدمين في المساحة، لذلك يجب أن تحذف الرسالة الحقل privateMessageViewer.

أثناء تنفيذ معاينات الروابط، قد تحتاج إلى تصحيح أخطاء تطبيق Chat من خلال قراءة سجلات التطبيق. لقراءة السجلّات، انتقِل إلى مستكشف السجلّات في وحدة تحكّم Google Cloud.