Guild/server specific commands - discord

So what I would like to do is allow my bot to do different commands based on the server. For example, if I am in one server and type !rules it would show the rules for just that server and if I go into another server it shows other rules.

You can access the id of a guild when a message is sent by message.guild.id. After that you can access the guild object and do a lot with it by bot.guilds.get(id) or client.guilds.get(id)
So now you can start defining some variables in your actual code
/* Assuming you have a variable called cmd that stores the command called */
if (cmd === 'RULES') {
let guildId = message.guild.id;
let guild = bot.guilds.get(guildId); // or replace with client
// Rest of your code
}

You just need to compare Guild#id to the guilds ID. Then you can handle the command differently for each guild.

Related

Discord bot issuing roles based on member usernames

I'm creating a bot for the purpose of Discord moderation, one of the components of this bot is the following task:
"When every new user comes to server, his role by default will be #NotMember, but when he changes his server nickname to the "Nickname | (Real name)", for example, CoolPerson (Alex), then his role is automatically changing to the #Member".
The one way of doing this that I can see is to check if the username contains the brackets, if not then his role is old #NotMember.
Is there any another way to detect if server members have changed their name to a nickname? And is this actually possible?
I'm making this bot in JavaScript, but Python is also welcome here.
You can use the guildMemberUpdate event that is triggered whenever a member changes their name, with this you will have access to the guild member and their old/new username. Note that your bot will need to have the Server Members Intent
enabled on the developer portal.
Example in Discord.js:
client.on("guildMemberUpdate", function(oldMember, newMember) {
// oldMember is the old guild member object before the change, you
// can use it to fetch their old username.
// Add a role to the newMember object.
newMember.roles.add(YOUR_ROLE_HERE);
});

Discord.js, message.guild.owner returns null

I'm coding a server-info command for my discord bot, and I want to get the owner username or tag from the actual guild. I found a way to do it in discord js 11, but it's not working anymore under 12th version :
const guild = client.guilds.get(message.guild.id);
message.channel.send(message.guild.member(guild.owner) ? guild.owner.toString() : guild.owner.user.tag);
// if the user is in that guild it will mention him, otherwise it will use .tag
So in discord js 12, client.guilds.get isn't a function, and guild.owner returns null.
message.guild.owner.user.usernameis also returning Cannot read property 'user' of null.
I took a look at the documentation, and message.guild.owner seems to be a real property (https://discord.js.org/#/docs/main/stable/class/Guild?scrollTo=owner). So I don't know why it's returning null.
I'd recommend that you first get the guild and make sure that it's available before trying to modify or access it. Therefore, your bot won't hit any errors. Additionally, as far as I know, guild.owner returns null but there is a way around this. You can get the guild owner ID through guild.ownerID and fetch the member as a guildMember. Here is the code:
const guild = message.guild; // Gets guild from the Message object
if(!guild.available) return; // Stops if unavailable
await message.guild.members.fetch(message.guild.ownerID) // Fetches owner
.then(guildMember => sOwner = guildMember) // sOwner is the owner
message.channel.send(guild.member(sOwner) ? sOwner.toString() : guild.owner.user.tag);
This is how you would get the owner's tag when you have the guild. This also does not rely on the cache, so if your bot restarts or the cache is cleared, it will work regardless.
let ownerTag = undefined;
<client>.users.fetch(<guild>.ownerID).then(user => ownerTag = user.tag);
.fetch() returns a promise, which is why I declared a variable and then assigned the value to it.
Make sure you enable these intents in your discord developer portal so your bot could access your server
After that, you could access your user owner tag.

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

send DM to user specified by command arg in discord.js

I am making a bot for my server and want it to send a DM to a user, I know about message.author.send("Your message here.") but what I want is for it to be done via a command. E.G. !dm {user} {message}. how do i do that?
Once you parse your arguments you can use this code within your command (make sure this is inside of an async function).
let mention = args[1].match(/^<#!?(\d+)>$/)[1];
if (!mention) return message.channel.send('Invalid user.');
let recipient = await client.fetchUser(mention);
recipient.send(args.slice(2));

Using guilds and channels without needing to read a message

I'm hosting my bot on glitch.com, but it restarts every night.
When my bot gets started, it reads a message from a specific channel and then writes in the others. The problem with this is that I can't use any guild or channel until the bot receives a message.
How can I avoid doing this?
You can use guild and channel IDs. Every element in Discord has a unique ID (called Snowflake) that identifies it.
If you want to get a specific guild or channel, you can save its ID and use it in the code. IDs are public, so there's no risk using them (they're not like passwords or tokens).
Guilds and channels are stored in Collections and mapped by their IDs, so you can use them like this:
let guild = client.guilds.get('guild id as a string');
let channel = guild.channels.get('channel id as a string');
To get your guild's ID (or the ID of pretty much any element in Discord) you can enable the Developer mode in the settings, then right-click on the guild and select "Copy ID".

Resources