My main goal is for someone with message managing permissions to type a command for deleting a message but be able to specify how many messages they'd like to delete.
I have tried messing with variables but I don't have much knowledge on them, usually ending in some errors. I've tried replacing the value of messages deleted (the 2) with the variable with success but I'm clueless when it comes to changing the variable with a message.
if(message.member.hasPermission('MANAGE_MESSAGES')) {
if(message.content.startsWith(`${prefix}delete`)) {
message.channel.bulkDelete(2)
}
}
I will suppose you have it on message event.
This is one of many ways you can do it:
if(message.content.startsWith(`${prefix}delete`)) {
const user = message.mentions.users.first();
// Parse Amount
const amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2])
//Check if it the amount for message to delete where declared
if (!amount) return message.reply('Must specify an amount to delete!').then(msg => msg.delete(15000));
// Fetch 100 messages (will be filtered and lowered up to max amount requested)
message.channel.fetchMessages({
limit: 100,
}).then((messages) => {
//I declare the messages like that with amount + 1 to delete the command itself
messages = messages.array().slice(0, amount + 1);
//And finally buldDelete deletes the desired amount
message.channel.bulkDelete(messages).then(messages => console.log(`Bulk deleted ${args[0]} messages`))
.catch(console.error);
});
You would need to split message.content, which will return an array that I'll name args for this example. Then, args[1] should be the number you are looking for.
const prefix = '#'
const args = message.content.split(' ')
if(message.member.hasPermission('MANAGE_MESSAGES')) {
if(message.content.startsWith(`${prefix}delete`)) {
message.channel.bulkDelete(args[1])
}
}
Et voilà ! You just need to make sure that args[1] is a number now.
Related
I'm looking for a way to get the number of bans a moderator has done, here is what I have so far. I'm guessing I have to loop thru each ban?
let targetMod = message.mentions.users.first()
message.guild.bans.fetch().then((bans) => {
bans.forEach((ban) => {
//My problem is here, I dont know how to check who did the ban
})
})
The moderator is not actually provided in the info. You will need to check the audit logs for this (will only go back to a certain time, it's not fully accurate)
let logs = await message.guild.fetchAuditLogs()
logs = logs.entries.filter(e => e.action === "MEMBER_BAN_ADD")
logs = logs.entries.filter(e => e.executor?.id === targetMod.id)
console.log(logs.size) //should be the rough amount of bans
I am not very efficient with my code which may be the reasons why this keeps failing. I am trying to remove and assign roles to "verified" users. The basic gist of the code is to loop through all "verified" users and assign them appropriate roles according to the data received from the API.
const fetch = require("node-fetch");
var i = 0;
function mainLoop(
guild,
redisClient,
users,
main_list,
Pilot,
Astronaut,
Cadet,
main_guild,
cadet_guild,
guest
) {
setTimeout(function () {
redisClient.GET(users[i], async function (err, reply) {
if (reply != null) {
var json = await JSON.parse(reply);
var uuid = Object.keys(json).shift();
if (Object.keys(main_list).includes(uuid)) {
var tag = users.shift();
var rank = main_list[uuid];
console.log(`${tag}: ${rank}`);
var role = guild.roles.cache.find(
(role) => role.name === `| ✧ | ${rank} | ✧ |`
);
await guild.members.cache.get(tag).roles.remove(guest);
await guild.members.cache.get(tag).roles.remove(Astronaut);
await guild.members.cache.get(tag).roles.remove(Cadet);
await guild.members.cache.get(tag).roles.remove(Pilot);
await guild.members.cache.get(tag).roles.remove(cadet_guild);
await guild.members.cache.get(tag).roles.add(main_guild);
await guild.members.cache.get(tag).roles.add(role);
} else {
var tag = users.shift();
console.log(`${tag}: Guest`);
await guild.members.cache.get(tag).roles.remove(Astronaut);
await guild.members.cache.get(tag).roles.remove(Cadet);
await guild.members.cache.get(tag).roles.remove(Pilot);
await guild.members.cache.get(tag).roles.remove(main_guild);
await guild.members.cache.get(tag).roles.remove(cadet_guild);
await guild.members.cache.get(tag).roles.add(guest);
}
}
i++;
if (i < users.length) {
mainLoop(
guild,
redisClient,
users,
main_list,
Pilot,
Astronaut,
Cadet,
main_guild,
cadet_guild,
guest
);
}
});
}, 5000);
}
The code will fetch api data, map the "verified" users and api data into an array. Then, when it starts looping through the users array, it will only log 3 times and not assign any roles. Any help would be appreciated.
I can provide extra explanation/code if needed.
One possible issue I see here is that you are both incrementing the index i and calling .shift() on the users array. This may be the cause of the problem you are experiencing, as this will entirely skip some of the users in the array. Array.shift() doesn't just return the first element of the array; it removes it from the array.
Consider, for example, that your users array looks like this:
var users = ["Ted", "Chris", "Ava", "Madison", "Jay"];
And your index starts at 0 like so:
var i = 0;
This is what is happening in your code:
Assign roles for users[i]; the index is currently 0, so get users[0] (Ted).
Get Ted's tag via users.shift(). users is now: ["Chris", "Ava", "Madison", "Jay"]
Increment the index with i++. i is now: 1.
Assign roles for users[i]; the index is currently 1, so get users[1] (now Ava, skips Chris entirely).
Get Ava's tag via users.shift() (actually gets Chris' tag). users is now: ["Ava", "Madison", "Jay"]
Increment the index with i++. i is now: 2.
Assign roles for users[i]; the index is currently 2, so get users[2] (now Jay, skips Madison entirely).
And so on, for the rest of the array; about half of the users in the users array will be skipped.
I don't know how many users are supposed to be in your users array, but this could be the reason why so few logs are occurring. Note, however, that this is just one cause of the problem you are experiencing; it is possible that there are more reasons why you are having that issue, such as rate limits.
My recommendation on how to fix this is to not use users.shift() to get the user's tag. Simply use users[i], which will return the proper tag value without messing with the length of the array. Another way to fix this would be to remove the index incrementation, and always use 0 as your index. Use one or the other, but not both.
I want to show you which number of users I entered in the argument is the order of joining the server. Like = when i use .join 1 I want to show the 1st member join in to the server. I use
let arr = message.guild.members.filter(a => !a.user.bot).array().sort((b, a) => b.joinedTimestamp - a.joinedTimestamp)
let map = arr.indexOf(sesmi) + 1
this command for showing joing position but im so confused how can i do as i said?
Try this:
// if the first argument is not a number (this message is kind of bad so you can change it)
if (isNaN(args[0])) return message.reply('you must specify what number user you want to get!')
const members = message.guild.members.cache
.filter(member => !member.user.bot)
// sorted is a member on Discord's utility class Collection that doesn't modify the original collection
.sorted((a, b) => a.joinedTimestamp - b.joinedTimestamp)
.array()
// the number user to get
const n = Number(args[0])
// if there are not enough members
if (n > members.length) {
// You only really need this if there is ever going to be only 1 member in the server
// and if you care about grammar. You could also just do
// return message.reply(`there are only ${members.length} members!`)
const plural = members.length !== 1
return message.reply(`there ${plural ? 'are' : 'is'} only ${members.length} member${plural ? 's' : ''}!`)
}
message.channel.send(members[n - 1].user.tag)
I'm assuming args will be an array of strings with the arguments passed into the command (e.g. .join 1 will have the args ['1'].
I am creating a login system and i want to implement a username system automatically after registration with the user first-name and last-name. Everything is working fine but in the case if the registered user with the same first-name and last-name is already in the system i want to concatenate a incrmental number to it.
Example if : firstname:Badmus Lastname:Kabiru is in the system as badmus.kabiru and the newly registered user is also named so the new user username will be badmus.kabiru.1 the next will be badmus.kabiru.2.
My code sample are.
assignUserTrendname: function(req_username, callback){
let userNewname = fetchUserName(req_username);
let inc = 1, newlyAssignUsername;
userNewname.then((usernames) => {
console.log(req_username+" ...................... "+usernames); //The data from the database is loging out
if (usernames.atusername == null || usernames.atusername == undefined) {
newlyAssignUsername = req_username;
console.log("Assign automaticaly "+ newlyAssignUsername);
} else {
newlyAssignUsername = req_username;
console.log(`Username Result is DB: ${usernames.atusername} Req: ${newlyAssignUsername} Search ${inc}`);
if(usernames.atusername.toString() == newlyAssignUsername.toString()){
console.log("User name exit and inc is "+ inc);
inc++;
newlyAssignUsername = `${req_username}.${inc}`;
console.log("New search..."+ newlyAssignUsername);
fetchusernames(newlyAssignUsername); // These is not fetching from the database
}
newlyAssignUsername = `${req_username}.${inc}`;
}
console.log("Assigned is ......"+ newTrendname);
callback(null, newTrendname);
})
.catch((err)=> {console.log(err); throw err;});
}
function fetchUserName(trendname){
return Trender.getUserByTrendname(trendname);
}
If i am taking the wrong route please let me know.
Thanks.
In the scenario that your.username already exists you can search your Users with a regex pattern: ((?:your\.username)\d+$). This will get all records that match: your.username{num} where {num} is any number. If your username's are formatted as your.username.123 the pattern would be: ((?:your\.username\.)\d+$).
Assuming this returns an array, existing_users, you can count the records, since you'll always be incrementing by one, which will give you your next incremented number. Pseudo code:
let inc = existing_users.length + 1;
However, in the scenario that you delete a user your count is going to be off. You would need to loop over your existing_users and extract the number at the end and only keep the largest number.
let largest_num = 0;
existing_users.forEach(user => {
let num = user.match(/\d+$/);
if ( num != null && parseInt(num[0]) > largest_num ) {
largest_num = num[0];
}
});
Then you could do the same as above: let inc = largest_num + 1 and add that to your your.username string.
I do not know what library/framework you're using to search your MongoDB so I cannot write a query and function snippet.
We cannot write your code for you. A general regex has already been given that could be a potential way to solve your problem. If you go that route you can make use of the $regex operator. If you were to store the increment of the username as a separate field you could also sort by that to get the max value as well.
Here is an example of that:
db.users.find({
username: {
$regex: < Your Regex Here >
}
}).sort({
usernameIncrement: -1
}).limit(1);
Please see:
http://mongoosejs.com/docs/queries.html
https://docs.mongodb.com/manual/reference/operator/query/regex/
https://docs.mongodb.com/manual/reference/method/cursor.sort/
How I can list members in a role using Discord.js.
My code:
client.on("message", message => {
var guild = message.guild;
let args = message.content.split(" ").slice(1);
if (!message.content.startsWith(prefix)) return;
if (message.author.bot) return;
if(message.content.startsWith(prefix + 'go4-add')) {
guild.member(message.mentions.users.first()).addRole('415665311828803584');
}
});
How would I go about listing all the members that have the go4 role in an embed. When the message .go4-list is entered in a channel I would like the bot to respond with the embed.
<Role>.members returns a collection of GuildMembers. Simply map this collection to get the property you want.
Here's an example according to your scenario:
message.guild.roles.get('415665311828803584').members.map(m=>m.user.tag);
This will output an array of user tags from members that have the "go4" role. Now you can .join(...) this array to your desired format.
Also, guild.member(message.mentions.users.first()).addRole('415665311828803584'); could be shortened down to: message.mentions.members.first().addRole('415665311828803584');
Here's a rough example of how it would look as a result:
client.on("message", message => {
if(message.content.startsWith(`${prefix}go4-add`)) {
message.mentions.members.first().addRole('415665311828803584'); // gets the <GuildMember> from a mention and then adds the role to that member
}
if(message.content == `${prefix}go4-list`) {
const ListEmbed = new Discord.RichEmbed()
.setTitle('Users with the go4 role:')
.setDescription(message.guild.roles.get('415665311828803584').members.map(m=>m.user.tag).join('\n'));
message.channel.send(ListEmbed);
}
});
As #Wright mentioned in his answer, if there are over many members it will throw an error as an embed can only hold 2048 characters maximum, so you may want to do some checks before sending out the embed and then handle oversized embeds by either splitting them into multiple embed messages, or using reaction based pages maybe.
if(message.content.startsWith("//inrole")){
let roleName = message.content.split(" ").slice(1).join(" ");
//Filtering the guild members only keeping those with the role
//Then mapping the filtered array to their usernames
let membersWithRole = message.guild.members.filter(member => {
return member.roles.find("name", roleName);
}).map(member => {
return member.user.username;
})
let embed = new discord.RichEmbed({
"title": `Users with the ${roleName} role`,
"description": membersWithRole.join("\n"),
"color": 0xFFFF
});
return message.channel.send({embed});
}
Example use on discord:
Do note though that if there are a lot of members with the role, you may get an error telling you that you have exceeded the number of chars you can put in an embed. In such a case, you can decide to send multiple embeds splitting the users.
I tried Newbie's solution, but it didnt work
message.guild.roles.get('415665311828803584').members.map(m=>m.user.tag);
Gave me an error that .get is not a function maybe something changed with discord.js,
Adding cache after roles made it work.
message.guild.roles.cache.find(r => r.name === args[0]);
Since Discord v12, you now have to use roles.add() instead of addRole()
To mention the user in the embed (this looks a lot better than just text) remove .tag so it is just
(m => m.user).join('\n')