Loop for display help command - javascript

Actually, i try to create a bot with discord.js and i try to do a help command.
i don't understand why my loop do this (i know it's not a good way for this)
let i = 0;
const embed = new RichEmbed();
if (args.length < 1) {
embed.setColor('#5B4DCA');
while (i < list_groups.length) {
let x = 0;
embed.setTitle(`${list_groups[i]}`)
while (x < groups.length) {
if (groups[x] === list_groups[i]) {
embed.addField('test1', 'test2')
}
x++;
}
message.channel.send(embed)
i++;
}
}
"Modérations" is supposed to display one command, "level & rank" too, "Outils" 4 command and "Sondage" too
enter image description here

I think you solutuion its not right way. If you will have more then 10 groups bot will spam commands list. The 1 way to do it its display all categories list if args.length===0, if args !==0 you try to find all commands in this category. To discord embed you can add only 18 fields, so if you have more then 18 command in categroy you will get api error. So you need spliced commands to pages.
This code will display all categories if args.length === 0, or command groups not fined.
If group fined bot send embed message with command in group (max 10), and react message if pages more then 1, so user can change page with reaction.
const {Discord,RichEmbed} = require('discord.js');
const {prefix,token,classic_roles} = require('../config.json');
const logs = require('../logs/logs');
module.exports.run = async (bot, message, args) => {
if(args.length === 0) {
//Show user all allowed groups commands
let commandCategories = bot.commands.map(command => `!help ${command.help.groups}`).filter(onlyUnique).join('\n') //find all categories and get onlyUnique
let helpMessage = `**The list of command groups:**\n\n ${commandCategories}`
let Embed = new Discord.RichEmbed()
.setAuthor(message.author.tag, message.author.displayAvatarUrl)
.setDescription(helpMessage)
.setColor('#e0c40b')
message.channel.send(Embed)
} else {
//try find required group
let commandsInCategory = bot.commands.filter(command => command.help.groups === args.join(' ').toLowerCase())
if(commandsInCategory.size === 0) {
// if no group find, then display user list of groups
let commandCategories = bot.commands.map(command => `!help ${command.help.groups}`).filter(onlyUnique).join('\n')
let helpMessage = `**For get command list use**\n\n ${commandCategories}`
let Embed = new Discord.RichEmbed()
.setAuthor(message.author.tag, message.author.displayAvatarUrl)
.setDescription(helpMessage)
.setColor('#e0c40b')
message.channel.send(Embed)
return
}
let counter = 0
let allCommands = []
commandsInCategory.map(command => {
allCommands.push({
name: command.help.name,
description: command.help.description
})
})
allCommands = generateHelpArray(allCommands)
//for better display, we will display only 10 in page
let Embed = new Discord.RichEmbed()
Embed.setAuthor(message.author.tag, message.author.displayAvatarUrl)
Embed.setDescription(`The list command of group : **${args.join(' ')}**`)
allCommands[counter].map(command => {
Embed.addField(`**${command.name}**`,`${command.description}`,false)
})
Embed.setColor('#E8DB0E')
Embed.setFooter(`Page ${counter+1} of ${allCommands.length}`)
message.channel.send(Embed).then(msg => {
if(allCommands.length < 2) return
// To change page we will use react emoji
msg.react(`◀️`).then(() => msg.react('▶️'))
const filter = (reaction, user) => {
return [`◀️`, '▶️'].includes(reaction.emoji.name) && user.id === message.author.id;
};
const collector = msg.createReactionCollector(filter, { max:50, time: 60000 });
collector.on('collect', (reaction, reactionCollector) => {
if (reaction.emoji.name === `◀️`) {
//Change counter, remove user reaction and call change embed function
reaction.remove(message.author.id)
counter-=1
if(counter < 0) counter = 0
editEmbed(message, msg, counter, args.join(' '), allCommands)
} else if (reaction.emoji.name === `▶️`) {
//Change counter, remove user reaction and call change embed function
reaction.remove(message.author.id)
counter+=1
if(counter >= allCommands.length) counter = allCommands.length -1
editEmbed(message, msg, counter, args.join(' '), allCommands)
}
});
collector.on('end', (reaction, reactionCollector) => {
msg.clearReactions()
})
})
}
}
module.exports.help = {
name: "help",
description: "Vous permet d'obtenir toutes les commandes accessibles pour vos rôles.",
access: "Public",
groups: "Outils"
}
const onlyUnique = (value, index, self) => {
return self.indexOf(value) === index;
}
const editEmbed = (message, msg, counter, category, allCommands) => {
let Embed = new Discord.RichEmbed()
Embed.setAuthor(message.author.tag, message.author.displayAvatarURL)
Embed.setDescription(`The list command of group : **${category}**`)
Embed.setColor('#E8DB0E')
allCommands[counter].map(command => {
Embed.addField(`**${command.name}**`,`${command.description}`,false)
})
Embed.setFooter(`Page ${counter+1} of ${allCommands.length}`)
msg.edit(Embed)
}
const generateHelpArray = (arr) => {
let newArray = [];
for (let i = 0; i < arr.length; i+=10) {
newArray.push(arr.slice(i,i+10))
}
return newArray
}

Related

(discord.js) How can i make a category then add a new channel too that category

What im trying to do is have discord.js make a category then after that make a channel then move that channel into the category if there is any possible way.
My Code Now:
if(command === 'spamcategory'){
let amount = args.slice(0).join(" ")
let name = args.splice(1,Infinity).join(" ")
for (var i = 0; i < 200; i++) {
message.guild.channels.create(name, { type: "GUILD_CATEGORY" });
}
}
message.guild.channels.create(name, { type: "GUILD_CATEGORY" })
.then(async (category) => {
await category.createChannel('channelName');
});

Record an entire conversation Discord.js

I want to record a entire conversation from Discord.JS v12. But, I'm don't really good in audio manipulation and other things like that.
I've this code :
const c = message.member.voice?.channel;
if(!c) {
// The user is not in voice channel
return message.channel.send("");
}
switch(args?.[0]?.toLowerCase()){
case 'on':
if(this.vocals.find(r => r.c === c.id && r.u === message.author.id)){
// The user have already an record launched
return message.channel.send("Vous avez déjà un enregistrement de démarré.");
}
const flux = await c.join();
const receiver = flux.receiver;
const audioChunk = this.createNewChunk((message.member.nickname || message.author.username).replace(/[^A-Za-z0-9]/g, ''));
this.vocals.push({
c: c.id,
u: message.author.id,
s: Date.now(),
r: audioChunk
});
flux.on('speaking', (user, speaking) => {
if (speaking) {
const audioStream = receiver.createStream(user, { mode: 'pcm' });
audioStream.on('data', (chunk) => audioChunk.write(chunk));
}
});
return message.channel.send("L'enregistrement a bien été lancé avec succès !")
break;
case 'off':
let f = this.vocals.find(r => r.c === c.id);
const channel = this.bot.channels.cache.get(f.c);
const members = channel.members.array();
f = this.vocals.find(r => r.c === c.id &&
(members.find(r => r.user.id === message.author.id) &&
r.u === message.author.id));
if(!f){
// The user doesnt have any record
return message.channel.send("Vous n'avez aucun enregistrement de démarré.");
}
console.log(f);
f.r.close();
return message.channel.send("L'enregistrement s'est bien terminé avec succès !", )
break;
default:
// const embed = ...
return message.channel.send(
this.help.usage.replace(/{prefix}/g, this.bot.config.prefix)
)
break;
}
And the createNewChunk function :
createNewChunk(name) {
return new wav.FileWriter(`./records/record-${name}.wav`);
}
But, when the users stop speaking in the channel, the record is stopped. Do you know how I can avoid this ?
Thanks you.
Okay, so It's really simple to do.
You have to create a audio chunck with Buffer. Then, detect when nobody is speaking. And you can push every 20ms your Buffer into the Stream.
const { Buffer } = require('buffer');
const emptyBuffer = Buffer.alloc(3840, 0); // You create a Buffer with a length of 3840, and a value to 0 (no sound).
Then, you have to put all your users into an array :
const users = [];
flux.on('speaking', (user, speaking) => {
if (speaking) {
users.push(user.id);
const audioStream = receiver.createStream(user, { mode: 'pcm' });
audioStream.on('end', () => {
users.splice(users.findIndex(r => r == user.id), 1); // Remove the users of users speaking array.
});
}
});
And THEN, you can add your buffer with no sound :
var emptyInterval = setInterval(() => {
if(users.length < 1){
audioChunk.write(emptyBuffer);
}
}, 20)
For stop the stream, stop clear the interval of emptyInterval and stop your event flux.on('speaking').
Works for nodejs v16 and more. I dont know if for nodejs v14 or lower it work.

Bot automatically removing reaction

I'm currently working on a music bot. I made a queue command which shows how many songs are currently in the queue. I wanted to make it look like if the songs in the queue are greater than 10 the bot will slice it and show the rest on a next "page". To scroll between pages I wanted to use reactions. My code is working, but the Bot automatically removes its own reaction. Why is that?
const Discord = require("discord.js");
module.exports.run = async (client, message, args, queue, searcher) => {
const serverQueue = queue.get(message.guild.id);
if(!serverQueue)
return message.channel.send("**Jelenleg nincs zene lejátszás alatt!**");
if(message.member.voice.channel != message.guild.me.voice.channel)
return message.channel.send("**Előbb lépj be a hang szobába!**")
let currentPage = 0;
if(serverQueue.songs.length <= 1) return message.channel.send(`**Lejátszás alatt:** [__${serverQueue.songs[0].title}__](${serverQueue.songs[0].url})`);
const embeds = embedGenerator(serverQueue)
//if(serverQueue.songs.length < 12) return message.channel.send(embeds);
const queueEmbed = await message.channel.send(`**Oldal:**: ${currentPage+1}/${embeds.length}`, embeds[currentPage])
await queueEmbed.react('⬅️');
await queueEmbed.react('➡️');
const reactionFilter = (reaction, user) => ['⬅️', '➡️'].includes(reaction.emoji.name) && (message.author.id === user.id)
const collector = queueEmbed.createReactionCollector(reactionFilter);
collector.on('collect', (reaction, user) => {
if(reaction.emoji.name === '➡️'){
if(currentPage < embeds.length-1){
currentPage+=1;
queueEmbed.edit(`**Oldal:**: ${currentPage+1}/${embeds.length}`, embeds[currentPage]);
message.reactions.resolve(reaction).users.remove(user)
}
}else if(reaction.emoji.name === '⬅️'){
if (currentPage !== 0){
currentPage -= 1;
queueEmbed.edit(`**Oldal:** ${currentPage+1}/${embeds.length}`, embeds[currentPage])
message.reactions.resolve(reaction).users.remove(user)
}
}
})
}
function embedGenerator(serverQueue){
const embeds = [];
let songs = 11;
for (let i = 1; i < serverQueue.songs.length; i += 10){
const current = serverQueue.songs.slice(i, songs)
songs += 10;
let j = i-1;
const info = current.map(song => `${++j}. [${song.title}](${song.url})`).join('\n')
const msg = new Discord.MessageEmbed()
.setDescription(`**Lejátszás alatt:** [${serverQueue.songs[0].title}](${serverQueue.songs[0].url}) \n ${info}`)
embeds.push(msg)
}
return embeds;
}
module.exports.config = {
name: "queue",
aliases: ['q']
}
Okay so I found the problem.It turned out that my other bot had a reaction event which removes reactions on messages after like 4 seconds.I didn't add an if(message.author.bot) return; line to that so it removed the reaction all the time.

Discord.js Bot giveaway command : embedSent.reactions.get is not a function

I am trying to make a Discord.js giveaway command that send an embed, save it to the variable embedSent then collect the reactions after the TimeOut with the reactions.get() method, but I keep getting the error TypeError: embedSent.reactions.get is not a function Here is the part of my code :
var embed = new Discord.MessageEmbed();
embed.setColor(0x3333ff);
embed.setTitle("Nouveau Giveaway !");
embed.setDescription("**" + item + "**");
embed.addField(`Durée : `, ms(ms(time), {
long: true
}), true);
embed.setFooter("Réagissez à ce message avec 🎉 pour participer !");
var embedSent = await message.channel.send(embed);
embedSent.react("🎉");
setTimeout(function () {
var peopleReacted = embedSent.reactions.get("🎉").users.filter(user => user.id !== client.user.id).array()
}, time);
Ok, after almost 2 months, I finally figured it out. The full, working command (DiscordJS v12) :
if (command == "giveaway") {
// !giveaway {time s/m/d} {item}
const messageArray = message.content.split(" ");
if (!message.member.hasPermission(["ADMINISTRATOR"])) return message.channel.send("You don't have enough permissions to start a giveaway !")
var item = "";
var time;
var winnerCount;
for (var i = 1; i < args.length; i++) {
item += (args[i] + " ");
}
time = args[0];
if (!time) {
return message.channel.send(`Invalid duration provided`);
}
if (!item) {
item = "No title"
}
var embed = new Discord.MessageEmbed();
embed.setColor(0x3333ff);
embed.setTitle("New Giveaway !");
embed.setDescription("**" + item + "**");
embed.addField(`Duration : `, ms(ms(time), {
long: true
}), true);
embed.setFooter("React to this message with 🎉 to participate !");
var embedSent = await message.channel.send(embed);
embedSent.react("🎉");
setTimeout(async () => {
try{
const peopleReactedBot = await embedSent.reactions.cache.get("🎉").users.fetch();
var peopleReacted = peopleReactedBot.array().filter(u => u.id !== client.user.id);
}catch(e){
return message.channel.send(`An unknown error happened during the draw of the giveaway **${item}** : `+"`"+e+"`")
}
var winner;
if (peopleReacted.length <= 0) {
return message.channel.send(`Not enough participants to execute the draw of the giveaway **${item}** :(`);
} else {
var index = Math.floor(Math.random() * peopleReacted.length);
winner = peopleReacted[index];
}
if (!winner) {
message.channel.send(`An unknown error happened during the draw of the giveaway **${item}**`);
} else {
console.log(`Giveaway ${item} won by ${winner.toString()}`)
message.channel.send(`🎉 **${winner.toString()}** has won the giveaway **${item}** ! Congratulations ! 🎉`);
}
}, ms(time));
}
Hope it helped some !
I guess this giveaway command works for me - Discord.js V13
don't forget to have npm i ms installed if you haven't already
const { Client, Intents, CommandInteraction, ReactionUserManager } = require('discord.js');
const INTENTS = new Intents(32767); // 32767 == full intents, calculated from intent calculator
const client = new Client({
intents: INTENTS
});
const Discord = require('discord.js');
const ms = require('ms') // make sure package ms is downloaded in console, to do this, simply type: npm i ms in your terminal
// https://www.npmjs.com/package/ms
client.once("ready" , () => {
console.log("I am online!")
});
client.on('messageCreate', async message => {
const prefix = "!" // this can be any prefix you want
let args = message.content.substring(prefix.length).split(" ")
// COMMAND FORMAT: !startgiveaway {duration} {winners} {#channel} {prize}
// E.g. !startgiveaway 24h 3w #giveaways Free Discord Nitro
if ((message.content.startsWith(`${prefix}startgiveaway`))) { // this condition can be changed to any command you'd like, e.g. `${prefix}gstart`
if (message.member.roles.cache.some(role => (role.name === 'Giveaway') )) { // user must have a role named Giveaway to start giveaway
let duration = args[1];
let winnerCount = args[2];
if (!duration)
return message.channel.send('Please provide a duration for the giveaway!\nThe abbreviations for units of time are: `d (days), h (hours), m (minutes), s (seconds)`');
if (
!args[1].endsWith("d") &&
!args[1].endsWith("h") &&
!args[1].endsWith("m") &&
!args[1].endsWith("s")
)
return message.channel.send('Please provide a duration for the giveaway!\nThe abbreviations for units of time are: `d (days), h (hours), m (minutes), s (seconds)`');
if (!winnerCount) return message.channel.send('Please provide the number of winners for the giveaway! E.g. `1w`')
if (isNaN(args[2].toString().slice(0, -1)) || !args[2].endsWith("w")) // if args[2]/winnerCount is not a number (even after removing end 'w') or args[2] does not end with 'w', condition returns:
return message.channel.send('Please provide the number of winners for the giveaway! E.g. `3w`');
if ((args[2].toString().slice(0, -1)) <= 0)
return message.channel.send('The number of winners cannot be less than 1!');
let giveawayChannel = message.mentions.channels.first();
if (!giveawayChannel || !args[3]) return message.channel.send("Please provide a valid channel to start the giveaway!")
let prize = args.slice(4).join(" ");
if (!prize) return message.channel.send('Please provide a prize to start the giveaway!');
let startGiveawayEmbed = new Discord.MessageEmbed()
.setTitle("🎉 GIVEAWAY 🎉")
.setDescription(`${prize}\n\nReact with 🎉 to participate in the giveaway!\nWinners: **${winnerCount.toString().slice(0, -1)}**\nTime Remaining: **${duration}**\nHosted By: **${message.author}**`)
.setColor('#FFFFFF')
.setTimestamp(Date.now() + ms(args[1])) // Displays time at which the giveaway will end
.setFooter("Giveaway ends");
let embedGiveawayHandle = await giveawayChannel.send({embeds: [startGiveawayEmbed]})
embedGiveawayHandle.react("🎉").catch(console.error);
setTimeout(() => {
if (embedGiveawayHandle.reactions.cache.get("🎉").count <= 1) {
return giveawayChannel.send("Nobody joined the giveaway :(")
}
if (embedGiveawayHandle.reactions.cache.get("🎉").count <= winnerCount.toString().slice(0, -1)) { // this if-statement can be removed
return giveawayChannel.send("There's not enough people in the giveaway to satisfy the number of winners!")
}
let winner = embedGiveawayHandle.reactions.cache.get("🎉").users.cache.filter((users) => !users.bot).random(winnerCount.toString().slice(0, -1));
const endedEmbedGiveaway = new Discord.MessageEmbed()
.setTitle("🎉 GIVEAWAY 🎉")
.setDescription(`${prize}\n\nWinner(s): ${winner}\nHosted By: **${message.author}**\nWinners: **${winnerCount.toString().slice(0, -1)}**\nParticipants: **${embedGiveawayHandle.reactions.cache.get("🎉").count - 1}**\nDuration: **${duration}**`)
.setColor('#FFFFFF')
.setTimestamp(Date.now() + ms(args[1])) // Displays time at which the giveaway ended
.setFooter("Giveaway ended");
embedGiveawayHandle.edit({embeds:[endedEmbedGiveaway]}); // edits original giveaway message to show that the giveaway ended successfully
const congratsEmbedGiveaway = new Discord.MessageEmbed()
.setDescription(`🥳 Congratulations ${winner}! You just won **${prize}**!`)
.setColor('#FFFFFF')
giveawayChannel.send({embeds: [congratsEmbedGiveaway]}).catch(console.error);
}, ms(args[1]));
} // end "Giveaway" role condition
}
})
client.login('INSERT YOUR BOT TOKEN HERE');

Getting a user input after an Embed (Discord.js)

So im trying to make a sort of pokemon catching bot just for fun and to test my skill, I've invited my friend to help me. We're trying to make a random spawn and a catching mechanism. The catching mechaninism didn't really work well since it detect the user input before the embed not after the embed which is impossible to catch. Any help will be much appreciate.
bot.on("message", async message => {
const args = message.content
.slice(prefix.length)
.trim()
.split(/ +/g);
let r = message.content.slice(bot.prefix.length+6)
let dex = Math.floor((Math.random() * 921) + 1);
let random = Math.floor((Math.random() * 5) + 1);
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) {
if(random===5){
const options = {
url: `https://pokeapi.co/api/v2/pokemon/${dex}`,
json: true
}
get(options).then(body => {
let Embed = new MessageEmbed()
.setTitle("A Wild pokemon has appeared")
.setDescription(`Quick, catch that pokemon!`)
.setThumbnail(body.sprites.front_default)
.setFooter(body.name)
.setColor("#00eaff")
message.channel.send(Embed);
})
get(options).then(body => {
if(message.content==(body.name)){
message.reply("You just caught a " + body.name);
}
else {
message.reply("Not that one!");
}
})
}
}
It is not impossible to catch. You can easily achieve this by using awaitMessages()
bot.on("message", async message => {
const args = message.content
.slice(prefix.length)
.trim()
.split(/ +/g);
let r = message.content.slice(bot.prefix.length + 6)
let dex = Math.floor((Math.random() * 921) + 1);
let random = Math.floor((Math.random() * 5) + 1);
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) {
if (random === 5) {
const options = {
url: `https://pokeapi.co/api/v2/pokemon/${dex}`,
json: true
}
get(options).then(async body => {
let Embed = new MessageEmbed()
.setTitle("A Wild pokemon has appeared")
.setDescription(`Quick, catch that pokemon!`)
.setThumbnail(body.sprites.front_default)
.setFooter(body.name)
.setColor("#00eaff")
const msg = await message.channel.send(Embed);
const filter = m => m.author.id === message.author.id
msg.channel.awaitMessages(filter, { max: 1, time: 60000, errors: ['time'] }) // 1 minute timer & max of 1 attempt at answering
.then(collected => {
get(options).then(body => {
if (collected.first().content == (body.name)) {
message.reply("You just caught a " + body.name);
}
else {
message.reply("Not that one!");
}
})
})
.catch(() => message.reply('you did not guess in time!'));
})
}
}

Categories