This is my code and im getting this error: RangeError [EMBED_DESCRIPTION]: MessageEmbed description must be a string can can someone help me please? i want to make leaderboard
const { MessageEmbed } = require("discord.js");
const Discord = require('discord.js');
const Database = require("#replit/database");
const db = new Database();
module.exports = {
name: "Leaderboard",
aliases: ['leader', 'leaderboard', 'топ', 'Топ'],
run: async (client, message, args) => {
const collection = new Collection();
await Promise.all(
message.guild.members.cache.map(async (member) => {
const id = member.id;
const bal = await db.get(`balance_${id}`);
console.log(`${member.user.tag} -> ${bal}`);
return bal !== 0
? collection.set(id, {
id,
bal,
})
: null;
})
);
const data = collection.sort((a, b) => b.bal - a.bal).first(10);
message.channel.send(
new MessageEmbed()
.setTitle(`Leaderboard in ${message.guild.name}`)
.setDescription(
data.map((v, i) => {
return `${i + 1}) ${client.users.cache.get(v.id).tag} => **${v.bal} coins**`;
})
)
);
},
};```
In setDescription you're calling data.map(...) which returns an array. You can use Array.prototype.join to create a string from the array elements: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join
data.map(...).join('\n')
If your array looked like this ['abc', 'def', 'ghi'] then the output of the join would be a string that looks like this:
abc
def
ghi
Related
this is my ../Events/Guild/guildMemberAdd.js https://sourceb.in/iEEfLj7uM7
im trying to set placeholders that will in turn give out an output like
Welcome to OnlyScoped.gg #azz#5271! We're glad to have you as the 500th member.
but output is
Welcome to OnlyScoped.gg <#undefined>! We're glad to have you join us as the undefinedth member.`
../Commands/Moderation/setup-welcome.js
const {Message, Client, SlashCommandBuilder, PermissionFlagsBits} = require("discord.js");
const welcomeSchema = require("../../Models/Welcome");
const {model, Schema} = require("mongoose");
module.exports = {
data: new SlashCommandBuilder()
.setName("setup-welcome")
.setDescription("Set up your welcome message for the discord bot.")
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
.addChannelOption(option =>
option.setName("channel")
.setDescription("Channel for welcome messages.")
.setRequired(true)
)
.addStringOption(option =>
option.setName("welcome-message")
.setDescription("Enter your welcome message.")
.setRequired(true)
)
.addRoleOption(option =>
option.setName("welcome-role")
.setDescription("Enter your welcome role.")
.setRequired(true)
),
async execute(interaction) {
const {channel, options} = interaction;
const welcomeChannel = options.getChannel("channel");
const welcomeMessage = options.getString("welcome-message");
const roleId = options.getRole("welcome-role");
if(!interaction.guild.members.me.permissions.has(PermissionFlagsBits.SendMessages)) {
interaction.reply({content: "I don't have permissions for this.", ephemeral: true});
}
welcomeSchema.findOne({Guild: interaction.guild.id}, async (err, data) => {
if(!data) {
const newWelcome = await welcomeSchema.create({
Guild: interaction.guild.id,
Channel: welcomeChannel.id,
Msg: welcomeMessage,
Role: roleId.id
});
}
interaction.reply({content: 'Succesfully created a welcome message', ephemeral: true});
})
}
}
../Models/Welcome.js
const { model, Schema } = require("mongoose");
let welcomeSchema = new Schema({
Guild: String,
Channel: String,
Msg: String,
Role: String,
});
module.exports = model("Welcome", welcomeSchema);
im attempting to use string.replace()but its not working as expected
i decided to put it in guildMemberAdd.js since when a member joins this gets runs so it would be unwise to place it in setup-welcome.js or Welcome.js since those are not listening for anything.
for reference here's my package.json:
https://sourceb.in/FMBgygjyoh
for the record i cant find any of the id's like member.id or member.count so those are wild guesses as to what they are. it could very well just be that as im still learning v14 this is my first project in it.
one other way i thought could work is if i just pass it off as an interpolated string in mongodb but it seems that the only string is with "" so i cant use default ones like ${member.count} so i decided to add placeholders
The basics of formatting a template are this:
const string = "Welcome to OnlyScoped.gg {tagUser}! We're glad to have you as the {memberCount} member.";
string = string.replace(/{tagUser}/g, member.toString());
string = string.replace(/{memberCount}/g, '500th');
return string; // "Welcome to OnlyScoped.gg <#123456789012345678>! We're glad to have you as the 500th member.";
To make something extensible, put template strings like this somewhere in your configuration:
{
"welcome_message": "Welcome to OnlyScoped.gg {tagUser}! We're glad to have you as the {ordinal:memberCount} member."
}
and make a function
function formatMessage(template, lookup) {
let output = template;
output = output.replace(/{ordinal:([^}]*)}/g, (_, target) => withOrdinalSuffix(lookup(target)));
output = output.replace(/{([^}]*)}/g, (_, target) => lookup(target));
return output;
}
// https://stackoverflow.com/a/31615643/3310334
// turn 1 into '1st', 500 into '500th', 502 into '502nd'
function withOrdinalSuffix(n) {
var s = ["th", "st", "nd", "rd"],
v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
}
and then use the function with a template and the lookup function:
client.on('guildMemberAdd', member => {
const welcomeMessageTemplate = config.welcome_message;
const memberCount = member.guild.members.filter(member => !member.user.bot).size;
const lookup = (item) => {
const items = {
memberCount,
tagUser: member.toString()
};
return items[item];
};
const welcomeMessage = formatMessage(welcomeMessageTemplate, lookup);
const welcomeChannel = member.guild.channels.cache.find(channel => channel.name === 'welcome');
welcomeChannel.send(welcomeMessage);
});
The main issue I can see is incorrect property names as you mention in the question.
DiscordJS Docs: GuildMember
member.id => The Members ID
member.user.username => The Members username
member.guild.name => The Server's Name
member.guild.memberCount => Number of users within the Server
I'd advise the user to input data in a specific format like Hello {userName}!. Then you could run a program like
while (string.includes('{userName}')) {
string = string.replace('{userName}', member.user.username);
}
I am trying to send an embed whenever a invite is created.
Channel set file
let config = require("../config.json");
const { MessageEmbed } = require("discord.js");
const Discord = require("discord.js");
const client = new Discord.Client();
module.exports = {
name: "setinvite",
description: "set invite channel log.",
async execute(message, args) {
if (!message.member.hasPermission(`ADMINISTRATOR`)) {
return message.channel.send(
`:x: You do not have permission to use this command!`
);
} else {
let channelx =
message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx)
return message.channel.send(
`:x: Please specify a channel to make it as the modlogs!`
);
message.channel.send(`${channelx} has been set!`);
}
},
};
Index.js Modules (PS: I took the most relevant ones.)
const Discord = require("discord.js");
const client = new Discord.Client();
const fs = require("fs");
const { MessageEmbed } = require("discord.js");
const guildInvites = new Map();
const { channelx } = require("./commands/setinvite");
Index.js file
client.on("inviteCreate, message", async (invite) => {
const setc = client.channels.cache.get(`${channelx}`);
message.guild.fetchInvites().then((invites) => {
let allInvites = invites.map((i) => ({
name: "Invite",
value: `**Inviter:** ${i.inviter}
**Code:** https://discord.gg/${i.code}
**Usages:** ${i.uses} of ${i.maxUses === 0 ? "∞" : i.maxUses}
**Expires on:** ${
i.maxAge
? new Date(i.createdTimestamp + i.maxAge * 1000).toLocaleString()
: "never"
}`,
inline: true,
}));
setc.send(new Discord.MessageEmbed().addFields(allInvites));
});
});
I don't think the two events (inviteCreate, message) belong I did it because I received a error:
ReferenceError: message is not defined
Now, the channel set features works as intended but whenever the invite is created the embed doesn't send.
You can't merge all events inside one function.
You only need to keep the inviteCreate event. Then, you have to find a way to get the guild without using the "message" variable. Instead you can use the "invite" parameter that is present inside the inviteCreate event.
client.on("inviteCreate", async (invite) => {
const setc = client.channels.cache.get(`${channelx}`);
invite.guild.fetchInvites().then((invites) => {
let allInvites = invites.map((i) => ({
name: "Invite",
value: `**Inviter:** ${i.inviter}
**Code:** https://discord.gg/${i.code}
**Usages:** ${i.uses} of ${i.maxUses === 0 ? "∞" : i.maxUses}
**Expires on:** ${
i.maxAge
? new Date(i.createdTimestamp + i.maxAge * 1000).toLocaleString()
: "never"
}`,
inline: true,
}));
setc.send(new Discord.MessageEmbed().addFields(allInvites));
});
});
I am trying to send a message to a specific channel, and it works only in the server, where the channel is in. Do you have any idea how to fix it?
What I tried:
message.guild.channels.cache.get("816714319172599828")
The error I get:
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'channels' of undefined
Edit: My full code:
const { DiscordAPIError } = require("discord.js");
const Discord = require('discord.js');
const client = new Discord.Client();
module.exports = {
name: "feedback",
description: "Send your feedback for the bot!",
async execute(message, args) {
const feedback = args.slice(0).join(" ");
const no_feedback = new Discord.MessageEmbed()
.setColor("#993333")
.setTitle("Feedback")
.setDescription("An error has occured.")
.addField("Error" , "You didn't type your feedback after the command!")
.addField("What to do?" , "Type `=feedback` and add your feedback right after.")
.setFooter(message.author.username)
.setTimestamp();
const confirm = new Discord.MessageEmbed()
.setColor("#993333")
.setTitle("Confirm")
.setDescription("Trolling results in not being able to do this command anymore.")
.addField("Limit" , `Reactions will not be accepted after 10 minutes.`)
.addField("Feedback" , `Your feedback will be shown as \n **${feedback}**`)
.setFooter(message.author.username)
.setTimestamp();
if(!feedback) return message.reply(no_feedback);
const confirmation = await message.channel.send(confirm);
const emojis = ['✅', '❌'];
emojis.forEach((emoji) => confirmation.react(emoji));
const filter = (reaction, user) =>
user.id === message.author.id && emojis.includes(reaction.emoji.name);
const collector = confirmation.createReactionCollector(filter, { max: 1, time: 600000 });
collector.on('collect', (reaction, user) => {
const [confirm, cancel] = emojis;
confirmation.delete();
if (reaction.emoji.name === cancel) {
const cancelEmbed = new Discord.MessageEmbed()
.setColor('#993333')
.setTitle('Cancelled')
.setDescription(
`Cancelled! The feedback has not been sent.`,
)
.setFooter(message.author.username)
.setTimestamp();
return message.channel.send(cancelEmbed);
}
if (reaction.emoji.name === confirm) {
const doneEmbed = new Discord.MessageEmbed()
.setColor('#993333')
.setTitle('Sent')
.setDescription(
`Your feedback has been sent!`,
)
.setFooter(message.author.username)
.setTimestamp();
message.channel.send(doneEmbed);
const feedback_admins = new Discord.MessageEmbed()
.setColor('#993333')
.setTitle('Feedback')
.setDescription(
`Unread`,
)
.addFields(
{name:"From" , value: message.author.username} ,
{name:"In" , value: message.guild.name} ,
{name:"Feedback" , value: feedback} ,
{name:"❌" , value: "React to this message if the \n feedback isn't helpful"} ,
)
.setFooter(message.author.username)
.setTimestamp();
const feedback_channel = message.guild.channels.cache.get("816714319172599828");
const fbmsg = feedback_channel.send(feedback_admins)
.then((embedMsg) => {
const emojis2 = ['✅', '❌'];
emojis2.forEach((emoji) => embedMsg.react(emoji))
const filter2 = (reaction, user) =>
!user.bot && emojis2.includes(reaction.emoji.name);
const collector_2 = embedMsg.createReactionCollector(filter2, {max: 1});
collector_2.on('collect', (reaction, user) => {
const [accept, deny] = emojis2;
embedMsg.delete();
if (reaction.emoji.name === accept) {
const accepted = new Discord.MessageEmbed()
.setColor('#009933')
.setTitle('Feedback')
.setDescription(
`Accepted`,
)
.addFields(
{name:"From" , value: message.author.username} ,
{name:"In" , value: message.guild.name} ,
{name:"Feedback" , value: feedback} ,
)
.setFooter(message.author.username)
.setTimestamp();
feedback_channel.send(accepted);
}
}
)
}
)
}})}}
You have to use message.client.channels.fetch(channelID) and since the method fetch() returns a Promise, you have to put an await in front of it and make your execute async.
So change this
execute: (message, args) => {
// your code
}
To this:
execute: async (message, args) => {
// example:
const channelID = '<Your target channel id>'
const channel = await message.client.channels.fetch(channelID)
}
So i am coding a bot , in Node.js with Visual Studio Code. I want to have a channel, that when a user joins the guild , will send 'Welcome user and invited by thisuser(Total Invites: 5)
The code is :
module.exports = (client) => {
const invites = {} // { guildId: { memberId: count } }
const getInviteCounts = async (guild) => {
return await new Promise((resolve) => {
guild.fetchInvites().then((invites) => {
const inviteCounter = {} // { memberId: count }
invites.forEach((invite) => {
const { uses, inviter } = invite
const { username, discriminator } = inviter
const name = `${username}#${discriminator}`
inviteCounter[name] = (inviteCounter[name] || 0) + uses
})
resolve(inviteCounter)
})
})
}
client.guilds.cache.forEach(async (guild) => {
invites[guild.id] = await getInviteCounts(guild)
})
client.on('guildMemberAdd', async (member) => {
const { guild, id } = member
const invitesBefore = invites[guild.id]
const invitesAfter = await getInviteCounts(guild)
console.log('BEFORE:', invitesBefore)
console.log('AFTER:', invitesAfter)
for (const inviter in invitesAfter) {
if (invitesBefore[inviter] === invitesAfter[inviter] - 1) {
const channelId = '731801004462571602'
const channel = guild.channels.cache.get(channelId)
const count = invitesAfter[inviter]
channel.send(
`Please welcome <#${id}> to the Discord! Invited by ${inviter} (${count} invites)`
)
invites[guild.id] = invitesAfter
return
}
}
})
}
This code works perfectly with console but i am facing a problem,never post the message in the channel!
The message might not be being sent because of the channel ID double check you are using the right channel ID and you might want to try changing
const channel = guild.channels.cache.get(channelId) to this
const channel = client.channels.cache.get(channelId)
i made a discord bot with discord.js and tried to do a help command to show the user all available commands.
example command: avatar.js
module.exports.run = async(bot, message, args) => {
let msg = await message.channel.send("doing some magic ...");
let target = message.mentions.users.first() || message.author;
await message.channel.send({files: [
{
attachment: target.displayAvatarURL,
name: "avatar.png"
}
]});
msg.delete();
}
module.exports.help = {
name: "avatar",
description: "show the avatar of a user",
usage: "[#user]"
}
Then i tried to send a message with the complete list of the commands like:
command 1
description
usage
command 2
description
usage
...
help.js
const fs = require("fs");
const Discord = require("discord.js");
module.exports.run = async(bot, message, args, con) => {
fs.readdir("./cmds/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
var namelist = "";
var desclist = "";
var usage = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.help.name;
desclist = props.help.description;
usage = props.help.usage;
});
message.author.send(`**${namelist}** \n${desclist} \n${usage}`);
});
}
module.exports.help = {
name: "help",
description: "show all commands",
usage: ""
}
my code is kinda working but it only sends the first command.
Im pretty new to javascript and i can't find a solution to this.
I tried to google everything on foreach maps discord collections and stuff but i cant find a example where the results get combined together.
If anybody can help me or give me a hint where i can search for something like this. Would be awesome.
The reason your code is only sending the one command is because your code only calls message.author.send('...' once. You successfully set the variables namelist, desclist, and usage with data from every file, but your .forEach(... loop just overwrites all of the data when it moves to the next files.
Try to send data inside each iteration of the .forEach(... loop like this:
var namelist = "";
var desclist = "";
var usage = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.help.name;
desclist = props.help.description;
usage = props.help.usage;
// send help text
message.author.send(`**${namelist}** \n${desclist} \n${usage}`);
});
you should do this in an Array and it'll solve the problem, so it should look like this.
module.exports.run = async(bot, message, args, con) => {
fs.readdir("./cmds/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
let filesArray = [props.help.name, props.help.description, props.help.usage]
message.author.send(`**${filesArray[0]}** \n${filesArray[1]} \n${filesArray[2]}`);
});
});
}
sorry for the late response.
Here is my take on this.... it works for me.
const Discord = require('discord.js');
const fs = require("fs");
module.exports = {
name: 'help',
description: 'Lists available commands',
async run(client, message, args, con) {
fs.readdir("./commands/", (err, files) => {
if(err) console.error(err);
let jsfiles = files.filter(f => f.split(".").pop() === "js");
if(jsfiles.length <= 0) {
console.log("No commands to load!");
return;
}
var namelist = "";
var desclist = "";
let result = jsfiles.forEach((f, i) => {
let props = require(`./${f}`);
namelist = props.name;
desclist = props.description;
message.author.send(`**${namelist}** \n${desclist} \n`);
});
});
}
I'm using DiscordJS 12 so this may not work on 11.
const discord = require('discord.js')
module.exports = {
name: 'cmd-list',
async run(client, message, args) {
const commandFiles = readdirSync(join(__dirname, "<your commands folder name>")).filter(file => file.endsWith(".js")); // Get files
const cmdmap = commandFiles.map(files => `${files}`).join(' | Working\n')
const embed = new discord.MessageEmbed()
.setDescription(cmdmap)
message.channel.send(embed)
}
}
You can just use discord 's normal embed system like this:
const { Message, MessageEmbed } = require('discord.js');
Add this to the top of your code then type everything as the following to make a normal embed like this:
const embed = new MessageEmbed()
.setTitle(`Your title!`)
.setColor(5814783)
.setTimestamp()
.setThumbnail('')
.setDescription(`Your description`)
.addFields(
{ name: 'Field 1', value: `Filed 1 Value`},
{ name: 'Field 2', value: `Filed 2 Value` },
{ name: 'Field 3', value: `Filed 3 Value`, inline: true },
{ name: 'Field 4', value: `Filed 4 Value`, inline: true },
{ name: 'Field 5', value: `Field 5 Value`, inline: true },
)
message.channel.send(embed2)