booly/bot.py

356 lines
14 KiB
Python
Raw Normal View History

2026-01-19 09:00:58 +00:00
import discord
2026-01-19 21:23:48 +00:00
from discord import app_commands
2026-01-19 09:00:58 +00:00
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 = {
'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
2026-01-19 21:23:48 +00:00
# Bot setup
class MyBot(commands.Bot):
def __init__(self):
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
super().__init__(command_prefix='/', intents=intents)
self.db = SimpleDB(CONFIG['data_file'])
async def setup_hook(self):
# Sync slash commands
await self.tree.sync()
logger.info('✅ Slash commands synced!')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
bot = MyBot()
2026-01-19 09:00:58 +00:00
# Events
@bot.event
async def on_ready():
logger.info(f'✅ Logged in as {bot.user}')
logger.info(f'📊 Connected to {len(bot.guilds)} guilds')
2026-01-19 21:23:48 +00:00
await bot.change_presence(activity=discord.Game(name="/help"))
2026-01-19 09:00:58 +00:00
logger.info('🚀 All systems operational!')
@bot.event
async def on_message(message):
if message.author.bot or not message.guild:
return
# XP System
2026-01-19 21:23:48 +00:00
user_data = bot.db.get_user(str(message.guild.id), str(message.author.id))
2026-01-19 09:00:58 +00:00
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**! 💰'
)
2026-01-19 21:23:48 +00:00
bot.db.set_user(str(message.guild.id), str(message.author.id), user_data)
2026-01-19 09:00:58 +00:00
await bot.process_commands(message)
2026-01-19 21:23:48 +00:00
# Slash Commands
@bot.tree.command(name='help', description='Show all available commands')
async def help_command(interaction: discord.Interaction):
2026-01-19 09:00:58 +00:00
embed = discord.Embed(
title='🤖 Bot Commands',
2026-01-19 21:23:48 +00:00
description='Here are all the slash commands you can use!',
2026-01-19 09:00:58 +00:00
color=0x5865F2
)
embed.add_field(
name='📊 Leveling',
2026-01-19 21:23:48 +00:00
value='`/rank` - View your rank\n`/leaderboard` - Top 10 users',
2026-01-19 09:00:58 +00:00
inline=False
)
embed.add_field(
name='💰 Economy',
2026-01-19 21:23:48 +00:00
value='`/balance` - Check balance\n`/daily` - Daily reward\n`/work` - Work for coins',
2026-01-19 09:00:58 +00:00
inline=False
)
embed.add_field(
name='🎮 Fun',
2026-01-19 21:23:48 +00:00
value='`/8ball` - Magic 8ball\n`/roll` - Roll dice\n`/flip` - Flip coin\n`/cat` - Random cat\n`/dog` - Random dog',
2026-01-19 09:00:58 +00:00
inline=False
)
2026-01-19 21:23:48 +00:00
embed.add_field(
name=' Info',
value='`/ping` - Check bot latency\n`/serverinfo` - Server information',
inline=False
)
await interaction.response.send_message(embed=embed)
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='ping', description='Check bot latency')
async def ping(interaction: discord.Interaction):
2026-01-19 09:00:58 +00:00
latency = round(bot.latency * 1000)
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'🏓 Pong! Latency: `{latency}ms`')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='rank', description='View your rank and level')
async def rank(interaction: discord.Interaction, member: discord.Member = None):
target = member or interaction.user
user_data = bot.db.get_user(str(interaction.guild.id), str(target.id))
2026-01-19 09:00:58 +00:00
xp_needed = user_data['level'] * CONFIG['xp_per_level']
2026-01-19 21:23:48 +00:00
all_users = bot.db.get_all_guild_users(str(interaction.guild.id))
2026-01-19 09:00:58 +00:00
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)
2026-01-19 21:23:48 +00:00
color = 0xFF6B6B if user_data['level'] >= 50 else 0xFFD93D if user_data['level'] >= 30 else 0x6BCB77 if user_data['level'] >= 15 else 0x4D96FF
embed = discord.Embed(color=color)
2026-01-19 09:00:58 +00:00
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
"""
2026-01-19 21:23:48 +00:00
embed.set_thumbnail(url=target.display_avatar.url)
await interaction.response.send_message(embed=embed)
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='leaderboard', description='View the server leaderboard')
async def leaderboard(interaction: discord.Interaction):
all_users = bot.db.get_all_guild_users(str(interaction.guild.id))[:10]
2026-01-19 09:00:58 +00:00
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!',
2026-01-19 21:23:48 +00:00
color=0x9B59B6,
timestamp=datetime.utcnow()
2026-01-19 09:00:58 +00:00
)
2026-01-19 21:23:48 +00:00
embed.set_footer(text='Top 10 users by level and XP')
await interaction.response.send_message(embed=embed)
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='balance', description='Check your coin balance')
async def balance(interaction: discord.Interaction, member: discord.Member = None):
target = member or interaction.user
user_data = bot.db.get_user(str(interaction.guild.id), str(target.id))
2026-01-19 09:00:58 +00:00
embed = discord.Embed(
title='💰 Balance',
2026-01-19 21:23:48 +00:00
description=f'{target.mention} has **{user_data["coins"]:,}** coins in wallet and **{user_data["bank"]:,}** in bank!\n**Total:** {user_data["coins"] + user_data["bank"]:,} coins',
2026-01-19 09:00:58 +00:00
color=0xFFD700
)
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(embed=embed)
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='daily', description='Claim your daily reward')
async def daily(interaction: discord.Interaction):
user_data = bot.db.get_user(str(interaction.guild.id), str(interaction.user.id))
2026-01-19 09:00:58 +00:00
now = datetime.now().timestamp()
if now - user_data['last_daily'] < 86400:
time_left = 86400 - (now - user_data['last_daily'])
hours = int(time_left / 3600)
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'⏳ You already claimed your daily! Come back in {hours} hours.', ephemeral=True)
2026-01-19 09:00:58 +00:00
return
reward = 100
user_data['coins'] += reward
user_data['last_daily'] = now
2026-01-19 21:23:48 +00:00
bot.db.set_user(str(interaction.guild.id), str(interaction.user.id), user_data)
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'✅ You claimed your daily reward of **{reward:,}** coins!\n💰 New balance: **{user_data["coins"]:,}** coins')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='work', description='Work to earn coins')
async def work(interaction: discord.Interaction):
user_data = bot.db.get_user(str(interaction.guild.id), str(interaction.user.id))
2026-01-19 09:00:58 +00:00
now = datetime.now().timestamp()
if now - user_data['last_work'] < 3600:
time_left = 3600 - (now - user_data['last_work'])
minutes = int(time_left / 60)
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'⏳ You need to rest! Come back in {minutes} minutes.', ephemeral=True)
2026-01-19 09:00:58 +00:00
return
earnings = random.randint(10, 50)
user_data['coins'] += earnings
user_data['last_work'] = now
2026-01-19 21:23:48 +00:00
bot.db.set_user(str(interaction.guild.id), str(interaction.user.id), user_data)
2026-01-19 09:00:58 +00:00
jobs = [
'You worked as a programmer and earned',
'You delivered pizza and earned',
2026-01-19 21:23:48 +00:00
'You streamed on Twitch and earned',
'You mowed lawns and earned',
'You washed cars and earned',
'You tutored students and earned'
2026-01-19 09:00:58 +00:00
]
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'💼 {random.choice(jobs)} **{earnings:,}** coins!\n💰 New balance: **{user_data["coins"]:,}** coins')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='8ball', description='Ask the magic 8ball a question')
async def eightball(interaction: discord.Interaction, question: str):
2026-01-19 09:00:58 +00:00
responses = [
2026-01-19 21:23:48 +00:00
'Yes, definitely!', 'It is certain.', 'Without a doubt.', 'You may rely on it.',
'As I see it, yes.', 'Most likely.', 'Outlook good.', 'Signs point to yes.',
'Reply hazy, try again.', 'Ask again later.', 'Better not tell you now.',
'Cannot predict now.', "Don't count on it.", 'My reply is no.', 'Very doubtful.'
2026-01-19 09:00:58 +00:00
]
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'🔮 **{question}**\n{random.choice(responses)}')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='roll', description='Roll a dice')
async def roll(interaction: discord.Interaction, sides: int = 6):
2026-01-19 09:00:58 +00:00
if sides < 2 or sides > 100:
2026-01-19 21:23:48 +00:00
await interaction.response.send_message('❌ Dice must have between 2 and 100 sides!', ephemeral=True)
2026-01-19 09:00:58 +00:00
return
result = random.randint(1, sides)
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'🎲 You rolled a **{result}** (1-{sides})')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='flip', description='Flip a coin')
async def flip(interaction: discord.Interaction):
2026-01-19 09:00:58 +00:00
result = random.choice(['Heads', 'Tails'])
2026-01-19 21:23:48 +00:00
await interaction.response.send_message(f'🪙 The coin landed on **{result}**!')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='cat', description='Get a random cat picture')
async def cat(interaction: discord.Interaction):
await interaction.response.defer()
2026-01-19 09:00:58 +00:00
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'])
2026-01-19 21:23:48 +00:00
embed.set_footer(text=f'Requested by {interaction.user.name}')
await interaction.followup.send(embed=embed)
2026-01-19 09:00:58 +00:00
except:
2026-01-19 21:23:48 +00:00
await interaction.followup.send('Failed to fetch a cat picture 😿')
2026-01-19 09:00:58 +00:00
2026-01-19 21:23:48 +00:00
@bot.tree.command(name='dog', description='Get a random dog picture')
async def dog(interaction: discord.Interaction):
await interaction.response.defer()
2026-01-19 09:00:58 +00:00
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'])
2026-01-19 21:23:48 +00:00
embed.set_footer(text=f'Requested by {interaction.user.name}')
await interaction.followup.send(embed=embed)
2026-01-19 09:00:58 +00:00
except:
2026-01-19 21:23:48 +00:00
await interaction.followup.send('Failed to fetch a dog picture 😥')
@bot.tree.command(name='serverinfo', description='Display server information')
async def serverinfo(interaction: discord.Interaction):
guild = interaction.guild
embed = discord.Embed(
title=f'📊 {guild.name}',
color=0x5865F2,
timestamp=datetime.utcnow()
)
if guild.icon:
embed.set_thumbnail(url=guild.icon.url)
embed.add_field(name='👑 Owner', value=guild.owner.mention, inline=True)
embed.add_field(name='👥 Members', value=guild.member_count, inline=True)
embed.add_field(name='📅 Created', value=guild.created_at.strftime('%Y-%m-%d'), inline=True)
embed.add_field(name='💬 Channels', value=len(guild.channels), inline=True)
embed.add_field(name='😀 Emojis', value=len(guild.emojis), inline=True)
embed.add_field(name='🎭 Roles', value=len(guild.roles), inline=True)
await interaction.response.send_message(embed=embed)
2026-01-19 09:00:58 +00:00
# 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)