Skip to main content
Righteous

Leveling

Nothing is tracked until you unlock it: then XP, derived levels, and role rewards that survive a rejoin.

A fresh server with leveling untouched has no XP anywhere. Every ,levels subcommand except one is either reading rows that don't exist yet or configuring a system nobody has switched on: the single most common leveling ticket is someone who set up rewards, waited, and never got a level because nothing was ever unlocked.

Turn leveling on

Syntax

,levels unlock

,levels unlock is the switch. Before it runs, messages earn nothing: not a reduced rate, not a queue waiting to be counted, nothing. Manage Server can run it.

Turning it back off keeps every member's XP where it is:

Syntax

,levels lock

,levels lock stops new XP from accruing. It does not wipe anything, so re-running unlock later picks up exactly where the server left off.

Members can opt out of the whole system for themselves: no XP, no leaderboard entry, no level-up ping:

Syntax

,levels notifyme [on|off]

Example

,levels notifyme off

How a level is worked out

A member's level is never stored. Righteous stores lifetime XP and works the level out from it on every read, using a fixed curve, so changing how much XP a level costs would apply retroactively to everyone rather than only to whoever levels up next. Levels are 1-based: a member with zero XP is level 1, not level 0.

Syntax

,levels rank [user]

Example

,levels rank @cami

,levels rank shows a level/XP card for yourself or someone else. ,levels leaderboard ranks the server by XP. You can also right-click a member, then Apps → Rank Card, for the same card.

Three settings shape how XP is earned:

Syntax

,levels setrate <0.1-5>

Example

,levels setrate 1.5

,levels setrate scales every member's XP gain at once.

Syntax

,levels ignore add <#channel|@role>

Example

,levels ignore add #trade-spam

,levels ignore exempts a channel or role from earning XP at all: ignore remove reverses it, ignore list shows what's currently exempt.

Syntax

,levels multiplier set <role> <value>

Example

,levels multiplier set @Booster 1.5

,levels multiplier gives one role a bonus (above

  1. or penalty (below 1) rate on top of the server rate. multiplier remove and multiplier list manage what's configured.

Give out reward roles

Add, move, and remove a reward

Syntax

,levels roles add <level> <role>

Example

,levels roles add 10 @Regular

,levels roles add attaches a role to a level. It checks the role against your own role hierarchy when you add it (you can't configure a reward above a role you don't hold), and Righteous checks again, against its own hierarchy this time, every time it actually hands the role out. A reward that passed the first check can still fail to apply later if the bot's own role gets moved below it.

Syntax

,levels roles remove <level>

Example

,levels roles remove 10
removes a reward, and

Syntax

,levels update <role> <level>

Example

,levels update @Regular 15
moves an existing one to a different level without deleting and re-adding it.

Choose whether rewards stack

Syntax

,levels roles stack <on|off>

Example

,levels roles stack off

,levels roles stack defaults to on. Stacked, a level-up only ever adds a role: every tier a member has passed stays on them. Turned off, a level-up keeps the single highest tier a member has earned and strips the lower reward roles the bot manages to make room for it. It never touches a role that isn't one of your configured rewards, so a role you handed out manually, or one another bot manages, is never in scope.

Fix reward roles without waiting for the next message

Syntax

,levels sync [@member]

Example

,levels sync

Run bare, ,levels sync reconciles your own reward roles against your own XP: anyone can run this on themselves. With Manage Server, the same command can target @member or the whole server:

Syntax

,levels sync server [++strip confirm]

Example

,levels sync server ++strip confirm

++strip removes reward roles a member no longer qualifies for as well as adding what they're missing, and it's refused on every scope except server, so it can't be used to strip one member's roles by accident. It also demands the typed word confirm. Only one sync can run per server at a time; starting a second while one is in progress is refused rather than queued or run twice.

Rewards come back on rejoin

If a member with earned reward roles leaves and returns, Righteous restores them from their stored XP automatically: there's no setting to turn this off, and no announcement when it happens. The one exception is a member who rejoins under an active mute or jail: reward roles are skipped for them along with role history and autorole, because a punishment that just got re-applied shouldn't be undone in the same breath by a fresh set of roles.

Choose where level-ups are announced

Syntax

,levels messagemode <current|channel|dm|off> [#channel]

Example

,levels messagemode channel #level-ups

,levels messagemode picks one of four destinations: the channel the triggering message was posted in (current), a fixed channel you set, a DM to the member, or off for no announcement at all. messagemode silent [on|off] sends the notification without pinging the member.

Syntax

,levels embeds <text|code> [++delete <duration|off>]

Example

,levels embeds ++delete 30s

,levels embeds sets the level-up message itself: embeds view previews it, embeds help lists the variables it understands, and embeds reset restores the default. ++delete auto-deletes the posted announcement after the duration you give it. It only applies to current and channel mode (a DM announcement is never auto-deleted, since a member may not have read it yet), and the timer is held in memory, so a restart mid-countdown leaves that one message up for good.

Start from a code that already works

A level-up that names the level reached, shows how far into the next one the member is, and puts their leaderboard position in the footer:

Syntax

,levels embeds <code> [++delete <duration|off>]

Example

,levels embeds {color: #fb4868}$p{author: {user} && {user.avatar}}$p{description: {user.mention} just reached **Level {level}** in {guild.name} — {xp.into} / {xp.needed} XP toward level {level.next}.}$p{thumbnail: {user.avatar}}$p{footer: {rank}} ++delete 1m

The same idea for a server that hands out reward roles, with the role just granted in its own field:

Syntax

,levels embeds <code>

Example

,levels embeds {color: #fb4868}$p{description: {user.mention} just reached **Level {level}** — {xp.total} XP all told.}$p{thumbnail: {user.avatar}}$p{field: Role unlocked && {reward}}

Both are ordinary embed codes: embed codes is the language itself. Five things are worth copying out of them:

  • {level}, {level.next}, {xp.into}, {xp.needed}, {xp.total}, {rank} and {reward} exist only here. The pass that fills them in runs while the level-up is being built and nowhere else, so one pasted into a welcome message or a Last.fm code reaches the general parser instead: which has never heard of it, drops the braces, and posts the bare word. {xp.into} in a welcome message renders the visible text xp.into, in every join message, until somebody notices. It is the same symptom as a plain misspelling, and it is never a blank. ,levels embeds help lists them with examples. Everything from the general set ({user}, {user.mention}, {user.avatar}, {guild.name}) works here exactly as it does anywhere else, with one odd exception: {channel.name} and {channel.id} cannot be saved, even though they would render correctly when a real level-up went out. The preview the save runs your code through is built without a channel, so those two throw there and the save is refused. Reach for {guild.name} instead.
  • {rank} and {reward} render blank when there is nothing to show: the one case where a level token really does leave nothing behind, on an unranked member or a level with no role attached. It resolves to an empty string, which is a different outcome from not resolving at all. A token alone in its own tag takes the tag down with it, which is why {footer: {rank}} simply disappears rather than leaving an empty line, while {footer: Rank {rank}} leaves an unranked member a footer reading "Rank". A {field:} is the exception: it keeps its name and shows an empty box, so give {reward} a field only if most announced levels actually grant a role.
  • {reward} renders role mentions, so put it where mentions render: a description, a field value, or {content:}. In a footer or an author line it comes out as raw <@&…> text.
  • ++delete needs a unit on this surface. 30s, 5m or 1h, up to an hour, or off to clear it. A bare ++delete 30 is refused here, unlike the message commands in server messages, and the flag has to be the last thing on the line: everything before it is read as your template.
  • Nothing in the code produces the ping. The member is notified by the announcement replying to the message that levelled them up, which is why channel mode notifies nobody: there is no message there to reply to. Add {content: {user.mention}} if you want a visible ping instead.

Tip

,levels embeds view renders your code through the same path a real level-up uses, against invented numbers: always level 5, always rank #1 of 1, and, for {reward}, the highest role you have configured at level 5 or below, or nothing if your rewards all start higher up. A code that renders to nothing at all is refused rather than saved, so an unusable template costs you one error message instead of every level-up until someone reports it.

It does not catch a misspelled token, which is the commoner mistake: {xp.inot} renders the visible word xp.inot, and a message with a visible word in it is not empty, so it saves happily. Read the preview, do not just check that one appeared.

A level-up message is read once, in a hurry, by someone who is pleased with themselves: write it short.

Manage XP and rank directly

These two need the server owner, not Manage Server

,levels reset and ,levels cleanup are gated on being the actual server owner: the same tier as ,antinuke. Manage Server, including a fake permission, does not open them.

Syntax

,levels xp set <member> <amount>

Example

,levels xp set @cami 5000

,levels xp sets, adds, or removes a member's XP directly: useful for backfilling a migration or correcting a mistake. Setting or removing checks role hierarchy against the member you're targeting; adding does not.

Syntax

,levels setlevel <member> <level>

Example

,levels setlevel @cami 10

,levels setlevel is the same idea expressed in levels instead of raw XP: it converts to the XP that level requires and writes that.

Syntax

,levels reset [member] confirm

Example

,levels reset confirm

Run bare, ,levels reset confirm wipes every member's XP in the server. Naming a member wipes only theirs. Either way it asks for the literal word confirm, and there's no undo.

,levels cleanup removes XP rows for members who have left and prunes reward or ignore entries that point at a role or channel that no longer exists: it's maintenance, not a way to wipe anyone's progress.

For a menu instead of typed commands, ,levels panel opens the leveling configuration panel with the same settings covered above.

Common issues

Members are talking and nothing is happening. Leveling was never unlocked. Run ,levels unlock: nothing above it matters until this has run once.

A reward role stopped being handed out. Most often the bot's own role was moved below the reward role in the server's role list. Reward roles are checked against the bot's hierarchy every time they're applied, not just when you configured them: move the bot's role back above it, then run ,levels sync server to catch anyone who was missed while it was misconfigured.

A member lost a role they should still have. Check whether ,levels roles stack is off. With stacking off, a new level-up strips lower reward roles on purpose: turn it back on if that's not what you want.

,levels reset or ,levels cleanup says no even though I have Manage Server. Both are server- owner only, the same as anti-nuke. There's no fake permission or admin override for either.

Nothing here fixed it. The shared common issues page works the same ground from the symptom end.