Socket IO Broadcast Emit sending to sender - javascript

I have an app where I need the users to be able to send a message. Right now, users can send a message and socket IO broadcasts the message, but the sender also receives. I need messages sent to go to everyone but sender
Current behavior: User A calls handleButton function, User A and User B receive broadcastMessage and console log guess
Wanted behavior: User A calls handleButton function. Only user B receives broadcastMessage and logs guess
Server code:
io.on("connection", (socket) => {
socket.on("upGuess", (guess, room) => {
if (room) {
socket.to(room).emit("broadcastMessage", guess);
} else {
socket.broadcast.emit("broadcastMessage", guess);
}
});
});
Client side Code:
socket.on("broadcastMessage", (guess) => {
console.log(guess);
});
const handleButton = () => {
socket.emit("upGuess", "TestGuess");
};

Related

Socket.io Client repeats event action multiple times from one emit

I am creating a simple diffie hellman demo with sockets and it seems that whenever my server emits any event, the client repeats it multiple times.
For example: On the client side whenever I add a message I emit this new message to the server like so.
const addMessage = (text) => {
var newMessage = {
id: nextID,
from: name,
message: text
}
socket.emit("send-message", newMessage);
setNextID(nextID + 1);
setMessages([...messages, newMessage]);
}
And then on the server side I add that message to the messages and emit the new bank of messages to the other clients.
// Send message to other person
socket.on("send-message", (message) => {
messages = [...messages, message];
console.log(messages, "Newline\n");
socket.broadcast.emit("receive-message", messages);
})
The clients receive it and updates their message bank. I console.log these actions.
socket.on("receive-message", (receivedMessages) => {
console.log("receieved messages");
setMessages(receivedMessages);
});
But when I send a message it console.logs it repeats it like 100 times??
This happens for a lot of my other client side events handlers, repeating a action more than once, from just one emit from the server.
Why does this happen and how can I stop it?
If you are using ReactJs, be aware that if you add the listener in your components, any time the component gets updated it will add a new socket listener and for example on second second render, you'll get 2 console.log s. So you must add the listener in your useEffect hook (componentDidMount in class component case).
And consider that even your components can be viewed a few times so then the listener will be duplicated. So you have to close your listeners on useEffect's return (componentWillUnmount in class component case)
So it must be like:
useEffect(() => {
socket.on("receive-message", (receivedMessages) => {
console.log("receieved messages");
setMessages(receivedMessages);
});
return () => {
socket.off("receive-message");
};
}, []);
try to change like:
client-side:
socket.emit(“your event name”, “msg”)
server-side:
var io = new require(“socket-io”)()
io.on(“connection”, (socket) => {
socket.on(“your event name”, (msg) => {
io.emit(“your event name”, msg)
})
})
try it out and it will be better :D
Just send the new message
Client
socket.on("receive-message", (receivedMessages) => {
console.log("receieved messages");
setMessages(prevMessage => [...prevMessage, receivedMessages]);
});
Server
socket.on("send-message", message => {
messages = [...messages, message];
console.log(messages, "Newline\n");
socket.broadcast.emit("receive-message", message);
})

React + Socket IO: Accessing the first message

I'm trying to create an auto reply after a user has sent his first message. I have no problems with the reply, it's just knowing when the a user has sent his first message (and first message only).
I have an USER prop that contains users id.
here is my hook that is responsible for the message sending
useEffect(() => {
if (socket) {
socket.on("msg", msg=> {
dispatch({
type: ACTIONS.MSG,
value: msg
});
});
in the reducer the messages is an array. So I've been thinking of just creating something like
PSEUDO CODE if (the user PROP.Type === 'userType1' && sends.message[0]) {
return autoReply
}

How to save proactive messages sent to the bot?

I'm sending message to my bot using Microsoft BotConnector but they are not being logged as normal messages. For logging messages to the DB I wrote custom logger :
class CustomLogger {
/**
* Log an activity to the transcript file.
* #param activity Activity being logged.
*/
constructor() {
this.conversations = {};
}
logActivity(activity) {
if (activity) {
console.log("Log information")
}
if (!activity) {
throw new Error("Activity is required.");
}
if (activity.conversation) {
var id = activity.conversation.id;
if (id.indexOf("|" !== -1)) {
id = activity.conversation.id.replace(/\|.*/, "");
}
}
if (activity.type === "message") {
Conv.create({
text: activity.text,
conv_id: activity.conversation.id,
from_type: activity.from.role,
message_id: activity.id || activity.replyToId
}).then(() => {
console.log("logged");
});
delete this.conversations[id];
}
}
}
it works great with normal messages but it is no working with the messages that are sent to
POST /v3/conversations/{conversationId}/activities
via microsoft bot connector.
When I send message using the the bot connector it doesn't log the request via activity.
Code that I'm using to send proactive msg:
/**
* Send message to the user.
*/
function sendMessage(token, conversation, name) {
var config = {
headers: { "Authorization": "Bearer " + token }
};
var bodyParameters = {
"type": "message",
"text": name
}
axios.post(
'https://smba.trafficmanager.net/apis/v3/conversations/29:XXXXXXXXXXXXXXX/activities',
bodyParameters,
config
).then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
});
}
let name = "Hey, How was your week?";
let conversation = "29:XXXXXXXXXXXXXXX";
run(conversation, name);
Instead of using the REST API to send proactive messages to users, I would recommend using the BotFramework Adapter to continue the conversation with the user. When you send the proactive message from the adapter, the activity passes through the logger middleware and gets saved to storage. If you would like to initiate the proactive message from an Azure Function, you can set up another messaging endpoint in the index file that you call from the function. Take a look at the code snippets below.
index.js
// Listen for incoming notifications and send proactive messages to user.
server.get('/api/notify/:conversationID', async (req, res) => {
const { conversationID } = req.params;
const conversationReference = conversationReferences[conversationID];
await adapter.continueConversation(conversationReference, async turnContext => {
await turnContext.sendActivity('proactive hello');
});
res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.write('<html><body><h1>Proactive messages have been sent.</h1></body></html>');
res.end();
});
For more details I would take a look at this Proactive Messages Sample. It is in the samples-work-in-progress branch and might change slightly, but it is a great example of how to configure your project to send a proactive message from a Restify endpoint.
Hope this helps!

Issue with socket.io updating component to show new message in chatroom

I am building a chat app with React, Node/Express and socket.io. I have my sockets successfully set to my express server via http.createServer. I have a listener on client and server listening for new messages coming into the chat room. Ideally, I want each instance of the chat to be updated when there is an additional message, like any chat room that ever existed :)
Now I have a successful listen between client and server. I know because of a console.log server-side. However, I am not re-rendering the chat component when I submit a new message from a different instance.
So my code in my client-side (again React) component is as follows and I am using the socket CDN with script tags in my index.html (script tags not shown):
Socket CDN here
var socket = io('')
So that is the socket you see client side :
componentDidMount() {
return axios.get(`api/messages`)
.then((result) => {
if (result.data.length) {
this.setState({
messages: [ ...this.state.messages, ...result.data]
} , () => {
console.log("The state after messages are mounted : ", this.state)
})
}
})
.catch((err) => { throw err})
socket.on('new message', msg => {
this.newMessage(msg);
})
};
newMessage(msg) {
this.setState({
messages: [...this.state.messages, msg]
}, () => {
this.setState({ message: '' })
return this.scrollToBottom()
});
};
onSubmitMessage(event) {
event.preventDefault();
const content = this.state.message;
const msg = {
content,
createdAt : new Date(),
userId : "one",
chatRoomId : "two"
}
axios.post(`api/messages/`, msg)
.then(() => {
this.newMessage(msg);
socket.emit('new message', msg); //HERE'S THE SOCKETS IN ACTION
})
};
Here is the server-side code Node/Express:
//in server.js
const io = new socketIo(server)
require('./socketEvents')(io);
const connections = [];
Then a separate file for my socket events
//in socketEvents.js
module.exports = (io) => {
io.on('connection', (socket) => {
console.log("Beautiful sockets are connected")
socket.once('disconnect', () => {
console.log("socket is disconnected");
});
//DOESN'T DO ANYTHING YET
socket.on('join global', (username) => {
socket.join(username);
console.log("New user in the global chat : ", username)
});
socket.on('new message', (msg) => {
console.log("The new message from sockets : ", msg);
socket.emit('new message', msg.content);
});
});
}
My sockets server side are linked up with the client. I'm just not seeing new messages in different instances. Is it because I'm not re-rendering after the server receives the message?
Thanks in advance, please let me know if you need me to clarify anything.
Cheers!
I figured it out... I'm going to leave this post up with a walkthrough in an attempt to help others who are having trouble with sockets. I may post a blog about it. Will update if I do.
So the code listens on the client side for a message to be sent inside of my onSubmitMessage function.
onSubmitMessage(event) {
event.preventDefault(); //prevents HTML <form> from going on its own post
const content = this.state.message;
//Create message object
const msg = {
content,
createdAt : new Date(),
userId : "one",
chatRoomId : "two"
}
//HERE'S THE IMPORTANT PART!!!
axios.post(`api/messages/`, msg)
.then(() => {
// wrapped in a promise, send a handler to server called
// ('new message') with the message object
this.newMessage(msg);
socket.emit('new message', msg);
})
.then(() => {
//Another promise then waits for the handler to come back from server
//*****IMPORTANT*************
//Then invoke newMessage function to get the post on all sockets
socket.on('message', (msg) => {
this.newMessage(msg);
})
})
};
Now on the server side this is what's happening:
// This is where the listener is for the client side handle
socket.on('new message', (msg) => {
// broadcast.emit will send the msg object back to client side and
// post to every instance expcept for the creator of the message
socket.broadcast.emit('message', msg);
});
SO the data path is (C) for client, (S) for server:
receive message object from user and -------->
(C)socket.emit('new message') -----> (S) socket.on('new message') -------> (S) socket.broadcast.emit('message') --------> (C)socket.on('message')
Back in the client side, I can invoke my newMessage function, which will set the message to state so I can display it.
I hope someone finds this useful! Surprisingly, this seems to go relatively unanswered on Stack. If anyone has any questions feel free to ask!

Why is my Wit.ai messenger bot parsing its own responses?

I'm building my first FB Messenger chat bot using Wit as the NLP engine. All my services are connected and seem to be working on the surface, but when I look at my Heroku logs it seems that my bot's responses are being sent back to Wit to be parsed as well as user inputted messages. This is obviously causing issues further through my conversation flow when it comes time to trigger actions.
How do I make it so that my bot only parses user input, then responds appropriately according to my story in Wit?
Messenger window:
Relevant part of my Wit conversation flow:
My logs:
As far as I can tell, this is the important code:
var actions = {
say (sessionId, context, message, cb) {
// Bot testing mode, run cb() and return
if (require.main === module) {
cb()
return
}
console.log('WIT HAS A CONTEXT:', context)
if (checkURL(message)) {
FB.newMessage(context._fbid_, message, true)
} else {
FB.newMessage(context._fbid_, message)
}
cb()
},
...
}
///
var read = function (sender, message, reply) {
console.log('READING LOG AAAAAAAAAAAAAAAAAAAAAA')
var sessionId = findOrCreateSession(sender)
console.log('READING LOG BBBBBBBBBBBBBBBBBBBBBB')
console.log(message)
// Let's forward the message to the Wit.ai bot engine
// This will run all actions until there are no more actions left to do
wit.runActions(
sessionId, // the user's current session by id
message, // the user's message
sessions[sessionId].context, // the user's session state
function (error, context) { // callback
console.log('READING LOG CCCCCCCCCCCCCC')
if (error) {
console.log('oops!', error)
} else {
// Wit.ai ran all the actions
// Now it needs more messages
console.log('READING LOG DDDDDDDDDDDDDDDD')
console.log('Waiting for further messages')
// Updating the user's current session state
sessions[sessionId].context = context
console.log('READING LOG EEEEEEEEEEEEEEEE')
}
})
}
///
app.post('/webhooks', function (req, res) {
var entry = FB.getMessageEntry(req.body)
// IS THE ENTRY A VALID MESSAGE?
if (entry && entry.message) {
if (entry.message.attachments) {
// NOT SMART ENOUGH FOR ATTACHMENTS YET
FB.newMessage(entry.sender.id, "That's interesting!")
} else {
// SEND TO BOT FOR PROCESSING
console.log('SENDING TO BOT FOR PROCESSING XXXXX')
Bot.read(entry.sender.id, entry.message.text, function (sender, reply) {
FB.newMessage(sender, reply)
return
})
console.log('SENDING TO BOT FOR PROCESSING YYYYY')
}
}
res.sendStatus(200)
})
When you create your Facebook messenger app, one of the webhooks events is message_echoes.
Make sure you you opt it out message_echoes for not receiving your own bot messages.
I used the 'is_echo' : true to discern wits messages from others and it's been working.
if (event.message.is_echo) {
console.log(`This sender is the wit bot.`);
return;
}

Categories