【问题标题】:How to have new version of botframework webchat remember user ID如何让新版本的 botframework 网络聊天记住用户 ID
【发布时间】:2021-02-03 02:45:50
【问题描述】:

开箱即用的旧版网络聊天用于在通过同一浏览器访问时跨会话记住用户。我认为这是通过使用cookies?新版本(“双子座”)不这样做。每次我关闭浏览器窗口并从同一个浏览器再次打开时,都会发送一个新 ID,因此我无法再访问保存的 userState 信息。为了恢复格式,我通过直接线路切换到 botframework-webchat 并遇到了同样的问题。 userID 有一个明确的输入,我不知道如何使特定用户的输入保持一致。

我不是 Web 开发人员,目前不需要将其作为强大的实现。我只是想让这项工作像以前的开箱即用网络聊天一样工作。任何人都可以阐明以前的版本是如何工作的,和/或我如何使直达版本具有相同的功能?

编辑:根据 Steven 对以下答案的评论,我尝试实现 get/set cookie,但它不起作用。下面是我试过的代码。我可以通过控制台看到我正在进入 if 语句并且正在生成用户 ID,但它没有被保存(我在 Application>Storage>Cookies 中没有看到它,所以它不仅仅是 get 不工作)。请指教!

           function setCookie(name,value,days) {
                var expires = "";
                if (days) {
                    var date = new Date();
                    date.setTime(date.getTime() + (days*24*60*60*1000));
                    expires = "; expires=" + date.toUTCString();
                }
                document.cookie = name + "=" + (value || "")  + expires + "; path=/";
            }
            function getCookie(name) {
                var nameEQ = name + "=";
                var ca = document.cookie.split(';');
                for(var i=0;i < ca.length;i++) {
                    var c = ca[i];
                    while (c.charAt(0)==' ') c = c.substring(1,c.length);
                    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
                }
                return null;
            }
            function eraseCookie(name) {   
                document.cookie = name+'=; Max-Age=-99999999;';  
            }

            if (!getCookie('userID')) {
                console.log('in if');
                var userID = Date.now() + '_' + Math.random().toString().substr(2, 9);
                console.log(userID);
                setCookie('userID',userID,999);
            }
            console.log('out of if');

【问题讨论】:

  • 接受/投票支持更大的 Stack Overflow 社区和任何有类似问题的人。如果您觉得我的回答足够,请“接受”并点赞。如果没有,请告诉我我还能提供哪些帮助!
  • 我有时间测试一下就可以了!

标签: botframework web-chat


【解决方案1】:

请看我发的this solution的前半部分。它讨论了如何在用户刷新或临时导航离开时使浏览器会话持续存在。

简而言之,它依赖于使用sessionStorage() 来存储tokenconversationId

虽然不让会话连续重新开始可能非常有用,但在测试期间不得不关闭并重新打开或硬刷新和删除会话存储以获得干净的状态也可能很烦人。

如果它不会干扰您的页面或您的需求,请在您的页面上放置一个按钮并将其链接到以下代码。这是一个非常有用的简单 hack。

const reloadBtn = document.getElementById('reloadBtn');
reloadBtn.onclick = () => {
  location.reload( true );
};

window.onbeforeunload = function() {
  window.sessionStorage.removeItem( 'conversationId' );
  window.sessionStorage.removeItem( 'token' );
};

希望有帮助!

【讨论】:

  • 我会检查一下这个,看看我是否能适应我的需求,但要明确的是,我试图保留 userId,而不是 conversationId。因此,如果我在关闭计算机后的第二天加载浏览器,我的 userState 仍将被保留(在我的机器人的情况下,例如帐号、搜索的最后订单,以及我想无限期保留的其他内容)。跨度>
  • 我不太了解尝试使该解决方案适应我的需求。您能否提供有关如何执行此操作以存储 userId(跨多个会话,包括关闭 PC)而不是 conversationId 的指导?我的家伙说也许有一个简单的 cookie 实现来在本地存储随机生成的 userId 并在它存在时重用它,但我不知道如何处理它。
  • 我想这取决于您的需求。您可以通过 cookie 保存 userId,方法是在网络聊天中分配它(document.cookie = "userId=" + userId...正确的解决方案here)。如果您想保留用户对话的各个方面以供以后访问,那么您将需要使用状态服务(即 CosmosDB、Mongo、SQL、Blob 存储)。
  • 但是,如果您想从中断的地方继续对话,请记住令牌在一小时后过期,并且 conversationId 的/对话最多只能在 24 小时内有效。您可以从状态服务中保存和检索对话,但它仅用于查看记录的对话。它不会从那个时候开始。使用状态服务将在您的机器人中。我不知道您使用的是什么语言,但存在一些社区包here。野外还有其他的。
  • 第一条评论应该解决我的问题。我会试一试,然后报告。我只关心记住用户,这样我就可以访问 userState 中的先前信息,而不是获取对话或对话状态值。
【解决方案2】:

最终我发现解决这个问题的方法是通过令牌启动聊天会话。当您在令牌请求的正文中提供user 属性时,它将正确启动会话并提取正确的用户状态(如果用户之前与机器人交谈过)。通过令牌启动网络聊天的文档有点轻。以下是我的做法。

首先,您需要在您的机器人中创建一个端点来生成令牌(我从浏览器中传入 userId,您稍后会看到)。

server.post('/directline/token', async (req, res) => {

    try {
        var body = {User:{Id:req.body.userId}};
        const response = await request({
            url: 'https://directline.botframework.com/v3/directline/tokens/generate',
            method: 'POST',
            headers: { Authorization: `Bearer ${process.env.DIRECTLINE_SECRET}`},
            json: body,
            rejectUnauthorized: false
        });
        const token = response.token;
        res.setHeader('Content-Type', 'text/plain');
        res.writeHead(200);
        res.write(token);
        res.end();
    } catch(err) {
        console.log(err);
        res.setHeader('Content-Type', 'text/plain');
        res.writeHead(500);
        res.write('Call to retrieve token from Direct Line failed');
        res.end();
    }
})

您可以在此处返回 JSON,但我选择仅将令牌作为文本返回。现在要调用该函数,您需要在部署机器人的任何位置从脚本中访问此端点(假设您使用的是 botframework-webchat CDN)。这是我使用的代码。

    const response = await fetch('https://YOURAPPSERVICE.azurewebsites.net/directline/token', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({userId:userID})
    });
    const token = await response.text();

请求正文必须是字符串化的 JSON。 Fetch 将响应作为流返回,因此您需要使用.text().json() 转换它,具体取决于您从机器人端点发送响应的方式(我使用了.text())。您需要同时等待fetch response.text()。我部署网络聊天的整个脚本都在一个异步函数中。

结合上面提到的用于设置和调用用户 ID 的 cookie 实现,只要他们的浏览器中还有 cookie,我就可以记住用户。请注意,这仅适用于 Directline。如果您使用的是 OOTB 网络聊天,它将不再记得您。我想说,在当前的实现中,OOTB 网络聊天仅适用于测试,我不建议在任何生产能力中使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多