【问题标题】:How to stop a Twilio Autopilot Dialogue on a custom chat channel programmatically?如何以编程方式在自定义聊天频道上停止 Twilio Autopilot 对话?
【发布时间】:2021-06-10 01:03:24
【问题描述】:

我正在为 Twilio Autopilot 机器人实施端到端测试。我使用自定义聊天频道开始与机器人的对话,方法是向此 URL 发出 HTTP POST: https://channels.autopilot.twilio.com/v2/AC8xxxxxxxxxxxxxx/UA6xxxxxxxxxxxxx/custom/chat

我假设在下面,这会创建一个名为 chat 的新聊天频道并将用户添加到该频道,然后开始一个新的对话。

此方法在此处的 Twilio 文档中进行了描述:https://www.twilio.com/docs/autopilot/channels/custom-channel

我收到的回复包括dialogue SID:

 "dialogue": {
    "sid": "UK32f8xxxxxxxxxxxxxxxxxx",
    ...
 }

由于我希望测试可重复并获得相同的结果,因此我希望能够以编程方式停止在每次测试结束时开始的对话。

在给定对话 SID 的情况下,有没有办法以编程方式停止对话?如果无法停止对话,有没有办法以编程方式删除自定义频道?其他解决此问题的方法也非常受欢迎。谢谢。

【问题讨论】:

    标签: twilio twilio-api twilio-programmable-chat


    【解决方案1】:

    虽然这没有回答“如何停止对话”或“如何删除自定义频道”,但这是我用来解决“可重复测试”要求的解决方案。

    我使用的是 Node 和 axios,虽然下面的代码主要是一个简单的 HTTP 请求,所以它可以复制成其他语言。

    帮助类非常不言自明 - 它只是在创建时生成一个新用户 ID 以避免对话冲突,然后调用我的问题中提到的自定义频道 URL:

    export class AutopilotUtils {
        private authHeaderValue: string;
        private userIdentity: string;
        private targetUrl: string;
        
        constructor(
            twilioAccountSid: string,
            twilioAuthToken: string,
            twilioAssistandSid: string) {
    
            const autopilotUrl = `https://channels.autopilot.twilio.com/v1/${twilioAccountSid}/${twilioAssistantSid}/custom/testchat`;
    
            // the Inbound Context becomes the value of the Memory parameter
            // on the target URL
            const inboundContext = {
                someProp: "somePropValue"
            };
            this.userIdentity = `testUser_${this.generateQuickGuid()}`;
            this.authHeaderValue = `Basic ${Buffer.from(twilioAccountSid + ":" + twilioAuthToken).toString("base64")}`;
            this.targetUrl = `${autopilotUrl}?Memory=${JSON.stringify(inboundContext)}`;
        }
    
        public async sendMessage(userInput: string): Promise<AxiosResponse<any>> {
            const result = await axios({
                method: "post",
                url: this.targetUrl,
                data: `user_id=${this.userIdentity}&text=${userInput}`,
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Accept": "application/json",
                    Authorization: this.authHeaderValue
                }
            });
            return result;
        }
    
        private generateQuickGuid() {
            return Math.random().toString(36).substring(2, 15) +
                Math.random().toString(36).substring(2, 15);
        }
    }
    

    然后它可以用在这样的测试中(使用 jest 和 chai):

    // make a new utils instance (which will use the same user identity
    // for the duration of its lifetime)
    const utils = new AutopilotUtils(acctSid, authToken, botSid);
    
    // send "hello" to the bot
    const result = await utils.sendMessage("hello");
    
    // result will contain the actions that were returned. for v1, the
    // shape of the returned object is:
    //
    // { says: [{speech: "blah"}, {speech: "blah again"}], listen: {}}
    //
    // the action names, order, and content will match what the bot
    // returns, so every action might have its own shape and would
    // need to be checked accordingly. we are checking the "data"
    // property only because that's how axios data comes back, it's
    // not part of the object shape returned from Twilio.
    expect(result).to.not.be.undefined;
    expect(result).to.have.property("data").that.has.property("says");
    const responseArray = result.data["says"];
    expect(responseArray).to
        .satisfy((s: {speech: string}[]) => s.some(i => i.speech && i.speech.includes("hi there")));
    

    代码中的 cmets 解释了它是如何工作的。

    【讨论】:

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