Better strategy for bot posting messages to multiple channels with DiscordJs - node.js

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

Related

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

How to get all non bot users in discord js using a discord bot in nodejs

I have created a discord bot by taking reference from this digital ocean link.
Now I can send message to any channel using the bot but my requirement is to send dm to user of that server.
For that I have tried many SO answers and followed other links, but all the solutions end up to be same.
I have tried this two way to get the users of a guild and send dm to any one selected user.
1st way - Get all users of guild (server)
const client_notification = new Discord.Client();
client_notification.on('ready', () => {
console.log("Notification manager ready");
let guild = client_notification.guilds.cache.get("Server ID");
guild.members.cache.forEach(member => console.log("===>>>", member.user.username));
});
client_notification.login("login");
Output
Notification manager ready
===>>> discord notification
By this way it only returns me the bot name itself. Although the membersCount is 6.
2nd way - send dm to user directly (server)
client.users.cache.get('<id>').send('<message>');
It gives me undefined in output.
My configs,
Node version: 10.16.3
discord.js version: 12.5.1
My question is how to get all the guild members in discord.js?
Discord added privileged gateway intents recently. So to fetch all member data you need to enable that in the developer portal. After that you need to fetch all the members available, for that we can use the fetchAllMembers client option, and then we need to filter out bot users, so that we don't message them.
const client_notification = new Discord.Client({fetchAllMembers:true}); //Fetches all members available on startup.
client_notification.on('ready', () => {
console.log("Notification manager ready");
let guild = client_notification.guilds.cache.get("Server ID");
guild.members.cache.filter(member => !member.user.bot).forEach(member => console.log("===>>>", member.user.username));
});
client_notification.login("login");
The .filter() method filters out all the bots and gives only the real users.
You should avoid using fetchAllMembers when your bot gets larger though, as it could slow down your bot and use lots of memory.
I think the problem is related to updating the bot policy for discord. Do you have this checkbox checked in the bot settings?
https://discord.com/developers/applications
Some info about client.users.cache:
Its a cache collection, so if you restart bot, or bot never handle user message or actions before, this collection will be empty. Better use guild.members.cache.get('')

How do I make a bot say a certain message when it first joins a server?

I'm trying to make a discord bot say a certain message when it first joins a Discord Server, so when the bot first joins a Discord Server, it will say something along the lines of "Hello everyone....". I looked at a lot of sources but none seem to be JavaScript. Can anyone help?
client.on('guildCreate', joinedGuild => {
//Blah
}
Documentation for the guildCreate handler here.
You can set up an event listener to execute whenever it registers a new guild.
For example:
Client.on("guildCreate", guild => {
// Code to be executed whenever a new guild is registered
});
You can find out more here.

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).

"Bind" socket to user

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

Resources