【问题标题】:Bot Framework Node.js ad hoc message TO A SPECIFIC USERBot Framework Node.js 给特定用户的临时消息
【发布时间】:2018-08-16 23:53:50
【问题描述】:

我已经盯着这个看了好几个小时,但找不到解决方案,尽管根据所有建议,它应该很容易 - https://docs.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-proactive-messages

我创建了一个简单的代码,它将“注册”用户并将他们的数据保存在 Azure 上的 cosmosDatabse 中。效果很好。

//ON "register" SAVE USER DATA AND SAY REGISTERED MESSAGE 
bot.dialog('adhocDialog', function(session, args) {

    var savedAddress = session.message.address;
    session.userData.savedAddress = savedAddress;
    //REGISTERED MESSAGE
    session.endDialog("*Congratulations! You are now registered in our network! (goldmedal)*");
})
.triggerAction({
    matches: /^register$/i
})
  • 但是,如果满足某个条件,我如何访问该特定用户并向他发送消息?(实际上是在 HTTP 请求上)

我相当肯定我们必须在某处写入对话 ID 或用户 ID。问题是在哪里?

function startProactiveDialog(address) {
    bot.beginDialog(address, "A notification!");
}
  • 我认为这应该是多么简单。但是你在哪里指定用户呢?

【问题讨论】:

  • “我相当肯定我们必须在某处写对话 ID 或用户 ID”是什么意思。地址对象包含conversationId 以及UserId。如果您使用开始对话框,它将为该地址所属的用户(在该特定频道中)开始对话框。您还可以使用 bot.send() 发送消息而不是启动对话框。
  • 我的意思是我必须以某种方式指定哪些用户会收到该消息。我不想联系每个存储的用户。只是一个特定的人。如果不是 ID,我该如何指定?
  • bot.send("this is a message", address) 会将消息发送给该地址所属的用户。你已经捕捉到了。同样使用bot.beginDialog("dialog name", address) 为该用户启动对话。无需指定任何 ID,它们都包含在地址对象中。只需传递该地址对象。如果您有任何机会使用 Typescript,您将能够看到地址对象的类型。它的IAddress,这就是那些发送方法所期望的。
  • 你很有帮助, bot.send("Message", address) 是我会很好用的东西,我不明白的东西(你可能会发现它很明显,而且这就是为什么你没有解决它)是我如何指定地址。我使用 savedAddress = session.message.address;对于每一个写寄存器的人。在数据库中,我有每个人的文件。但是我如何指定那个特定人的对象呢?
  • 如果我使用 bot.send("Message", savedAddress) 这可能是错误的,但我想不出别的,那么它不知道要给哪个人发短信。你知道我现在有什么问题吗?

标签: node.js azure botframework skype-bots


【解决方案1】:

您已通过将用户地址保存到session.userData.savedAddress 将其保存在数据库中。当事件触发时,对您的数据库执行查询以检查满足两个条件的用户。

  1. 他们已注册监听事件
  2. 他们的地址已保存在数据库中。

在您的情况下,您可以将属性保存到 session.userData 对象,该属性列出了他们正在侦听的事件。如果您只是需要向用户发送消息,那么您可以简单地使用bot.loadSession(savedAddress) ping 用户。


编辑:

因此,您应该向 CosmosDB 发送查询,以查找具有对应于事件的“listen-to”布尔类型标志的条目,而不是专门通过用户 ID 查找。

一开始您不必担心用户 ID,您只是检索所有带有查询的条目,该查询(广义上)如下所示: SELECT * FROM BotState WHERE data LIKE 'listenForEvent=1.

因此,要设置您的 session.userData 以使上述理论查询有效,您需要将问题中的代码 sn-p 修改为如下所示:

bot.dialog('adhocDialog', function(session, args) {
    var savedAddress = session.message.address;
    session.userData.savedAddress = savedAddress;
    session.userData.listenForEvent = 1 // Our property we're going to look for.

    session.endDialog("*Congratulations! You are now registered in our network! (goldmedal)*");
})
.triggerAction({
    matches: /^register$/i
})

【讨论】:

  • 好的,谢谢,这很有用,loadSession 不是我设法找到的。但是如何加载特定地址来 ping 特定用户呢? savedAddress 是所有地址,在数据库中每个人都有一个文件。有 ID 等(你可能知道),所以如果我想 ping 一个用户,我需要以某种方式指定哪个用户。整个 userData 有一个特定的 ID,然后有一个对话的 ID,我们将使用哪个并不重要,我认为可以通过我在那里的对话 ID 来 ping 一个对话。我将如何使用您的解决方案来做到这一点?
  • 我已经编辑了我的答案,这有助于解决问题吗?
  • 好的,所以我接受了您的建议并开始尝试让它发挥作用。问题是,即使 listenForEvent = 1 被添加到用户的文件中,我仍然必须以某种方式解决机器人如何知道 WHO 在他的文件中有这一行。我以非常艰难的方式尝试让机器人侦听数据库中的文件。 5 个小时以来,我试图让query: 'SELECT * FROM root... 工作,但它只是没有。每个人的基本想法是,如果用户数据易于保存,则易于获取。但我只是没有找到一个这样做的人的例子。然而很多人说它有效。
  • 现在...我是 JavaScript 的初学者,但有 2 位专业程序员试图和我一起解决它,但没有运气。他们之前没有看过 Bot Framework,但他们对 JS 本身非常了解。所以问题是,我们是否缺少 Bot Framework 中的某些功能?你会做像bot.loadSession(savedAddress.event1) 这样简单的事情吗?感谢您的耐心等待!
【解决方案2】:

其实savedAddress应该是IAddress的一个实例,而且Message类下的函数loadSession(address: IAddress, callback: (err: Error, session: Session) => void): void;address(adr: IAddress): Message;都需要IAddress作为参数。

所以首先,你应该将整个地址json对象保存在cosmosDB中以备后用。

由于 Node.js 的 botbuilder 是在 Restify 或 Express 上构建的,您可以为您的用户构建一个附加路由来触发和发送主动消息。工作流程可能如下:

  1. 引导用户注册并保存用户的地址对象与您的数据库中的帐户映射
  2. 在 Restify 或 Expressjs 中创建一个路由来触发主动消息:

    server.get('/api/CustomWebApi', (req, res, next) => {
       //find the user's address in your DB as `savedAddress`
        var msg = new builder.Message().address(savedAddress);
        msg.text('Hello, this is a notification');
        bot.send(msg);
        res.send('triggered');
        next();
      }
    );
    

    或者如果你想利用loadSession

    server.get('/api/CustomWebApi', function (req, res, next) {
        bot.loadSession(savedAddress, (err, session) => {
            if (!err) {
                session.send('Hello, this is a notification')
                session.endConversation();
            }
        })
        res.send('triggered');
        next();
    });
    

【讨论】:

  • 感谢您的帖子,我几乎以为人们放弃了这个问题。当我尝试您的代码时,它总是在 Skype 中显示“default_error”,并且在频道中报告“未知活动类型”。我试图以更多方式来表达你的想法,但没有成功。我尝试过的最简单的方法是bot.send(address(savedAddress),"This is a message");。语法有问题吗?编辑:我还应该补充一点,当我没有指定地址时,它可以正常工作(只是没有明显发送到任何地方)
  • 没有bot.send(address(savedAddress),"This is a message");的语法!首先,您可以尝试运行github.com/Microsoft/BotBuilder-Samples/blob/master/Node/… 这个示例以获得一些提示。
  • 好吧,这只是尝试之一,首先我按照您的示例进行操作。现在我尝试应用您发送的链接的结构,但机器人根本不起作用。甚至没有错误。这是我的代码的链接以及它包含的确切内容(除了大多数与主题无关的内容,如对话框)link
  • 更新 - 这次能够得到正确的错误,它与 server.postserver.get 有问题。规格。它说它无法读取未定义的属性“post”。
  • 你还没有在你的代码中定义restify服务器,请查看简单示例的全图,尤其是github.com/Microsoft/BotBuilder-Samples/blob/master/Node/…。或者该链接是您的整个项目还是部分项目?
【解决方案3】:

我创建了一个 users.json 文件,其中保存了所有用户。它按我需要的方式工作。我想数据库会更好,但我真的不知道从哪里开始。数据库是一个全新的篇章我还没有遇到过,所以当项目需求解决了之后再去研究它是没有意义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    相关资源
    最近更新 更多