it used to be possible in botkit to dynamically generate the quick_replies field on the message object when inside of a conversation. now, the only path i can find to doing this is by leveraging custom events / event system and doing a global bot.say.
when starting a conversation, in the beforeHook, where you could potentially fetch some dynamic data, try to set variables and then in the .addQuestion step, try to use those variables to dynamically create quick replies. it doesn't seem possible.
This is currently tricky. There is no official way of tapping into the message as it passes through the conversation in order to mutate the template for this purpose. I am honestly not 100% sure how to do this with BotkitConversation right now -- though it is certainly something we need to figure out!
One possibility:
Could introduce a special case where if the quick_replies field is a string it could be interpreted as a template tag or the name of a key where replies are found, for example:
// some way to point at a variable
message.quick_replies = '@replies'
// later
convo.setVar('replies', [dynamic_quick_replies]);
OR, perhaps less magical if we add a new property like message.quick_replies_source which would inherently be treated as a key name containing the quick replies.
One concern I have is: are there other elements that should also be treated this way? Like for example attachment cards?
I think you raise a couple of really good points. On one hand I like the idea of "expanding" the templating abilities of botkit to include dynamic quick_replies with convo.setVar('replies', // dynamic stuff) and then latermessage.quick_replies = @replies`. On the other hand I think that functionality would be just as useful with attachments, etc.
At the end of the day, being able to attach dynamically "fetched" JSON to a message adhoc is what is truly valuable here imho. And, if I could get the ability to have it automatically map to how botkit has handled quick_replies in the past, even better 馃帀
@wolfejw86 nice find and definitely a must feature, I am also facing a similar restriction in migrating to 4.0 version @benbrown your concern is valid. The other elements like attachments should also have the capability of dynamic generation.
For our startup's use case, we use a lot of custom fields and data whenever bot replies to the user hence we had to generate the bot question objects dynamically depending on conversation flow. We were able to achieve on the older version by using convo.transitionTo( on the handler functions which is no more available.
@benbrown do you think the current Botkit version can overcome this problem by changing the behaviour of how conversation objects are loaded and executed? Pass a function to .addQuestion as parameter which returns the type as BotkitMessageTemplate ?
convo.addQuestion(getBotkitMessageTemplate(), [], "default","default");
Currently, the getBotkitMessageTemplate() function is executed when the conversation is loaded but not when the actual question/s are asked. This feature would add a lot of flexibility & dynamicity to the Botkit project.
Hello,
Any update regarding this?
What if:
First arg of dialog ask would be string | BotkitMessage | (results: object): BotkitMessage ?
I think, if we would have the possibility (similiar with controller.hears) to dynamically construct the question, that would solve the problem.
from
dialog.say("How are you today, {{vars.name}}", (...) )
to
dialog.say(vars => ({
text: `How are you today, ${vars.name}`,
quick_replies: [
{
title: "Good",
payload: "good"
},
{
title: "Awesome",
payload: "awesome"
}
]
}), (...))
Side note
Would it be possible, to make this function async? Sometimes, we need to ask remote services based on the user's previous input, so this should handle Promise<BotkitMessage>
@wolfejw86 , @benbrown What do you think guys?
@benbrown Can you check this solution?
5e180fc
I'll take a look asap!
Here's where I landed with this:
In 4.5, you will be able to pass in an async function for quick_replies, blocks, and attachments that are then responsible for generating the actual content.
The signature of these functions is all basically the same:
async (line, vars) => { return [stuff]) }
line is the actual template of the message passed in to convo.say or convo.ask or whatever, and vars is the _current_ state of convo.vars whenever the function is called.
This way, there are no new methods or magical keys or special tokens or whatever! I'd love to hear any feedback anyone has!
Most helpful comment
Here's where I landed with this:
In 4.5, you will be able to pass in an async function for quick_replies, blocks, and attachments that are then responsible for generating the actual content.
The signature of these functions is all basically the same:
async (line, vars) => { return [stuff]) }line is the actual template of the message passed in to convo.say or convo.ask or whatever, and vars is the _current_ state of convo.vars whenever the function is called.
This way, there are no new methods or magical keys or special tokens or whatever! I'd love to hear any feedback anyone has!