如何让新版botframework webchat记住用户ID

How to have new version of botframework webchat remember user ID

开箱即用的旧版网络聊天过去常常在通过同一浏览器访问时跨会话记住用户。我假设这是通过使用 cookie?新版本("gemini")没有这样做。每次我关闭浏览器 window 并从同一个浏览器再次打开时,都会发送一个新的 ID,因此我无法再访问已保存的 userState 信息。为了恢复格式,我通过直线切换到 botframework-webchat 并遇到了同样的问题。用户 ID 有一个明确的输入,我不知道如何使它对特定用户保持一致。

我不是 Web 开发人员,目前不需要使它成为一个可靠的实现。我只是想让这项工作像以前开箱即用的网络聊天一样工作。任何人都可以阐明以前的版本是如何工作的,and/or 我如何使直线版本具有相同的功能?

编辑: 根据史蒂文对以下答案的评论,我尝试实施 get/set cookie,但它不起作用。下面是我试过的代码。我可以通过控制台看到我正在进入 if 语句并且正在生成 userID,但它没有被保存(我在 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');

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

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

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

如果它不影响您的页面或您的需求,请在您的页面上放置一个按钮,然后 link 将其连接到以下代码。这是一个非常有用的简单技巧。

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

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

希望得到帮助!

最终我发现处理这个问题的方法是通过令牌启动聊天会话。当您在令牌请求正文中提供 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();
    }
})

您可以在此处 return JSON,但我选择 return 仅将标记作为文本。现在要调用该函数,您需要在部署机器人的任何地方从脚本中访问此端点(假设您使用的是 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 return 将响应作为流,因此您需要使用 .text().json() 将其转换,具体取决于您从机器人端点发送响应的方式(我使用.text())。您需要同时等待 fetch response.text()。我部署网络聊天的整个脚本都在一个异步函数中。

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