145 lines
5.4 KiB
Python
145 lines
5.4 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
import datetime
|
|
import logging
|
|
from typing import Optional
|
|
|
|
# Import database functions from the sibling module
|
|
from . import database
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class UtilityCommands(commands.Cog):
|
|
"""Cog containing utility-related economy commands."""
|
|
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
|
|
@commands.hybrid_command(
|
|
name="balance", description="Check your or another user's balance."
|
|
)
|
|
@commands.cooldown(1, 5, commands.BucketType.user) # Basic discord.py cooldown
|
|
async def balance(self, ctx: commands.Context, user: Optional[discord.User] = None):
|
|
"""Displays the economy balance for a user."""
|
|
target_user = user or ctx.author
|
|
balance_amount = await database.get_balance(target_user.id)
|
|
embed = discord.Embed(
|
|
title=f"{target_user.display_name}'s Balance",
|
|
description=f"💰 **${balance_amount:,}**",
|
|
color=discord.Color.blue(),
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
|
|
@commands.hybrid_command(
|
|
name="moneylb",
|
|
aliases=["mlb", "mtop"],
|
|
description="Show the richest users by money.",
|
|
) # Renamed to avoid conflict
|
|
@commands.cooldown(1, 30, commands.BucketType.user) # Prevent spam
|
|
async def moneylb(self, ctx: commands.Context, count: int = 10): # Renamed function
|
|
"""Displays the top users by balance."""
|
|
if not 1 <= count <= 25:
|
|
embed = discord.Embed(
|
|
description="❌ Please provide a count between 1 and 25.",
|
|
color=discord.Color.red(),
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
results = await database.get_leaderboard(count)
|
|
|
|
if not results:
|
|
embed = discord.Embed(
|
|
description="📊 The leaderboard is empty!", color=discord.Color.orange()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
embed = discord.Embed(
|
|
title="💰 Economy Leaderboard", color=discord.Color.gold()
|
|
)
|
|
description = ""
|
|
rank = 1
|
|
for user_id, balance in results:
|
|
user = self.bot.get_user(user_id) # Try to get user object for display name
|
|
# Fetch user if not in cache - might be slow for large leaderboards
|
|
if user is None:
|
|
try:
|
|
user = await self.bot.fetch_user(user_id)
|
|
except discord.NotFound:
|
|
user = None # User might have left all shared servers
|
|
except discord.HTTPException:
|
|
user = None # Other Discord API error
|
|
log.warning(f"Failed to fetch user {user_id} for leaderboard.")
|
|
|
|
user_name = user.display_name if user else f"User ID: {user_id}"
|
|
description += f"{rank}. {user_name} - **${balance:,}**\n"
|
|
rank += 1
|
|
|
|
embed.description = description
|
|
await ctx.send(embed=embed)
|
|
|
|
@commands.hybrid_command(name="pay", description="Transfer money to another user.")
|
|
async def pay(self, ctx: commands.Context, recipient: discord.User, amount: int):
|
|
"""Transfers currency from the command author to another user."""
|
|
sender_id = ctx.author.id
|
|
recipient_id = recipient.id
|
|
|
|
if sender_id == recipient_id:
|
|
embed = discord.Embed(
|
|
description="❌ You cannot pay yourself!", color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
if amount <= 0:
|
|
embed = discord.Embed(
|
|
description="❌ Please enter a positive amount to pay.",
|
|
color=discord.Color.red(),
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
sender_balance = await database.get_balance(sender_id)
|
|
|
|
if sender_balance < amount:
|
|
embed = discord.Embed(
|
|
description=f"❌ You don't have enough money! Your balance is **${sender_balance:,}**.",
|
|
color=discord.Color.red(),
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
# Perform the transfer
|
|
await database.update_balance(sender_id, -amount) # Decrease sender's balance
|
|
await database.update_balance(
|
|
recipient_id, amount
|
|
) # Increase recipient's balance
|
|
|
|
current_sender_balance = await database.get_balance(sender_id)
|
|
embed_sender = discord.Embed(
|
|
title="Payment Successful!",
|
|
description=f"💸 You successfully paid **${amount:,}** to {recipient.mention}.",
|
|
color=discord.Color.green(),
|
|
)
|
|
embed_sender.add_field(
|
|
name="Your New Balance", value=f"${current_sender_balance:,}", inline=False
|
|
)
|
|
await ctx.send(embed=embed_sender)
|
|
try:
|
|
# Optionally DM the recipient
|
|
embed_recipient = discord.Embed(
|
|
title="You Received a Payment!",
|
|
description=f"💸 You received **${amount:,}** from {ctx.author.mention}!",
|
|
color=discord.Color.green(),
|
|
)
|
|
await recipient.send(embed=embed_recipient)
|
|
except discord.Forbidden:
|
|
log.warning(
|
|
f"Could not DM recipient {recipient_id} about payment."
|
|
) # User might have DMs closed
|
|
|
|
|
|
# No setup function needed here
|