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 });
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 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 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");
}
}
]);
I have a single dialog which has multiple Prompts(Prompts.text, Prompts.number, Prompts.Choice, Prompts.confirm). Though Prompts.choice and Prompts.confirm seems to have inbuilt validations but how to validate Prompts.text?
I have gone through this thread How to handle wrong input from the user? but it was rectified by converting text into choice.
Also I do not want to restart the whole dialog as it ask the questions form beginning then as shown in create custom prompts to validate input
Here is shorter version for my dialog:
bot.dialog('/getDetails', [
function (session, args, next) {
let options = {
retryPrompt: 'The response id invalid'
}
builder.Prompts.text(session, 'What is your full name?', options);
//passing options as argument works for Prompts.choice, which seems an inbuilt validation
},
function (session, results, next){
var name = session.dialogData.name;
//How to to reprompt if user does not enters its full name?
if (results.response) {
name.fullname = results.response;
}
builder.Prompts.text(session, 'Can you please provide your country name?');
},
function (session, results) {
var name = session.dialogData.name;
//How to reprompt only last Prompts.text if user enter an invlid value?
if (results.response) {
name.text = results.response;
}
}
}]).triggerAction({
matches: 'GetDetails',
})
Here is how i solved it through DialogAction.validatedPrompt
bot.dialog('/getDetail', [
function (session) {
session.beginDialog('/validateAge', { prompt: "What's your age?" });
//if false response, then prmopts "I did not understand {age}""
},
function (session, results) {
if (results.response) {
session.send("Thank you for adding your age");
}
}
]).triggerAction({
matches: /^lets validate$/i
})
bot.dialog('/validateAge', builder.DialogAction.validatedPrompt(builder.PromptType.text, function (response) {
if(response> 0 && response < 70){
return response;
}
}));
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.