你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

实现通道特定的功能

适用于:SDK v4

某些通道提供的功能不能仅使用邮件文本和附件实现。 若要实现特定于通道的功能,可以将本机元数据传递给活动对象的通道数据属性。 例如,机器人可使用通道数据属性来指示 Telegram 发送贴纸或指示 Office365 发送电子邮件。

本文介绍如何使用消息活动的通道数据属性来实现此通道特定的功能:

Channel 功能
电子邮件 发送和接收包含正文、主题和重要性元数据的电子邮件。
Facebook 以本机方式发送 Facebook 通知。
LINE 发送实现特定于 LINE 的消息类型的消息。
Slack 发送完全保真 Slack 消息。
Teams 处理 Microsoft Teams 消息中的 @-mention。
Telegram 执行电报特定的操作,例如共享语音备忘录或贴纸。

注意

活动对象的通道数据属性的值是 JSON 对象。 因此,本文中的示例显示了各种方案中 channelData JSON 属性的预期格式。 要使用 .NET 创建 JSON 对象,请使用 JObject (.NET) 类。

创建自定义电子邮件

若要创建自定义电子邮件,请将活动 channelData 属性设置为包含以下属性的 JSON 对象:

properties 说明
bccRecipients 添加到邮件“Bcc(密件抄送)”字段的用分号 (;) 分隔的电子邮件地址字符串。
ccRecipients 添加到邮件“Cc(抄送)”字段的用分号 (;) 分隔的电子邮件地址字符串。
htmlBody 用于指定电子邮件正文的 HTML 文档。 要了解受支持的 HTML 元素和特性,请参阅通道的相关文档。
importance 电子邮件的重要性级别。 有效值为 high、normal 和 low 。 默认值为 normal 。
toRecipients 添加到邮件“收件人”字段的用分号 (;) 分隔的电子邮件地址字符串。

用户与机器人之间的传出消息和传入消息可能会有一个 channelData 活动,其中包含一个在上表中指定了其属性的 JSON 对象。 下面的代码片段显示传入自定义电子邮件消息(从机器人到用户)的 channelData 属性的示例。

{
    "type": "ActivityTypes.Message",
    "locale": "en-Us",
    "channelID": "email",
    "fromName": { "id": "mybot@mydomain.com", "name": "My bot"},
    "recipientName": { "id": "joe@otherdomain.com", "name": "Joe Doe"},
    "conversation": { "id": "123123123123", "topic": "awesome chat" },
    "channelData":
    {
        "htmlBody": "<html><body style = \"font-family: Calibri; font-size: 11pt;\" >This is more than awesome.</body></html>",
        "importance": "high",
        "ccRecipients": "Yasemin@adatum.com;Temel@adventure-works.com",
    }
}

创建 Facebook 通知

若要创建 Facebook 通知,请将活动对象的通道数据属性设置为指定以下属性的 JSON 对象:

properties 说明
notification_type 通知的类型,例如 REGULARSILENT_PUSHNO_PUSH
attachment 附件(用于指定图像、视频或其他多媒体类型)或模板化附件(如收据)。

注意

要详细了解 notification_type 属性和attachment 属性的格式和内容,请参阅 Facebook API 文档

此代码片段显示了Facebook 收据附件的 channelData 属性示例。

"channelData": {
    "notification_type": "NO_PUSH",
    "attachment": {
        "type": "template"
        "payload": {
            "template_type": "receipt",
            //...
        }
    }
}

创建 LINE 消息

若要创建实现特定于 LINE 的消息类型 ((如贴纸、模板或特定于 LINE 的操作类型(如打开手机相机) ),请将活动对象的通道数据属性设置为指定 LINE 消息类型和操作类型的 JSON 对象。

属性 说明
type LINE 操作/消息类型名称

支持以下 LINE 消息类型:

  • 便签
  • Imagemap
  • 模板(按钮、确认、轮播)
  • Flex

以下 LINE 操作可以在消息类型为 JSON 对象的操作字段中指定:

  • 回发
  • 消息
  • URI
  • Datetimerpicker
  • 照相机
  • 本机照片
  • 位置

若要详细了解这些 LINE 方法及其参数,请参阅 LINE 机器人 API 文档

此代码片段显示了一个 channelData 属性示例,该属性指定频道消息类型和 ButtonTemplate 三种操作类型:“camera”、“cameraRoll”和“datetimepicker”。

"channelData": {
    "type": "template",
    "altText": "This is a buttons template",
    "template": {
        "type": "buttons",
        "thumbnailImageUrl": "https://example.com/bot/images/image.jpg",
        "imageAspectRatio": "rectangle",
        "imageSize": "cover",
        "imageBackgroundColor": "#FFFFFF",
        "title": "Menu",
        "text": "Please select",
        "defaultAction": {
            "type": "uri",
            "label": "View detail",
            "uri": "http://example.com/page/123"
        },
        "actions": [{
                "type": "cameraRoll",
                "label": "Camera roll"
            },
            {
                "type": "camera",
                "label": "Camera"
            },
            {
                "type": "datetimepicker",
                "label": "Select date",
                "data": "storeId=12345",
                "mode": "datetime",
                "initial": "2017-12-25t00:00",
                "max": "2018-01-24t23:59",
                "min": "2017-12-25t00:00"
            }
        ]
    }
}

创建全保真的 Slack 消息

若要创建完全保真 Slack 消息,请将活动对象的通道数据属性设置为 JSON 对象,该对象指定:

注意

要使用户能在 Slack 消息中使用按钮,必须在将机器人连接到 Slack 通道时启用“交互式消息” 。

此代码片段显示了自定义 Slack 消息的 channelData 属性示例。

"channelData": {
   "text": "Now back in stock! :tada:",
   "attachments": [
        {
            "title": "The Further Adventures of Slackbot",
            "author_name": "Stanford S. Strickland",
            "author_icon": "https://api.slack.com/img/api/homepage_custom_integrations-2x.png",
            "image_url": "http://i.imgur.com/OJkaVOI.jpg?1"
        },
        {
            "fields": [
                {
                    "title": "Volume",
                    "value": "1",
                    "short": true
                },
                {
                    "title": "Issue",
                    "value": "3",
                    "short": true
                }
            ]
        },
        {
            "title": "Synopsis",
            "text": "After @episod pushed exciting changes to a devious new branch back in Issue 1, Slackbot notifies @don about an unexpected deploy..."
        },
        {
            "fallback": "Would you recommend it to customers?",
            "title": "Would you recommend it to customers?",
            "callback_id": "comic_1234_xyz",
            "color": "#3AA3E3",
            "attachment_type": "default",
            "actions": [
                {
                    "name": "recommend",
                    "text": "Recommend",
                    "type": "button",
                    "value": "recommend"
                },
                {
                    "name": "no",
                    "text": "No",
                    "type": "button",
                    "value": "bad"
                }
            ]
        }
    ]
}

当用户单击 Slack 消息中的按钮时,机器人将收到一条答复消息,其中的通道数据属性填充了 payload JSON 对象。 payload 对象指定原始消息的内容,标识单击的按钮,并标识单击该按钮的用户。

此代码片段显示了当用户单击 Slack 消息中的按钮时,机器人收到的消息中 channelData 属性的示例。

"channelData": {
    "payload": {
        "actions": [
            {
                "name": "recommend",
                "value": "yes"
            }
        ],
        //...
        "original_message": "{...}",
        "response_url": "https://hooks.slack.com/actions/..."
    }
}

机器人可以按常规方式回复此消息,也可以将其答复直接发布到由 payload 对象的 response_url 属性指定的终结点。 要了解何时以及如何将答复发布到 response_url,请参阅 Slack 按钮

可以使用以下 JSON 创建动态按钮:

{
    "text": "Would you like to play a game ? ",
    "attachments": [
        {
            "text": "Choose a game to play!",
            "fallback": "You are unable to choose a game",
            "callback_id": "wopr_game",
            "color": "#3AA3E3",
            "attachment_type": "default",
            "actions": [
                {
                    "name": "game",
                    "text": "Chess",
                    "type": "button",
                    "value": "chess"
                },
                {
                    "name": "game",
                    "text": "Falken's Maze",
                    "type": "button",
                    "value": "maze"
                },
                {
                    "name": "game",
                    "text": "Thermonuclear War",
                    "style": "danger",
                    "type": "button",
                    "value": "war",
                    "confirm": {
                        "title": "Are you sure?",
                        "text": "Wouldn't you prefer a good game of chess?",
                        "ok_text": "Yes",
                        "dismiss_text": "No"
                    }
                }
            ]
        }
    ]
}

若要创建交互式菜单,请使用以下 JSON:

{
    "text": "Would you like to play a game ? ",
    "response_type": "in_channel",
    "attachments": [
        {
            "text": "Choose a game to play",
            "fallback": "If you could read this message, you'd be choosing something fun to do right now.",
            "color": "#3AA3E3",
            "attachment_type": "default",
            "callback_id": "game_selection",
            "actions": [
                {
                    "name": "games_list",
                    "text": "Pick a game...",
                    "type": "select",
                    "options": [
                        {
                            "text": "Hearts",
                            "value": "menu_id_hearts"
                        },
                        {
                            "text": "Bridge",
                            "value": "menu_id_bridge"
                        },
                        {
                            "text": "Checkers",
                            "value": "menu_id_checkers"
                        },
                        {
                            "text": "Chess",
                            "value": "menu_id_chess"
                        },
                        {
                            "text": "Poker",
                            "value": "menu_id_poker"
                        },
                        {
                            "text": "Falken's Maze",
                            "value": "menu_id_maze"
                        },
                        {
                            "text": "Global Thermonuclear War",
                            "value": "menu_id_war"
                        }
                    ]
                }
            ]
        }
    ]
}

将机器人添加到 Teams

添加到团队的机器人将成为另一个团队成员,在聊天过程中可以 @mentioned(提到)它们。 事实上,机器人仅在是 时才 @mentioned接收消息,因此通道上的其他对话不会发送到机器人。 有关详细信息,请参阅使用 Microsoft Teams 机器人进行通道和组聊天

由于组或通道中的机器人仅在消息中提及 (@botname) 时响应,因此组通道中的机器人收到的每条消息都包含其自己的名称,并且必须确保消息分析能够处理该消息。 此外,机器人还可以分析提到的其他用户,并在其消息中提到用户。

检查和去除 @bot 点名

Mention[] m = sourceMessage.GetMentions();
var messageText = sourceMessage.Text;

for (int i = 0;i < m.Length;i++)
{
    if (m[i].Mentioned.Id == sourceMessage.Recipient.Id)
    {
        //Bot is in the @mention list.
        //The below example will strip the bot name out of the message, so you can parse it as if it wasn't included. Note that the Text object will contain the full bot name, if applicable.
        if (m[i].Text != null)
            messageText = messageText.Replace(m[i].Text, "");
    }
}
var text = message.text;
if (message.entities) {
    message.entities
        .filter(entity => ((entity.type === "mention") && (entity.mentioned.id.toLowerCase() === botId)))
        .forEach(entity => {
            text = text.replace(entity.text, "");
        });
    text = text.trim();
}

重要

不建议出于测试目的以外的任何其他目的通过 GUID 添加机器人。 这会严重限制机器人的功能。 应将生产环境中的机器人作为应用的一部分添加到 Teams。 请参阅创建机器人以及测试和调试 Microsoft Teams 机器人

创建 Telegram 消息

若要创建实现特定于 Telegram 的操作的消息,例如共享语音备忘录或贴纸,请将活动对象的通道数据属性设置为指定以下属性的 JSON 对象:

properties 说明
method 要调用的 Telegram 机器人 API 方法。
parameters 已指定的方法的参数。

支持以下 Telegram 方法:

  • answerInlineQuery
  • editMessageCaption
  • editMessageReplyMarkup
  • editMessageText
  • forwardMessage
  • banChatMember
  • sendAudio
  • sendChatAction
  • sendContact
  • sendDocument
  • sendLocation
  • sendMessage
  • sendPhoto
  • sendSticker
  • sendVenue
  • sendVideo
  • sendVoice
  • unbanChatMember

要详细了解这些 Telegram 方法及其参数,请参阅 Telegram 机器人 API 文档

注意

  • chat_id 参数可通用于所有 Telegram 方法。 如果未将 指定 chat_id 为参数,框架将为你提供 ID。
  • 不要内联传递文件内容,而是使用 URL 和媒体类型指定文件,如下面的示例所示。
  • 在机器人从 Telegram 通道接收的每条消息中,ChannelData 属性都将包含机器人之前发送的消息。

此代码片段显示了指定单个 Telegram 方法的属性示例 channelData

"channelData": {
    "method": "sendSticker",
    "parameters": {
        "sticker": {
            "url": "https://domain.com/path/gif",
            "mediaType": "image/gif",
        }
    }
}

此代码片段显示了指定 Telegram 方法数组的属性示例 channelData

"channelData": [
    {
        "method": "sendSticker",
        "parameters": {
            "sticker": {
                "url": "https://domain.com/path/gif",
                "mediaType": "image/gif",
            }
        }
    },
    {
        "method": "sendMessage",
        "parameters": {
            "text": "<b>This message is HTML formatted.</b>",
            "parse_mode": "HTML"
        }
    }
]

实现 Telegram 方法时,机器人会收到一条答复消息,其中的通道数据属性填充了 JSON 对象。 此响应对象指定原始消息的内容,其中包括 update_id 以及最多一个可选参数。 若要了解如何接收传入响应,请参阅获取更新

此代码片段显示了创建轮询时机器人收到的消息中的 属性示例 channelData

"channelData": {
    "update_id": 43517575,
    "message": {
        "message_id": 618,
        "from": {
            "id": 803613355,
            "is_bot": false,
            "first_name": "Joe",
            "last_name": "Doe",
            "username": "jdoe",
            "language_code": "en"
        },
        "chat": {
            "id": 803613355,
            "first_name": "Joe",
            "last_name": "Doe",
            "username": "jdoe",
            "type": "private"
        },
        "date": 1582577834,
        "poll": {
        "id": "5089525250643722242",
        "question": "How to win?",
        "options": [
            {
                "text": "Be the best",
                "voter_count": 0
            },
            {
                "text": "Help those in need",
                "voter_count": 0
            },
            {
                "text": "All of the above",
                "voter_count": 0
            }
        ],
        "total_voter_count": 0,
        "is_closed": false,
        "is_anonymous": true,
        "type": "regular",
        "allows_multiple_answers": false
        }
    }
}

其他资源