How to get all guilds where a member is in? - discord

I know how to get all members from a guild but I need to do the opposite operation : Getting all the guilds (IDs) where a specified member is registered in.
When fetching user like this client.users.cache.get(memberID); I don't see anything in the result that can allow me to see all the member's guilds :
User {
id: '706498754712807398',
system: null,
locale: null,
flags: UserFlags { bitfield: 0 },
username: 'johndoe',
bot: false,
discriminator: '1023',
avatar: null,
lastMessageID: null,
lastMessageChannelID: null
}
Any suggestion ?

You can do this by using the following code:
const userID = '3383083830389'; // the ID of the user
const guilds = client.guilds.cache.filter((guild) => guild.members.cache.has(userID));
and guilds is a Collection of guilds where the user is in. This has two limitations :
you can only get the guilds where the bot is in too
this won't work if the member is not cached (this can be resolved by trying to fetch the member in each guild)

You cannot view servers that a user is in that you do not have access to the account. This is a Discord limitation and falls under the privacy category, you don't want to do this anyways as it can be used maliciously.
The only way you can access the guilds a user is in if you are logged in as that account, otherwise without logging into that account, you cannot see what kind of servers they are in.
But if you want to check what kind of servers your bot is in, the code is quiet simple.
const allGuilds = (client.guilds.cache)
console.log(allGuilds)
I have not tested this myself, but it should point you in the right direction.

Related

Trouble sending DM to Message to stored user in DB discord.js

So Im making a ticket command and when you say .new it will open a channel and store message.author so it can dm you a transcript later on when you close it. When I log Console.log(message.author) and the stored person in the db, the message.author has User before the brackets and in the db it does not. Also the db has more lines while message.author has less:
MEMBER: {
id: '708457617013342249',
system: false,
locale: null,
flags: 128,
username: 'chuli',
bot: false,
discriminator: '0001',
avatar: 'a_483669232f603ee04c099c0449e8dc6a',
lastMessageChannelID: '829491485866065971',
createdTimestamp: 1588979858402,
defaultAvatarURL: 'https://cdn.discordapp.com/embed/avatars/1.png',
tag: 'chuli#0001',
avatarURL: 'https://cdn.discordapp.com/avatars/708457617013342249/a_483669232f603ee04c099c0449e8dc6a.webp',
displayAvatarURL: 'https://cdn.discordapp.com/avatars/708457617013342249/a_483669232f603ee04c099c0449e8dc6a.webp'
}
MESSAGE.AUTHOR User {
id: '708457617013342249',
system: false,
locale: null,
flags: UserFlags { bitfield: 128 },
username: 'chuli',
bot: false,
discriminator: '0001',
avatar: 'a_483669232f603ee04c099c0449e8dc6a',
lastMessageID: '842016982039134249',
lastMessageChannelID: '841958995890667530'
}
So I get an error when trying to send to the stored db user:
member.send(pembed).catch()
^
TypeError: member.send is not a function
Ive been breaking my head over this so I hope someone has the answer to this out there!
The reason they have different amount of lines is because they are two different things. message.author is a User, but what's stored in the db is a GuildMember. What's the difference?
The reason that message.author has User in front of it is that it's a class. What's in the db was originally a class, and would've been logged with GuildMember in front of it, however you unfortunately cannot keep classes in quick.db. Nor should you want to, as it would take up an insane amount of storage. Methods such as #send are only available on the GuildMember class (as opposed to the GuildMember class turned into an object by quick.db), so you can't access it from the db.
Instead, store the user ID in the db, as it's a unique identifier and you can get the user from it without storing huge objects in a db. You can use client.users.fetch(id) to get the user.
// await db.set('channel_id', 'author_id');
const id = await db.get('channel_id');
const user = await client.users.fetch(id);
user.send(...);
Ok I fixed thanks to #Lioness100
Heres what I did
const memberid = db.fetch(`ticket_${message.channel.id}`)
const user = message.guild.members.cache.find(c=> c.id === memberid)
Works fine! :) Thanks for helping guys.

How to give a role to all members, with a interval

I want to make a command so i can give all the users in my discord server a role.
Problem is now with the code i have, that he gives not all the members the specified role because it are to much members and it will spam the discord api.
How can i make it so that after i do the command, the bot will give all the members the specified role, but not directly to prevent spamming the API, but for example every 10 min he gives 5 members the role until all the members got the role.
Hope some one could helpe me
this is what i have now :
module.exports = {
name: "give-roles",
aliases: ["gr"],
category: "roles",
description: "Give's all members the Verified-Member role",
usage: `${prefix}give-roles`,
run: async (Client, message) => {
message.guild.members.fetch()
.then(console.log)
.catch(console.error);
let role = message.guild.roles.cache.find(r => r.name === 'Verified-Member')
if (!role) return message.channel.send(`**${message.author.username}**, role not found`)
message.guild.members.cache.filter(m => !m.user.bot).forEach(member => member.roles.add(role))
message.channel.send(`**${message.author.username}**, role **${role.name}** was added to all members`)
},
}```
A way to get round this is to add a role when a member joins instead of all at once (which will never work since not all members will be cached)
<client>.on('guildMemberAdd', member => {
var memberRole = member.guild.roles.cache.find(role => role.name === "<role name here>");
member.roles.add(memberRole); //auto assign role on join
});
change the code in <> to fit your needs
The reason you cannot add a role to all members is due to the v12 addition of cache.
Managers/Cache
v12 introduces the concept of managers, you will no longer be able to directly use collection methods such as Collection#get on data structures like Client#users. You will now have to directly ask for cache on a manager before trying to use collection methods. Any method that is called directly on a manager will call the API, such as GuildMemberManager#fetch and MessageManager#delete.
I would recommend that you read the docs to further understanding of how bots work here

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

Creating channel permission overwrites

I am creating a bot command so that when you type !setup it sets up the whole server (creating channels and roles, etc). I have already set it to create the roles and channels but there are some channels that only specific roles can type in, whereas, other roles can only read the channel. I don't know how to set up permission overwrites for certain roles.
I have already looked on the Discord.js documentation and it doesn't help much. I receive an error that supplied parameter was neither a user nor a role, but I don't know how to gain the role ID.
message.guild.createRole({
name: 'Admin',
color: '#2494ad',
permissions: ['ADMINISTRATOR', 'VIEW_AUDIT_LOG', 'MANAGE_GUILD', 'MANAGE_CHANNELS', 'SEND_TTS_MESSAGES', 'CREATE_INSTANT_INVITE', 'KICK_MEMBERS', 'BAN_MEMBERS', 'ADD_REACTIONS', 'PRIORITY_SPEAKER', 'READ_MESSAGES', 'SEND_MESSAGES', 'MANAGE_MESSAGES', 'EMBED_LINKS', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY', 'MENTION_EVERYONE', 'USE_EXTERNAL_EMOJIS', 'CONNECT', 'SPEAK', 'MUTE_MEMBERS', 'DEAFEN_MEMBERS', 'MOVE_MEMBERS', 'USE_VAD', 'CHANGE_NICKNAME', 'MANAGE_NICKNAMES', 'MANAGE_ROLES', 'MANAGE_WEBHOOKS', 'MANAGE_EMOJIS']
});
message.guild.createRole({
name: 'Requesting Role',
color: '#1bb738',
permissions: ['READ_MESSAGES', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY',]
});
//Categories and Channels
message.guild.createChannel('clan-communications', {
type: 'category',
permissionOverwrites: [{
id:'25311096',
deny: ['SEND_MESSAGES']
}]
});
//Permissions
message.channel.overwritePermissions('25311096', {
SEND_MESSAGES: false
});
break;
I would like roles to have base permissions for the whole server. But certain roles have overwrites for different channels. Instead it says the supplied parameter was neither a user nor a role.
First and foremost, welcome to Stack Overflow. Hopefully we can be of help to you.
Let's walk through a solution step by step to achieve your desired result.
When you create your roles, you should declare a variable to store them. That way, you can use what the client just created later on. Since Guild.createRole() returns a promise, we can save the fulfilled result into a variable.
Note that the keyword await must be placed in async context (within an async function).
const vip = await message.guild.createRole('VIP', { ... });
Then, when you need to use that role, you can refer to the variable.
await message.guild.createChannel('VIPs Only', {
type: 'category',
permissionOverwrites: [
{
id: vip.id,
allow: ['READ_MESSAGES']
}, {
id: message.guild.defaultRole.id, // #everyone role
deny: ['READ_MESSAGES']
}
]
});
If the role already exists, you can retrieve it from the Collection of roles returned by Guild.roles.
const testRole = message.guild.roles.get('IDhere');
const adminRole = message.guild.roles.find(r => r.name === 'Admin');
Other simple improvements.
In your code snippet, I don't see any error handling. The methods you're using return promises. If an error occurs in any, the promise state will become rejected. Any rejected promises that aren't caught will throw errors. To fix this, attach catch() methods to each promise (better for individual handling) or wrap async code in a try...catch statement.
When creating your Admin role, know that the ADMINISTRATOR permission automatically grants all other permissions (and allows users to bypass channel-specific permissions). Therefore, there's no need to list any other permission, or change the role's permission overwrites in any channels.
Your IDs in your code don't appear to be valid. Discord IDs are snowflakes, represented by strings of 18 digits. You can access them through Developer Mode in Discord. However, you shouldn't have to hard-code them with this solution, unless they already exist.
In the permissions array for your Requesting Role role, you have an extra comma.

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