"Bind" socket to user - node.js

I'm fairly new to sockets and wanted to give an existing application a few realtime elements, like notifications. I'm using SailsJS (and Passport with local strat) and wanted a service which can be called like
Notification.send(userID, message);
This would also be a pretty cool way for all other kinds of realtime events (private messages, ...). But what I need to know is how to "bind" a socket to a UserID.
Any ideas or articles (couldn't find anything on Google - probably because I don't know what exactly to search for...)? Thanks.

Assuming you have the pubsub hook enabled (it's enabled as long as you don't see pubsub: false) in your .sailsrc, You can have a client subscribe to their own user model like this so they will receive any notifications sent to their userId:
User.findOne(userId).then(function (me) {
User.subscribe(req.socket, me, 'message');
})
Then you can call this to send notifications to a specific user in controllers:
User.message(recieverUserId, {type: "message", data: notification});
Just change type to whatever is relevant like type: "new Match" and send the appropriate data.
Edit: basically, .message() is the sails pubsub library's way of sending notifications to the subscribed Model. you could also pass an array of users into User.subscribe

Related

Better strategy for bot posting messages to multiple channels with DiscordJs

I am trying to execute bot functions from a node express server and it seems the best option is the DiscordJs package (correct me if I'm wrong for this use-case). For example, a user takes some action on my web application that would grant them a role to access different channels. The DiscordJs docs all seem to focus on actions like this being prompted from the discord server through bot commands or detecting changes with members.
I would like to execute bot functions from my express server by instantiating one client, logging that client in, and executing functions from the server. Something to the effect of
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
client.on("<some event on express server>", (event) =>{
//event actions
});
client.login(token)
Is DiscordJs the right tool for this use case? Should I be using something other than Discord.Client to do this? Any suggestions/input would be appreciated.
DiscordJs is a great package, I have a fair amount of experience using it.
For your use case I think it would work great.
client.on(event, function) will only take Discord events as event arguments. These are listed here:
https://discord.js.org/#/docs/discord.js/stable/class/Client
You could however use events from your web server using something similar to below
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
yourWebServer.on("yourEvent", (event) => {
client.doSomething()
}
client.login(token)
The main problem to tackle if you wish to use the discord client in this way is identifying the Guild/Message/Role/Whatever you want to change.
Normally, discord bots react to messages so they have access to a lot of data very quickly. In the below example, the bot can get a great deal of information from the message data alone, like the author, the guild it was posted in, the roles in that guild etc. You can see a list of properties here: https://discord.js.org/#/docs/discord.js/stable/class/Message
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
client.on("messageCreate", (message) => {
client.doSomething()
});
client.login(token)
If you plan to use this discord bot on just 1 server messing around with your friends or whatever (i do this a lot), you can find your server's Guild ID and hardcode it somewhere into your bot. You can then fetch all roles/messages/users/whatever as you wish.
For any wider usage you'd have to get the context from somewhere else, e.g. inputting ids on a form on your web server.
Have a good read of the discord.js documentation, its very well made in my opinion. Get an idea of what information you want to access, and how you can access it. It will then be easier to determine what context you need to give the bot to find this information.
For those wondering how to use discordjs client commands outside of an event listener it is possible but requires diligent use of async/await. Check this thread for more insight https://github.com/discordjs/discord.js/issues/3100

Websocket vs SSE to implement a real time friend invitation system on React/Node

I would like to implement a system that allows users to add each other as friends and share data between them. I have gotten the authentication done and currently researching ways to do this real time. This project of mine is purely a learning experience so I am looking for many ways to perform this task to grow my knowledge.
I have experience using Websockets on a previous project and it was easy to use. Websockets seems like the best solution to my problem as it allows the user to send and receive invites through the open socket. However I have also learnt that the downside would be a long open socket connection that might be potentially performance taxing(?) Since I'm only sending/receiving information only when an invite is sent/received, websockets might be overutilized for a simple function.
At the same time I would like to learn about new technologies and I found out about Server Sent Events that would be less performance heavy(?) Using SSE would be much efficient as it only sends HTTP requests to the clients/server whenever the user send the invite.
Please correct me if I'm wrong for what I typed out above as this is what I gathered through my reading online. So now I'm having a hard time understanding whether SSE is better than websocket for my project. If there are other technologies please do let me know too! Thank you
how you doing ?
The best advise would be always to use websocket in this context, cuz your project can grow and need some feature that would be better using websocket
But you got another options, one of the is Firebase, Yes, FIREBASE!
You can do a nice reactive application with firebase, becouse the its observers update data in realtime, just like the websockets do.
But here go some cons and pros.
Websocket: Can make your project escalable, its more complete, you can use it in any context, BUT: is hard to implement and takes more time to be learned and understood.
Firebase, Easy and fast to implement, you can do a chat in 20 minuts, and surelly would help you with your problem, There is Firestore and Reatime database.. even the firestore updates in realtime.. BUT: Firebase costs in a big project can be expensive, i dont think is a good option for a big project.
Thats it.. the better options to do a real time data application to me.
A little bit more about. Firebase vs Websocket
https://ably.com/compare/firebase-vs-socketio
to send a friend invitation, you just send an API request. WebSocket is used for real time communication. From react.js, get the email and send the email to the server
export const sendFriendInvitation = async (data) => {
try {
return axios.post("/friend-invitation", data);
} catch (exception) {
console.error(error)
}
};
On node.js side, write a controller to control this request:
const invitationRequest = async (req, res) => {
// get the email
const { targetMail } = req.body;
// write code to handle that same person is not sending req to himself
// get the details of user who sent the email
const targetUser = await User.findOne({
mail: targetMail.toLowerCase(),
});
if (!targetUser) {
return res
.status(404)
.send("send error message");
}
// you should have Invitations model
// check if invitation already sent.
// check if the user we would like to invite is our friend
// now create a new invitation
// if invitation has been successfully created, update the user's friend
return res.status(201).send("Invitation has been sent");
};

recommended way to implement request-password-reset in Loopback

To implement password reset request in loopback (send email to the user with reset link), we need to handle the event resetPasswordRequest.
This is a possible implementation below
Client.on('resetPasswordRequest', function(info) {
var options = {
type: 'email',
to: info.email,
from: '....',
...
};
Client.email.send(options, function(err, res) {
if (err) console.log(err);
});
});
With this approach, if an error occurs it is simply logged to the console. Throwing an error that won't be handled doesn't feel like a better solution either.
Why is it not mentioned in the docs to use an afterRemoteHook to add this logic or even create a new custom endpoint ? Both solutions seem better at handling errors.
I think your code is based on example application, isn't it? If so, this approach is used by developer of example application but is not required implementation. You may use any other appropriate solution and one is that what you've mentioned in your question.
As for emitting event - it has it's advantage. You emit event and immediately send response to request. So client app will not wait until email sending part will send email - this can take from seconds to tens of seconds.
You may implement email sending log and make another request to it while user is waiting for password reset email thus notify him if any error will occur.
From the other hand this is only example but not required implementation for using in production.

How to send a message to all subscribed users with kik bot

I'm just a beginner trying to learn how to write a bot for kik.
I'm trying to write it with the node js framework that kik has provided.
I want to send a message to all subscribed users of the bot; I found this in their docs:
bot.send(Bot.Message.text('Hey, nice to meet you!'), 'a.username');
but I'm confused as to how they get the username of the subscribed user. I tried using bot.getUserProfile.username, but it seems to be undefined.
Thanks for any help! Also, any tips on how this bot works would be appreciated! I have no web development experience; why does this bot have to be on a server?
First of all, if you want to send a blast to all of your users, I'd recommend using the broadcast API, which allows you to send messages by batches of 100 (instead of 25 for the regular send() API).
You can use the broadcast API like this:
bot.broadcast(Bot.Message.text('some message'), ['username1', 'username2']);
Documentation for this method can be found here.
As for sending messages to all of your users, you will need to have a list of usernames somewhere (in a database, for example). At the moment, Kik does not provide a way to get your list of subscribers.
Something like this would work:
bot.use((msg, next) => {
let username = msg.from; // Find the username from the incoming message
registerInDatabase(username); // Save it somewhere
next(); // Keep processing the message
});
You will need to make sure that this is placed before you declare any other handler (such as bot.onTextMessage(), for instance).

Trying to broadcast socket.io message to all connected sockets in e.g. room

Challenge:
I would like to use SailsJS, and be able to join a room, by means of socket.io, and receive unsolicited messages from this room, not just when one enters or leaves the room but also receive objects.
So several clients connect to the server.
Afterwards broadcast (initiated from the server) messages/objects to every room and thus everey connected socket in this room.
I maybe could just send every connected socket a message, but dearly would like a example on how to do this with SailsJS 0.10, and a elegant method in the SailsJS 0.10 way.
I am looking at : https://github.com/balderdashy/sailsChat, but I think this is to close to the models themselves, with like e.g: autosubscribe: ['destroy', 'update']
In my opinion this should be more loosely coupled, and not so tied to the model itself.
Thanks in advance!
I.
The purpose of the SailsChat example is to demonstrate how Sails JS resourceful pubsub can take a lot of hassle out of socket messaging when you are mainly concerned with sending messages about models. The fact that you can make a full-featured chat app in Sails with very little back-end code is what makes it impressive. For situations where resourceful pubsub is not appropriate--or if you just plain don't want to use it--Sails exposes lower-level methods on the sails.sockets namespace. The docs are pretty clear on how they work.
To join a socket to an arbitrary room, do sails.sockets.join(<socket>, <roomName>), where <socket> is either a raw socket (probably from req.socket or a socket ID).
To broadcast a message to all sockets in a room, do sails.sockets.broadcast(<roomName>, <data>).
These and more methods are described in detail in the Sails JS documentation.
I'm just starting with SailsJS, and already a big fan.
I need to find out if this is also scalable with e.g. Heroku or other flavors of SAAS providers, but seems not that hard.
So just a follow up on what I did with SailsJS 0.10:
Server-side:
Made a controller with the following:
join: function (req, res) {
if (req.isSocket === true) {
sails.sockets.join(req.socket, 'mysecretroom');
return res.send(200, 'joined');
}
return res.send(200);
},
sendToRoom: function( req, res ) {
if (req.isSocket === true ) {
sails.sockets.broadcast('mysecretroom', 'messageevent', {message:'Listen very carefully, I'll shall say this only once..!'});
}
return res.send(200);
}
Client-side:
io.socket.on('messageevent', function (data) {
console.log(data);
})
+1 kudos #sgress454!
Thanks!

Resources