Get a list of users in a socket.io chat - reactjs

I'm currently working on a socket.io based chat application.
I found a LOT of tutorials on how to manage messages, but I'm struggling with the users list.
I'd like to display a list of connected users, with a few twists:
When a user joins the chat, he has to pick a name
Once he has picked a name, he can talk, and see a list with the names of other users
I'm struggling with this last part: for the messages, its quite easy, I can fetch the existing messages in my database. But how can I retrieve and display the list of connected users ?
I tried with the following pieceo f cade, in my react application:
const [players, setPlayers] = useState([])
const [step, setStep] = useState('lobby')
const socket = socketIOClient(ENDPOINT);
useEffect(() => {
socket.emit('data', {
type: 'joinedRoom',
})
socket.on("FromAPI", data => {
if (data.type === 'newPlayer') {
setPlayers([{
name: data.payload.name,
}])
}
if (data.type === 'joinedRoom') {
socket.emit('data', {
type: 'getPlayers',
players,
})
}
if (data.type === 'getPlayers') {
if (data.players && data.players.length) {
setPlayers([...players, data.players])
}
}
});
But this doesn't work: for any new user, the players state fragment is initialized as an empty array.
I'm fairly new to websockets in general, any help about how to handle data-sharing would be greatly appreciated :)

Are you using nodejs on your backend?,if so than u can either create a users arrry,and push new user into tht array when ever a new user is connected.thn u can access tht anytime,dont forget to delete user whn disconnected

Related

Accessing the collection inside a document of a parent collection in firestore

I am looking to fetch the data of collection named users which has documents with an id of logged-in users' uid. Further, these documents contain some data and a subCollection called posts.
which looks like -
So now, I need to fetch all four(4) of these documents along with the posts collection data together so that I can display it.
My approach -
( here I fetched the document ids - middle section of image IDs)
// Fetching Firestore Users Document IDs
const [userDocs, setUserDocs] = React.useState([]);
React.useEffect(() => {
try {
const data = firestore.collection('users')
.onSnapshot(snap => {
let docIDs = [];
snap.forEach(doc => {
docIDs.push({id: doc.id});
});
setUserDocs(docIDs);
})
}
catch(err) {
console.log(err);
}
}, [])
Now, I have tried to fetch the entire data using the following way (which isn't working)
// Fetching Firestore Posts Data
const [postData, setPostData] = useState([]);
React.useEffect(() => {
try {
userDocs.map(data => {
const data = firestore.collection('users/'+currentUser.uid+'/posts')
.onSnapshot(snap => {
let documents = [];
snap.forEach(doc => {
documents.push({...doc.data(), id: doc.id});
});
setPostData(documents);
})
})
}
catch(err) {
console.log(err);
}
}, [])
Finally, I should end up with postData array which I can map on my card component to render all posted images and captions to the UI.
I am not sure if this is the right way to achieve what I am doing here, please help me correct this error and if there's a more subtle and easy way to do it please let me know. Thank You.
I have tried to fetch the entire data
Looking at the code you wrote for fetching "the entire data" (i.e. the second snippet) it seems that you don't need to link a post document to the parent user document when fetching the post documents. In other words, I understand that you want to fetch all the posts collection independently of the user documents.
Therefore you could use a Collection Group query.
If you need, for each post document returned by the Collection Group query, to get the parent user doc (for example to display the author name) you can do as explained in this SO answer, i.e. using the parent properties.

Discord.js Filter Discord Events From Only 1 Server

I am working on trying to filter events for only 1 server rather than all servers the bot is in, but I'm trying to figure out how to exactly save each guild the bot is in as an collection so I can just filter events based on a guild ID I desire. Is this even possible? This is a snippet of the code I have to date, it's able to display the server names and ID's the bot is currently in, the events are working properly but triggering for all servers rather than the one I desire, how would I go about filtering for one guild collection?
const Discord = require('discord.js')
const bot = new Discord.Client()
const config = require('./config.json')
bot.on('ready', () => {
console.log(`Logged in as ${bot.user.tag}!`);
//Sets Activity
//client.user.setStatus('invisible')
bot.user.setActivity("Discord Cooks", { type: "WATCHING"})
console.log("Set User Activity!");
//Online Webhook
const webhookClient = new Discord.WebhookClient('','');
const embed = new Discord.MessageEmbed()
.setTitle(`${bot.user.tag} is online`)
.setColor('#FFFF00')
.setTimestamp()
webhookClient.send(embed);
bot.guilds.cache.forEach((guild) => {
console.log(guild.name, guild.id);
});
});
bot.on("channelCreate", (channel) => {
console.log(`channelCreate: ID: ${channel.id} Name: ${channel.name}`);
});
bot.on("channelUpdate", (oldChannel, newChannel) => {
console.log(`channelUpdate -> ${oldChannel.name} to ${newChannel.name}`);
});
bot.on("channelDelete", (channel) => {
console.log(`channelDelete: ID: ${channel.id} Name: ${channel.name}`);
});
bot.login(config.bottoken)
You can only execute code if event happened on exact server in much easier way:
if(guild.id == "GUILD_ID") {
// code
}
Also as #MrMythical said, you can just use if (message.guild.id !== "GUILD_ID") return; if you only need to run your code for 1 guild!

React Firebase make new Collection on button click

Hellooo ! I would like to make a chatroom (similar to Instagram) in my app. I'm working with react and Firebase and now I'm wondering how to write a function that makes ChatRoom2, ChatRoom3, etc. when you click on the "Add Chat" button?
I figured the best way to structure the db is to go with this structure :
ChatRooms (collection)
ChatRoom1 (document)
Messages (collection)
...
ChatRoom2 (document)
Messages (collection)
...
But I'm not sure how to write the function.
To create a collection you just need to add a document in that CollectionReference.
// The button to create new chat
<button onClick={createNewChat}>
const createNewChat = async () => {
const newChatDoc = await addDoc(collection(db, "ChatRooms"), {
...newChatFields
});
const firstMsgDoc = await addDoc(collection(db, "ChatRooms", newChatDoc.id, "messages"), {
content: "Welcome to Chat."
});
console.log(`New chat created: ${newChatDoc.id}`)
}

MongoDB Webhook function to save forminput in database

I've been trying to save data from my form in my MongoDB for some time.
I also get a response from the database.
See also: create object in mongo db api onclick sending form
Unfortunately there are not enough tutorials in my mother tongue and I don't seem to understand everything in English.
I've tried some of the documentation, but I always fail.
What is missing in my webhook function so that the form data can be stored?
exports = function(payload) {
const mongodb = context.services.get("mongodb-atlas");
const mycollection = mongodb.db("created_notifications").collection("dpvn_collection");
return mycollection.find({}).limit(10).toArray();
};
The Webhookfunction was totally wrong.
READ THE DOCUMENTATION FIRST
exports = function(payload, response) {
const mongodb = context.services.get("mongodb-atlas");
const requestLogs = mongodb.db("created_notifications").collection("dpvn_collection");
requestLogs.insertOne({
body: EJSON.parse(payload.body.text()),
query: payload.query
}).then(result => {
})
};

Firebase onDisconnect not deleting user name on disconnection

Perhaps I am mis-using onDisonnect(), but I looked at the example code on the firebase.blog and am doing my best.
When a user submits a user name, I call the code below, which adds the username to a firebase db. Then on disconnection, I want the username to be deleted from the db. This would mean that the db would only show users that are connected to the app at that moment in time.
I am doing it this way so I can then call the data and then map through the array to display currently logged-in users.
I have made two attempts in deleting the name, which you can see in the code below under con.onDisconnect().remove();, neither of which work the way I need. That said, if I log in once again from the same computer, the first user name replaces the second user name!
Here is my code
setName = e => {
e.preventDefault()
let name = this.state.name;
let connectedRef = firebase.database().ref('.info/connected');
connectedRef.on('value', function (snap) {
if (snap.val() === true) {
// Connected
let con = myConnectionsRef.push();
myConnectionsRef.set({
name
})
// On disconnect
con.onDisconnect().remove();
myConnectionsRef.orderByChild('name').equalTo(name).once('child_added', function (snapshot) {
snapshot.ref.remove();
// var nameRef = firebase.database().ref('users/'+name);
// nameRef.remove()
})
}
});
Where am I going wrong? Is there a better way to use onDisconnect? From the example on the fb forum, it isn't clear where I would put that block of code, hence why I am attempting to do it this way.
Thanks.
If I understand correctly what is your goal, you don't need to do
myConnectionsRef.orderByChild('name').equalTo(name).once('child_added', function (snapshot) {
snapshot.ref.remove();
// var nameRef = firebase.database().ref('users/'+name);
// nameRef.remove()
})
as the onDisconnect().remove() call will take care of that.
Also, as explained in the blog article you refer to (as well as shown in the doc):
The onDisconnect() call shall be before the call to set() itself. This is to
avoid a race condition where you set the user's presence to true and
the client disconnects before the onDisconnect() operation takes
effect, leaving a ghost user.
So the following code should do the trick:
setName = e => {
e.preventDefault()
let name = this.state.name;
const connectedRef = firebase.database().ref('.info/connected');
const usersRef = firebase.database().ref('users');
connectedRef.on('value', function (snap) {
if (snap.val() === true) {
// Connected
const con = usersRef.child(name); //Here we define a Reference
// When I disconnect, remove the data at the Database location corresponding to the Reference defined above
con.onDisconnect().remove();
// Add this name to the list of users
con.set(true); //Here we write data (true) to the Database location corresponding to the Reference defined above
}
});
The users node will display the list of connected users by name, as follows:
- users
- James: true
- Renaud: true

Resources