javascript- Wait till function finish before continuing - javascript

I'm building a chatbot. Some example of the chat scripts are as follows:
var convpatterns = new Array (
new Array (".*ask me a question*", Question1),
new Array ("I need (.*)" , "Why do you need $1?" , "Are you sure you need $1?"),
new Array (".*sorry.*", "Please dont apologise", "Apologies are not necessary", "it is ok, it didn't bother me")
);
So basically if the user types "ask me a question", it will direct the user to the Question1() function. And if the user types "I need a friend", the chatbot will reply by asking "why do you need a friend?" or "Are you sure you need a friend?".
function Question1(){
var textbox=document.getElementById("messages").value;
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Do you smoke?");
if (textbox="Yes"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Oh, do you know smoking is bad for your health?");
} else if (textbox="No"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"That's great to hear that you don't smoke!");
}
}
The window.ispeech.speak will allow the chatbot to verbally speak the words.
So when the chatbot asks the question, "Do you smoke?", and the user types either "yes" or "no" in the textbox, the chatbot then responds based on the reply.
What I want is for the Question1() function to finish running before the chatbot goes about and asks other things (so it waits for the user to type either "yes" or "no" before the function can be finished and a new script can begin), as I don't want the user's response to clash with the other scripts available in the arrays (e.g. the input "yes" to the textbox might clash with another "Yes" array in the script).

You actually need something like a state machine. But can always hold the current -let's say- command in a variable. Then you always check for the command to be finished. As long as a current command is not set to null(means no current command) you can not listen to another command. Each of you command should have at least one final state. It can be a value that will be entered by user. When the final state condition(s) of current command were meet you can set it to null.

Related

Discord.js - Secretly getting user input

I am making a 2-player rock-paper-scissors game using Discord.js.
Sadly the Discord API is really slow and afaik doesn't provide any type of middleware. When someone chooses their shape, the other person sees the reaction (or chat message) for quite a while until the bot deletes it, therefore ruining the whole game.
The only way of secretly getting an input I could think of, was sending the user a message in private chat, to which he can react. But having to switch from the server to private chat and then back to the server just makes the game unplayable in my opinion. It's just too much work for the user, compared to simply clicking a reaction.
Another option would be sending a message in the chat, which only a specific user can see. It could say something like "1 = Scissors, 2 = Rock, 3 = Paper". (The mapping would be randomized for each player). The user then picks the corresponding reaction from the options 1, 2 and 3.
But it seems, Discord does not allow to send a message in chat, which only a specific user can see. Or is there a way?
And is there any way of secetly getting user-input without the user having to switch chats?
Does the API maybe provide any kind of middle-ware for messages or reactions which I have overlooked?
Discord does not allow to send a message in chat, which only a specific user can see. Or is there a way?
No, there isn't. Discord API doesn't allow you to specify users that can see a specific guild message.
And is there any way of secetly getting user-input without the user having to switch chats?
There definitely is!
You could use a fairly new feature, buttons. Below is an example code, you can use to base your game on. Things left to implement are:
Gamestate, e.g. who is on turn, who has how much points, etc.
Update gamestates (identify gamestate by id?) in the interactionCreate event's callback.
Showing the gamestate to the players, e.g. updating the original message.
Don't allow players to modify the gamestate of other playing pairs.
Let the user specify an opponent in !createGame command.
The actual game logic (determining who won, who gets a point, etc.)
That is all I can think of for now. Take those more of a suggestions than requirements. There is no boundary to ones creativity.
// ... Some object to store the gamestates in? ...
client.on("messageCreate", async (message) => {
// Don't reply to bots
if (message.author.bot) return;
// Basic command handler, just for showcasing the buttons
if (message.content.startsWith("!createGame")) {
// ... Probably some argument handling for the opponent (e.g. a mention) ...
// Create an action row component with buttons attached to it
const actionRow = new Discord.MessageActionRow()
.addComponents(
[["Rock", "🗿"], ["Paper", "🧻"], ["Scissors", "✂️"]].map((buttonProperties) => {
return new Discord.MessageButton()
.setStyle("PRIMARY")
.setLabel(buttonProperties[0])
.setEmoji(buttonProperties[1])
.setCustomId(`rpsgame_${buttonProperties[0].toLowerCase()}`);
})
);
// Send the game message/playground
message.channel.send({
content: "Rock, Paper and Scissors: The game!",
components: [actionRow]
});
}
});
To handle the button clicks, we use the interactionCreate event.
client.on("interactionCreate", (interaction) => {
// If the interaction is a button
if (interaction.isButton()) {
// If the button belongs to our game
if (interaction.customId.startsWith("rpsgame")) {
// Log what the user has selected to console, as a test
console.log(`A user '${interaction.member.user.tag}' selected ${interaction.component.emoji.name}.`);
// Don't forget to reply to an interaction,
// otherwise an error will be shown on discord.
interaction.update("Update GameState...");
}
}
});
No one will see what the other users have selected, unless you want them to.
Using discord.js ^13.0.1. If you are on v12, there is a nice package called discord-buttons.

Is there any way to create a "Free-write" section for a Chatbot?

Quite new here and have been using Dialogflow and rasa to try making a chatbot for user reports, Stuck at a certain segment where I want the user to "report" to the bot what it has done for the day, regardless of the content the bot will reply with a "Thanks for your time" response and saves the user's response, I can't seem to figure this out, as the bot will try to analyze the layer of texts the user sends and then goes to default fallback intent....
You will need FormAction for free write action (given you don't want any intent for it).
In the actions.py, add following code
class FormFreeText(FormAction):
def name(self):
return "form_free_text"
#staticmethod
def required_slots(tracker):
return ["free_text"]
def slot_mappings(self):
return {
"free_text": self.from_text()
}
def submit(self, dispatcher, tracker, domain):
return []
In domain.yml, add following lines
slots:
free_text:
type: unfeaturized
responses:
utter_ask_free_text:
- text: "Please enter the text for your report"
actions:
- form_free_text
In stories.md, add the following lines where ever you want user input.
- form_free_text
- form{'name':'form_free_text'}
- form{'name':null}
There are some naming convenstions like using utter_ask to ask any question using FormAction.
I hope this helps.
In DialogFlow your option is to use a fulfilment which allows to drive the conversation logic using events, for example:
user answers what's wrong or good about the day
webhook receives the payload with the answer and the associated intent (or better define an action)
webhook triggers an event (EVENT_DONE)
the event (EVENT_DONE) belongs to an intent (THANK_YOU) which sends a response to the user
In Rasa the options are to either train an intent (inform) with training data (you can still capture/recognise what the user talks about) or use an FormAction where user input is captured in a slot (even if you don't really need to use/store it)

When using a string to call a function from another function, how would one go about it?

For clarity:
The user will never be expected to input code. User inputs, aside from name customization (which customized names will NEVER be run through code), will be limited to button presses (which will then potentially activate functions which are waiting in the database entries).
I have one defined constructor in my javascript code, and essentially will have a database which allows the user certain inputs, be they pre-defined inputs (the majority of the time) which will execute other code or customized inputs (which would never have the potential to change anything which can execute code).
An example would be the following code: new DatabaseItem("511", ["feat", "general", "1"], "Armor Proficiency", ["description", "if(database[5][0][0].returnData().includes(0)){possible=["500","Cancel"];database[5][0][0].forEach(function tempFunction(value,index){if(value==0){possible.push(index);}});}else{database[5][0][0].addTrait("invalid");alert("No eligible targets. Please select another feat.");}"])
which would create a new DatabaseItem at position 511 with traits "feat", "general", "1"; the title "Armor Proficiency"; and data of "description" and would execute the following code when triggered:
if(database[5][0][0].returnData().includes(0)) {
possible = ["500", "Cancel"];
database[5][0][0].forEach(
function tempFunction(value, index) {
if(value==0) {possible.push(index);}
}
);
} else {
database[5][0][0].addTrait("invalid");
alert("No eligible targets. Please select another feat.");
}
Then after the user selects a choice (be it "Cancel", or one of the valid indexes) supposing that choosing this was valid in the first place, it would then execute more code based on the user's choice.
Based on what I've read, the eval() function would work (but is generally considered unsafe) but Function() may also work. What would be the recommended course of action?
Relevant information:
-this is a stand-alone webpage-based application. The framework is provided in the html file, and this is an excerpt from the js file.
-nothing is stored after the webpage is closed. Save data is generated via a savestring which implements changes the user makes and the positions of said changes, which the user is then free to copy to a text file. Invalid savestrings would be rejected by the loader.

Discord bot conversation

I'm creating a discord bot that will run a function based on questions asked, of which multiple are yes/no questions. Answering "yes" will do a certain function while "no" should end the question.
I do not want the bot to run a random function every time it reads "yes".
The only solution I could think of is once the question has been asked (based on a word trigger), the user gets stuck in a loop where the bot will not respond to any trigger other than "yes" / "no".
If yes, the related function will run.
If no, the user gets out of the loop and is able to trigger another question.
Other than yes/no, the bot will say "please reply with yes or no"
How can I code this in node.js/discord.js?
If this is a command that the users must run to initiate this conversation...I recommend referencing this in the discord.js official documentaion that talks about awaitMessages. Basically, you could use this followed by a series of .then() and if statements that will take the user down multiple paths based on their answers that can be filtered out.
If this is a default function of the bot without needing a trigger command, I recommend you tread carefully in this area as something like this could be quite spammy.
An example:
message.channel.send('Is this a great bot?').then(async (start) => {
message.channel.awaitMessages(filter, { maxMatches: 1, time: 60000, errors: ['time']}).then(async (collected) => {
if (collected.first().content === "yes") {} else if (collected.first().content === "no") {}
})
You can filter messages with the filter or another way so that yes/no are the only acceptable answers.

Function not waiting till everything is executed before moving on

I am building a chatbot. I have a function as below:
function Smoking(){
var userinput=document.getElementById("messages").value
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Do you smoke?");
if (userinput=="Yes"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Oh no! Smoking is not good for your health!");
}else if(userinput=="No"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Good to hear that you are not smoking!");
}
}
The Smoking() function is called when user ask the chatbot to ask a question:
var convpatterns = [
[".*hi.*", "Hello there!","Greetings!"],
[".*ask me.*", Smoking],
["Yes","You seem quite sure.","OK, but can you elaborate a bit?"]
The window.iSpeech.speak plugin allow the system to speak the words and the plugin is installed correctly and works in other functions. However when the Smoking() function is called, the system only speak "Do you smoke?", and doesn't wait for user input. When user typed in the textbox "Yes" or "No", the system moves on and recognise the input text as the "Yes" array instead of the "Yes" within the Smoking() function. So if the user typed "Yes", the chatbot will say "You seem quite sure", instead of "Oh no! Smoking is not good for your health!"
So I was just wondering if there is a way for the function to wait till all lines are executed before moving on?
UPDATE
I've tried putting them into two separate function but it is still not working:
function Smoking(){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Do you smoke?");
SmokingAnswer()
}
function SmokingAnswer(){
var userinput=document.getElementById("messages").value
if (userinput=="Yes"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Oh no! Smoking is not good for your health!");
}else if(userinput=="No"){
window.iSpeech.speak(speakPluginResultHandler,nativePluginErrorHandler,"Good to hear that you are not smoking!");
}
}
The SmokingAnswer() function is not executed.
The way I understand it is, you want to ask the question to the user by voice, and the user should reply to it in the chat box.
For your application to work the proper way, you should separate it into multiple JS functions.
First function gets called when user enters the site, or focuses the chat box. This function will ask the question.
Then the user enters something, and lets say the function second runs after the user clicks a button. The second function would then check the input and evaluate the possible answer. "oh god no ..." / "good to hear..."
The way your function is designed, is this: once it runs it will ask the question, but it needs the answer already in the chatbox, which at that point is most probably empty since you havent asked the user yet.

Categories

Resources