Cache a guild user by id discord.js - discord.js

I'm making a moderation bot with my friend and I am trying to make it so if a user is muted when the bot restarts or crashes, on startup it loops all users in my database per guild and checks if they still have mute time to serve, then use a setTimeout() to wait however long until their muted role gets removed, however the bot does not have the user cached so I get an error where the user is undefined. If anyone knows how to cache a user by id or do this in another way any help is appreciated.
My code:
client.on("ready", () => {
client.user.setActivity(process.env.STATUS);
console.log(`Logged in as ${client.user.tag}`);
console.log(`Guilds: ${client.guilds.cache.size}`);
client.guilds.cache.forEach(function (guild) {
console.log(guild.name, ":", guild.id);
for (user in db.get(`${guild.id}.users`)) {
if (
ms(db.get(`${guild.id}.users.${moderation.mute.time}`)) +
Date.now(db.get(`${guild.id}.users.${moderation.mute.date}`)) >=
Date.now()
) {
let mutedRole = message.guild.roles.cache.find(
(mR) => mR.name === "Muted"
);
if (!mutedRole)
mutedRole = await message.guild.roles.create({
data: { name: "Muted", color: "#000000", permissions: [] },
});
client.guild.channels.cache.forEach(async (channel) => {
await channel.updateOverwrite(mutedRole, {
SEND_MESSAGES: false,
SPEAK: false,
VIDEO: false,
ADD_REACTIONS: false,
SEND_TTS_MESSAGES: false,
ATTACH_FILES: false,
});
});
let user = client.users.cache.get(user);
user.roles.remove(mutedRole);
}
}
});
});

You can cache or even save the id of a user and get the assigned GuildMember back by this method:
// 'user' will become the GuildMember of your cached id
let user = null;
// 'cachedId' is the id of the cached user
let cachedId = yourCachedId;
client.users.fetch(cachedId).then(usr => {user = usr})

Related

Discord.js V13 Adding role when using a slash command

I am trying to code a bot that when you use a certain slash command, it gives you a role. I have looked for a solution but haven't been able to find one. Nothing is seeming to work for me, i keep getting errors about the code, like "message not found, did you mean Message"
This is my first time trying to code a bot so if its a dumb issue, please bear with me.
Here is my code:
import DiscordJS, { Intents, Message, Role } from 'discord.js'
import dotenv from 'dotenv'
dotenv.config()
const client = new DiscordJS.Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
],
})
// Slash Commands
//ping pong command
client.on('ready', () => {
console.log('BOT ONLINE')
//bot test server
const guildId = '868857440089804870'
const guild = client.guilds.cache.get(guildId)
const role = client.guilds.cache.find(r => r.name == "Test Role to
give")
let commands
if (guild) {
commands = guild.commands
} else {
commands = client.application?.commands
}
commands?.create({
name: 'ping',
description: 'says pong'
})
commands?.create({
name: "serverip",
description: 'Gives user the server IP'
})
commands?.create({
name: "giverole",
description: 'Gives user the role'
})
})
client.on('interactionCreate', async (interaction) => {
if(!interaction.isCommand()) {
return
}
const { commandName, options } = interaction
//This is the role id that i want to give
const role = '884231659552116776'
//these are the users that i want to give the role to
const sniper = '725867136232456302'
const josh = '311981346161426433'
if (commandName === 'ping') {
interaction.reply({
content: 'pong',
ephemeral: true,
})
} else if (commandName === 'serverip') {
interaction.reply({
content: 'thisisserverip.lol',
ephemeral: true,
})
} else if (commandName === 'giverole') {
interaction.reply({
content: 'Role given',
ephemeral: true,
})
}
})
client.login(process.env.test)
You can just simply retrieve the Interaction#Member and add the role to them using GuildMemberRoleManager#add method!
const role = client.guilds.cache.find(r => r.name == "Test Role to
give");
await interaction.member.roles.add(role); // and you're all set! welcome to stackoverflow πŸ˜„
if (commandName === 'giverole') {
const role = client.guilds.cache.find(r => r.name == "Ahmed1Dev")
await user.roles.add(role)
message.channel.send("Done Added Role For You") // Fixed By Ahmed1Dev
}

Cant get the reactions to recognise on a specific message now

In a pervious post I was having issues getting the bot to recognise reactions and the fix worked however and then changed it to react on a message that the bot says afterwards and now it isnt working again, I have tried changing the user condition so its the original command author but that didn't seem to work
So you run the code and it makes the embed perfectly and reacts to it however it doesnt recognise when you react and makes the timeout message
exports.run = async (client, message, args) => {
message.delete()
const MINUTES = 5;
const questions = [
{ answer: null, field: 'placeholdquestion' },
{ answer: null, field: 'placeholdquestion' },
{ answer: null, field: 'placeholdquestion' },
]; //to add more questions just add another line of the above code {answes: null, field: `Question Here`}
let current = 0;
const commanduser = message.author.id
// ...
// wait for the message to be sent and grab the returned message
// so we can add the message collector
const sent = await message.author.send(
`${questions[current].field}`,
);
const filter = (response) => response.author.id === message.author.id;
// send in the DM channel where the original question was sent
const collector = sent.channel.createMessageCollector(filter, {
max: questions.length,
time: MINUTES * 60 * 1000,
});
// fires every time a message is collected
collector.on('collect', (message) => {
//if (questions > 1 && questions < 10) {
// add the answer and increase the current index HERE
questions[current++].answer = message.content;
const hasMoreQuestions = current < questions.length; //change to be an imput of how many questions you want asked
if (hasMoreQuestions) {
message.author.send(
`${questions[current].field}`,
);
}
});
// fires when either times out or when reached the limit
collector.on('end', (collected, reason) => {
if (reason === 'time') {
return message.author.send(
`I'm not saying you're slow but you only answered ${collected.size} questions out of ${questions.length} in ${MINUTES} minutes. I gave up.`,
);
}
const embed = new MessageEmbed()
.setTitle("LOA Request")
.addFields(
{ name: 'placehold', value: questions[0].answer+'/10' },
{ name: 'placehold', value: questions[1].answer+'/10' },
{ name: 'placehold', value: questions[2].answer+'/10', inline: true },)
.setColor(`#1773BA`)
.setTimestamp()
.setThumbnail("https://media.discordapp.net/attachments/772915309714735205/795378037813805126/mvg_clean_2.png")
.setFooter("request by: " + message.author.tag);
;
message.channel.send(embed)
.then(function (message) {
message.react("πŸ‘")
message.react("πŸ‘Ž")})
const filter = (reaction, user) => {
return ['πŸ‘', 'πŸ‘Ž'].includes(reaction.emoji.name) && user.id === commanduser; //changed to try and fix it didnt work as message.author.id or this
};
message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] } )
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'πŸ‘') {
message.channel.send('you reacted with a thumbs up.');
}
else {
message.reply('you reacted with a thumbs down.');
}
})
.catch(collected => {
console.log(`After a minute, only ${collected.size} out of 4 reacted.`);
message.reply('you didn\'t react with neither a thumbs up, nor a thumbs down.');
});
});
;
}
You have a slight logic error. You need to fit the code from your second filter to the message.awaitReactions inside of your message.channel.send(embed).then(function (message)...) method. In your code, the bot is trying to check for reactions from the original message, which you already deleted (since the awaitReactions is outside the scope of your function where you send and react to the embed).
Like this:
message.channel.send(embed)
.then(function (message) {
message.react("πŸ‘")
message.react("πŸ‘Ž")
const filter2 = (reaction, user) => {
return ['πŸ‘', 'πŸ‘Ž'].includes(reaction.emoji.name) && user.id === commanduser;
};
message.awaitReactions(filter2, { max: 1, time: 60000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'πŸ‘') {
message.channel.send('you reacted with a thumbs up.');
}
else {
message.reply('you reacted with a thumbs down.');
}
})
.catch(collected => {
console.log(`After a minute, only ${collected.size} out of 4 reacted.`);
message.reply('you didn\'t react with neither a thumbs up, nor a thumbs down.');
});
})

Difficulty creating the mute command - DIscord.js

I'm having problems making my mute command. I tested it but it doesn't create the Muted role. Maybe I made some mystakes in the over-writing section. I wish someone could help me. Anyway, here's my code:
if (message.content.startsWith(config.prefix + "mute")) {
let toMute = message.mentions.users.first();
if (!message.guild.member(message.author).hasPermission("MANAGE_MESSAGES")) {
return message.channel.send('You do not have the permission for mute users!');
}
if (!message.guild.member(client.user).hasPermission("MANAGE_MESSAGES")) {
return message.channel.send("I don’t have the permission for mute users!");
}
if (!toMute) {
return message.channel.send("You need to ping a user or the user can't be found!");
}
let mutedRole = message.guild.roles.cache.find(mR => mR.name === "Muted");
if (!mutedRole) {
try {
mutedRole = await message.guild.createRole({
name: "Muted",
color: "#000000",
permissions: []
});
message.guild.channels.forEach(async (channel, id) => {
await channel.overwritePermissions(mutedRole, {
SEND_MESSAGES: false,
ADD_REACTIONS: false
})
});
} catch (err) {
console.log(err.stack);
}
}
if (message.guild.member(toMute).roles.cache.has(mutedRole.id)) return message.channel.send("This user is already muted!");
await message.guild.member(toMute).roles.add(mutedRole);
message.channel.send(`${toMute} got muted by <#${message.author.id}> πŸ”‡`)
let {guild} = message;
toMute.send(`You got muted in **${guild.name}** by ${message.author}`)
}
and I'm getting this error.
Can someone help me fixing please? Thanks in advance!

Discord.js-commando how would I check if a mentioned user has a role, like a muted role for example?

So I have been trying to figure out how to check if the mentioned user has the muted role before attempting to add it, and if they do, say they are already muted, and I can't figure it out. Here is my code for my mute command, any help is appreciated.
const { Command } = require('discord.js-commando');
const { MessageEmbed } = require('discord.js');
module.exports = class MuteCommand extends Command {
constructor(client) {
super(client, {
name: 'mute',
aliases: ['mute-user'],
memberName: 'mute',
group: 'guild',
description:
'Mutes a tagged user (if you have already created a Muted role)',
guildOnly: true,
userPermissions: ['MANAGE_ROLES'],
clientPermissions: ['MANAGE_ROLES'],
args: [
{
key: 'userToMute',
prompt: 'Please mention the member that you want to mute them.',
type: 'member'
},
{
key: 'reason',
prompt: 'Why do you want to mute this user?',
type: 'string',
default: message =>
`${message.author.tag} Requested, no reason was given`
}
]
});
}
run(message, { userToMute, reason }) {
const mutedRole = message.guild.roles.cache.find(
role => role.name === 'Muted'
);
if (!mutedRole)
return message.channel.send(
':x: No "Muted" role found, create one and try again.'
);
const user = userToMute;
if (!user)
return message.channel.send(':x: Please try again with a valid user.');
user.roles
.add(mutedRole)
.then(() => {
const muteEmbed = new MessageEmbed()
.addField('Muted:', user)
.addField('Reason', reason)
.setColor('#420626');
message.channel.send(muteEmbed);
})
.catch(err => {
message.reply(
':x: Something went wrong when trying to mute this user.'
);
return console.error(err);
});
}
};
To see if a mentioned user has a role you can do:
member = message.mentions.first();
if (member._roles.includes('<role ID>') {
//code
}
and obviously, replace <role ID> with the role id of the muted role.
This works because members objects have a _roles array that contains all the IDs of the roles they have.

How can I change user permissions for sending messages for all channels?

How can I change user permissions for sending messages for all channels?
I want to block user sending messages to all channels by discord.js.
I try this in code:
let member = message.mentions.members.first()
member.updateOverwrite(client.guild.roles.member, { SEND_MESSAGES: false });
You can iterate over the channels in a particular guild, then modify the permissions for a particular user.
client.on('message', message => {
if (message.mentions.members.array().length === 0) return message.reply('No user was mentioned.');
message.guild.channels.cache.each(channel => {
channel.overwritePermissions([{
id: message.mentions.members.first().id, // user ID
deny: 'SEND_MESSAGES'
}]).catch(err => console.error(err));
});
});
If you want to only edit the permissions on certain channels, you can use this:
client.on('message', message => {
if (message.mentions.members.array().length === 0) return message.reply('No user was mentioned.');
[/* channel IDs */].forEach(channel => {
message.guild.channels.cache.get(channel).overwritePermissions([{
id: message.mentions.members.first().id, // user ID
deny: 'SEND_MESSAGES'
}]).catch(err => console.error(err));
});
});
});
If you want to exclude certain channels from all of them, you can use this:
client.on('message', message => {
if (message.mentions.members.array().length === 0) return message.reply('No user was mentioned.');
message.guild.channels.cache.each(channel => {
if ([/* channel IDs */].includes(channel.id) return;
channel.overwritePermissions([{
id: message.mentions.members.first().id, // user ID
deny: 'SEND_MESSAGES'
}]).catch(err => console.error(err));
});
});
References:
GuildChannel.overwritePermissions()

Resources