Placeholders
Contribute live values to the bot activity status and add placeholder buttons to configuration fields.
Medusa has two placeholder systems:
- Placeholder providers in
resources/placeholders/contribute live values (such as%tickets_open%) to the bot activity status. Every provider shows up as a button under the status text on the dashboard Bot page. - Field placeholders declared with
placeholderson astringortextconfiguration field render buttons under that input that insert the token at the cursor.
Placeholder Providers
Providers reside in resources/placeholders/ and load from every *.js file located directly in that directory. One provider can supply several keys.
import { Placeholders } from "#medusa/modules";
export class TicketPlaceholders extends Placeholders {
constructor(medusa) {
super(medusa, { name: "tickets" });
}
keys() {
return [
{ key: "tickets_open", label: "Open Tickets", sample: "7" },
{ key: "tickets_total", label: "Total Tickets", sample: "319" }
];
}
async values() {
const model = this.medusa.modules.models.get("ticket", "ticket_tickets");
return { tickets_open: await model.count({ status: "open" }), tickets_total: await model.count() };
}
}Constructor Options
| Property | Type | Default | Description |
|---|---|---|---|
name | string | Required | Provider identifier, unique within the module. |
order | number | 0 | Sort priority between providers of the same module. Core providers are always listed first. |
Methods
| Method | Returns | Description |
|---|---|---|
keys() | Array<{ key, label, sample }> | The tokens this provider fills. key is used as %key%. Prefix keys with the module id (tickets_open, giveaways_active) so they never collide. |
values(context) | Promise<Record<string, string | number>> | Resolves every key. context holds client (the Discord.js client of the bot whose status is being set) and bot. |
values only runs when the status text contains one of the provider's keys, so a provider can query the database without slowing down statuses that do not use it. A provider that throws is logged and its keys stay unresolved.
Translating Labels
The dashboard reads button labels from placeholder.<module>.<key> in the module's resources/lang/<code>/common.json, falling back to the English label:
{
"placeholder.ticket.tickets_open": "Offene Tickets"
}Built-in Keys
Core ships these keys, and the global placeholders from embeds.fill (custom Placeholders settings, %server%, %version%, %name%) also work in the status:
| Key | Value |
|---|---|
%servers% | Servers the bot is in. |
%members% | Total members across those servers. |
%channels% | Cached channels. |
%ping% | Gateway ping in milliseconds. |
%uptime% | Uptime such as 2d 4h or 3h 12m. |
%modules% | Loaded modules. |
%bot_name% | The bot's username. |
Refresh
When any status line contains %, the bot re-applies the current line every 60 seconds so the values stay current. Rotation between several lines keeps its own interval.
Placeholder Manager Methods
const keys = this.medusa.placeholders.list();
const text = await this.medusa.placeholders.fill("Watching %tickets_open% tickets", { client, bot });| Method | Returns | Description |
|---|---|---|
list() | Array<{ key, label, sample, module }> | Every key from enabled modules, Core first. Served at GET /api/placeholders. |
fill(text, context) | Promise<string> | Resolves the providers used in text, then runs embeds.fill for global placeholders and custom emojis. |
Field Placeholders
Add placeholders to a string or text field, top-level or inside a list item, to render insert buttons under the input. The value is only a hint for the dashboard; your code still fills the tokens, usually through this.medusa.embeds.fill(template, tokens).
naming: {
type: "string",
default: "ticket-%number%",
label: "Channel Naming",
placeholders: [
{ key: "number", label: "Ticket Number", sample: "42" },
{ key: "user", label: "Username", sample: "muffiny" }
]
}Button labels translate through schema.<module>.config.<group>.<field>.placeholders.<key> for top-level fields and schema.<module>.config.<group>.<list>.<field>.placeholders.<key> for list item fields.
Keep the placeholders list in sync with the tokens your code passes to embeds.fill. A button for a token the code never fills leaves the raw %key% in the output.