- #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
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.
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.
The adventure
From a polled API to live events
I built the bot with
discord.py. Anaiohttploop 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. 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.
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.
Commands
/set-clansets the clan the bot follows./announce-donationschooses the channel for the announcements./mute-donationspauses them.
How a donation becomes a message
Poll
Anaiohttploop asks the BIG Games API for the clan's donation totals.Diff
Totals are compared with the last snapshot, with a debounce so one donation never produces two messages.Enrich
The Roblox API supplies the donor's name and avatar, and the podium is recomputed.Announce
A styled embed goes to the donation channel.
The code
Building the announcement
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
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
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 podiumThe 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.
Aug 19, 2024
Project started
Development began after I discovered the BIG Games API: the first bot structure, with discord.py.
Aug 19, 2024
Donation tracking
Real-time donation monitoring through the BIG Games API, with an automatic embed for every new donation.
Aug 19, 2024
Admin commands
Slash commands for clan management:
/set-clan,/announce-donations,/mute-donationsand configuration.Aug 20, 2024
Better embeds
Custom colours, user avatars and a detailed leaderboard, with medals for the top 3.
Aug 20, 2024
Multi-server planning
Planning for multi-server support and a public release, and refactoring for scalability and configuration.
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.
More work

- #api-integration
- #cli
- #roblox
Player Clan Finder
A command-line tool that finds a Roblox player's Pet Simulator 99 clan, built to follow a scammer.

- #discord
- #bots
- #api-integration
BotFire
A Discord bot for my streaming community: game suggestions and my Twitch schedule, synced to Google Calendar.

- #web
- #discord
- #bots
Arise Crossover Tools
Live dungeon and event timers for Arise Crossover, fed by a Discord bot that reads the official announcements.