I created a simple bot to test some new resources, but I'm facing an issue with fulfillment responses on some clients. I'm testing with many integrations.
✅ The fulfillment work fine with: Web Demo and Dialogflow Messenger
🔥 The fulfillment fails with: Facebook Messenger, Slack and Telegram
I wrote two intents to test:
"Hello" - Text Response Intent
"Hi" - Fulfillment Intent answered by node using actions-on-google package.
What happened:
"Hello" - intent works on all integrations, like expected.
"Hi" - intent works like expected with Dialogflow native integrations (✅ )
"Hi" - intent doesn't work with other integrations (🔥), but it shows "Typing..." while my node backend creates the answer, but the text response is never showed.
In debug mode, I see that the request is received, the intent match, and the Response object are like expected.
Node code:
const { dialogflow } = require('actions-on-google');
const app = dialogflow({ debug: true });
...
app.intent('Hi', conv => {
console.log('>> Hi Fulfillment reached');
conv.ask(`Hi! I'm a fulfillment response on node!`);
});
Node response (console output):
>> Hi Fulfillment reached
Response {
"status": 200,
"headers": {
"content-type": "application/json;charset=utf-8"
},
"body": {
"payload": {
"google": {
"expectUserResponse": false,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hi! I'm a fulfillment response on node!"
}
}
]
}
}
}
}
}
POST /api/chatBot/ 200 156 - 1419.611 ms
I recorded my screen to show better that behavior.
Any help is appreciated!
You are using the actions-on-google nodeJS library. This library is used to build bots on the Actions on Google platform using Dialogflow. You can use it to build some basic things for other integrations, but you might run into limitations as it is build specifically for Google Assistant.
If you want to build bots for multiple integrations of Dialogflow it is better to use the dialogflow fulfillment library. This is ment for building chatbots for multiple integrations for Dialogflow.
https://www.npmjs.com/package/dialogflow-fulfillment
Related
I have a Bot I have built with MS BotFramework, hosted on Azure. The Bot is built to start the convo with a Welcome Message. When I test the bot through emulator, or on Azure test webchat, the bot will initiate the conversation as expected with the welcome message.
However, in my chat client using BotFramework-DirectLineJS, it isn't until I send a message that the bot will respond with the Welcome message (along with a response to the message the user just sent).
My expectation is that when I create a new instance of DirectLine and subscribe to its activities, this Welcome message would come through. However, that doesn't seem to be happening.
Am I missing something to get this functionality working?
Given this is working for you on "Test in Webchat", I'm assuming your if condition isn't the issue, but check if it is if (member.id === context.activity.recipient.id) { (instead of !==). The default on the template is !== but that doesn't work for me outside of emulator. With === it works both in emulator and other deployed channels.
However, depending on your use cases you may want to have a completely different welcome message for Directline sessions. This is what I do. In my onMembersAdded handler I actually get channelId from the activity via const { channelId, membersAdded } = context.activity;. Then I check that channelId != 'directline' before proceeding.
Instead, I use the onEvent handler to look for and respond to the 'webchat/join' event from Directline. That leaves for no ambiguity in the welcome response. For a very simple example, it would look something like this:
this.onEvent(async (context, next) => {
if (context.activity.name && context.activity.name === 'webchat/join') {
await context.sendActivity('Welcome to the Directline channel bot!');
}
await this.userState.saveChanges(context);
await this.conversationState.saveChanges(context);
})
You'll still want to have something in your onMembersAdded for non-directline channel welcome messages if you use this approach.
I want to make a POST (add a new task) through chatting with Watson.
I have the POST function which works very well, I tested it on Postman. And I have the Watson nodes created.
Here is my endpoint from the POST in Node js:
MainRouter.post('/welcome', (req, res) => {
TaskPost.postTask(req.body).then(message => {
return res.json(message);
}).catch((error) => {
return res.status(404).json(error);
});
});
Here is my conversation with Watson (is working very well):
I also included this in the main.js and changed the password and url:
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');
const assistant = new AssistantV2({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
serviceUrl: 'https://api.us-south.assistant.watson.cloud.ibm.com',
version: '2018-09-19'
});
How do I make this connection ? What do I have to include?
I would recommend the official Node.js SDK for the IBM Watson services. It includes support for Watson Assistant and is easy to use.
If you still want to use the V2 API directly, then take a look at how the SDK utilizes the API. As alternative, the API docs for Watson Assistant have code snippets for Node.js.
The basic flow is that you authenticate, then establish a session, and finally send messages with the user input to Watson Assistant.
To get to your dialog node with the task, the user (or your code) would need to send the right intents and entities for navigating from the root node to that specific subnode.
I have this code:
bot.on('conversationUpdate', (message) => {
if (message.membersAdded) {
message.membersAdded.forEach((identity) => {
if (identity.id === message.address.bot.id) {
bot.beginDialog(message.address, 'start');
}
});
}
});
bot.dialog('start', [
(session) => {
var msg = new builder.Message(session);
msg.attachments([
new builder.HeroCard(session)
.title('test')
.buttons([{ title: 'testButton', type: 'imBack', value: 'testButton' }])
]);
builder.Prompts.choice(session, msg, ['testButton']);
},
(session, results) => {
session.send('Reached 2nd function!');
console.dir(results);
var message = results.response.entity;
session.beginDialog('anotherDialog', message);
}
]);
It works fine by using Bot Framework Emulator.
Bot Framework Emulator Result
However, It doesn't reach 2nd function in the waterfall steps by using Web Chat(Azure Console).
Test in Web Chat Result
What is the difference of behavior between Bot Framework Emulator and Web Chat?
And what should I modify in the code?
Do you have any idea?
Node.js version: 8.10.0
Bot Framework Emulator version: 4.0.15-alpha
I understand that what you want to do is have the bot start the conversation instead of waiting for the user to say something, which is a very common objective. Unfortunately this is not exactly an easy task with built-in functionality, but fortunately there is a blog post explaining how to do it. The blog post is taken from a workaround posted in a GitHub issue that's linked to in the one Fei Han linked.
The gist is that conversationUpdate events don't contain enough information to allow for bot state and so dialogs and prompts and such shouldn't be spawned from the event handler. You can get around this by generating your own event in your client-side code. Of course this probably wouldn't help you when testing in the Azure portal.
In general you should expect there to be many differences between the different channels, especially when it comes to the nature of the events produced by the channels. conversationUpdate is a particularly contentious event, and it's known to behave differently in Bot Emulator from the other channels. From the blog post (emphasis mine):
If you’re using WebChat or directline, the bot’s ConversationUpdate is
sent when the conversation is created and the user sides’
ConversationUpdate is sent when they first send a message. When
ConversationUpdate is initially sent, there isn’t enough information
in the message to construct the dialog stack. The reason that this
appears to work in the emulator, is that the emulator simulates a sort
of pseudo DirectLine, but both conversationUpdates are resolved at the
same time in the emulator, and this is not the case for how the actual
service performs.
If you want to avoid writing client code and you're sure your bot is only going to be used in channels that support the conversationUpdate event, I may have another workaround for you. Even though the blog post is clear that you shouldn't be using conversationUpdate, it may still be acceptable in cases when you just need to send a single message. You could simulate a prompt by sending a single message in your event handler and then behaving as though you're following up on that message in your root dialog. Here's a proof of concept:
bot.on('conversationUpdate', (message) => {
if (message.membersAdded) {
message.membersAdded.forEach((identity) => {
if (identity.id === message.address.bot.id) {
var msg = new builder.Message()
.address(message.address)
.attachments([
new builder.HeroCard()
.title('test')
.buttons([{ title: 'testButton', type: 'imBack', value: 'testButton' }])
]);
bot.send(msg);
}
});
}
});
bot.dialog('/', function (session) {
if (session.message.text == "testButton") {
session.send('Reached 2nd function!');
session.beginDialog('/getStarted');
} else {
builder.Prompts.choice(session, "I didn’t understand. Please choose an option from the list.", ['testButton']);
}
});
Note that this proof of concept is far from robust. Since the root dialog is likely to be accessed from many different places in a real bot, you'll probably want to put a condition in there to make sure it only responds to the intro prompt one time and you'll also probably want to spawn other dialogs.
I am trying to subscribe/registering for push notification and push that to mine server.
Here is what I am trying
axios.post(`https://www.googleapis.com/gmail/v1/users/me/watch`, {
"topicName": "projects/gpubsub/topics/subcription"
}, util.authHeader(token))
The API is working correctly. Now I have some questions like
How to apply a filter like getting notified only with the particular user or subject. I have saw filters are using in Microsoft flow for Gmail
How to send extra data so that I can receive it in
attributes property on pushing notification to my server
Filters are sent as part of optional parms.
watch (cb) {
const params = {
userId: 'me',
resource: {
labelIds: ['INBOX'],
labelFilterAction: 'include',
topicName: configure.Google.TopicName
}
};
this.gmail.users.watch(params, cb);
}
remember lableid is the id of the label not its name use lables.list to find the ids.
I recommend you look into using the official Google apis node.js library rather than coding this yourself.
I'm working on a Node.js slack app containing a bot user. But I don't know how to respond to a user with a rich message as a bot.
Example:
I can respond with simple messages without problems using this code:
import * as SlackClient from '#slack/client';
slackBot = new SlackClient.RtmClient(bot_access_token)
slackBot.on(SlackClient.RTM_EVENTS.MESSAGE, message => {
slackBot.sendMessage('Hello', message.channel);
});
slackBot.start();
But RTM API doesn't support rich messages:
The RTM API only supports posting simple messages formatted using our default message formatting mode. It does not support attachments or other message formatting modes. To post a more complex message as a user clients can call the chat.postMessage Web API method with as_user set to true.
so I tried to use the web client to respond with rich messages and moved to this code:
import * as SlackClient from '#slack/client';
slackWebClient = new SlackClient.WebClient(access_token);
slackBot = new SlackClient.RtmClient(bot_access_token)
slackBot.on(SlackClient.RTM_EVENTS.MESSAGE, message => {
slackWebClient.chat.postMessage(message.channel, 'Hello', { attachments: myAttachments });
});
slackBot.start();
this approach is working when I testing the bot with my account. But if an other team user writes a DM to the bot, slackWebClient.chat.postMessage fails with the error error: channel_not_found. (I also tried to add a parameter as_user: true - but behaviour is the same, except that messages are signed with my name instead of bot name).
Solved: I created a SlackClient.WebClient instance with the Bot User OAuth Access Token instead of the OAuth Access Token (also with as_user set to true) and now it works as intended. I didn't know that the Bot User OAuth Access Token can be also used as a token for the Web API client.
Working code:
import * as SlackClient from '#slack/client';
slackWebClient = new SlackClient.WebClient(bot_access_token);
slackBot = new SlackClient.RtmClient(bot_access_token)
slackBot.on(SlackClient.RTM_EVENTS.MESSAGE, message => {
slackWebClient.chat.postMessage(message.channel, 'Hello', { attachments: myAttachments, as_user: true });
});
slackBot.start();