I am building a bot with the Bot Dialogs extension, but i'm having an issue on a Waterfall Dialog in my project. If the user says to the bot "i want to enter a new message" the bot will respond with a series of questions like "when do you want the message to be delivered to the user", "what do you want the message to say", etc. What i'm searching for is that when the user is asked for a date, if it responds "tomorrow" luis will return the respective date, but if the user says "foo" the bot will ask for a date again.
What i've come to do this is a code like this:
public class NewMessageDialog : ComponentDialog
{
private readonly BotStateService _botStateService;
private readonly BotServices _botServices;
public NewMessageDialog(string dialogId, BotStateService botStateService, BotServices botServices) : base(dialogId)
{
_botStateService = botStateService ?? throw new ArgumentNullException(nameof(botStateService));
_botServices = botServices ?? throw new ArgumentNullException(nameof(botServices));
InitializeWaterfalls();
}
private void InitializeWaterfalls()
{
var waterfallSteps = new WaterfallStep[]
{
DateToSendStep,
ExpirationTimeStep,
BodyContentStep,
SummaryStep
};
AddDialog(new WaterfallDialog($"{nameof(NewMessageDialog)}.mainFlow", waterfallSteps));
AddDialog(new DateTimePrompt($"{nameof(NewMessageDialog)}.dateCreation")); //tb
AddDialog(new NumberPrompt<double>($"{nameof(NewMessageDialog)}.expirationTime"));
AddDialog(new TextPrompt($"{nameof(NewMessageDialog)}.body.content"));
InitialDialogId = $"{nameof(NewMessageDialog)}.mainFlow";
}
private async Task<DialogTurnResult> DateCreatedStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync($"{nameof(NewMessageDialog)}.dateCreation", new PromptOptions
{
Prompt = MessageFactory.Text("What is the date you want to send the message?"),
RetryPrompt = MessageFactory.Text("Please enter a date")
}, cancellationToken);
}
private async Task<DialogTurnResult> ExpirationTimeStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["dateToSend"] = Convert.ToDateTime(((List<DateTimeResolution>)stepContext.Result).FirstOrDefault().Value);
return await stepContext.PromptAsync($"{nameof(NewMessageDialog)}.expirationTime", new PromptOptions
{
Prompt = MessageFactory.Text("What is the expiration time?"),
RetryPrompt = MessageFactory.Text("Please enter a decimal number")
}, cancellationToken);
}
private async Task<DialogTurnResult> BodyContentStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["expirationTime"] = Convert.ToDateTime(((List<DateTimeResolution>)stepContext.Result).FirstOrDefault().Value);
return await stepContext.PromptAsync($"{nameof(NewMessageDialog)}.body.content", new PromptOptions
{
Prompt = MessageFactory.Text("What is the message body?")
}, cancellationToken);
}
And so on...
I haven't come to a proper way to do this: I could ask LUIS twice (once in a validator to see if the intent is to set a date, and once in the next step to get the correct datetime from an entity), I could ask luis in the validator and then save it into a class property to finally get the date value from there... Is there an efficient way to do this?
Also I don't know anything about chat maker, I have seen it in another websites while searching...