Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

118
Views
Replace multiple placeholders with their corresponding values in string

I have a command to make a custom welcome message so when someone say changes the title to the custom placeholder {user.id} it would change the title to the joining users ID

I tried ${(cardText, placeholders)} but that just returns [object Object] in the embed

So cardText is {user.tag} so i want it to look in placeholders and see if there is a placeholder in the string and if there is change it to the right value so in this case it would change it to member.user.tag

Code:

module.exports = async (client, member) => {
    
    const guildSchema = require('../../models/guildSchema');
    const data = await guildSchema.findOne({
        id: member.guild.id
    });
 
    const placeholders = {
        '{client.avatar}': client.user.displayAvatarURL(),
        '{client.username}': client.user.username,
        '{client.mention}': client.user,
        '{client.tag}': client.user.tag,
        '{client.id}': client.user.id,
 
        '{user.avatar}': member.user.displayAvatarURL(),
        '{user.username}': member.user.username,
        '{user.mention}': member.user,
        '{user.tag}': member.user.tag,
        '{user.id}': member.user.id,
 
        '{guild.memberCount}': member.guild.memberCount,
        '{guild.icon}': member.guild.iconURL,
        '{guild.name}': member.guild.name,
        '{guild.id}': member.guild.id,
    };
    
    const cardTitle = (data.welcome.title === null) ? 'Welcome To The Server' : data.welcome.title;
    const cardText = (data.welcome.text === null) ? '{user.tag}' : data.welcome.text;
    const cardSubtitle = (data.welcome.subtitle === null) ? 'Member Count: {guild.memberCount}' : data.welcome.text;
 
        const embed = new Discord.MessageEmbed()
        .setTitle(`${(cardTitle, placeholders)}`),
        .setDescription(`${(cardText, placeholders)}`),
        .setFooter(`${(cardSubtitle, placeholders)}`),
 
        channel.send({ embeds: [embed] });
}
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

The problem with OP's code was that the example they were following had some conventions that let users have templating in their message text denoted by {}.

For example, in 'Member Count: {guild.memberCount}', the {guild.memberCount} would be replaced to give us 'Member Count: 123' or something.

But the function to replace this placeholders was missing from their source.

Hence, a parsing function such as:

const replacePlaceholder = (template, placeholders) => {
  //if there is no placeholder, return.
  if (template.indexOf('{') === -1) return template;
  //get the string inside the {}
  const toReplace = template.slice(
    template.indexOf('{'),
    template.indexOf('}') + 1
  );

  //keep replacing until { character is not found.
  return replacePlaceholder(
    template.replace(toReplace, placeholders[toReplace]),
    placeholders
  );
};

was needed. In this context, it also makes sense why OP was using:

const embed = new Discord.MessageEmbed()
  .setTitle(`${(cardTitle, placeholders)}`),
  .setDescription(`${(cardText, placeholders)}`),
  .setFooter(`${(cardSubtitle, placeholders)}`),

They were originally function calls such as:

const embed = new Discord.MessageEmbed()
  .setTitle(`${replacePlaceholder(cardTitle, placeholders)}`),
  .setDescription(`${replacePlaceholder(cardText, placeholders)}`),
  .setFooter(`${replacePlaceholder(cardSubtitle, placeholders)}`),
about 4 years ago · Juan Pablo Isaza Report

0

Let's use regular expressions to do the matching for us. Because your keys have characters that have special meaning in regular expressions ({ and }), we'll need to escape those.

Pulled from escape-string-regexp:

const escapeRegex = (string) => string
    .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
    .replace(/-/g, '\\x2d');

Then let's write a function that takes a template and the placeholders. We should create a regular expression from the placeholder like this:

const regex = new RegExp("(" + Object.keys(placeholders).map(escapeRegex).join("|") + ")", "g");

For each key in the placeholders object, we escape the special characters, and join it all with |, wrapping the result in parentheses. Then we give it the g (global) flag so it provides us all the matches.

For you, this generated regex would look something like:

/(\{client.avatar\}|\{client.username\}|...|\{guild.id\})/g

Lastly, we want to use this regex and replace all occurrences of placeholders with their corresponding value.

return template.replace(regex, (_, match) => placeholders[match]);

So the full code looks like this:

const escapeRegex = (string) => string
    .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
    .replace(/-/g, '\\x2d');

function fill(template, placeholders) {
    const regex = new RegExp("(" + Object.keys(placeholders).map(escapeRegex).join("|") + ")", "g");

    return template.replace(regex, (_, match) => placeholders[match]);
}

Example usage:

fill("My name is {name}!", { "{name}": "Kelly" }); // "My name is Kelly!"

You can try it out here, just click the link and hit "Run". To the right you'll see the output.


Why don't we just use something like this:

template
    .replaceAll("{client.avatar}", placeholders["{client.avatar}"])
    .replaceAll("{client.username}", placeholders["{client.username}"])
    .replaceAll(...)
    // ...

Well first of all, that's not really DRY, is it? You could help with that using a loop:

for (const [place, value] of Object.entries(placeholders)) {
    template = template.replaceAll(place, value);
}

But then there's a catch! What if some placeholder's value contained another placeholder? Then you'd replace the new placeholder with a new value! This might lead to unexpected behavior, which is why I suggested using this solution instead; replace all matches at once, preventing this from happening.

Placeholders:

{bar} => i love {foo}
{foo} => 42

And then:

say {bar}
say i love {foo}
say i love 42

Uh oh!

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!