Back to Side Projects
Back to Side Projects
LegitBot
Cancelled

LegitBot

A Discord bot designed for Pet Simulator 99 clans to track diamond donations and manage clan activities. Built for the LEGIT clan, it featured real-time donation tracking, automated announcements, and clan management tools.

Tags

PythonDiscordRobloxAPI IntegrationAutomationGamingBotPS99

Technologies Used

PythonDiscord.pyaiohttpRoblox APIBigGames APIJSONAsync Programming

Project Links

Project Details

August 19, 2024
Side Project
Portfolio Showcase

Quick Stats

8
Tags
7
Technologies

Project Overview

LegitBot was born from my experience in the LEGIT clan in Pet Simulator 99. I noticed that the game had a public API, particularly the clan sections, which caught my attention. I decided to create a Discord bot to enhance our clan's Discord server with useful commands for tracking donations and managing clan activities.

The bot was designed to automatically monitor clan donations and send beautiful embed messages to a designated channel whenever someone donated diamonds. It featured real-time tracking, donation leaderboards, and clan management tools that made it easier for clan leaders to keep track of member contributions.

After several months of development and planning to make the bot public and multi-guild, I decided to discontinue the project. Pet Simulator 99 released their official Discord bot that was already multi-guild ready. While my design was more visually appealing and had more flair, the official bot was more consistent code-wise. Additionally, I stopped playing Pet Simulator 99 and bid farewell to both the game and the clan.

Key Features

Real-time Donation Tracking

Automatically monitors clan donations through the BigGames API and sends instant notifications

Automated Discord Embeds

Beautiful, formatted embed messages with user avatars, donation amounts, and leaderboard updates

Clan Management Commands

Admin commands to set clan tags, configure donation channels, and manage bot settings

Configurable Settings

Easy configuration system for clan tags, donation channels, and bot preferences

Technical Implementation

API Integration

The bot integrated with two main APIs:

  • BigGames API: For fetching clan data, donation information, and member statistics
  • Roblox API: For retrieving user information, usernames, and avatar thumbnails

Donation Tracking System

The core functionality involved:

  • Periodic API calls to check for new donations
  • Debouncing system to prevent duplicate notifications
  • Real-time leaderboard updates with ranking positions
  • Formatted number display (k, m, b, t suffixes)

Discord Integration

Built using discord.py with features like:

  • Slash commands for admin configuration
  • Rich embed messages with custom styling
  • Role-based permission system
  • Asynchronous event handling

Example: Donation Notification Embed

When a clan member donated diamonds, the bot would automatically send a beautifully formatted embed message like this to the designated donation channel:

Example of LegitBot donation notification embed message showing user donation, rank, and leaderboard

Example of LegitBot donation notification embed message showing user donation, rank, and leaderboard

The embed included user avatar, donation amount, current rank, and updated top 3 leaderboard

Code Examples

Donation Message Generation

Python legtbot.py
1async def send_donation_message(channel_id, user_id, amount):
2 try:
3 channel = bot.get_channel(channel_id)
4 if channel is None:
5 logging.error("Failed to find channel with ID %s", channel_id)
6 return
7
8 user = await get_user(user_id)
9 podium = await bigApi.get_donations_podium(user_id)
10 user_rank = podium["Current"]["rank"]
11
12 first = await get_user(podium["1st"]["user_id"])
13 second = await get_user(podium["2nd"]["user_id"])
14 third = await get_user(podium["3rd"]["user_id"])
15
16 badge = f"{'🥇' if user_rank == 1 else '🥈' if user_rank == 2 else '🥉' if user_rank == 3 else '#'}"
17
18 gememoji = f"{os.getenv('GEM_EMOJI_ID')}"
19 message = f"""### **{user['username']}** has donated **{utils.int_to_rap(amount)}** {gememoji}
20 Current rank: {badge}{user_rank}
21 Donated: {utils.int_to_rap(podium["Current"]["donated"])} {gememoji}
22
23 **Top 3**
24 > 🥇 **{first["username"]}**: {utils.int_to_rap(podium["1st"]["donated"])}
25 > 🥈 **{second["username"]}**: {utils.int_to_rap(podium["2nd"]["donated"])}
26 > 🥉 **{third["username"]}**: {utils.int_to_rap(podium["3rd"]["donated"])}
27 """
28
29 embed = discord.Embed(
30 description=message,
31 color=discord.Color.from_str("#19e0ff"),
32 )
33 embed.set_thumbnail(url=user["avatar"])
34 embed.set_author(name="New donation!", icon_url=author_icon)
35 embed.set_footer(
36 text=f"Total Donations: {utils.int_to_rap(await bigApi.get_deposited_diamonds())}",
37 icon_url="https://i.imgur.com/Vpwopvz.png"
38 )
39 await channel.send(embed=embed)
40 except Exception as e:
41 logging.error("Error occurred while sending donation message: %s", e)

Number Formatting Utility

Python utils.py
1def int_to_rap(amount):
2 # Convert an amount to a string with k for thousands and m for millions
3 if amount >= 1_000_000_000_000: # 1 trillion
4 return f"{amount / 1_000_000_000_000:.2f}t"
5 elif amount >= 1_000_000_000: # 1 billion
6 return f"{amount / 1_000_000_000:.2f}b"
7 elif amount >= 1_000_000: # 1 million
8 return f"{amount / 1_000_000:.2f}m"
9 elif amount >= 1_000: # 1 thousand
10 return f"{amount / 1_000:.2f}k"
11 else:
12 return str(amount)

API Integration

Python biggamesapi.py
1async def get_clan_data():
2 # Fetch clan data from Big Games API asynchronously
3 config = bot_commands.load_config()
4 clan_tag = config.get("clan_tag")
5
6 async with aiohttp.ClientSession() as session:
7 try:
8 async with session.get(f"{API_URL}{clan_tag}") as response:
9 if response.status == 200:
10 data = await response.json()
11 return data.get("data", {})
12 else:
13 logging.error(f"Failed to retrieve data: {response.status}")
14 return None
15 except Exception as e:
16 logging.error(f"Error occurred while fetching data: {e}")
17 return None
18
19async def get_donations_podium(user_id):
20 clan_data = await get_clan_data()
21 members = clan_data.get("Members", [])
22
23 # Sort members by donation amount
24 sorted_members = sorted(members, key=lambda x: x["Diamonds"], reverse=True)
25
26 podium = {
27 "1st": {"user_id": sorted_members[0]["UserID"], "donated": sorted_members[0]["Diamonds"]},
28 "2nd": {"user_id": sorted_members[1]["UserID"], "donated": sorted_members[1]["Diamonds"]},
29 "3rd": {"user_id": sorted_members[2]["UserID"], "donated": sorted_members[2]["Diamonds"]},
30 "Current": {"rank": 0, "donated": 0}
31 }
32
33 # Find current user's rank
34 for rank, member in enumerate(sorted_members, start=1):
35 if member['UserID'] == user_id:
36 podium["Current"]["donated"] = member["Diamonds"]
37 podium["Current"]["rank"] = rank
38 break
39
40 return podium

Technology Stack

Python

Version3.x
RoleLanguage
UsageCore, API

Discord.py

Version2.4.0
RoleFramework
UsageCommands, Embeds
Key FeaturesAsync Events

Roblox API

Version2.0.0
RoleUser Data
UsageAvatars, Names

BigGames API

TypeExternal API
RoleClan Data
UsageDonations, Stats

Skills & Technologies Learned

Discord Bot Development
Discord.py Framework
Learned to build sophisticated Discord bots using discord.py, including slash commands, embed messages, role-based permissions, and event handling. Gained experience with Discord's API and bot architecture.
Asynchronous Programming
aiohttp & Async/Await
Developed strong skills in asynchronous programming using Python's async/await syntax. Learned to handle concurrent API calls, manage async sessions, and implement proper error handling in async contexts.
API Integration
External APIs & Data Processing
Gained experience integrating multiple external APIs (BigGames API, Roblox API) and processing real-time data. Learned to handle API rate limits, implement caching strategies, and design robust data flow systems.
Configuration Management
JSON Configuration & Environment Variables
Implemented a flexible configuration system using JSON files and environment variables. Learned to design user-friendly admin commands and create persistent settings that survive bot restarts.

Project Conclusion

LegitBot was a valuable learning experience that taught me about Discord bot development, API integration, and building tools for gaming communities. The project demonstrated the importance of understanding user needs and creating solutions that enhance community engagement.

While the project was discontinued due to the release of an official bot and my departure from the game, it provided valuable insights into the challenges of maintaining community tools and the importance of timing in software development. The experience reinforced the value of building for real users and understanding the ecosystem you're developing for.

The skills learned from this project, particularly in Discord bot development and API integration, have been valuable for subsequent projects and continue to inform my approach to building community-focused tools.