I have a button on my chatbot which once being clicked,
it should resume the dialog to the next step of the waterfall dialog.
I cannot find a payload value that will do that, I tried action?resume and action?next.
[
(session, args, next) => {
let msg = new builder.Message().text('welcome')
.attachments([new builder.HeroCard(session)
.buttons([builder.CardAction.imBack(session, 'next', 'next')])])
session.send(msg);
}, (session, args, next) => {
//I'm here if button clicked - if not, handle somewhere else
}
]
I guess you want to use a hero card to prompt something, i.e. wait for the user to click some button on hero card. Here is the code sample
bot.dialog("/", function(session) {
session.beginDialog("test");
});
bot.dialog("test", [
function(session) {
// create a hero card
let msg = new builder.Message()
.text("welcome")
.attachments([
new builder.HeroCard(session).buttons([
builder.CardAction.imBack(session, "next", "next")
])
]);
// prompt user using hero card
builder.Prompts.text(session, msg);
},
function(session, result) {
// if user clicked some button, then do someting useful
if (result.response === "next") {
// do something, like calling another dialog
} else { // user didn't clicked button, so prompt the hero card again
session.send("please click a button");
session.replaceDialog("test");
}
}
]);
Related
I have a bot where the root dialog is a choice prompt(yes/no) which I want to show the user when the bot starts. Below are the code snippets for conversationUpdate and the root dialog. The issue here is when the user clicks yes or no in the root dialog i.e welcome message, the root dialog is triggered second time and it again asks the user to click yes or no. After that the bot is continuing its normal flow but I want the root dialog to trigger only once.
Thanks in Advance
bot.on('conversationUpdate', function (message) {
if (message.membersAdded && message.membersAdded.length > 0) {
message.membersAdded.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
bot.beginDialog(message.address, '/');
}
});
}
});
Root Dialog code:
bot.dialog('/', [
function (session) {
builder.Prompts.choice(session,"some text", ["yes", "no"], { listStyle: builder.ListStyle.button });
},
function (session, results) {
if (results.response.entity == "yes"){
session.send("some text");
}
else if (results.response.entity == "no"){
session.send("some text");
}
session.beginDialog('/nextDialog');
}
]);
This seems to be a known issue
https://github.com/Microsoft/BotBuilder/issues/4387
I have a bot dialog which asks a user for an order id:
bot.dialog("orderId", [
(session, args, next) => {
return builder.Prompts.text(session, "Please provide order id");
},
(session, results, next) => {
const matched = results.response.match(/\d{3}-?\d{7}/g);
if (matched) {
// ...
session.endDialogWithResult(matched);
} else {
// ...
}
}
]);
This works as expected when user enters a valid order id and has validation
code which is omitted.
The problem i am facing is that users from time to time upload a screenshot
of the order id which triggers a default action which is just to re-prompt with a system prompt.
I know i can use retryPrompt property if the IPromptOptions interface, but this does not solve my issue.
I want to be able to start another dialog or end the conversation.
Any ideas how should i make this work ?
Edit:
In another case instead of saying "Yes" or any other positive phrase, user replies to Prompts.text with a "Thumbs Up" image from Facebook Messenger. which will also break Prompts.text flow.
I want to be able to treat the "Thumbs Up" image as a positive answer
to my question and control conversation flow according to that.
As build-in Prompts will create a individual dialog, and Prompts.text() will verify the user input strictly for string type only, when you upload an image file to bot, which will not be verified by Prompts.text() dialog, and that raises your issue.
You can consider to add an step for your user to choice one approch to verify the code (by inputing code string, or uploading code picture).
var bot = new builder.UniversalBot(connector, [
(session) => {
const choices = ['code', 'image'];
var msg = new builder.Message(session)
.text("Which will you prefer to provide your code?")
.suggestedActions(
builder.SuggestedActions.create(
session, [
builder.CardAction.imBack(session, "code", "By Code"),
builder.CardAction.imBack(session, "image", "By Image")
]
)
);
builder.Prompts.choice(session, msg, choices);
}, (session, args, next) => {
const type = args.response.entity;
session.send(`Your choice is ${type}`);
if (type == 'code') {
session.replaceDialog('verifyCode')
} else {
session.replaceDialog('verifyAttachmenet')
}
}
]);
bot.dialog('verifyCode', [(session) => {
builder.Prompts.text(session, 'Input your code');
}, (session, args, next) => {
session.send(args.response);
session.endDialog();
}])
bot.dialog('verifyAttachmenet', [(session) => {
builder.Prompts.attachment(session, 'update your image');
}, (session, args, next) => {
session.send(`You upload ${args.response.length} images`);
session.endDialogWithResult(args.response);
}])
I am trying to call a dialog in the bot which has to go to specific function, Here is the scenario...
I have a dialog bot as shown below
bot.dialog('/Welcome', [
function(session){
builder.Prompts.text(session, "Welcome to the Bot");
},
function (session, args) {
// Has some code
},
function (session, args){
//has some code
}......
When ever i do replace dialog ie.
bot.replaceDialog('/Welcome')
it should not go to the first function ie. Welcome to the Bot It should skip this and go to next function.
Is there any way to accomplish this in azure bot?
This is quite simple if you look at their article
https://learn.microsoft.com/en-us/azure/bot-service/nodejs/bot-builder-nodejs-dialog-replace
Their example is like below
// This dialog prompts the user for a phone number.
// It will re-prompt the user if the input does not match a pattern for phone number.
bot.dialog('phonePrompt', [
function (session, args) {
if (args && args.reprompt) {
builder.Prompts.text(session, "Enter the number using a format of either: '(555) 123-4567' or '555-123-4567' or '5551234567'")
} else {
builder.Prompts.text(session, "What's your phone number?");
}
},
function (session, results) {
var matched = results.response.match(/\d+/g);
var number = matched ? matched.join('') : '';
if (number.length == 10 || number.length == 11) {
session.userData.phoneNumber = number; // Save the number.
session.endDialogWithResult({ response: number });
} else {
// Repeat the dialog
session.replaceDialog('phonePrompt', { reprompt: true });
}
}
]);
So yours would be something like below
bot.dialog('/Welcome', [
function(session, args, next){
if (!args || args.prompt)
builder.Prompts.text(session, "Welcome to the Bot");
else
next();
},
function (session, args) {
// Has some code
},
function (session, args){
//has some code
}......
and you will call it like below
bot.replaceDialog('/Welcome', {prompt: false}))
I use following method to ask question by bot when user connects first time. But after user answering the question, instead of going to next step bot goes to new dialog.
This works fine with emulator, but not with directline api.
bot.on('conversationUpdate', function (message) {
if (message.membersAdded) {
message.membersAdded.forEach(function (identity) {
if (identity.id === message.address.bot.id) {
bot.beginDialog(message.address, '/startConversation');
}
});
}
});
bot.dialog('/startConversation', [
function (session) {
builder.Prompts.text(session, 'I\'m the SPF VA Assistant. How may I address you?');
},
function (session, results) {
session.userData.name = results.response;
session.send('Hi, %s, Please choose one of the options below to lodge a Police report.', session.userData.name);
var cards = getReportsAsCards();
var reportOptions = new builder.Message(session)
.attachmentLayout(builder.AttachmentLayout.carousel)
.attachments(cards);
session.send(reportOptions).endDialog();
}
]);
After you send the question "Please choose one of the options below..." you are calling endDialog(). This is what causes it to go to the new dialog like you said.
If you want to prompt the user for input, use a Choice Prompt, and add another step in your waterfall dialog to handle the user's choice input.
For example, to get the user's name, first ask the question using a text prompt, then handle the user's response in step 2 of the waterfall dialog. The user's response text will be available in the results.response object in step 2.
bot.dialog('greetings', [
// Step 1
function (session) {
builder.Prompts.text(session, 'Hi! What is your name?');
},
// Step 2
function (session, results) {
session.endDialog('Hello %s!', results.response);
}
]);
To prompt the user with a series of choices use a waterfall dialog combined with a builder.Prompts.choice() call. For example:
var noiseComplaintName = "Noise Complaint";
var trashDumpingName = "Trash Dumping";
var weirdSmellName = "Weird Smell";
var trafficSignalName = "Traffic Signal";
var reportTypes = [
noiseComplaintName,
trashDumpingName,
weirdSmellName,
trafficSignalName
];
bot.dialog('pick-report-type', [
function(session) {
session.send('Choice prompt example:');
var promptOptions = {
listStyle: builder.ListStyle.button
};
builder.Prompts.choice(session, "What do you want to report?", reportTypes, promptOptions);
},
function (session, results) {
// handle response from choice prompt
var selectedReportType = results.response.entity;
switch (selectedReportType) {
case noiseComplaintName:
// handle response here
break;
case trashDumpingName:
// handle response here
break;
case weirdSmellName:
// handle response here
break;
case trafficSignalName:
// handle response here
break;
default
// handle response here
break;
}
}
]);
For a more detailed example that combines prompts with Rich Cards, check out the sample code: BotBuilder-Samples/Node/cards-RichCards on GitHub.
I'm trying to find a way exiting a CommandDialog dialog by a user when using back or cancel or otherwise changes their mind.
var startCommands = new builder.CommandDialog();
bot.add('/', [
function (session, results) {
session.send('Hello %s', session.userData.name);
// starting a dialog based on CommandDialog
session.beginDialog('/begin');
},
function (session, results) {
// This is where I want to be when dialog cancel of back is initiated by a user inside /begin
session.send("you are back at the main dialog, start finshing process")
session.beginDialog('/finish');
}
]);
// defining a dialog for CommandDialog class
bot.add('/begin', startCommands)
bot.add('/finish', finishCommands)
startCommands.matches('yo', [
function (session) {
session.send('yo-yo');
}
]);
startCommands.matches('tu', [
function (session) {
session.send('tu-tu');
}
]);
startCommands.matches('.*', [
function (session) {
session.send('any-any');
session.endDialog();
}
]);
To exit a dialog, CommandDialog or otherwise, use a triggerAction on a dialog handler that calls session.endConversation().
For example, here is an exit dialog which ends the conversation when the user sends the message exit or quit.
bot.dialog('exit', function (session) {
session.endConversation('Goodbye!');
}).triggerAction({ matches: /(quit|exit)/i });