Discord.js event updatePresence spamming - discord.js

I use the updatePresence event to log into the console when a user changes the status (online, dnd, etc.).
My problem is: If I change my status, the message is output 6 times in the console.
Does anyone have a solution for the problem?
user is now online
user is now online
user is now online
user is now online
user is now online
user is now online
user is now online

This may be because the user involved is in multiple Guilds in common with the bot.
presenceUpdate is fire by each guilds.
Try to output the guild name to see if your user Presence is from multiple guilds :
client.on("presenceUpdate", (oldPresence, newPresence) => {
if (oldPresence.status !== newPresence.status) {
console.log(`${newPresence.user.tag} user is now ${newPresence.status} in guild ${newPresence.guild.name}`);
}
});

Related

Is it possible to fetch the user inviting your bot?

When my Discord bot joins a guild, I want to send a private message to the member inviting the bot. I am using Discord.js.
Now, i know there is a guildCreate event i can use on the client, that fires when the bot joins a guild.
This event however, only provides the Guild the bot has been invited in.
I've seen multiple bots sending me private messages this way, so i know there must be a way. One could get the guild owner and send him private message, but there is a chance that the owner is not the one inviting the bot. And unfortunately, since i was always the owner when it happened, i can't say if it was this or not.
Is there a way to retrieve the GuildMember, or the User that invited the bot ?
This requires view audit log permissions for the bot:
let logs = await guild.fetchAuditLogs()
logs = logs.entries.filter(e => e.action === "BOT_ADD")
let user = logs.find(l => l.target?.id === client.user.id)?.executor
//user is the inviter

Discord, sending a message to a different category and channel depending upon which reaction is selected

I have been working on a way within my discord server to try to automate the flow of users who want to try out for a team using bots. Currently I have adopted YAGPDB and have a role menu created in a community level (category) #general_tryouts channel with reactions to specify which game they want to pursue. When they select a reaction they are assigned a temporary role (24 hours) which will grant them access to the game specific category #tryouts channel they've selected. I've been successful with getting all of the roles assigned using YAG's gui interface. However, I would also like for a message to be sent to the game specific #tryouts channel with an embed (similar to a welcome message) stating that they would like to tryout, to notify the 'team' that they are "in the queue". So the process would look something like this:
User A pops into (Some Community) #general-tryouts -> reads the menu asking them which team they want to tryout for and selects option 1 (':one:') -> User A is given the role for TempGame1 and can now see (Some Game) #tryouts AND simultaneously a message is sent to (Some Game) #tryouts on their behalf.
If they choose option 2 they will receive a TempGame2 role and a message should be sent to (Another Game) #tryouts.
If they choose option 3 they will receive a TempGame3 role and a message should be sent to (ThisOther Game) #tryouts.
YAGPDB has the option with it's custom commands to fire a command triggered by a reaction given in a certain channel by someone with a certain role. The issue is getting the result of which reaction they selected, and that dictating where the message is sent. I'm really not even concerned if it's just a generic message. I just want User A to be able to react at a 'community' level and a message to get passed in to (Some Game) #tryout, (Another Game) #tryouts, or (ThisOther Game) #tryouts based on their selection.
My apologies in advance. I am only proficient enough to code a simple I say "ping" you output "pong" sort of transaction, and got in a little over my head in short order. I have looked at the developer resources trying to piece something together to no avail, as well as pulling a similar snippet of code from here and attempting to modify it to suit my needs, also to no avail. Any help would be greatly appreciated.
Code Sample
if (reaction.message.id === '730000158745559122') {
let channel = reaction.message.guild.channels.cache.get(targetChannelId);
console.log(reaction.emoji)
if (channel) {
let embed = new Discord.MessageEmbed();
embed.setAuthor(
user.tag,
user.displayAvatarURL({
dynamic: true,
format: 'png',
}),
);
embed.setDescription(`${user} has react a: ${reaction.emoji}`);
channel.send(embed);
}
}
Visual Representation
New
in the code if (reaction.message.id === '730000158745559122') the 73000 portion represents that whole message as a focal point on what the bot is 'listening' for. Any reaction to it, be it 1, 2, or 3 will trigger this singular process. So by what you are saying by using the (id === 123 || id === 456 || id === 789) {} would likely be the way to go if I had more than one message is was 'collecting' on for a lack of better way to state it. I believe what I need to do is
`if (reaction(':one:').message.id === 123 {send message ('nifty embed')to channel.id 12345}
if (reaction(':two:').message.id === 123 {send message ('nifty embed') to channel.id 67890}
if (reaction(':three:').message.id === 123 {send message ('nifty embed') to channel.id 16273}`

Trying to implement Patreon-only commands/functions on my discord bot, how would I accomplish this?

My discord bot gives the role of 'Patreon' to my patreon supporters. This role is given on my main discord bot server. So right now I'm trying to write some commands that would be only available to users who have the role 'Patreon' in the BOTS discord server, how can I accomplish this?
Like is there a way I can be like -
message.member.has('Patreon Role').in('My Discord Server)?
Let's go over the tasks you need to accomplish this.
Get the "home guild" with your users and corresponding Patreon role.
See Client.guilds and Map.get().
Find the user in the guild.
See Guild.member().
Check whether or not the user has the Patreon role.
See GuildMember.roles and Collection.find().
You can define a function to help you out with this, export it and require it where you need it (or define it within relevant scope), and then call it to check if a user is one of your Patreon supporters.
Here's what this function would look like...
// Assuming 'client' is the instance of your Discord Client.
function isSupporter(user) {
const homeGuild = client.guilds.get('idHere');
if (!homeGuild) return console.error('Couldn\'t find the bots guild!');
const member = homeGuild.member(user);
if (!member) return false;
const role = member.roles.find(role => role.name === 'Patreon');
if (!role) return false;
return true;
}
Then, as an example, using this function in a command...
// Assuming 'message' is a Message.
if (!isSupporter(message.author)) {
return message.channel.send(':x: This command is restricted to Patreon supporters.')
.catch(console.error);
}
message.member.roles.find('name', 'Patreon Role');//this returns either undefined or a role
What that does is it searches the users collection to see if the have "Patreon Role"
If the message is on the same server, otherwise you could do
client.guild.find('name','My Discord Server').member(message.author).roles.find('name', 'Patreon Role'); //this also returns undefined or a role
Clearly that second option is long, but what is basically does is searches the servers the bot is in for a server called 'My Discord Server' then it finds the GuildMember form of the message.author user resolvable, then it searches their roles for the role 'Patreon Role'
There is a chance it will crash though if they aren't on the server(the documentation doesn't say if it returns and error or undefined for some reason) so if it does crash you could instead do
client.guild.find('name','My Discord Server').members.find('id', message.author.id).roles.find('name', 'Patreon Role'); //this also returns undefined or a role
You can read more here: https://discord.js.org/#/docs/main/stable/class/User
and here
https://discord.js.org/#/docs/main/stable/class/Client
and here
https://discord.js.org/#/docs/main/stable/class/Guild
To try and give a full example, assuming this is in your message event
if (message.member.roles.find(r => r.name === 'Patreon') == undefined &&
commandIsExclusive || message.guild.id !== 'this-id-for-BOTS-server') {
// Don't allow them in here
}
Essentially, to run a command they must be a supporter, in a specific server and if it is exclusive and the other criteria aren't met, they are denied

How to get username from client id after the user has left the guild

I have statistics. I am downloading from the User Id database and I am replacing the ID with its name, but if the user has left the server, there is an error because there is no such user.
I have bot.users.get(id) but when a user leaves the server, an error pops up.
Can I get the username with the ID differently if the user is not on the server?
Sorry for being late, like literally. You can perform a request to get a user from Discord by a UserResolvable with Client#fetchUser(<UserResolvable>);.
In practice, the code should look like this;
const Discord = require("discord.js");
const Client = new Discord.Client();
Client.login("YoUr.nIcE.toKe.n");
Client.on("ready", function () { // Should do that when the client is ready.
const User = Client.fetchUser("123456789012345678");
console.log(User); // Some user object.
});
Hope I helped you nonetheless.
~Q
Since client.users stores only cached users, you won't be able to retrieve their username in a reliable way from there.
DISCLAIMER: This method is really inefficient, but discord.js hasn't been made for this kind of work. If you want to make it easier, just write Unknown user (client_id)
If you're not able to get the username from a user list you could try to use messages: use channel.fetchMessages() on every channel of your guild until you find a message in which message.author.id == your_id, when you find it you can get the username with message.author.username
There's also another solution: a self-bot. Keep in mind that this one is not supported by Discord itself, and could result in a permanent ban for the account you're using.
With that said, if you use a self-bot you can use the TextChannel.search() method to quickly find a message with your author id and then grab the username from the author.

Using emotes to give roles Discord.js

In my discord server, as a verification method, I want my bot to have all users react to the message and then get given the verified role, and remove the old role. The current code I have doesn't grant or remove roles, but doesn't error.
client.on("messageReactionAdd", function(users) {
users.addRole(users.guild.roles.find("name", setup.verify));
users.removeRole(users.guild.roles.find("name", setup.default));
});
There is a problem in the current code. The messageReactionAdd event returns a User object, which does not contain the property .guilds which you attempt to access: users.guilds.r- .
Instead of this perhaps you should the id of the User object and plug that into message.guild.members.get("id here"). Then use the returned Member object with your current code. That should work!
References:
Guild Member
, Message Reaction Event, User Object
Would something like this work?
I'm not sure it will I haven't tested it. This should add the role if the message they reacted to consists of the word "role1" and if they react to a different message it will remove the role. I don't know if this is what you're going for but in theory this should work.
client.on("MessageReactionAdd", function(users) {
if (message.content === "role1") {
users.addRole(users.guild.roles.find("name", setup.verify))
} else if (!message.content === "role1") {
user.removeRole(users.guild.role.find("name", setup.default))
}
});
Are the names of the roles; setup.verify & setup.default?
If not, that's why it is not working.
Try:
client.on("messageReactionAdd", function(users) {
users.addRole(users.guild.roles.find("id", ROLEIDHERE));
users.removeRole(users.guild.roles.find("id", ROLEIDHERE));
});
where ROLEIDHERE put the role id to find the role id just tag the role and before you hit send put \ before the tag and it will supply the id

Resources