Skip to main content

The short version

Almost every place that accepts variables runs the same resolver: it takes your text, finds every {variable} in it and swaps it for data from whatever set the message off (the member who joined, the giveaway that ended, the message that matched an autoresponder). The data it has depends on that event, the rules don’t.

The order of the steps

1

Pictures and reactions are taken out

{imgcard:name} is removed from the text and turns into the image card of the message. {reactreply:emoji} is removed and becomes a reaction on the sent message.
Petto welcomes Mia with an embed whose picture is the welcome card with her name and member number, and a 👋 reaction under it

In Discord: {imgcard:welcome} became the card of the embed and {reactreply:👋} a reaction.

2

Functions run

{choose:a|b|c}, {timestamp:<when>|<style>}, {range:1-100}, {arg1} … {arg10} and {args_from:N} are worked out, fresh every time. The same saved message gives a different {choose:…} or {range:…} each time it is sent.
kira runs !roll twice and gets a different number and a different line each time

In Discord: the same command twice: {range} and {choose} are picked again each time.

3

Everything else is looked up in one pass

Each remaining {name} is matched, ignoring case and spaces inside the braces, against Petto’s list and then against the names other bots use. What a variable gives is never read again, so a member who writes {server_owner} in a message doesn’t make {message_content} ping the owner.
nova writes {server_owner} in a message and Petto's answer repeats it as text, without mentioning the owner

In Discord: {server_owner} written by a member stays text inside {message_content}.

Because functions run first, a function can’t contain other variables: in {choose:Hi {user}|Hey} the first } closes the function early. Write {choose:Hi|Hey} {user} instead.

Known, unknown and empty

Petto fills {user} with chu, leaves {level} empty between the brackets and keeps {usr} as it was written

In Discord: a known variable, a known one without data here, and an unknown one.

This is why the Leveling variables only make sense in the level-up message and {gw.*} only in giveaway messages. Using them elsewhere is harmless, they just give nothing.

Two naming styles, same result

{user_name} and {user.name} resolve identically. The underscore style is the original set, the dot style was added for readability and matches {guild.*}, {channel.*} and the rest. Neither is going away, use whichever reads better.

Words and dates follow the server’s language

The words Petto itself writes into a variable (Yes, Never, Level 2, Not boosting), dates like {user.joined_at} and the ordinal endings (1st, 1.º, 1º) follow the server’s language. Your own text, names and the server’s data are never translated. {date} uses Colombia time (GMT-5); for a time that shows in each reader’s own time zone use the {timestamp…} variables.
Petto fills {user.boost}, {user.boost_since}, {user.joined_at}, {user.join_position_suffix} and {guild.boost_tier} for chu

In Discord: the words, dates and ordinal endings that Petto writes, in the server's language.

Silent mentions

Put a ! right before a mention and it shows as the normal blue mention, but nobody is notified. Without the !, the mention works as always. It works in any message Petto sends, so you can write who a message is about without waking them.
Petto posts in announcements: @everyone Movie night starts at 8 PM in the voice lounge. Questions? Ask @Moderators. Both mentions show as blue pills

In Discord: the message was written with !@everyone and !@Moderators. Both show as mentions and nobody gets a notification.

The forms

Example

The rules

  • The ! goes at the start of the text or after a space, a new line or punctuation. Hello !@here and (!@here) are silent, hello!@here is not.
  • To show the characters !@everyone as plain text, write \!@everyone.
  • It matters in plain messages and in Components V2 text, which are where a mention can notify. In the title, description, fields and footer of a classic embed a mention never notifies, so the ! is only removed there.
  • A message with silent and normal mentions notifies only the normal ones.
  • The one limit: a silent @everyone next to a normal @everyone in the same message does notify, because Discord decides it once per message. Use one kind in a message.
  • The ! only ever removes notifications. A feature that never pings (timers and feeds, for example) does not ping with or without it.
  • The previews of the dashboard draw a silent mention as a normal mention, without the !.

When to use it

Use it when a message should show who it is about or who to ask, without waking anyone: an announcement that names !@everyone or !@Moderators as text, a welcome that says Ask !@Moderators if you need help, or a giveaway message that names the winners’ role. For a real ping, write the mention as always.

Testing a message

You don’t need a real event to see the result:
  • !welcome test, !leave test, !boost test and !dmonjoin test send the message with your own account as the member.
  • !embed preview <name> builds a saved embed with you as the member and the current channel, so variables are filled in.
  • The dashboard previews fill variables with sample data (a member called Liam, a server with 1,204 members), and a test message sent from the dashboard uses your real account and server.
liam runs !welcome test and Petto writes the welcome with liam as the member, the server name, the member count and one of the two choices

In Discord: a welcome text tested with !welcome test, every variable filled in.

Variables of one event (a case number, a giveaway prize, a level) stay empty in a preview, because there is no event yet.

Where this resolver is used

Welcome, leave, boost, DM on join and birthday messages, autoresponders, custom commands, level-ups, giveaways, bump messages, sanction messages, starboard and monkeyboard, suggestions, confessions, polls, partners, requests, forms, honeypot messages, counter milestone embeds, verification, Vanity and Server Tag messages, Quest and Rollout alerts, auto-thread names, button responders, the uploads welcome, and every field of a saved embed or image card. A few texts have their own short placeholders instead and don’t run this resolver: counter names, ticket channel names and welcome texts, quick replies, ticket staff hours, appeal messages, VoiceMaster names, suggestion thread names, command aliases and the plain text of sticky messages. Timers send their text as written. See Placeholders of one feature. For conditions, loops or saved data, use Petto Code, documented at code.petto.sbs.