如何解决 Microsoft Bot Framework 中的内容类型错误?

How do I solve a content type error in the Microsoft Bot Framework?

我正在使用 Microsoft Bot Builder Python SDK 构建一个机器人。它托管在 Heroku 上,与 Skype 交换短信效果很好。但是我 运行 遇到了发送文件的问题。机器人生成一个 JSON 文件并将其发送给用户。我正在使用 _get_upload_attachment method of the attachments bot code (see with my changes below) and when the bot runs locally the file is sent to the Bot Framework Emulator with no issues. After deployment to Heroku the file is sent successfully via the test tool in the Bot Framework portal。但是触发Skype发送文件后,出现如下错误。似乎此错误特定于 Skype 频道。

什么可能会导致此错误,我该如何解决?

错误:

2021-02-18T08:28:32.579790+00:00 app[web.1]: [on_turn_error] unhandled error: Operation returned an invalid status code 'Not Found'
2021-02-18T08:28:32.581176+00:00 app[web.1]: Traceback (most recent call last):
2021-02-18T08:28:32.581226+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/bot_adapter.py", line 128, in run_pipeline
2021-02-18T08:28:32.581227+00:00 app[web.1]: context, callback
2021-02-18T08:28:32.581229+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/middleware_set.py", line 69, in receive_activity_with_status
2021-02-18T08:28:32.581230+00:00 app[web.1]: return await self.receive_activity_internal(context, callback)
2021-02-18T08:28:32.581247+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/middleware_set.py", line 79, in receive_activity_internal
2021-02-18T08:28:32.581248+00:00 app[web.1]: return await callback(context)
2021-02-18T08:28:32.581249+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botbuilder/core/activity_handler.py", line 68, in on_turn
2021-02-18T08:28:32.581250+00:00 app[web.1]: await self.on_message_activity(turn_context)
2021-02-18T08:28:32.581266+00:00 app[web.1]: File "/app/bot.py", line 140, in on_message_activity
2021-02-18T08:28:32.581267+00:00 app[web.1]: reply.attachments = [await self._get_upload_attachment(turn_context)]
2021-02-18T08:28:32.581268+00:00 app[web.1]: File "/app/bot.py", line 426, in _get_upload_attachment
2021-02-18T08:28:32.581269+00:00 app[web.1]: type = "application/json"
2021-02-18T08:28:32.581288+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/botframework/connector/aio/operations_async/_conversations_operations_async.py", line 1138, in upload_attachment
2021-02-18T08:28:32.581289+00:00 app[web.1]: raise models.ErrorResponseException(self._deserialize, response)
2021-02-18T08:28:32.581316+00:00 app[web.1]: botbuilder.schema._models_py3.ErrorResponseException: Operation returned an invalid status code 'Not Found

获取附件方法:

async def _get_upload_attachment(self, turn_context: TurnContext) -> Attachment:
    """
    Creates an "Attachment" to be sent from the bot to the user from an uploaded file.
    :param turn_context:
    :return: Attachment
    """
    with open("/tmp/exports/export.json", "rb") as in_file:
        json_data = in_file.read()
    connector = await turn_context.adapter.create_connector_client(
        turn_context.activity.service_url
    )
    conversation_id = turn_context.activity.conversation.id
    response = await connector.conversations.upload_attachment(
        conversation_id,
        AttachmentData(
            name = "export.json",
            original_base64 = json_data,
            type = "application/json"
        )
    )
    base_uri: str = connector.config.base_url
    attachment_uri = (
        base_uri
        + ("" if base_uri.endswith("/") else "/")
        + f"v3/attachments/{response.id}/views/original"
    )
    return Attachment(
        name = "export.json",
        content_type = "application/json",
        content_url = attachment_uri,
    )

更新: 我已经用 XLSX 替换了 JSON 导出并面临同样的问题:XLSX 文件已成功发送到 Bot Framework portal 中的测试工具(我可以下载并保存它),但是 “机器人遇到错误或错误。要继续 运行 这个机器人,请修复机器人源代码。” 消息返回到 Skype 频道。 Heroku 日志显示与上述错误示例类似的错误。

机器人发送的文件是由建议的操作按钮触发的,如下面的屏幕截图所示。

随着调试 Python 代码的经验越来越丰富,您可能会发现 Python 堆栈跟踪中的行号是指多行函数调用的最后一行,而不是第一的。当您考虑解释器如何从上到下一次读取一行并且在知道所有参数是什么之前无法调用该函数时,这是有道理的。这意味着即使您在堆栈跟踪中看到的行是 type = "application/json",那只是因为它是函数调用的最后一个解释行,所以您应该注意被调用的函数:upload_attachment.您的问题与内容类型无关。

我们可以看到 upload_attachment 抛出“未找到”错误。您可能会认为这是与 404 关联的消息。这意味着您的连接器客户端正在调用的基础 REST API operation 对于给定服务 URL 不存在,这意味着该操作不支持Skype 频道。这应该不足为奇,因为大多数操作都是特定于频道的。

我尝试通过 conventional way 向 Skype 发送附件,但出现 400 错误:

{
    "error": {
        "code": "BadSyntax",
        "message": "File attachments aren’t supported for this bot"
    }
}

这并没有给我们留下很多选择。如果您真的想在 Skype 中向用户发送文件附件,您必须自己将其上传到某个外部服务器,然后将其 URL 提供给用户。如果您不介意将文件上传到 public URL 那么这将是最简单的,但是如果您希望文件是私有的那么您需要将它上传到某个安全系统机器人和用户具有凭据。这可能会变得复杂。

您可能会对这个答案感到失望,但我认为您不会得到更好的答案。 Skype 机器人已经 deprecated 一年多了,这意味着您不应该指望在您的 Skype 机器人问题上获得任何官方帮助。我的建议是切换到另一个聊天平台,比如 Teams。