The current embed I have looks like this:
However, I want the sections named Total to be in the same line. I'm not sure how you break the inline without the second Total not being in the same line as well.
The result I'm looking for:
My current code:
//ignore the card[1], card[0], etc. Those are arrays for what I want to post as emoji's/card values
const embed = new Discord.MessageEmbed()
.setTitle(`Blackjack`)
//card[1] = rank; card[0] = suit
.addFields(
{ name: 'Your Hand', value: `${card[1]}${card[0]}${card3[1]}${card3[0]}`, inline: true },
{ name: "Dealer's Hand", value : `${card2[1]}${card2[0]}`, inline: true },
{ name: "Total: [calculate later]", value: "\u200B" },
{ name: "Total: [to create later]", value: "\u200B", inline: true },
)
.setFooter("Commands\n!stand\n!hit\n!double\n!fold\n!split");
message.channel.send(embed);
I think it would be easier to add the total value in the same column by including it in the hands' value on the next line after the cards. You could also add some extra space between the two columns:
const embed = new MessageEmbed().setTitle(`Blackjack`).addFields(
{
name: 'Your Hand',
value: `A♦2♠7♦\n\nTotal: **10/20**`,
inline: true,
},
{
name: '\b',
value: '\b',
inline: true,
},
{
name: "Dealer's Hand",
value: `K♦4♣\n\nTotal: **14**`,
inline: true,
},
);
message.channel.send(embed);
You need to set both field's inline option to true. Keep in mind that the result may be different on different sized screens
{ name: "Total: [calculate later]", value: "\u200B", inline: true},
{ name: "Total: [to create later]", value: "\u200B", inline: true},
Related
I want to send data from an array in one embed message with few fields but my code sends them as 4 different embed messages with one field
I tried with this Code :
const pListEmbed = new Discord.MessageEmbed()
.setColor('#03fc41')
.setTitle('Connected')
.setDescription(Total : ${list.length})
.setThumbnail(config.logo)
.addFields(
array.flatMap(user => [
{ name: 'ID', value: user.id, inline: true },
{ name: 'Name', value: user.user_name, inline: true },
{ name: 'Identifier', value: user.identifier, inline: true }
])
)
)
.setTimestamp(new Date())
.setFooter('Used by: ' + message.author.tag, ${config.SERVER_LOGO});
message.channel.send(pListEmbed);
But it sends 4 embed messages with just one field that have id,username and identifier, and i don't want it like this. I want it to send one embed message with 4 different fields that have these 4 id,username and identifiers (we don't know how many of them we have)
Array :
[
{
id: '46892319372',
user_name: 'testerOne',
identifier: '20202'
}
]
[
{
id: '15243879678',
user_name: 'testerTwo',
identifier: '20201'
}
]
[
{
id: '02857428679',
user_name: 'testerThree',
identifier: '20203'
}
]
[
{
id: '65284759703',
user_name: 'testerFour',
identifier: '20204'
}
]
Your question is very unclear. If you want to send one embed for every user containing the ID, name and identifier, then you could do this:
list.forEach(user => {
const pListEmbed = new Discord.MessageEmbed()
.setColor('#03fc41')
.setTitle('Connected')
.setDescription(Total : ${list.length})
.setThumbnail(config.logo)
.setTimestamp(new Date())
.setFooter('Used by: ' + message.author.tag, ${config.SERVER_LOGO});
.addFields(
{
name: "ID"
value: user.id,
inline: true
},
{
name: "Name"
value: user.user_name,
inline: true
},
{
name: "Identifier"
value: user.identifier,
inline: true
}
)
message.channel.send(pListEmbed);
})
If on the other hand you want to send one embed only and it contains all the IDs, all the names, and all the identifiers, then this is impossible. Embed have character limits and since you don't know how many users you have, there could be thousands, thus busting the limit. And that would block you from sending the embed.
Also your "array" is in fact multiple arrays containing only one element each. I don't know if that's what you intended or not but it's not an array but multiple little ones.
I am trying to make a toggle able slash command, if they pick the disable option it turns it off but when if you pick the enable option it asks to pick a channel but it gives this error
Error:
DiscordAPIError[50035]: Invalid Form Body
23.name[BASE_TYPE_REQUIRED]: This field is required
rawError: {
code: 50035,
errors: { '23': [Object] },
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'put',
url: 'https://discord.com/api/v9/applications/971024098098569327/commands'
Code:
module.exports = {
name: 'welcomer',
permissions: 'MANAGE_CHANNELS',
description: 'Set Where Welcome Messages Get Sent To.',
options: [
{
name: 'toggle',
description: 'Toggle On/Off The Welcomer',
type: 3,
required: true,
choices: [
{
name: 'disable',
value: 'off',
},
{
name: 'enable',
value: 'on',
choices: [
{
name: 'channel',
description: 'Select channel to send welcome messages to',
type: 7,
required: true,
},
]
},
],
},
],
Those would be an example of a subcommand and need to be indicated as such and will need descriptions in a couple places.
module.exports = {
name: 'welcomer',
permissions: 'MANAGE_CHANNELS',
description: 'Set Where Welcome Messages Get Sent To.',
options: [{
name: 'disable',
description: `'Disable welcomer`, // Added needed description
type: 1, //converted to subcommmand
}, {
name: 'enable',
description: `'Enable welcomer`, // Added needed description
type: 1, //converted to subcommmand
options: [{
name: 'channel',
description: 'Select channel to send welcome messages to',
type: 7,
required: true,
channel_types: [0] // allows only text channels to be selected
}]
}],
// run command pick only one of the below two
// if command.execute()
async execute(client, interaction, args)
// if command.run()
run: async (client, interaction, args) =>
// command code below here assumes you have the code in your `interactionCreate` listener to set up args
{
if (args.disable) {
// Code to turn off
} else if (args.enable) {
const channel = args.channel
// Code to turn on
};
}
}
I was coding a userInfo command but when I use the command, the joinedAtTimeStamp is showing <t:NaN:R> in the embed. It's the only problem in this code.
My code:
const { MessageEmbed, ContextMenuInteraction } = require("discord.js");
module.exports = {
name: "userInfo",
aliases: ["user"],
permissions: ["SEND_MESSAGES", "ATTACH_FILES"],
description: "user",
async execute(message, args, cmd, client, Discord, profileData) {
const target = message.mentions.users.first();
if(!args[0]) {
const response2 = new MessageEmbed()
.setColor("RANDOM")
.setAuthor({name: message.author.tag, iconURL: message.author.displayAvatarURL({dynamic: true})})
.setThumbnail(message.author.displayAvatarURL({dynamic: true}))
.addFields(
{name: "ID", value: message.author.id},
{name: "Joined Server", value: `<t:${parseInt(message.author.joinedTimestamp / 1000)}:R>`, inline: true},
{name: "Account Created", value: `<t:${parseInt(message.author.createdTimestamp / 1000)}:R>`, inline: true},
);
message.reply({embeds:[response2]});
}
const response = new MessageEmbed()
.setColor("RANDOM")
.setAuthor({name: target.tag, iconURL: target.displayAvatarURL({dynamic: true})})
.setThumbnail(target.displayAvatarURL({dynamic: true}))
.addFields(
{name: "ID", value: target.id},
{name: "Joined Server", value: `<t:${parseInt(target.joinedTimestamp / 1000)}:R>`, inline: true},
{name: "Account Created", value: `<t:${parseInt(target.createdTimestamp / 1000)}:R>`, inline: true},
);
message.reply({embeds: [response], ephemeral: true})
}
}
I am using discord.js v13 and node 16.
message.author is a User and it doesn't have a joinedTimestamp property, only GuildMembers have. message.member represents the author of the message as a guild member, so you can use that as it will have a joinedTimestamp property.
The reason you see NaN instead of the correct value is because parseInt will return NaN if you try to parse undefined:
console.log('undefined:', parseInt(undefined / 1000, 10));
console.log('3459192421512:', parseInt(3459192421512 / 1000, 10));
The following code should work as expected
.addFields(
{ name: 'ID', value: message.author.id },
{
name: 'Joined Server',
value: `<t:${parseInt(message.member.joinedTimestamp / 1000, 10)}:R>`,
inline: true,
},
{
name: 'Account Created',
value: `<t:${parseInt(message.author.createdTimestamp / 1000, 10)}:R>`,
inline: true,
},
);
As for target, it's the same issue; message.mentions.users.first() is a User. You could create a new variable, e.g. targetMember and assign message.mentions.members.first(), so it will be a GuildMember:
const target = message.mentions.users.first();
const targetMember = message.mentions.members.first();
And then, just replace target:
.addFields(
{ name: 'ID', value: target.id },
{
name: 'Joined Server',
value: `<t:${parseInt(targetMember.joinedTimestamp / 1000, 10)}:R>`,
inline: true,
},
{
name: 'Account Created',
value: `<t:${parseInt(target.createdTimestamp / 1000, 10)}:R>`,
inline: true,
},
);
PS: It's a good idea to use the radix in parseInt. That's why I added 10 as the second parameter in parseInt.
Could you verify the type of target.joinedTimestamp?
It could be that the double conversion you are doing here:
parseInt(target.joinedTimestamp / 1000)
destroyed your number.
(You are converting whatever target.createdTimestamp is to number, dividing it by 100 (making it a floating point number) and then discarding the floating point by converting back to int.)
Trying to write an info command. I don't think I'm correctly getting the guild member to get the .joinedAt value, and I haven't been able to find a recent example. Here is the relevant code. Any help appreciated:
const user = await interaction.options.getUser("user").fetch(true);
embed.setTitle(`User info for ${user.username}`);
embed.addFields(
{ name: "User Tag:", value: `${user.tag}`, inline: true },
{ name: "User ID:", value: `${user.id}`, inline: true },
{ name: "Bot Status:", value: `${user.bot}`, inline: true },
{
name: "Account Creation Date:",
value: `${user.createdAt}`,
inline: false
},
// I'm trying to get the .joinedAt value here
{
name: "Guild Join Date:",
value: `${interaction.message.guild.member(user).joinedAt}`,
inline: false
}
);
You are getting just common user using getUser instead of getMember which is server member
Currently having a choice_prompt that asks the user for some options to validate. To move to the next step of the waterfall, the user's input has to either be the value, or a synonym associated with that value.
If a user types something that is not the value or synonym, the choicePrompt just loops. I want to warn the user "Enter a number between 1 - 6".
async question2_1(step) {
return await step.prompt(CHOICE_PROMPT, {
prompt: '"1/3: How easy were the course materials to navigate and follow?',
choices: ChoiceFactory.toChoices([' = Very Hard', '', '', '', '', ' = Very Easy']),
style: ListStyle.list
});
}
You need to add a retryPrompt option like this:
async question2_1(step) {
return await step.prompt(CHOICE_PROMPT, {
prompt: '"1/3: How easy were the course materials to navigate and follow?',
choices: ChoiceFactory.toChoices([' = Very Hard', '', '', '', '', ' = Very Easy']),
style: ListStyle.list,
retryPrompt: 'Enter a number between 1 - 6'
});
}
If you want any of the original prompt to be re-prompted, you'll need to add that too. The user will only get re-prompted with the text you add under retryPrompt.
EDIT: I was looking at this again to use synonyms and I think despite displaying as a numbered list, you aren't going to get the expected values with all those null strings. Maybe I'm wrong because I haven't done a choice like that, but I would probably explicitly define my choices like below. This allows you to set a separate Title (shown) and Value (send on backend) for each choice, as well as add synonyms if you want (you can also add synonyms with the simpler definition as you have above).
async question2_1(step) {
return await step.prompt(CHOICE_PROMPT, {
prompt: '"1/3: How easy were the course materials to navigate and follow?',
choices: [
{value:'1', action: {type: 'imBack', title: '= Very Hard', value: '1'}, synonyms: ['1']},
{value: '2', action: {type: 'imBack', title: ' ', value: '2'}, synonyms: ['2']},
{value: '3', action: {type: 'imBack', title: ' ', value: '3'}, synonyms: ['3']},
{value: '4', action: {type: 'imBack', title: ' ', value: '4'}, synonyms: ['4']},
{value: '5', action: {type: 'imBack', title: ' ', value: '5'}, synonyms: ['5']},
{value: '6', action: {type: 'imBack', title: '= Very Easy', value: '6'}, synonyms: ['6']},
],
style: ListStyle.list,
retryPrompt: 'Enter a number between 1 - 6'
});
}