Docs / Developers / Cookbook / 17) XP levels that scale: /rank with SQL
BuildSDK 0.10.1

17) XP levels that scale: /rank with SQL

These docs are public. To publish a plugin you need a YourBot account: sign in to open the Dev Portal.

Recipe 4's KV leaderboard scans at most 100 keys per call. When your plugin lands on big servers, keep counts in ctx.sql instead — a real table sorts any number of users. Needs the storage:sql capability (staff-reviewed); bootstrap the schema in on_ready, the designed place for per-server init.

@plugin.on_ready
def init_schema(ctx: Context):
    ctx.sql.execute(
        "CREATE TABLE IF NOT EXISTS xp ("
        "  user_id TEXT PRIMARY KEY,"
        "  points  BIGINT NOT NULL DEFAULT 0)"
    )

@plugin.on_event("message_create")
def award_xp(ctx: Context, event: dict):
    if event.get("author_bot"):
        return
    ctx.sql.execute(
        "INSERT INTO xp (user_id, points) VALUES (%s, 5) "
        "ON CONFLICT (user_id) DO UPDATE SET points = xp.points + 5",
        [event["author_id"]],
    )

@plugin.on_slash_command("rank")
def rank(ctx: Context, event: dict):
    rows = ctx.sql.query(
        "SELECT user_id, points FROM xp ORDER BY points DESC LIMIT 10")
    if not rows:
        ctx.interaction.respond(content="No XP yet - say something!")
        return
    lines = [f"{i+1}. <@{r['user_id']}>: {r['points']} XP"
             for i, r in enumerate(rows)]
    ctx.interaction.respond(content="**XP leaderboard**\n" + "\n".join(lines))
YourBot docs Reference tables are generated from the code that is running. Ask in Discord Suggest a correction