React + Socket IO: Accessing the first message - javascript

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
}

Related

Problem with creating online user list with socket.io and React

I am trying to add a list of online users to my chat app, but I ran into this problem:
On the front end I emit the currently logged in user's name, and then update the state of my users array:
useEffect(() => {
if (Auth.loggedIn()) {
const { data } = Auth.getUserInfo();
socket.emit("user_connected", data.username);
}
// if I remove these brackets I get an infinite loop in my server
}, []);
useEffect(() => {
socket.on("online_users", (onlineUsers) => {
setUsers(onlineUsers);
console.log(users);
});
});
I created the user array in the back end using the emitted username:
const onlineUsers = [];
io.on("connection", (socket) => {
socket.join("public_chat");
console.log(`A user has joined the chat`);
socket.on("user_connected", (user) => {
const userExists = checkUserArray(user, onlineUsers);
if (!userExists) {
onlineUsers.push({ user, id: socket.id });
}
console.log(onlineUsers);
socket.in("public_chat").emit("online_users", onlineUsers);
console.log(`${user} is now online.`);
});
});
I opened two separate browsers with two different logged in users to test, and when I refresh the page on one browser, the other gets the updated online user list in real-time, but the browser I initially refreshed on has an empty array for the user state. Do I need to make a global state store using redux or something?

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);
})

Make a bot react to a message above it

I need a bot to react to a message above the user who sent the command. Right now the bot only reacts to the user who sent the command.
client.on('message', (msg) => {
if (msg.content === 'Boo Hoo') {
const reactionEmoji = msg.guild.emojis.cache.find(
(emoji) => emoji.name === 'BooHoo'
);
msg.react(reactionEmoji);
}
});
how would I modify/rewrite this code to make it react to a message above the user who sent the command? I'm thinking it might have something to do with MessageManager, and fetching messages but I don't know.
Here, use the .fetch() method:
message.channel.messages
.fetch({ limit: 2 }) // get the two latest messages in that channel (cmd and the one aaobve it)
.then((messages) => messages.last().react(reactEmoji)); // get last (second) entry and react to it

How to automatically join conversation in Microsoft web chat (bot framework)

I'm using https://github.com/Microsoft/BotFramework-WebChat/blob/master/README.md
I want the bot to receive a "join" message whenever the web-chat widget is displayed on the site.
The idea is that the human does not have to initiate the conversation. The bot can respond to somebody joining the conversation with a welcome message.
How is this possible?
This "Welcome feature" has been a long term discussion and topic since Webchat v3. It looks like it has been fixed 2 days ago with this pull request: https://github.com/Microsoft/BotFramework-WebChat/pull/1286
There is now a sample on how to do that, located here:
https://github.com/Microsoft/BotFramework-WebChat/blob/master/samples/15.d.backchannel-send-welcome-event/index.html
In a few words, the demo is the following:
(async function () {
// In this demo, we are using Direct Line token from MockBot.
// To talk to your bot, you should use the token exchanged using your Direct Line secret.
// You should never put the Direct Line secret in the browser or client app.
// https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
// We are using a customized store to add hooks to connect event
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
// When we receive DIRECT_LINE/CONNECT_FULFILLED action, we will send an event activity using WEB_CHAT/SEND_EVENT
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
value: { language: window.navigator.language }
}
});
}
return next(action);
});
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
Please note that due to the fact that this PR is quite new, it's not embedded in the latest release so you have to point to the master version of webchat.js file, not latest:
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
And it's working: your bot side is notified of an activity of type Event, where you will be able to reply to your user, before he typed anything:

Snapshot Always Undefined

So I am attempting to use Firebase cloud messaging to send push notifications to my app. However, it seems to fail continuously for some odd reason. I am using the onCreate method to listen for the creation of a node under a certain path. It is getting the UID from that info gathered in the onCreate method but then when I try to get the user info from a different node to grab the fcmToken so I can send the notification. It always says undefined.
My index.js looks like this:
//listen for reply notification and then trigger a push notification
exports.observeNotification = functions.database.ref('/notifications/{uid}/{commentId}/')
.onCreate(event => {
// Grab the current value of what was written to the Realtime Database.
//const notification = event.data.val();
console.log('User ID is: ', event.params.uid);
console.log('Comment ID Is: ', event.params.commentId);
return admin.database().ref('/users/' + event.params.uid).once('value', snapshot => {
var userWeAreSendingTo = snapshot
console.log('User ID is: ', userWeAreSendingTo);
console.log('FCM Token of that user is: ', userWeAreSendingTo.fcmToken);
var payload = {
notification: {
title: "",
body: snapshot.content
}
};
admin.messaging().sendToDevice(userWeAreSendingTo.fcmToken, payload)
.then((res) => {
// Response is a message ID string.
console.log('Successfully sent message:', res);
return true
})
.catch((error) => {
console.log('Error sending message:', error);
return true
})
})
})
This is a snapshot of the child node under the user node in my database.
"9mzAHeX3lcdzriPdC4TfbRTkaUm2" : {
"fcmToken" : "coC8uorosgc:APA91bGur2vvH4fwIProh87pUzVw0jYTOOFW3KfqWRVk4WdX0x8M1iBFwg28wM3tFyB5iRrowTWCZ_45oGwo0_7BFD6YvULE30NNZXxvE2O2XLjlLd_fqYwMfkndOqSUem2HqO-qvNcZ",
"profilePic" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/profile_images%2F832F8156-C14A-4EF3-86EB-D8F4CFC784E5.PNG?alt=media&token=b9d11ea1-8cb3-4d0f-b111-b0baf567ac7b",
"username" : "lol123"
}
This screenshot of the console log
enter image description here

Categories