import discord from discord.ext import commands import os import json import random import asyncio from datetime import datetime import aiohttp import logging # Setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger('bot') # Configuration CONFIG = { 'prefix': '!', 'xp_min': 15, 'xp_max': 25, 'xp_cooldown': 60, 'xp_per_level': 100, 'level_up_multiplier': 10, 'data_file': 'data.json' } # Simple JSON Database class SimpleDB: def __init__(self, filename): self.filename = filename self.data = self.load() def load(self): if os.path.exists(self.filename): try: with open(self.filename, 'r') as f: return json.load(f) except: return {'users': {}, 'guilds': {}} return {'users': {}, 'guilds': {}} def save(self): with open(self.filename, 'w') as f: json.dump(self.data, f, indent=2) def get_user(self, guild_id, user_id): key = f"{guild_id}_{user_id}" if key not in self.data['users']: self.data['users'][key] = { 'coins': 0, 'bank': 0, 'level': 1, 'xp': 0, 'last_message': 0, 'last_daily': 0, 'last_work': 0 } return self.data['users'][key] def set_user(self, guild_id, user_id, data): key = f"{guild_id}_{user_id}" self.data['users'][key] = data self.save() def get_all_guild_users(self, guild_id): users = [] for key, data in self.data['users'].items(): if key.startswith(f"{guild_id}_"): user_id = key.split('_')[1] users.append({'user_id': user_id, 'data': data}) users.sort(key=lambda x: (x['data']['level'], x['data']['xp']), reverse=True) return users # Initialize intents = discord.Intents.default() intents.message_content = True intents.members = True bot = commands.Bot(command_prefix=CONFIG['prefix'], intents=intents) db = SimpleDB(CONFIG['data_file']) # Events @bot.event async def on_ready(): logger.info(f'āœ… Logged in as {bot.user}') logger.info(f'šŸ“Š Connected to {len(bot.guilds)} guilds') await bot.change_presence(activity=discord.Game(name=f"{CONFIG['prefix']}help")) logger.info('šŸš€ All systems operational!') @bot.event async def on_message(message): if message.author.bot or not message.guild: return # XP System user_data = db.get_user(str(message.guild.id), str(message.author.id)) now = datetime.now().timestamp() if now - user_data['last_message'] >= CONFIG['xp_cooldown']: user_data['last_message'] = now xp_gain = random.randint(CONFIG['xp_min'], CONFIG['xp_max']) user_data['xp'] += xp_gain xp_needed = user_data['level'] * CONFIG['xp_per_level'] if user_data['xp'] >= xp_needed: user_data['level'] += 1 user_data['xp'] = 0 coin_reward = user_data['level'] * CONFIG['level_up_multiplier'] user_data['coins'] += coin_reward messages = [ f'šŸŽ‰ GG {message.author.mention}! You leveled up to **Level {user_data["level"]}**!', f'⭐ Congrats {message.author.mention}! You\'re now **Level {user_data["level"]}**!', f'šŸš€ Level up! {message.author.mention} reached **Level {user_data["level"]}**!' ] await message.channel.send( f'{random.choice(messages)} You earned **{coin_reward:,} coins**! šŸ’°' ) db.set_user(str(message.guild.id), str(message.author.id), user_data) await bot.process_commands(message) # Commands @bot.command(name='bothelp') async def help_command(ctx): embed = discord.Embed( title='šŸ¤– Bot Commands', color=0x5865F2 ) embed.add_field( name='šŸ“Š Leveling', value='`!rank [@user]` - View rank\n`!leaderboard` - Top 10 users', inline=False ) embed.add_field( name='šŸ’° Economy', value='`!balance [@user]` - Check balance\n`!daily` - Daily reward\n`!work` - Work for coins', inline=False ) embed.add_field( name='šŸŽ® Fun', value='`!8ball ` - Magic 8ball\n`!roll [sides]` - Roll dice\n`!flip` - Flip coin\n`!cat` - Random cat\n`!dog` - Random dog', inline=False ) await ctx.send(embed=embed) @bot.command(name='ping') async def ping(ctx): latency = round(bot.latency * 1000) await ctx.send(f'šŸ“ Pong! Latency: `{latency}ms`') @bot.command(name='rank') async def rank(ctx, member: discord.Member = None): target = member or ctx.author user_data = db.get_user(str(ctx.guild.id), str(target.id)) xp_needed = user_data['level'] * CONFIG['xp_per_level'] all_users = db.get_all_guild_users(str(ctx.guild.id)) rank = next((i + 1 for i, u in enumerate(all_users) if u['user_id'] == str(target.id)), 'Unranked') progress = int((user_data['xp'] / xp_needed) * 20) if xp_needed > 0 else 0 bar = 'ā–ˆ' * progress + 'ā–‘' * (20 - progress) embed = discord.Embed(color=0x4D96FF) embed.set_author(name=f"{target.display_name}'s Profile", icon_url=target.display_avatar.url) embed.description = f""" **RANK** • #{rank} / {len(all_users)} **LEVEL** • {user_data['level']} **XP** • {user_data['xp']:,} / {xp_needed:,} `{bar}` **šŸ’° BALANCE** • {user_data['coins']:,} coins """ await ctx.send(embed=embed) @bot.command(name='leaderboard', aliases=['lb']) async def leaderboard(ctx): all_users = db.get_all_guild_users(str(ctx.guild.id))[:10] description = [] for i, u in enumerate(all_users): medal = 'šŸ„‡' if i == 0 else '🄈' if i == 1 else 'šŸ„‰' if i == 2 else f'**{i+1}.**' description.append( f'{medal} <@{u["user_id"]}>\n' f'ā”” Level {u["data"]["level"]} ({u["data"]["xp"]:,} XP) • {u["data"]["coins"]:,} coins' ) embed = discord.Embed( title='šŸ† Server Leaderboard', description='\n'.join(description) if description else 'No users yet!', color=0x9B59B6 ) await ctx.send(embed=embed) @bot.command(name='balance', aliases=['bal']) async def balance(ctx, member: discord.Member = None): target = member or ctx.author user_data = db.get_user(str(ctx.guild.id), str(target.id)) embed = discord.Embed( title='šŸ’° Balance', description=f'{target.mention} has **{user_data["coins"]:,}** coins!', color=0xFFD700 ) await ctx.send(embed=embed) @bot.command(name='daily') async def daily(ctx): user_data = db.get_user(str(ctx.guild.id), str(ctx.author.id)) now = datetime.now().timestamp() if now - user_data['last_daily'] < 86400: time_left = 86400 - (now - user_data['last_daily']) hours = int(time_left / 3600) await ctx.send(f'ā³ You already claimed your daily! Come back in {hours} hours.') return reward = 100 user_data['coins'] += reward user_data['last_daily'] = now db.set_user(str(ctx.guild.id), str(ctx.author.id), user_data) await ctx.send(f'āœ… You claimed your daily reward of **{reward:,}** coins!\nšŸ’° New balance: **{user_data["coins"]:,}** coins') @bot.command(name='work') async def work(ctx): user_data = db.get_user(str(ctx.guild.id), str(ctx.author.id)) now = datetime.now().timestamp() if now - user_data['last_work'] < 3600: time_left = 3600 - (now - user_data['last_work']) minutes = int(time_left / 60) await ctx.send(f'ā³ You need to rest! Come back in {minutes} minutes.') return earnings = random.randint(10, 50) user_data['coins'] += earnings user_data['last_work'] = now db.set_user(str(ctx.guild.id), str(ctx.author.id), user_data) jobs = [ 'You worked as a programmer and earned', 'You delivered pizza and earned', 'You streamed on Twitch and earned' ] await ctx.send(f'šŸ’¼ {random.choice(jobs)} **{earnings:,}** coins!\nšŸ’° New balance: **{user_data["coins"]:,}** coins') @bot.command(name='8ball') async def eightball(ctx, *, question): responses = [ 'Yes, definitely!', 'No way!', 'Maybe...', 'Ask again later', 'Absolutely!', 'I doubt it', 'Signs point to yes', 'Very doubtful' ] await ctx.send(f'šŸ”® {random.choice(responses)}') @bot.command(name='roll') async def roll(ctx, sides: int = 6): if sides < 2 or sides > 100: await ctx.send('āŒ Dice must have between 2 and 100 sides!') return result = random.randint(1, sides) await ctx.send(f'šŸŽ² You rolled a **{result}** (1-{sides})') @bot.command(name='flip') async def flip(ctx): result = random.choice(['Heads', 'Tails']) await ctx.send(f'šŸŖ™ The coin landed on **{result}**!') @bot.command(name='cat') async def cat(ctx): async with aiohttp.ClientSession() as session: try: async with session.get('https://api.thecatapi.com/v1/images/search') as resp: data = await resp.json() embed = discord.Embed(title='🐱 Random Kitty!', color=0xFF69B4) embed.set_image(url=data[0]['url']) await ctx.send(embed=embed) except: await ctx.send('Failed to fetch cat 😿') @bot.command(name='dog') async def dog(ctx): async with aiohttp.ClientSession() as session: try: async with session.get('https://api.thedogapi.com/v1/images/search') as resp: data = await resp.json() embed = discord.Embed(title='🐶 Random Doggy!', color=0xFF69B4) embed.set_image(url=data[0]['url']) await ctx.send(embed=embed) except: await ctx.send('Failed to fetch dog 😄') # Run bot if __name__ == '__main__': token = os.getenv('DISCORD_TOKEN') if not token: logger.error('āŒ DISCORD_TOKEN not set!') exit(1) logger.info('šŸš€ Starting bot...') bot.run(token)