如何获得这两套代码的满足感?

时间:2018-11-27 01:45:04

标签: javascript node.js dialogflow actions-on-google

我正在Dialogflow上创建一个聊天机器人,该机器人可以执行各种操作(我基本上已经遵循了Dialogflow推出的一些教程,对代码进行了小幅重新格式化,并为自己进行了一些调整)。

代码很长,因此我将链接放在下面的Github上。另外,我在dialogflow上使用内联编辑器

问题/我不确定自己要做什么,因为我有一个用户登录部分(第33至51行),用户可以在其中通过语音登录自己的Google帐户。

在教程中,他们具有履行能力(我几乎可以肯定这是它不起作用的原因):

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app)

但是问题是,要实现我的其他功能,我需要具备以下条件:

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
 ..... Functions under }

我曾尝试写一些变体,认为这可能有效:

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((app, request, response)

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app(request, response) 
// Syntax error

如何让代码的两半一起工作?是否可以执行此操作,还是必须重新设置格式,还是只需要对履行线做些不同的事情?

感谢您的帮助!

代码here

注意::在Github上的代码中,我没有更改履行行,而是以其他功能可以使用的形式将其保留。 该代码已经过登录和工作的测试,无法与我编写的其他功能一起使用。

2 个答案:

答案 0 :(得分:2)

您似乎在混合两种不同版本的Google图书馆中的操作。建议您坚持使用V2,这意味着将Intent-map改为Intent处理程序。

// Intent that starts the account linking flow.
app.intent('Start Signin', conv => {
  conv.ask(new SignIn('To get your account details'));
});

// Create a Dialogflow intent with the `actions_intent_SIGN_IN` event.
app.intent('Get Signin', (conv, params, signin) => {
    if (signin.status === 'OK') {
        const payload = conv.user.profile.payload;
        conv.ask(`Welcome back ${payload.name}. What do you want to do next?`);
  } else {
      conv.ask(`I won't be able to save your data, but what do you want to do next?`);
  }
});

app.intent('Make Appointment', (conv) => {
    /* some code here */
});

app.intent('ReadFromFirestore', (conv) => {
    // Get the database collection 'dialogflow' and document 'agent'
    const dialogflowAgentDoc = db.collection('dialogflow').doc('agent');

    // Get the value of 'entry' in the document and send it to the user
    return dialogflowAgentDoc.get().then(doc => {
        if (!doc.exists) {
          conv.tell('No data found in the database!');
        } else {
          conv.ask(doc.data().entry);
        }
    }).catch(() => {
        conv.ask('Error reading entry from the Firestore database. Please add a entry to the database first by saying, "Write <your phrase> to the database"');
    });
});

app.intent('WriteToFirestore', (conv) => {
    /* some code here */
});

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

(省略了方法)

“ app”(对话框流)对象已经包装了请求和响应参数,因此您无需采取任何措施来干扰这些参数。

如果您想在dialogflow之外使用单独的端点来完成工作:您可以添加其他功能,例如:

exports.someOtherFunction = functions.https.onRequest((request, response) => {
    /* do something with the request and response here */
});

这些与Dialogflow没有直接关系。

答案 1 :(得分:2)

问题在于这两个库具有不同的方式来设置用于处理请求/响应对象的侦听器以及设置意图处理程序注册。您不能将两者混合使用(如您所知)。您需要选择一个并以另一种方式转换注册的功能。

为节省大量输入时间,我将Google-Actions库称为a-o-g,将dialogflow-fulfillment库称为d-f。

使用Google动作库

您可以使用以下方式初始化监听器:

const app = dialogflow({
  // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
  clientId: '<CLIENT ID>',
});

// Intent handler declarations go here

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

转换dialogflow-fulfillment-style处理程序相对简单。 a-o-g conv对象与d-f agent对象非常相似。例如,两者都具有add()方法,在处理动作时其行为方式相同。

conv对象还具有parameters属性,尽管最好在函数调用中使用第二个参数,但它包含相同的内容。同样,它具有arguments属性,该属性包含与传递给处理程序的第三个参数相同的内容。

还值得注意的是,app.intent()不必具有箭头功能,甚至不必像这样直接内联。您可以单独编写该函数,只需将其作为参数传递即可。

因此,您的makeAppointment()函数可能会被重写并注册为类似的内容

  function makeAppointment (conv) {
    // Calculate appointment start and end datetimes (end = +1hr from start)
    const dateTimeStart = new Date(Date.parse(conv.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('-')[0] + timeZoneOffset));
    const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
    const appointmentTimeString = dateTimeStart.toLocaleString(
      'en-US',
      { month: 'long', day: 'numeric', hour: 'numeric', timeZone: timeZone }
    );

    // Check the availibility of the time, and make an appointment if there is time on the calendar
    return createCalendarEvent(dateTimeStart, dateTimeEnd).then(() => {
      conv.add(`Okay, I have you booked for ${appointmentTimeString}!`);
    }).catch(() => {
      conv.add(`I'm sorry, there are no slots available for ${appointmentTimeString}.`);
    });
  }
  app.intent( 'Make Appointment', makeAppointment );

使用对话流程实现库

您已经通过这种方式设置了侦听器和处理程序

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });

  // Declare your functions here

  let intentMap = new Map();
  // Map intent name to functions here
  agent.handleRequest(intentMap);
});

所以问题是如何将似乎在函数参数中具有a-o-g特定信息的处理程序转换为d-f兼容处理程序。

d-f agent对象可以获取(几乎)等效的conv对象。毫不奇怪,它是agent.getConv()。真。然后,您可以使用如上所述的parametersarguments属性来获取第二个和第三个函数参数的等效项。您将使用agent.add()添加一条消息(也可以使用conv,但要复杂一些)。

“获取登录”处理程序可能看起来像这样:

function getSignin (agent){
  let conv = agent.getConv();
  let params = conv.parameters;
  let signin = conv.arguments;
  if (signin.status === 'OK') {
    const payload = conv.user.profile.payload;
    agent.ask(`Welcome back ${payload.name}. What do you want to do next?`);
  } else {
    agent.ask(`I won't be able to save your data, but what do you want to do next?`);
  }
}

然后确保您在适当的位置注册了处理程序

intentMap.set('Get Signin', getSignin);