How to fix 'Supplied parameter was neither a User or Role.' - discord.js

I'm trying to make a bot make a role and go to a specified channel in the arguments of a command.
The code will make the bot go to the specified channel, and add permissions for the role that the bot just made, and that's where the problem is.
The console in VSC says that "a role / user was not specified" and it skips over that.
I've tried changing the arole to a var, and setting the arole (message.arole) to arole.id and it still didn't work. Messing around and changing the settings did not work at all.
let woaID = message.mentions.channels.first();
if (!woaID) return message.channel.send("Channel is nonexistant or command was not formatted properly. Please do s!woa #(channelname)");
let specifiedchannel = message.guild.channels.find(t => t.id == woaID.id);
var arole = message.guild.createRole({
name: `A marker v1.0`,
color: 0xcc3b3b,
hoist: false,
mentionable: false,
permissions: ['SEND_MESSAGES']
}).catch(console.error);
message.channel.send("Created role...");
message.channel.send("Role set up...");
/*const sbwrID = message.guild.roles.find(`null v1.0`);
let specifiedrole = message.guild.roles.find(r => r.id == sbwrID.id)*/
message.channel.send('Modified');
specifiedchannel.overwritePermissions(message.arole, {
VIEW_CHANNEL: true,
SEND_MESSAGES: false
})
.then(updated => console.log(updated.permissionOverwrites.get(arole.id)))
.catch(console.error);
I expect the bot able to access the specified channel in the args, and create a role and overwrite role permissions for that channel.
The actual output is that the bot does everything fine, but the role does not have special permissions for the channel.

There are two main issues with your code:
The Guild.createRole() does not synchronously return a Role: it returns a Promise<Role>, so you're in fact not providing a role as argument for .overwritePermissions()
After you create the role (if you properly store it in arole) you can't access it as message.arole.
You can either do that with async/await or using the .then() promise method.
If you're not confident with promises or asynchronous code you should try to learn something about it, it's really useful: check out Using promises, the Promise and async function docs by MDN.
Here's an example:
message.guild.createRole({
name: `A marker v1.0`,
color: 0xcc3b3b,
hoist: false,
mentionable: false,
permissions: ['SEND_MESSAGES']
}).then(async arole => {
let updated = await specifiedchannel.overwritePermissions(arole, {
VIEW_CHANNEL: true,
SEND_MESSAGES: false
});
console.log(updated.permissionOverwrites.get(arole.id));
}).catch(console.error);

Related

How can I DM the user an embed before he is kicked (discord.js)

I'm trying to make a blacklist command, and how do I make it so it sends an embed instead of normal message.
(Also, I'm new to discord.js)
Here's my script:
module.exports = {
data: new SlashCommandBuilder()
.setName('blacklist')
.setDescription('Blacklist someone from the server')
.addUserOption((option) => option.setName('member')
.setDescription('Who are you blacklisting?')),
async execute(interaction) {
await interaction.deferReply();
const member = interaction.options.getMember('member');
if (!interaction.member.roles.cache.some(r => r.name === "Blacklist perms")) {
return interaction.editReply({ content: 'You do not have permission to use this command!' });
}
member.send("You have been blacklisted!")
member.kick().catch(err => {
interaction.editReply({ content: `I do not have enough permissions to do that.`})
})
await interaction.editReply({ content: `${member} has been succesfully blacklisted!` });
},
};```
Since your function is already async, simply await sending the message before you call kick.
await member.send("You have been blacklisted!")
member.kick().catch(err => {
interaction.editReply({ content: 'I do not have enough permissions to do that.'})
})
You might also wanna catch() on the send method because users can have DMs from server members disabled or blocked your bot.
You also might consider banning the user instead, because this system would fail if your bot ever happens to go offline when a blacklisted user tries to join. Additionally, depending on how fast your bot reacts, the user may still have time to spam in channels or do something harmful before your bot is able to kick them.
To send an embed either use an EmbedBuilder or a plain JavaScript object with the correct embed structure.
Example:
member.send({ embeds:[{
title: "Title",
description: "Hello World!"
}] })

Permissions checking discord.js

I tried to make a bot that can kick users and I have a probem with checking if user has a permision to do so. I have aready searched for it trough the whole internet and everywere it was sad to use .has but it doesn't seems to work, console always returns error: Cannot read properties of undefined (reading 'has').
Here's my code:
const { SlashCommandBuilder } = require("#discordjs/builders");
const { Permissions } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName("kick")
.setDescription("Kicks someone")
.addUserOption(option =>
option
.setName("user")
.setDescription("Select the user")
.setRequired(true)),
async execute(interaction){
const user = interaction.options.getUser("user");
const userId = interaction.guild.members.cache.get(user.id);
if(!interaction.user.permissions.has(Permissions.FLAGS.KICK_MEMBERS)) return interaction.reply("You dont have perrmisions to kick KEKW!");
if(!interaction.guild.permissions.me.has(Permissions.FLAGS.KICK_MEMBERS)) return interaction.reply("I dont have perrmisions to kick KEKW!");
if(userId == interaction.user.id) return interaction.reply(
{
content: "You cant kick yourself bro!",
ephemeral: true
});
interaction.reply({
content: `You have succesfuly kicked user: ${user}!`,
ephemeral: true
});
userId.kick();
}
}
Here's the error:
https://ibb.co/86xPdJv
interaction.user is a User object, so methods only available to GuildMember, like permissions.has cannot be applied to the interaction.user. Change it to interaction.member will solve the problem. It's also a good idea to read more about User and GuildMember objects and their differences in the discord.js documentation and guide. I've linked these below:
discord.js documentation pages on topic:
https://discord.js.org/#/docs/discord.js/stable/class/User -User
https://discord.js.org/#/docs/discord.js/stable/class/GuildMember -GuildMember
discord.js guide on topic:
https://discordjs.guide/popular-topics/faq.html#what-is-the-difference-between-a-user-and-a-guildmember

Custom Roles on join with enmap

I’ve tried to add code to allow people to customise which role people get when they join a server which can be set on a per server basis however I cannot seem set get it working. The greeting channel, the greeting and the DM are all working. It is only the role adding. If you could point me in the right direction then that would be very helpful.
client.settings = new Enmap({
name: "settings",
fetchAll: false,
autoFetch: true,
cloneLevel: 'deep'
});
// Just setting up a default configuration object here, to have somethign to insert.
const defaultSettings = {
prefix: "!",
modLogChannel: "mod-log",
modRole: "Moderator",
adminRole: "Administrator",
welcomeChannel: "chat",
welcomeMessage: "Welcome to the server, {{user}} 😉",
welcomeDMMessage: "text",
rolesOnJoin: "Basic"
}
client.on("guildDelete", guild => {
// When the bot leaves or is kicked, delete settings to prevent stale entries.
client.settings.delete(guild.id);
});
client.on("guildMemberAdd", member => {
client.settings.ensure(member.guild.id, defaultSettings);
let roleAdd = client.settings.get(member.guild.id, "rolesOnJoin");
let welcomeMessage = client.settings.get(member.guild.id, "welcomeMessage");
let welcomeDMMessage = client.settings.get(member.guild.id, "welcomeDMMessage");
let role = member.guild.roles.find(role => role.name == roleAdd);
welcomeMessage = welcomeMessage.replace("{{user}}", member.user.tag)
member.guild.channels
.find("name", client.settings.get(member.guild.id, "welcomeChannel"))
.send(welcomeMessage, {files: ["https://cdn.glitch.com/ecc1aef4-3247-42a1-9361-cfc56e9c5ba1%2F75AC6C9B-3E71-4F25-B8CF-47050B4B8F21.jpeg"]})
.catch(console.error);
member.send(welcomeDMMessage);
member.addRole(role);
});
addRole() needs the role ID (or the Role as an object), you can still find it via it's name with
let role = guild.roles.find(role => role.name == roleAdd)
member.addRole(role);
Presumably the problem is that addRole() expects either a Role object or a role ID:
https://discord.js.org/#/docs/main/stable/class/GuildMember?scrollTo=addRole
https://discord.js.org/#/docs/main/stable/typedef/RoleResolvable
"Basic" is neither.
If all you have is the role name, you need to find it by that name in the guild.roles Collection.

Saving roles from mentioned user

I am trying to make a tempmute command, I followed a tutorial online which worked... But my own server has users with multiple roles, and these roles allow them to talk even when they receive the "muted" role.
Is there any way to save all the roles from a mentioned user and then to remove and add those roles?
I already tried to make a new let variable
let roleHistory = tomute.member.roles;
and then adding and removing them with:
await(tomute.removerole(roleHistory));
tomute.addRole(roleHistory);
But that didn't work
module.exports.run = async (bot, message, args) => {
let tomute = message.guild.member(message.mentions.users.first() || message.guild.members.get(args[0]));
if(!tomute) return message.reply("Couldn't find user.");
if(tomute.hasPermission("MANAGE_MESSAGES")) return message.reply("Can't mute them!");
let muterole = message.guild.roles.find(`name`, "muted");
if(!muterole){
try{
muterole = await message.guild.createRole({
name: "muted",
color: "#000000",
permissions:[]
})
message.guild.channels.forEach(async (channel, id) => {
await channel.overwritePermissions(muterole, {
SEND_MESSAGES: false,
ADD_REACTIONS: false
});
});
}catch(e){
console.log(e.stack);
}
}
let mutetime = args[1];
if(!mutetime) return message.reply("You didn't specify a time!");
await(tomute.addRole(muterole.id));
message.reply(`<#${tomute.id}> has been muted for ${ms(ms(mutetime))}`);
setTimeout(function(){
tomute.removeRole(muterole.id);
message.channel.send(`<#${tomute.id}> has been unmuted!`);
}, ms(mutetime));
}
I want the bot to take the roles away, tempmute the user and giving the roles back after the Timeout.
Your attempt is on the right track, but you missed a small detail. A Guild Member has a method addRole and removeRole which you used. However, these methods are meant for adding/removing a single role.
When you first fetch the user roles with let roleHistory = tomute.member.roles;, it returns a Collection of roles. If you then attempt to use removeRole(roleHistory) it attempts to remove a single role equal to the complete collection (which doesn't exist obviously).
To make it work, you need the methods addRoles and removeRoles which adds/removes an entire collection. So your code would be:
let roleHistory = tomute.roles;
// Removing all the roles
await(tomute.removeRoles(roleHistory));
// Adding all the roles
tomute.addRoles(roleHistory);
P.s. Since your tomute variable is already a user you need to change your code to fetch the roles from let roleHistory = tomute.member.roles; to let roleHistory = tomute.roles;

Discord.js creating a private voice channel and role

I am trying to make a discord bot with Discord.js, that can create a private channel and a new role and assign that role to the channel. So any users with the new role can access the channel.
The following code, creates a channel from the name i give it through 'eventName' it also creates a role of the same name.
But how do i make the voice channel private, set a role to exclusively access it and set some permissions to the new role?
function addChannel(message,args,eventName){
var server = message.guild;
var permsName = eventName+"-"+message.author.username;
message.guild.createRole({
//data: {
name: permsName,
permissions: []
//},
//reason: 'new Event'
}).then(role => {
message.member.addRole(role,permsName)
.catch(error => client.catch(error))
}).catch(error => client.catch(error))
server.createChannel(eventName, 'voice').then( // Create the actual voice channel.
(chan) => {
chan.setParent("427382662240534535").then( // Move the voice channel to the current message's parent category.
(chan2) => {
console.log("stage 3");
console.log(chan2);
//console.log(`Set the category of ${chan2.name} to ${chan2.parent.name}`);
chan2.overwritePermissions(message.guild.roles.find('name', '#everyone'), { 'CREATE_INSTANT_INVITE' : false }); // Give the channel some standard permissions.
chan2.overwritePermissions(message.guild.roles.find('name', permsName), {
'CREATE_INSTANT_INVITE' : false, 'ADD_REACTIONS': true,
'READ_MESSAGES': true, 'SEND_MESSAGES': true,
'SEND_TTS_MESSAGES': true, 'MANAGE_MESSAGES': true,
'EMBED_LINKS': true, 'ATTACH_FILES': true,
'READ_MESSAGE_HISTORY': true, 'MENTION_EVERYONE': true,
'EXTERNAL_EMOJIS': true, 'CONNECT': true,
'SPEAK': true
});
console.log("stage 4");
}
).catch(console.error);
}
).catch(console.error);
return '```Added```';
}
Theres two problems here, for one you are using a lot of unnessecary permissions here, for Voice obviously reactions reading and sending messages etc are not important, important are only VIEW_CHANNEL, SPEAK, CONNECT, and CREATE_INSTANT_INVITE, and you have to explicitely forbid everyone for a standard discord server setup since everyone usually has these rights Serverwide unless locally overwritten.
So what you want for your overwrite permissions is:
chan2.overwritePermissions(message.guild.roles.find('name', '#everyone'), { // Disallow Everyone to see, join, invite, or speak
'CREATE_INSTANT_INVITE' : false, 'VIEW_CHANNEL': false,
'CONNECT': false, 'SPEAK': false
});
chan2.overwritePermissions(message.guild.roles.find('name', permsName), {//Explicitely allow the role to see, join and speak
'VIEW_CHANNEL': true, 'CONNECT': true, 'SPEAK': true,
});
Note that you do not have to explicitely disallow CREATE_INSTANT_INVITE since that is inherited from everyone if not explicitely changed.

Resources