how to trace user reply to a specific chatbot message in node.js - node.js

I wonder how to catch a user reply to a specific chatbot question? I mean for example if the user asks the chatbot for the weather and the chatbot responds back by asking the user for in which city. I would then like to trace what the user responds to that question. So that the city could be used for calling a weather api for the city. I don't know how to track the user reply to that question. Does anyone know if and how this is possible?

So that multiple users can access the chatbot simultaneously, it's best to keep track of each user, and each user's conversation state. In the case of the Messenger API, this would be:
const users = {}
const nextStates = {
'What country are you in?': 'What city are you in?',
'What city are you in?': 'Let me look up the weather for that city...'
}
const receivedMessage = (event) => {
// keep track of each user by their senderId
const senderId = event.sender.id
if (!users[senderId].currentState){
// set the initial state
users[senderId].currentState = 'What country are you in?'
} else {
// store the answer and update the state
users[senderId][users[senderId].currentState] = event.message.text
users[senderId].currentState = nextStates[users[senderId.currentState]]
}
// send a message to the user via the Messenger API
sendTextMessage(senderId, users[senderId].currentState)
}
Then you will have the answer for each user stored in the users object. You can also use a database to store this.

..I solved it by setting a global variable when the chatbot asks the question
global.variable = 1;
When the user replies the incoming text message event is fired and I can check if the global flag is set. This indicates that this is the user reply after the question was asked. I can then get the message text city from that message. This works fine in my case but if anyone knows a better alternative please let me know

Related

Using the onUpdate function in firebase, how do I pass in information from the front end?

So basically, I have a function that sends a user an email when a room Status becomes "Available"
exports.sendAvailableRoomEmail = functions.firestore.document('rooms/{roomId}/Status').onUpdate(async (snap, context) => {
const newVal = snap.after.data();
const oldVal = snap.before.data();
if(newVal == "Available"){
// send email
}
})
what I need passed into the function is the specific room that the user wants a notification from: {roomId}
How can I pass that specific room only when the user clicks the notify me button right next to it?
The triggers for a Cloud Function needs to be known when you deploy that function. That means you can either trigger for all rooms, or you can trigger for a specific room, but you can't trigger for rooms that meet a dynamic condition such as yours.
The common way to implement the use-case is to query Firestore inside the Cloud Functions code to find if any user need to be notified for the specific room that was updated.

Pass User to Conversation

I want to have someone say to a bot in slack:
#Bot setup #usertosetup
This should then start a conversation with that user to be setup. If I'm right and I've read correctly, the one that starts the conversation with the bot will be the one it listens to?
So the flow would be to bring the new user, an admin and the bot into their own room on slack, then start the conversation. Ideally, would be if you could say in the main chat window that phrase and it starts a private message with the user to set up, but I don't think that's possible due to the channel not existing yet?
I'm using Botkit to get this done.
Solved it.
controller.hears('setup','direct_mention', function(bot,message) {
var x = message.text.indexOf("#");
var usr = message.text.substr(x - 2, message.text.length);
usr = usr.substring(3, usr.length - 1);
bot.api.im.open({user: usr}, function(err, response) {
bot.startConversation({
user:usr,
channel: response.channel.id
}, "Hello");
});
So, it finds the index of the message sent to the bot with the # symbol, pulls it out and does some substring fun to reduce it. Then, launches the conversation by the channel.

Private messaging a user

I am currently using the discord.js library and node.js to make a discord bot with one function - private messaging people.
I would like it so that when a user says something like "/talkto #bob#2301" in a channel, the bot PMs #bob#2301 with a message.
So what I would like to know is... how do I make the bot message a specific user (all I know currently is how to message the author of '/talkto'), and how do I make it so that the bot can find the user it needs to message within the command. (So that /talkto #ryan messages ryan, and /talkto #daniel messages daniel, etc.)
My current (incorrect code) is this:
client.on('message', (message) => {
if(message.content == '/talkto') {
if(messagementions.users) { //It needs to find a user mention in the message
message.author.send('Hello!'); //It needs to send this message to the mentioned user
}
}
I've read the documentation but I find it hard to understand, I would appreciate any help!
The send method can be found in a User object.. hence why you can use message.author.send... message.author refers to the user object of the person sending the message. All you need to do is instead, send to the specified user. Also, using if(message.content == "/talkto") means that its only going to run IF the whole message is /talkto. Meaning, you can't have /talkto #me. Use message.content.startsWith().
client.on('message', (message) => {
if(message.content.startsWith("/talkto")) {
let messageToSend = message.content.split(" ").slice(2).join(" ");
let userToSend = message.mentions.users.first();
//sending the message
userToSend.send(messagToSend);
}
}
Example use:
/talkto #wright Hello there this is a dm!

What is the right way to save/track state inside a Facebook Messenger bot?

If my bot asks different questions and if the user answers each of them, how do I find out which answer relates to which question. There is a field called metadata that you can attach to the sendTextMessage API but when the user responds, this metadata comes in as undefined. Do you guys use any node-cache for tracking state or an FSM such as machina.js? How can I best figure out at what of the conversation we are currently stuck in?
When your app receives a message, there's no payload or metadata associated with it. This is as opposed to a quick-reply or post-back which can have a payload. The only way to associate a response with a question this is to manually track the conversation state in your app as suggested by #anshuman-dhamoon
To do this, it's best to maintain a state for each user, as well as the next state for each state.
// optionally store this in a database
const users = {}
// an object of state constants
const states = {
question1: 'question1',
question2: 'question2',
closing: 'closing',
}
// mapping of each to state to the message associated with each state
const messages = {
[states.question1]: 'How are you today?',
[states.question2]: 'Where are you from?',
[states.closing]: 'That\'s cool. It\'s nice to meet you!',
}
// mapping of each state to the next state
const nextStates = {
[states.question1]: states.question2,
[states.question2]: states.closing,
}
const receivedMessage = (event) => {
// keep track of each user by their senderId
const senderId = event.sender.id
if (!users[senderId].currentState){
// set the initial state
users[senderId].currentState = states.question1
} else {
// store the answer and update the state
users[senderId][users[senderId].currentState] = event.message.text
users[senderId].currentState = nextStates[users[senderId.currentState]]
}
// send a message to the user via the Messenger API
sendTextMessage(senderId, messages[users[senderId].currentState])
}
Note If you wanted, you can even make the values of nextStates into callable functions that take the answer of the current state and branch off into different conversation flows by passing the user to a different state depending on his/her response.
As per my knowledge,in Facebook chatbot you can send data from user to chatbot just by setting payload from postback buttons as they have given in API reference.
And chatbot won't store your session or any states/flags.you can set status or flags or arrays but all will be lost when you update your application or restart your server.
so,if you really want to set status you should use database for that.and senderID will remain same everytime so you can handle data from database by that particular id for particular user.
For more details checkout technical referance here.
I hope this will help you.if so,kindly mark it as an answer.
You can have a status code in your code, to keep track of where the user conversation with the bot is.
For eg. if you have 10 questions, keep statuscode = 0 initially, and ask the first question. When you receive a message to your webhook, check if statuscode==0, and store that user message as a response to your first question. Then increment statusCode=1 and ask the next question.
You can have multiple flags and statusCodes to deal with different conversation flows.
I'm running into this issue myself. Though it hasn't been mentioned at all in their documentation, I don't think attaching an in-memory database is out of the question. It seems that the user_id is the same regardless of when the conversation is initiated.
Making an API call every time the user rejoins the session would probably slow down the performance of the bot. Also, I noticed that you can't really construct a "pseudo-distributed database" by using the metadata key in the API if that is what you were suggesting. The metadata tag can be sent from Server -> Client (Messenger) but not from Client -> Server from what the documentation says.
I've spent some time working with this. The best solution is to use a database to track the user's conversation flow. The POST object contains the senders ID. You can use this ID to make a row in the database in which you'd definitely need to store this ID, any answers to the questions, and a field to keep track of of which step in the conversation.
Then you can use if statements in your code to return the proper responses. Some example code below:
if( $currentStep == '1' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your name?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
} elseif( $currentStep == '2' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your email address?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
} elseif( $currentStep == '3' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your address?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
}

Facebook Messenger Bot, can someone tell me how i catch the answer of a something i asked

So i working on my Facebook Messenger Bot.
I want to know ho can i catch a answer for a question like
Bot: Enter your E-mail
User: enters e-mail
Bot: adress was added
My code looks like the sample app from Facebook
app.post('/webhook', function (req, res) {
var data = req.body;
// Make sure this is a page subscription
if (data.object == 'page') {
// Iterate over each entry
// There may be multiple if batched
data.entry.forEach(function(pageEntry) {
var pageID = pageEntry.id;
var timeOfEvent = pageEntry.time;
// Iterate over each messaging event
pageEntry.messaging.forEach(function(messagingEvent) {
if (messagingEvent.optin) {
receivedAuthentication(messagingEvent);
} else if (messagingEvent.message) {
receivedMessage(messagingEvent);
} else if (messagingEvent.delivery) {
receivedDeliveryConfirmation(messagingEvent);
} else if (messagingEvent.postback) {
receivedPostback(messagingEvent);
} else {
console.log("Webhook received unknown messagingEvent: ", messagingEvent);
}
});
});
// Assume all went well.
//
// You must send back a 200, within 20 seconds, to let us know you've
// successfully received the callback. Otherwise, the request will time out.
res.sendStatus(200);
}
});
You can set a flag for their ID that the E-Mail prompt was sent, and then after they respond check to see if it's an E-mail, and if so, then save it and echo it back to them.
If the bot is based on question/answer, what I normally do to handle response tracking is treat the bot like a finite state automata. Assign every "state" your bot can be in to some unique state identifier, and use said state identifier to determine what the user is replying to. You could also store callbacks instead of state ids, but high level this will behave the same way.
For Example:
First define a finite automata. In this case, lets assume it's:
0 --> 1 --> 2
Where 0 means new user, 1 means waiting for email response, 2 means user successfully completed registration.
User messages bot
We check our database and see it's a new user. We assume
state==0.
Because state is 0, we ignore what was sent and prompt for email
Change state to 1 to denote the email was prompted.
User replies with email.
We check database and see state==1. We use the "1" routine to do fancy stuff to verify the email and store it.
Change state to 2 to denote the email was received and the program has ended.
Note:
If the conversation id for the platform you're targeting is reset
after a certain amount of inactivity (or if you just want the bot to
mimic real conversations), store the time of each user's last
interaction and purge all inactive conversations well after the
conversation has been terminated.

Resources