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

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('')

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

How To Send A Discord.JS Startup Message To All Servers

I wanted to inquire on something I’ve been trying to do recently. I have a Discord.JS bot, and it’s pretty public (130+ servers), and I want it to send a message to any channel in every single server it’s in, when the bot starts up, the purpose is to create a “New Update” notification in one of the channels.
Please do not plan on doing this, as this will get you rate limited really quickly.
This is kind of possible. There is a problem, there is no default guild channel, so you cannot get their "main" channel just by their guild object. If you would want to do that you, would need them to select their channel and store that ID somewhere.
This is a simple solution, where you loop through every guild of your Discord client, and send some channel a message. You don't know what channel with this solution specifically, but you will send some channel a message if it is not a voice channel.
const Discord = require("discord.js");
require("dotenv").config();
// Creating our Client
const client = new Discord.Client();
// Event listener: when the bot is ready
client.on("ready", () => {
// Looping through every guild the bot is in
client.guilds.cache.forEach((guild) => {
// Getting one of their channels
let channel = guild.channels.cache.array()[2];
// Sending the channel a message
channel.send("Hey");
});
});
client.login(process.env.DISCORD_BOT_TOKEN);

Is there a way to make a discord bot detect if the author of the command is on a certain server? discord.js

I have a Bug report command that send me an email with the bug report (works good), but I want that the person that use were on the support server to contact him if I need more information. Is there any way to a discord bot detect if a user is in a certain server?
You could look at all the guilds the bot is in using client.guilds.cache and check if the user you want is in one or more of those guilds using guild.member().
client.guilds.cache.forEach((guild) => {
const member = guild.member(args[0]);
if (member !== null) {
message.channel.send(`${member!.guild.name} (ID: ${member!.guild.id})`);
}
});
If you're looking for checking the server when a user executes a command, you can just use message.channel.guild.id, which returns the ID of the server the command was used in. You can then compare it to a specific server ID.

Is the Bot Framework Emulator handling new members differently from Bot Framework Webchat?

According to this official sample project (https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/typescript_nodejs/13.core-bot/src/bots/dialogAndWelcomeBot.ts) I can identity new members and send them a welcome message using this (my code):
this.onMembersAdded(async (context) => {
const welcomeCardTemplate = require("../lib/data/resources/cards/welcomeCard.json");
const membersAdded = context.activity.membersAdded;
for (const member of membersAdded) {
if (member.id !== context.activity.recipient.id) {
const welcomeCard = CardFactory.adaptiveCard(welcomeCardTemplate );
await context.sendActivity({ attachments: [welcomeCard] });
}
}
});
It works great when using the emulator. As soon as I connect to the chat I get my welcome message, but when using the Chat on Azure or the WebChat it's not triggered until I first enter some kind of text input to the chat.
One thing I noticed is that when I'm using the emulator two activities are sent to the bot as soon as I connect to the chat, one that contains the Id of the bot and one that contains the Id of the user but when using the other chat options (Azure Chat and WebChat) only one activity is being sent (where the memberId is the same as the recipientId) so it never goes past the if-statement.
What am I missing here, why is only one activity being sent from the Azure Chat and WebChat?
At this time, WebChat and DirectLine behaves differently from the emulator in certain scenarios like the one you describe. There is an open issue for this particular situation where you can find more information.
As stated in the issue, there is a workaround to force the ConversationUpdate event which you can try and test if it suits your needs (I haven't tried myself).

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.

Resources