توضّح هذه الصفحة كيفية إعداد الأوامر التي تبدأ بشرطة مائلة والاستجابة لها لتطبيق Google Chat.
الأمر الذي يبدأ بشرطة مائلة هو طريقة شائعة يستدعي بها المستخدمون أحد تطبيقات Chat وتفاعلهم معه. وتساعد هذه الأوامر أيضًا المستخدمين في اكتشاف الميزات الرئيسية لتطبيق Chat واستخدامها.
لاستخدام أمر شرطة مائلة، يكتب المستخدمون شرطة مائلة (/
) ثم طلبًا نصيًا قصيرًا،
مثل /about
للحصول على معلومات عن تطبيق Chat.
يمكن للمستخدمين اكتشاف أوامر الشرطة المائلة المتاحة عن طريق كتابة شرطة مائلة في
Google Chat، الذي يعرض نافذة تسرد الأوامر المتاحة لتطبيق Chat:
عندما يرسِل أحد المستخدِمين رسالة تحتوي على أمر شرطة مائلة، لا تظهر الرسالة إلّا للمستخدم وتطبيق Chat.
لتحديد ما إذا كان عليك إعداد الأوامر التي تبدأ بشرطة مائلة، ولفهم كيفية تصميم تفاعلات المستخدمين، راجِع مقالة تحديد جميع تجارب المستخدمين.
المتطلّبات الأساسية
Node.js
- حساب على Google Workspace لديه إمكانية الوصول إلى Google Chat
- تطبيق في Chat: لإنشاء تطبيق في Chat، اتّبِع خطوات quickstart هذه.
برمجة تطبيقات
- حساب على Google Workspace لديه إمكانية الوصول إلى Google Chat
- تطبيق في Chat: لإنشاء تطبيق في Chat، اتّبِع خطوات quickstart هذه.
Python
- حساب على Google Workspace لديه إمكانية الوصول إلى Google Chat
- تطبيق في Chat: لإنشاء تطبيق في Chat، اتّبِع خطوات quickstart هذه.
إعداد أمر شرطة مائلة
يوضح هذا القسم كيفية إكمال الخطوات التالية لإعداد أمر شرطة مائلة:
- أنشئ اسمًا للأمر الشرطة المائلة.
- ضبط الأمر الشرطة المائلة في Google Chat API.
أدخِل اسمًا للأمر الذي يبدأ بشرطة مائلة.
إنّ اسم الأمر الذي تبدأ بشرطة مائلة هو ما يكتبه المستخدمون في رسالة Chat لاستدعاء تطبيق Chat. ويظهر وصف موجز أيضًا تحت الاسم ليطلب منهم المزيد من المعلومات عن كيفية استخدام الأمر:
عند اختيار اسم ووصف للأمر الذي تبدأ بشرطة مائلة، ضع في اعتبارك التوصيات التالية:
لتسمية الأمر الشرطة المائلة:
- استخدِم كلمات أو عبارات قصيرة ووصفية وقابلة للتنفيذ لجعل الأوامر واضحة وبسيطة للمستخدم. على سبيل المثال، بدلاً من قول
/createAReminder
، استخدِم/remindMe
. - إذا كان الأمر يحتوي على أكثر من كلمة واحدة، فساعد المستخدمين على قراءة الأمر
من خلال استخدام أحرف صغيرة في الكلمة الأولى ثم استخدام حرف كبير في بداية
الحرف الأول من الكلمات الإضافية. على سبيل المثال، استخدِم
/updateContact
بدلاً من/updatecontact
. - ضع في اعتبارك ما إذا كنت تريد استخدام اسم فريد أو شائع للأمر. إذا كان الأمر يصف تفاعلاً أو ميزة نموذجية، يمكنك استخدام اسم شائع يمكن للمستخدمين التعرّف عليه ويتوقعونه، مثل
/settings
أو/feedback
. وإذا لم يكن الأمر كذلك، حاوِل استخدام أسماء أوامر فريدة، لأنّه إذا كان اسم الأمر هو نفسه لتطبيقات Chat الأخرى، على المستخدم الفلترة من خلال أوامر مشابهة للعثور على طلبك واستخدامه.
- استخدِم كلمات أو عبارات قصيرة ووصفية وقابلة للتنفيذ لجعل الأوامر واضحة وبسيطة للمستخدم. على سبيل المثال، بدلاً من قول
لوصف الأمر الذي تبدأ بشرطة مائلة:
- أبقِ الوصف قصيرًا وواضحًا حتى يعرف المستخدمون ما يمكن توقعه عند استدعاء الأمر.
- أخبِر المستخدمين بما إذا كانت هناك أي متطلبات تنسيق للأمر.
على سبيل المثال، إذا أنشأت الأمر
/remindMe
الذي يتطلب نص وسيطة، اضبط الوصف علىRemind me to do [something] at [time]
. - يمكنك إبلاغ المستخدمين بما إذا كان تطبيق Chat يردّ على جميع
المستخدمين في المساحة، أو بشكلٍ خاص على المستخدم الذي يستدعي الأمر.
على سبيل المثال، بالنسبة إلى الأمر الشرطة المائلة
/about
، يمكنك وصفه على أنّهLearn about this app (Only visible to you)
. للرد بشكل خاص على أمر يبدأ بشرطة مائلة، راجع القسم الرد برسالة خاصة.
ضبط الأمر الشرطة المائلة في Google Chat API
لإنشاء أمر شرطة مائلة، عليك تحديد معلومات حول الأمر في إعدادات تطبيق Chat لواجهة برمجة تطبيقات Google Chat.
لإعداد أمر شرطة مائلة في واجهة برمجة تطبيقات Google Chat، أكمِل الخطوات التالية:
في Google Cloud Console، انقر على رمز القائمة > واجهات برمجة التطبيقات والخدمات > واجهات برمجة التطبيقات والخدمات التي تم تفعيلها > Google Chat API
انقر على الإعدادات.
ضمن أوامر Slash، انقر على إضافة أمر شرطة مائلة.
أدخِل اسمًا ومعرِّف الأمر ووصفًا للأمر:
- الاسم: هو الاسم المعروض للأمر، وما يكتبه المستخدمون لاستدعاء تطبيقك. ويجب أن يبدأ بشرطة مائلة، وأن يحتوي على نص فقط، وألا يزيد طوله عن 50 حرفًا.
- الوصف: النص الذي يوضّح طريقة استخدام الأمر وتنسيقه. ويمكن أن يصل طول الأوصاف إلى 50 حرفًا.
- معرِّف الطلب: رقم من 1 إلى 1000 يستخدمه تطبيق Chat للتعرّف على الأمر الذي يبدأ بشرطة مائلة وعرض استجابة.
اختياري: إذا كنت تريد أن يستجيب تطبيق Chat للأمر من خلال مربع حوار، ضَع علامة في مربّع الاختيار فتح مربّع حوار.
انقر على حفظ.
تم الآن ضبط الأمر slash لتطبيق Chat.
الرد على أمر يبدأ بشرطة مائلة
عندما ينشئ المستخدمون رسالة Chat تحتوي على أمر شرطة مائلة،
سيتلقّى تطبيق Chat حدث تفاعل MESSAGE
.
تحتوي حمولة الحدث على معلومات عن الأمر الشرطة المائلة،
بما في ذلك الحقلين slashCommand
وslashCommandMetadata
. يمكنك استخدام هذه الحقول لتحديد معرف الأمر وعرض استجابة مخصصة.
يوضّح المثال التالي حمولة JSON لحدث تفاعل MESSAGE
الذي يتضمّن أمر الشرطة المائلة /vote
:
{
...
"message": {
...
"text": "/vote yes",
"argumentText": " yes",
"slashCommand": {
"commandId": 2
},
"annotations": [
{
"length": 5,
"startIndex": 0,
"type": "SLASH_COMMAND",
"slashCommand": {
"commandName":"/vote",
"commandId":1,
"type": "INVOKE",
"bot": {
"avatarUrl": "https://www.example.com/images/vote-app-icon.png",
"displayName": "Voter Chat App",
"name": "users/1234567890987654321",
"type": "BOT"
}
}
}
]
}
}
للاستجابة لأحد الأوامر التي تبدأ بشرطة مائلة، يمكنك اكتشاف ما إذا كان الحقل slashCommand
موجودًا في حمولة الحدث، وإذا كان الأمر كذلك، يمكنك عرض استجابة للأمر.
يوضّح نموذج الرمز البرمجي التالي كيفية الاستجابة لحدث تفاعل MESSAGE
يحتوي على أمر شرطة مائلة:
Node.js
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/
exports.onMessage = function onMessage(req, res) {
// Stores the Google Chat event as a variable.
var event = req.body;
// Checks for the presence of event.message.slashCommand.
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case ID: // The ID for your slash command
res.json(runFunction); // The response to the slash command.
}
}
برمجة تطبيقات
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/
function onMessage(event) {
// Checks for the presence of event.message.slashCommand
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case ID: // The ID for your slash command
return runFunction; // The response to the slash command.
}
}
}
Python
from typing import Any, Mapping
import flask
import functions_framework
@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
"""Responds to a MESSAGE event in Google Chat that includes a slash command.
Args:
req (flask.Request): the event object from Chat API.
Returns:
Mapping[str, Any]: function in response to a slash command.
"""
if req.method == 'GET':
return 'Sorry, this function must be called from a Google Chat.'
request = req.get_json(silent=True)
if slash_command := request.get('message', dict()).get('slashCommand'):
command_id = slash_command['commandId']
if command_id == ID:
return runFunction
لاستخدام الرمز، استبدل ما يلي:
ID
: معرّف الأمر الذي تحدّده عند ضبط الأمر slash في Google Chat API.runFunction
: دالة تنشئ استجابة للأمر الشرطة المائلة.
اختياري: الرد برسالة خاصة
لا تظهر الرسائل التي تحتوي على أوامر تبدأ بشرطة مائلة إلا للمستخدم الذي أرسل الرسالة ولتطبيق Chat الذي يتلقّى الأمر. في حال ضبط تطبيق Chat لإضافته إلى المساحات مع عدة أشخاص، ننصحك بالردّ على الأمر الشرطة المائلة بشكل خاص للحفاظ على خصوصية التفاعل بين المستخدم وتطبيق Chat.
على سبيل المثال، إذا كان فريق يستخدم تطبيقًا في Chat يدير خدمة دعم العملاء، يمكن للمستخدمين استدعاء أمر شرطة مائلة مثل /myCases
لعرض طلبات الحصول على الدعم المخصّصة لهم. إذا أضاف الفريق تطبيق Chat إلى مساحة، قد يريد المستخدم الذي يستخدم أمر الشرطة المائلة هذا
في المساحة أن يستجيب تطبيق Chat له فقط. لتجنّب نشر طلبات الحصول على الدعم المقدَّمة من المستخدمين لجميع المشاركين في المساحة، يمكن لتطبيق Chat الردّ بخصوصية تامة.
للرد على أمر شرطة مائلة بشكل خاص، يُرجى الاطّلاع على مقالة إرسال رسائل خاصة إلى مستخدمي Google Chat.
مثال كامل: إعداد جهات الاتصال باستخدام تطبيق Rolodex Chat
يوضّح المثال التالي تطبيق Chat يستجيب للأوامر التالية التي تبدأ بشرطة مائلة:
- يعرض الأمر
/help
رسالة نصية توضّح كيفية الحصول على الدعم لتطبيق Chat. تم ضبط معرّف الطلب على1
. - يفتح الأمر
/createContact
مربّع حوار حيث يمكن للمستخدمين إدخال تفاصيل حول جهة الاتصال. تم ضبط معرّف الأمر على2
.
قبل تشغيل هذا النموذج، اتّبِع خطوات ضبط الأوامر التي تبدأ بشرطة مائلة في Google Chat API.
Node.js
/**
* Responds to messages that have links whose URLs
* match URL patterns configured for link previews.
*
* @param {Object} event The event object from Chat
* API.
*
* @return {Object} Response from the Chat app
* attached to the message with the previewed link.
*/
exports.onMessage = function onMessage(req, res) {
// Store the Google Chat event as a variable.
const event = req.body;
if (req.method === "GET" || !event.message) {
res.send("Hello! This function is meant to be used in a Google Chat " +
"Space.");
}
// Checks for the presence of event.message.slashCommand.
// If the slash command is "/help", responds with a text message.
// If the slash command is "/createContact", opens a dialog.
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case 1: // /help
res.json({"text": "Contact bot helps you update your address book!"});
case 2: // /createContact
res.json(openDialog(event));
}
}
// If the Chat app doesn"t detect a slash command, it responds
// with a card that prompts the user to add a contact
else {
res.json({
"cardsV2": [{
"cardId": "addContact",
"card": {
"header": {
"title": "Rolodex",
"subtitle": "Manage your contacts!",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
"imageType": "CIRCLE"
},
"sections": [
{
"widgets": [
{
"buttonList": {
"buttons": [
{
"text": "Add Contact",
"onClick": {
"action": {
"function": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}
]
}
}
]
}
]
}
}]
});
}
// Respond to button clicks on attached cards
if (event.type === "CARD_CLICKED") {
if (event.common.invokedFunction === "openDialog") {
res.json(openDialog(event));
}
if (event.common.invokedFunction === "openSequentialDialog") {
res.json(openSequentialDialog(event));
}
if (event.common.invokedFunction === "confirmDialogSuccess") {
res.json(confirmDialogSuccess(event));
}
}
};
/**
* Opens and starts a dialog that lets users add details about a contact.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openDialog(event) {
return {
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Name",
"type": "SINGLE_LINE",
"name": "name"
}
},
{
"textInput": {
"label": "Address",
"type": "MULTIPLE_LINE",
"name": "address"
}
},
{
"decoratedText": {
"text": "Add to favorites",
"switchControl": {
"controlType": "SWITCH",
"name": "saveFavorite"
}
}
},
{
"decoratedText": {
"text": "Merge with existing contacts",
"switchControl": {
"controlType": "SWITCH",
"name": "mergeContact",
"selected": true
}
}
},
{
"buttonList": {
"buttons": [
{
"text": "Next",
"onClick": {
"action": {
"function": "openSequentialDialog"
}
}
}
]
}
}
]
}
]
}
}
}
}
};
};
/**
* Opens a second dialog that lets users add more contact details.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openSequentialDialog(event) {
return {
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Notes",
"type": "MULTIPLE_LINE",
"name": "notes"
}
},
{
"selectionInput": {
"type": "RADIO_BUTTON",
"label": "Contact type",
"name": "contactType",
"items": [
{
"text": "Work",
"value": "Work",
"selected": false
},
{
"text": "Personal",
"value": "Personal",
"selected": false
}
]
}
},
{
"buttonList": {
"buttons": [
{
"text": "Submit",
"onClick": {
"action": {
"function": "confirmDialogSuccess",
"parameters": [
{
"key": "confirmDialogSuccess",
"value": "confirmDialogSuccess"
}
]
}
}
}
]
},
"horizontalAlignment": "END"
}
]
}
]
}
}
}
}
};
}
/**
* Checks for a form input error, the absence of
* a "name" value, and returns an error if absent.
* Otherwise, confirms successful receipt of a dialog.
*
* Confirms successful receipt of a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
function receiveDialog(event) {
// Checks to make sure the user entered a name
// in a dialog. If no name value detected, returns
// an error message.
if (event.common.formInputs.contactName.stringInputs.value[0] === "") {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": {
"statusCode": "OK",
"userFacingMessage": "Don't forget to name your new contact!"
}
}
}
};
// Otherwise the app indicates that it received
// form data from the dialog. Any value other than "OK"
// gets returned as an error. "OK" is interpreted as
// code 200, and the dialog closes.
} else {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "OK"
}
}
};
}
}
برمجة تطبيقات
في هذا المثال، يتم إرسال رسالة بطاقة من خلال عرض البطاقة JSON. يمكنك أيضًا استخدام خدمة بطاقة "برمجة تطبيقات Google".
Python
from typing import Any, Mapping
import flask
import functions_framework
@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
"""Responds to a MESSAGE event in Google Chat that includes the /createContact
slash command by opening a dialog.
Args:
req (flask.Request): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
if req.method == 'GET':
return 'Sorry, this function must be called from a Google Chat.'
request = req.get_json(silent=True)
if request.get('type') == 'CARD_CLICKED':
invoked_function = request.get('common', dict()).get('invokedFunction')
if invoked_function == 'open_dialog':
return open_dialog(request)
elif invoked_function == 'open_sequential_dialog':
return open_dialog(request)
elif invoked_function == "receive_dialog":
return receive_dialog(request)
else:
return {
'cardsV2': [{
'cardId': 'addContact',
'card': {
'header': {
'title': 'Rolodex',
'subtitle': 'Manage your contacts!',
'imageUrl': 'https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png',
'imageType': 'CIRCLE'
},
'sections': [
{
'widgets': [
{
'buttonList': {
'buttons': [
{
'text': 'Add Contact',
'onClick': {
'action': {
'function': 'open_dialog',
'interaction': 'OPEN_DIALOG'
}
}
}
]
}
}
]
}
]
}
}]
}
def open_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a dialog in Google Chat.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Name',
'type': 'SINGLE_LINE',
'name': 'name'
}
},
{
'textInput': {
'label': 'Address',
'type': 'MULTIPLE_LINE',
'name': 'address'
}
},
{
'decoratedText': {
'text': 'Add to favorites',
'switchControl': {
'controlType': 'SWITCH',
'name': 'saveFavorite'
}
}
},
{
'decoratedText': {
'text': 'Merge with existing contacts',
'switchControl': {
'controlType': 'SWITCH',
'name': 'mergeContact',
'selected': True
}
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Next',
'onClick': {
'action': {
'function': 'open_sequential_dialog'
}
}
}
]
}
}
]
}
]
}
}
}
}
}
def open_sequential_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a second dialog that lets users add more contact details.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Notes',
'type': 'MULTIPLE_LINE',
'name': 'notes'
}
},
{
'selectionInput': {
'type': 'RADIO_BUTTON',
'label': 'Contact type',
'name': 'contactType',
'items': [
{
'text': 'Work',
'value': 'Work',
'selected': False
},
{
'text': 'Personal',
'value': 'Personal',
'selected': False
}
]
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Submit',
'onClick': {
'action': {
'function': 'receive_dialog',
'parameters': [
{
'key': 'receiveDialog',
'value': 'receiveDialog'
}
]
}
}
}
]
},
'horizontalAlignment': 'END'
}
]
}
]
}
}
}
}
}
def receive_dialog(event: Mapping[str, Any]) -> Mapping[str, Any]:
"""Checks for a form input error, the absence of a "name" value, and returns
an error if absent. Otherwise, confirms successful receipt of a dialog.
Args:
event (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: the response.
"""
if event.get('common', dict()) \
.get('formInputs', dict()).get('contactName', dict()) \
.get('stringInputs').get('value', list()):
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': 'OK'
}
}
}
else:
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': "Don't forget to name your new contact!"
}
}
}