First Commit
This commit is contained in:
Executable
+423
@@ -0,0 +1,423 @@
|
||||
import logging
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from utils.bank_functions import *
|
||||
from discord.ext import commands
|
||||
from datetime import datetime, timedelta
|
||||
from random import randint
|
||||
from typing import Literal
|
||||
import datetime
|
||||
|
||||
|
||||
async def check_transfer(
|
||||
ctx: commands.Context,
|
||||
payer_balance: int,
|
||||
receiver_balance: int,
|
||||
member: discord.Member,
|
||||
amount: int,
|
||||
) -> bool:
|
||||
"""Check if a transfer is valid.
|
||||
|
||||
Args:
|
||||
- ctx (commands.Context): The context of the invoked command.
|
||||
- payer_balance (int): The balance of the payer.
|
||||
- receiver_balance (int): The balance of the receiver.
|
||||
- member (discord.Member): The member to check against.
|
||||
- amount (int): The amount to transfer.
|
||||
|
||||
Returns:
|
||||
- bool: Whether the transfer is valid.
|
||||
"""
|
||||
if payer_balance is None or receiver_balance is None:
|
||||
await ctx.reply("Bank account doesn't exist.")
|
||||
return False
|
||||
if payer_balance >= amount > 0:
|
||||
payer_balance = payer_balance - amount
|
||||
receiver_balance = receiver_balance + amount
|
||||
if ctx.author.id != member.id:
|
||||
return True
|
||||
else:
|
||||
await ctx.reply("You cannot give yourself money.")
|
||||
return False
|
||||
else:
|
||||
await ctx.reply(
|
||||
f"You do not have {int(amount):,}<:flooney:1194943899765051473>.\nYou have {int(payer_balance):,}<:flooney:1194943899765051473>."
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
class Economy(commands.Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.db = DatabaseManager("")
|
||||
|
||||
r"""
|
||||
.----------------. .----------------. .----------------. .----------------. .-----------------.
|
||||
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
|
||||
| | __ | || | ________ | || | ____ ____ | || | _____ | || | ____ _____ | |
|
||||
| | / \ | || | |_ ___ `. | || ||_ \ / _|| || | |_ _| | || ||_ \|_ _| | |
|
||||
| | / /\ \ | || | | | `. \ | || | | \/ | | || | | | | || | | \ | | | |
|
||||
| | / ____ \ | || | | | | | | || | | |\ /| | | || | | | | || | | |\ \| | | |
|
||||
| | _/ / \ \_ | || | _| |___.' / | || | _| |_\/_| |_ | || | _| |_ | || | _| |_\ |_ | |
|
||||
| ||____| |____|| || | |________.' | || ||_____||_____|| || | |_____| | || ||_____|\____| | |
|
||||
| | | || | | || | | || | | || | | |
|
||||
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
|
||||
'----------------' '----------------' '----------------' '----------------' '----------------'
|
||||
"""
|
||||
|
||||
@commands.command(
|
||||
name="give_money",
|
||||
aliases=["addmoney"],
|
||||
usage="<member*: @member> <amount*: integer>",
|
||||
)
|
||||
@commands.is_owner()
|
||||
@commands.cooldown(3, 2 * 60, commands.BucketType.user)
|
||||
async def add_money(
|
||||
self, ctx: commands.Context, member: discord.Member, amount_str: str
|
||||
):
|
||||
"""Add money to a user's bank."""
|
||||
if member.bot:
|
||||
return await ctx.reply("You can't add money to a bot", mention_author=False)
|
||||
if not member:
|
||||
member = ctx.author
|
||||
|
||||
try:
|
||||
amount = int(amount_str)
|
||||
except ValueError:
|
||||
return await ctx.reply("Please enter a valid amount")
|
||||
|
||||
if amount <= 0:
|
||||
return await ctx.reply("Please enter an amount greater than 0")
|
||||
|
||||
limit = 1_000_000
|
||||
if amount > limit:
|
||||
return await ctx.reply(f"You cannot add money more than {limit:,}")
|
||||
|
||||
await update_money(member, amount)
|
||||
await ctx.reply(
|
||||
f"You added {amount:,} in {member.mention}'s bank.", mention_author=False
|
||||
)
|
||||
|
||||
@commands.command(
|
||||
aliases=["remoney"],
|
||||
usage="<member*: @member> <amount*: integer> <mode: wallet or bank>",
|
||||
)
|
||||
@commands.is_owner()
|
||||
@commands.cooldown(3, 2 * 60, commands.BucketType.user)
|
||||
async def remove_money(
|
||||
self, ctx, member: discord.Member, amount_str: str, mode: str = "bank"
|
||||
):
|
||||
mode = mode.lower()
|
||||
if member.bot:
|
||||
return await ctx.reply(
|
||||
"You can't remove money from a bot", mention_author=False
|
||||
)
|
||||
|
||||
try:
|
||||
amount = int(amount_str)
|
||||
if amount <= 0:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
return await ctx.reply("Please enter a valid amount")
|
||||
|
||||
if mode not in ["wallet", "bank"]:
|
||||
return await ctx.reply("Please enter either wallet or bank only")
|
||||
|
||||
user_balance = await bank_data(member)
|
||||
current_balance = user_balance["BANK" if mode == "bank" else "WALLET"]
|
||||
|
||||
if current_balance < amount:
|
||||
return await ctx.reply(
|
||||
f"You can only remove {current_balance:,} from {member.mention}'s {mode}"
|
||||
)
|
||||
|
||||
if mode == "bank":
|
||||
await update_money(member, bank=-amount)
|
||||
else:
|
||||
await update_money(member, wallet=-amount)
|
||||
|
||||
await ctx.reply(
|
||||
f"You removed {amount:,} from {member.mention}'s {mode}",
|
||||
mention_author=False,
|
||||
)
|
||||
|
||||
@commands.command(usage="<member*: @member>")
|
||||
@commands.is_owner()
|
||||
@commands.cooldown(2, 3 * 60, commands.BucketType.user)
|
||||
async def reset_money(self, ctx, member: discord.Member):
|
||||
if member.bot:
|
||||
return await ctx.reply(
|
||||
"Bots don't have bank accounts", mention_author=False
|
||||
)
|
||||
|
||||
await reset_bank(member)
|
||||
|
||||
return await ctx.reply(
|
||||
f"{member.mention}'s account has been reset", mention_author=False
|
||||
)
|
||||
|
||||
r"""
|
||||
.----------------. .----------------. .-----------------. .----------------.
|
||||
| .--------------. || .--------------. || .--------------. || .--------------. |
|
||||
| | ______ | || | __ | || | ____ _____ | || | ___ ____ | |
|
||||
| | |_ _ \ | || | / \ | || ||_ \|_ _| | || | |_ ||_ _| | |
|
||||
| | | |_) | | || | / /\ \ | || | | \ | | | || | | |_/ / | |
|
||||
| | | __'. | || | / ____ \ | || | | |\ \| | | || | | __'. | |
|
||||
| | _| |__) | | || | _/ / \ \_ | || | _| |_\ |_ | || | _| | \ \_ | |
|
||||
| | |_______/ | || ||____| |____|| || ||_____|\____| | || | |____||____| | |
|
||||
| | | || | | || | | || | | |
|
||||
| '--------------' || '--------------' || '--------------' || '--------------' |
|
||||
'----------------' '----------------' '----------------' '----------------'
|
||||
"""
|
||||
|
||||
@commands.command(
|
||||
name="balance",
|
||||
aliases=["bal"],
|
||||
brief="Check your money",
|
||||
description="Check how much money you have.",
|
||||
)
|
||||
async def _balance(
|
||||
self, ctx: commands.Context, member: discord.Member | None = None
|
||||
):
|
||||
"""
|
||||
Check how much money you have.
|
||||
"""
|
||||
target: discord.Member | discord.User = member or ctx.author
|
||||
|
||||
# Ensure the target is not a bot
|
||||
if target.bot:
|
||||
return
|
||||
|
||||
# Get the user's data
|
||||
user_data = await bank_data(target)
|
||||
wallet_balance = user_data.get("WALLET", 0)
|
||||
bank_balance = user_data.get("BANK", 0)
|
||||
|
||||
# Create an account if one does not exist
|
||||
if bank_balance is None or wallet_balance is None:
|
||||
await create_account(target)
|
||||
user_data = await bank_data(target)
|
||||
wallet_balance = user_data.get("WALLET", 0)
|
||||
bank_balance = user_data.get("BANK", 0)
|
||||
|
||||
# Reply with the user's balance
|
||||
await ctx.reply(
|
||||
f"{target.mention} has {bank_balance:,}<:flooney:1194943899765051473> in their bank and "
|
||||
f"{wallet_balance:,}<:flooney:1194943899765051473> in their wallet."
|
||||
)
|
||||
|
||||
@commands.command(name="give")
|
||||
async def _give(self, ctx, target: discord.Member, amount: int):
|
||||
"""Give money to another user."""
|
||||
|
||||
payer_wallet = int((await bank_data(ctx.author)).get("WALLET", 0))
|
||||
receiver_wallet = int((await bank_data(target)).get("WALLET", 0))
|
||||
|
||||
if await check_transfer(ctx, payer_wallet, receiver_wallet, target, amount):
|
||||
await update_money(target, wallet=amount)
|
||||
await update_money(ctx.author, wallet=-amount)
|
||||
|
||||
await ctx.reply(
|
||||
f"You gave {target} {amount:,} flooneys.", mention_author=False
|
||||
)
|
||||
|
||||
@commands.command(name="transfer")
|
||||
async def _transfer(self, ctx, target: discord.Member, amount: int):
|
||||
"""
|
||||
Transfer money from your bank account to another user's bank account.
|
||||
"""
|
||||
payer_bank = int((await bank_data(ctx.author)).get("BANK", 0))
|
||||
receiver_bank = int((await bank_data(target)).get("BANK", 0))
|
||||
|
||||
if await check_transfer(ctx, payer_bank, receiver_bank, target, amount):
|
||||
await update_money(target, bank=amount)
|
||||
await update_money(ctx.author, bank=-amount)
|
||||
|
||||
await ctx.reply(
|
||||
f"Transferred {amount:,} flooneys to {target}.", mention_author=False
|
||||
)
|
||||
|
||||
@commands.command(
|
||||
name="deposit",
|
||||
aliases=["dep"],
|
||||
brief="Deposit money",
|
||||
description="Deposit money from your wallet to the bank",
|
||||
)
|
||||
async def _deposit(self, ctx, amount: int | Literal["all"] = 0) -> None:
|
||||
"""Deposit money from your wallet to your bank account. Amount can be an integer or 'all' to deposit all money from wallet."""
|
||||
|
||||
user_data = await bank_data(ctx.author)
|
||||
if user_data is None:
|
||||
await create_account(ctx)
|
||||
user_data = await bank_data(ctx.author)
|
||||
|
||||
wallet_balance = int(user_data.get("WALLET", 0))
|
||||
|
||||
if amount == "all":
|
||||
amount = wallet_balance
|
||||
|
||||
if 0 <= amount <= wallet_balance:
|
||||
await update_money(ctx.author, bank=amount, wallet=-amount)
|
||||
await ctx.reply("Transaction successful.")
|
||||
else:
|
||||
await ctx.reply("Insufficient funds in wallet")
|
||||
|
||||
@commands.command(name="withdraw", brief="Withdraw money from bank to wallet")
|
||||
async def _withdraw(self, ctx, amount: int | Literal["all"] = 0) -> None:
|
||||
"""Withdraw money from your bank account to your wallet. Amount can be an integer or 'all' to withdraw all money from bank."""
|
||||
|
||||
user_data = await bank_data(ctx.author)
|
||||
if user_data is None:
|
||||
await create_account(ctx)
|
||||
user_data = await bank_data(ctx.author)
|
||||
|
||||
bank_balance = int(user_data.get("BANK", 0))
|
||||
|
||||
if amount == "all":
|
||||
amount = bank_balance
|
||||
|
||||
if 0 <= amount <= bank_balance:
|
||||
await update_money(ctx.author, bank=-amount, wallet=amount)
|
||||
await ctx.reply("Transaction successful.")
|
||||
else:
|
||||
await ctx.reply("Insufficient funds")
|
||||
|
||||
@commands.command(aliases=["lb"])
|
||||
@commands.guild_only()
|
||||
async def leaderboard(self, ctx):
|
||||
users_data = self.db.fetch_all(
|
||||
"SELECT * FROM economy ORDER BY BANK + WALLET DESC"
|
||||
)
|
||||
|
||||
leaderboard_entries = []
|
||||
position = 1
|
||||
for user_data in users_data:
|
||||
user_id = int(user_data["ID"])
|
||||
user = ctx.guild.get_member(user_id) or self.client.get_user(user_id)
|
||||
if user is None:
|
||||
try:
|
||||
user = await self.client.fetch_user(user_id)
|
||||
user_display = (
|
||||
user.display_name
|
||||
if hasattr(user, "display_name")
|
||||
else str(user)
|
||||
)
|
||||
except Exception:
|
||||
user_display = f"User {user_id}"
|
||||
else:
|
||||
user_display = (
|
||||
user.display_name if hasattr(user, "display_name") else str(user)
|
||||
)
|
||||
|
||||
total_balance = int(user_data["BANK"]) + int(user_data["WALLET"])
|
||||
flooney_icon = "<:flooney:1194943899765051473>"
|
||||
|
||||
if position <= 3:
|
||||
entry = f"{['🥇', '🥈', '🥉'][position-1]}**{position} {user_display}** -- {total_balance:,}{flooney_icon} "
|
||||
else:
|
||||
entry = (
|
||||
f"**{position} {user_display}** -- {total_balance:,}{flooney_icon}"
|
||||
)
|
||||
|
||||
leaderboard_entries.append(entry)
|
||||
position += 1
|
||||
if position > 10:
|
||||
break
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Top {len(leaderboard_entries)} Richest Users - Leaderboard",
|
||||
description="\n".join(leaderboard_entries),
|
||||
color=discord.Color(0x00FF00),
|
||||
timestamp=datetime.datetime.utcnow(),
|
||||
)
|
||||
embed.set_footer(text=f"GLOBAL - {ctx.guild.name}")
|
||||
await ctx.reply(embed=embed, mention_author=False)
|
||||
|
||||
r"""
|
||||
.----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------.
|
||||
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
|
||||
| | ______ | || | _________ | || | _______ | || | _____ | || | ____ | || | ________ | || | _____ | || | ______ | || | __ | || | _____ | || | _____ | || | ____ ____ | |
|
||||
| | |_ __ \ | || | |_ ___ | | || | |_ __ \ | || | |_ _| | || | .' `. | || | |_ ___ `. | || | |_ _| | || | .' ___ | | || | / \ | || | |_ _| | || | |_ _| | || | |_ _||_ _| | |
|
||||
| | | |__) | | || | | |_ \_| | || | | |__) | | || | | | | || | / .--. \ | || | | | `. \ | || | | | | || | / .' \_| | || | / /\ \ | || | | | | || | | | | || | \ \ / / | |
|
||||
| | | ___/ | || | | _| _ | || | | __ / | || | | | | || | | | | | | || | | | | | | || | | | | || | | | | || | / ____ \ | || | | | _ | || | | | _ | || | \ \/ / | |
|
||||
| | _| |_ | || | _| |___/ | | || | _| | \ \_ | || | _| |_ | || | \ `--' / | || | _| |___.' / | || | _| |_ | || | \ `.___.'\ | || | _/ / \ \_ | || | _| |__/ | | || | _| |__/ | | || | _| |_ | |
|
||||
| | |_____| | || | |_________| | || | |____| |___| | || | |_____| | || | `.____.' | || | |________.' | || | |_____| | || | `._____.' | || ||____| |____|| || | |________| | || | |________| | || | |______| | |
|
||||
| | | || | | || | | || | | || | | || | | || | | || | | || | | || | | || | | || | | |
|
||||
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
|
||||
'----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------'
|
||||
"""
|
||||
|
||||
@commands.command(name="daily", help="Claim your daily pocket money")
|
||||
async def claim_daily_money(self, ctx: commands.Context) -> None:
|
||||
"""Claim your daily pocket money. You can claim once every 24 hours."""
|
||||
try:
|
||||
user_data = await bank_data(ctx.author)
|
||||
last_claim = user_data.get("DAILY")
|
||||
now = discord.utils.utcnow() # Modern, timezone-aware
|
||||
|
||||
# Convert last_claim to datetime if it's a timestamp (int or float)
|
||||
if last_claim:
|
||||
if isinstance(last_claim, (int, float)):
|
||||
last_claim_dt = datetime.datetime.fromtimestamp(
|
||||
last_claim, tz=datetime.timezone.utc
|
||||
)
|
||||
elif isinstance(last_claim, str):
|
||||
try:
|
||||
last_claim_dt = datetime.datetime.fromtimestamp(
|
||||
float(last_claim), tz=datetime.timezone.utc
|
||||
)
|
||||
except Exception:
|
||||
last_claim_dt = None
|
||||
elif isinstance(last_claim, datetime.datetime):
|
||||
# If it's naive, make it aware
|
||||
if last_claim.tzinfo is None:
|
||||
last_claim_dt = last_claim.replace(tzinfo=datetime.timezone.utc)
|
||||
else:
|
||||
last_claim_dt = last_claim
|
||||
else:
|
||||
last_claim_dt = None
|
||||
else:
|
||||
last_claim_dt = None
|
||||
|
||||
if not last_claim_dt or (now - last_claim_dt).total_seconds() >= 86400:
|
||||
daily_reward = randint(200, 1000)
|
||||
await update_money(ctx.author, daily_reward)
|
||||
# Save the new timestamp as a float (UNIX time)
|
||||
await update_daily_timestamp(ctx.author, now)
|
||||
await ctx.reply(
|
||||
f"Your daily pocket money is {daily_reward:,}<:flooney:1194943899765051473>",
|
||||
mention_author=False,
|
||||
)
|
||||
else:
|
||||
next_claim = last_claim_dt + timedelta(days=1)
|
||||
time_left = next_claim - now
|
||||
hours, remainder = divmod(int(time_left.total_seconds()), 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
await ctx.reply(
|
||||
f"Already claimed today. You need to wait **{hours}H {minutes}M {seconds}S**.",
|
||||
mention_author=False,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Error in daily claim: {e}")
|
||||
await ctx.reply(
|
||||
f"An error occurred while claiming your daily reward. {e}",
|
||||
mention_author=False,
|
||||
)
|
||||
|
||||
r"""
|
||||
.----------------. .----------------. .----------------. .----------------.
|
||||
| .--------------. || .--------------. || .--------------. || .--------------. |
|
||||
| | _____ | || | ____ | || | ______ | || | _______ | |
|
||||
| | |_ _| | || | .' `. | || | |_ _ \ | || | / ___ | | |
|
||||
| | | | | || | / .--. \ | || | | |_) | | || | | (__ \_| | |
|
||||
| | _ | | | || | | | | | | || | | __'. | || | '.___`-. | |
|
||||
| | | |_' | | || | \ `--' / | || | _| |__) | | || | |`\____) | | |
|
||||
| | `.___.' | || | `.____.' | || | |_______/ | || | |_______.' | |
|
||||
| | | || | | || | | || | | |
|
||||
| '--------------' || '--------------' || '--------------' || '--------------' |
|
||||
'----------------' '----------------' '----------------' '----------------'
|
||||
"""
|
||||
|
||||
|
||||
async def setup(client):
|
||||
await client.add_cog(Economy(client))
|
||||
Reference in New Issue
Block a user