Custom Roles on join with enmap - discord.js

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.

Related

role.setPosition() in Discord.js v12

In Discord.js v11 you could use guild.setRolePosition({ role: '123456789012345678', position: 1 }); to set the position of a specific role. How can you specify a role (like i.e. 'Muted') with the new role.setPosition() method? It seems to only accept a position number and a few options like options.relative. What I want is to assign a role position to the roles Admin, Friends, Muted in the roleCreate() event. I know that the roleCreate event only runs when a role is created, but somehow the 'position' parameter doesn't work well with guild.roles.create.
GuildRoleManager.create() actually works fine with the position parameter, you just have to add it ass a property to the data object.
guild.roles.create({
data: {
name: 'Role Name',
// any other options...
position: 1
},
});
If you still want to use role.setPosition(), you'll have to fetch the role object before-hand, then call the method on that object.
// <guild> is a placeholder for the guild object
// get the role by id
const role = <guild>.roles.cache.get('Role ID');
// get role by name (or other property)
const role = <guild>.roles.cache.find((role) => role.name === 'Role Name');
role.setPosition(1);

identifying admins from mentions discordjs

I want to find out if there are mentions in a message which I am doing using if(message.mentions.users.first()) but now among all the mentions I also want to filter out mentions of the admin team and not those of the community members. How to achieve that?
I tried filtering users based on roles like this
let r = [];
message.mentions.users.forEach( user => {
console.log('user' + user)
user.roles.forEach(role => {
console.log('role' + role)
r.push(role);
})
console.log('roles' + r);
var member = false;
for (i in r) {
if (i == 'admin') {
member = true;
}
}
})
This doesn't seem to work.
const adminName = ['<role name>'];
const adminId = ['<role ID>'];
client.on('message', (msg) => {
let admins = msg.mentions.members.filter( (user) => {
return adminId.some(id => user.roles.has(id)) || user.roles.some(r => adminName.includes(r.name));
});
console.log(admins.map(d => d.user.username));
});
There, I created 2 arrays, one with the role ID and another with the role name. You can use both, or only one (I prefer to use the id, because you can change a role name, but you can't change an id, except if you delete the role).
Then, I iterate through the members in the mentions of the messages. Why the members and not the users? Because the GuildMember is a type linked to a guild, which is an instance of an user in a guild, and so it has the role of the user.
Then I check if one of the id of my admins roles is in the roles of the user or if one of the roles name is inside my adminName.
The variable admins is a collection of GuildMember.
You can change the function inside the some to match whatever condition make someone an admin for you.

Grabbing the permissions from a TextChannel - Discord.js

Basically, I need to grab the permissions from the current text channel the user is in. I have already got the channel name, if I need to get the ID that should be pretty easy to do.
const Discord = require("discord.js");
module.exports.run = async (client, message, args) => {
let currentChannel = message.channel.name;
let category = message.channel.parent;;
message.guild.createChannel(currentChannel).then(mchannel => {
mchannel.setParent(category).then(() => {
message.channel.delete();
});
});
}
module.exports.help = {
name: "a.cleanchannel"
}
// Need the channel permissions to overwrite the new channel's permissions with the old ones
The expected results are that the channel should have the same permissions as the old one.
To answer your question directly, you can use GuildChannel#permissionOverwrites to create the new channel with the same permissions as the old one. For example...
message.guild.createChannel(message.channel.name, {
type: 'text',
permissionOverwrites: message.channel.permissionOverwrites
});
However, it looks like you're trying to clone a channel. To help make that easier, there's a method built into Discord.js for it - GuildChannel#clone(). You can use it like so...
message.channel.clone(undefined, true, true) // Same name, same permissions, same topic
.then(async clone => {
await clone.setParent(message.channel.parent);
await clone.setPosition(message.channel.position);
await message.channel.delete();
console.log(`Cloned #${message.channel.name}`);
})
.catch(console.error);

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

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);

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;

Resources