Skip to content
All work
  • #discord
  • #bots
  • #api-integration
  • #roblox
  • #open-source
  • #freeware

LegitBot

A Discord bot for the LEGIT clan in Pet Simulator 99: it watched the clan’s diamond donations through the BIG Games API and announced each one with an updated leaderboard.

Role
Solo developer, open source.
Outcome
Ran for the LEGIT clan. Retired once Pet Simulator 99 shipped an official multi-server bot, and I left the game.
Year
2024
Status
retired
Stack
  • Python
  • discord.py
  • aiohttp
  • BIG Games API
  • Roblox API
  1. The start

    Donations nobody saw

    LegitBot was born in LEGIT, my clan in Pet Simulator 99. Looking at the game's public API, the clan sections caught my eye: BIG Games exposes clan data, including who donated how many diamonds. Donations kept the clan going, but they happened silently. Nobody saw them, and nobody got credit for them.

  2. The goal

    Every donation, celebrated in Discord

    Make each donation show up in our Discord server the moment it happens, with the donor's avatar, the amount, their new rank and the updated top 3. Give clan leaders the commands to manage it all, and make the whole thing feel good to look at, because people only read messages that look worth reading.

  3. The adventure

    From a polled API to live events

    I built the bot with discord.py. An aiohttp loop polled the BIG Games API for the clan's donation totals, compared them with the last snapshot to spot new donations, and fetched the donor's name and avatar from the Roblox API. Each donation became a styled embed with medals for the podium, and slash commands let admins set the clan, the channel and the mute state. I then started refactoring for multi-server support and a public release.

    A donation announcement.
  4. The difficulties

    Two messages for one donation, and an official rival

    Turning a polled API into reliable events took care: without a debounce, one donation could produce two announcements. Big numbers needed to stay readable, so amounts are shortened to k, m, b and t. Then Pet Simulator 99 released its own official Discord bot, multi-server from day one.

  5. The end

    A good-looking bot, retired at the right time

    My design had more flair; the official bot was more consistent code-wise and had official support. I was leaving the game and the clan anyway, so I discontinued LegitBot there. It taught me async Python, API integration and building for a real community, and above all how much timing matters when you build in someone else's ecosystem.

  • Real-time donation tracking

    Watches the clan's donations through the BIG Games API and announces each new one right away.

  • Styled Discord embeds

    Each message carries the donor's avatar, the amount, their rank and the updated top 3, with medals.

  • Clan management commands

    Admin slash commands to set the clan tag, choose the announcement channel and manage the bot.

  • Configurable

    Clan tag, channels and preferences live in a configuration that survives restarts.

A donation announcement

When a clan member donated diamonds, the bot posted a message like this one in the donation channel: avatar, amount, current rank and the top 3.

A donation announcement.

Commands

  • /set-clan sets the clan the bot follows.
  • /announce-donations chooses the channel for the announcements.
  • /mute-donations pauses them.

How a donation becomes a message

  1. Poll

    An aiohttp loop asks the BIG Games API for the clan's donation totals.
  2. Diff

    Totals are compared with the last snapshot, with a debounce so one donation never produces two messages.
  3. Enrich

    The Roblox API supplies the donor's name and avatar, and the podium is recomputed.
  4. Announce

    A styled embed goes to the donation channel.

The code

Building the announcement

py
async def send_donation_message(channel_id, user_id, amount):
    try:
        channel = bot.get_channel(channel_id)
        if channel is None:
            logging.error("Failed to find channel with ID %s", channel_id)
            return

        user = await get_user(user_id)
        podium = await bigApi.get_donations_podium(user_id)
        user_rank = podium["Current"]["rank"]

        first = await get_user(podium["1st"]["user_id"])
        second = await get_user(podium["2nd"]["user_id"])
        third = await get_user(podium["3rd"]["user_id"])

        badge = f"{'🥇' if user_rank == 1 else '🥈' if user_rank == 2 else '🥉' if user_rank == 3 else '#'}"

        gememoji = f"{os.getenv('GEM_EMOJI_ID')}"
        message = f"""### **{user['username']}** has donated **{utils.int_to_rap(amount)}** {gememoji}
        Current rank: {badge}{user_rank}
        Donated: {utils.int_to_rap(podium["Current"]["donated"])} {gememoji}

        **Top 3**
        > 🥇 **{first["username"]}**: {utils.int_to_rap(podium["1st"]["donated"])}
        > 🥈 **{second["username"]}**: {utils.int_to_rap(podium["2nd"]["donated"])}
        > 🥉 **{third["username"]}**: {utils.int_to_rap(podium["3rd"]["donated"])}
        """

        embed = discord.Embed(description=message, color=discord.Color.from_str("#19e0ff"))
        embed.set_thumbnail(url=user["avatar"])
        embed.set_author(name="New donation!", icon_url=author_icon)
        embed.set_footer(
            text=f"Total Donations: {utils.int_to_rap(await bigApi.get_deposited_diamonds())}",
            icon_url="https://i.imgur.com/Vpwopvz.png",
        )
        await channel.send(embed=embed)
    except Exception as e:
        logging.error("Error occurred while sending donation message: %s", e)

Readable numbers

py
def int_to_rap(amount):
    # Shorten an amount: k for thousands, m for millions, b for billions, t for trillions
    if amount >= 1_000_000_000_000:
        return f"{amount / 1_000_000_000_000:.2f}t"
    elif amount >= 1_000_000_000:
        return f"{amount / 1_000_000_000:.2f}b"
    elif amount >= 1_000_000:
        return f"{amount / 1_000_000:.2f}m"
    elif amount >= 1_000:
        return f"{amount / 1_000:.2f}k"
    return str(amount)

Clan data and the podium

py
async def get_clan_data():
    # Fetch clan data from the BIG Games API asynchronously
    clan_tag = bot_commands.load_config().get("clan_tag")
    async with aiohttp.ClientSession() as session:
        try:
            async with session.get(f"{API_URL}{clan_tag}") as response:
                if response.status == 200:
                    return (await response.json()).get("data", {})
                logging.error(f"Failed to retrieve data: {response.status}")
                return None
        except Exception as e:
            logging.error(f"Error occurred while fetching data: {e}")
            return None

async def get_donations_podium(user_id):
    members = (await get_clan_data()).get("Members", [])
    sorted_members = sorted(members, key=lambda x: x["Diamonds"], reverse=True)
    podium = {
        "1st": {"user_id": sorted_members[0]["UserID"], "donated": sorted_members[0]["Diamonds"]},
        "2nd": {"user_id": sorted_members[1]["UserID"], "donated": sorted_members[1]["Diamonds"]},
        "3rd": {"user_id": sorted_members[2]["UserID"], "donated": sorted_members[2]["Diamonds"]},
        "Current": {"rank": 0, "donated": 0},
    }
    for rank, member in enumerate(sorted_members, start=1):
        if member["UserID"] == user_id:
            podium["Current"] = {"rank": rank, "donated": member["Diamonds"]}
            break
    return podium

The stack

  • Python

    3.x

    The language for the bot and the API layer.

  • discord.py

    2.4.0

    Slash commands, embeds, role-based permissions and asynchronous event handling.

  • BIG Games API

    Clan data

    Donations and member statistics for the clan.

  • Roblox API

    User data

    Usernames and avatar thumbnails for the announcements.

Skills I gained

  • Discord bot development

    discord.py

    Slash commands, embed design, role-based permissions, event handling and how Discord bots are structured.

  • Asynchronous programming

    aiohttp, async/await

    Concurrent API calls, async sessions and proper error handling in async code.

  • API integration

    BIG Games and Roblox

    Combining two external APIs and processing their data in real time, with rate limits in mind.

  • Configuration management

    JSON, environment variables

    Admin-friendly commands and persistent settings that survive restarts.

Why did you create LegitBot?

To solve a real problem in my community. The LEGIT clan in Pet Simulator 99 needed a way to track donations and keep members engaged, and when I found out the game had a public API, I saw a chance to build something that made our Discord server better.

How did the donation tracking work?

The bot regularly asked the BIG Games API for the clan's data, including members' donations. When it spotted a new donation, it posted a formatted embed in a dedicated channel with the donor's details, the amount, their current rank and the updated leaderboard.

What made it different from the official bot?

More visual flair: custom-styled embeds with avatars, formatted numbers and detailed leaderboards. The official bot, on the other hand, had a more consistent codebase and multi-server support from the start.

Why did you discontinue it?

Two reasons. Pet Simulator 99 released its official Discord bot, already multi-server, and I stopped playing the game and left the clan. My design looked better, but the official bot was more consistent and officially supported.

What did you learn from it?

discord.py, asynchronous Python, integrating external APIs, configuration management and building tools for gaming communities. Above all, the importance of understanding what users actually need.

Would you build something similar again?

Absolutely. It taught me a lot about community tools, API integration and timing, and I'd happily apply it to other communities.

  1. Aug 19, 2024

    Project started

    Development began after I discovered the BIG Games API: the first bot structure, with discord.py.

  2. Aug 19, 2024

    Donation tracking

    Real-time donation monitoring through the BIG Games API, with an automatic embed for every new donation.

  3. Aug 19, 2024

    Admin commands

    Slash commands for clan management: /set-clan, /announce-donations, /mute-donations and configuration.

  4. Aug 20, 2024

    Better embeds

    Custom colours, user avatars and a detailed leaderboard, with medals for the top 3.

  5. Aug 20, 2024

    Multi-server planning

    Planning for multi-server support and a public release, and refactoring for scalability and configuration.

  6. Aug 20, 2024

    Discontinued

    Pet Simulator 99 released its official Discord bot and I left the game, so I stopped here.

Need something like this?

Tell me what it should do, where it runs and when you need it.

Get in touch