Compare commits

...

5 Commits

Author SHA1 Message Date
Stijn De Clercq d46a31a7be
Merge pull request #182 from stijndcl/fix/markdown-names
Fix formatting edge case for usernames starting with "XX."
2024-02-12 22:58:36 +01:00
stijndcl 165be35f8e Fix name formatting 2024-02-12 22:55:35 +01:00
Stijn De Clercq 35d1d871de
Merge pull request #181 from stijndcl/return-dinks
Re-enable some currency commands
2024-02-12 20:20:51 +01:00
stijndcl cc75dd8909 Fix typing 2024-02-12 20:16:52 +01:00
stijndcl 685e4d953e Re-enable currency, add withdraw and cf 2024-02-12 20:07:57 +01:00
6 changed files with 190 additions and 23 deletions

View File

@ -15,12 +15,14 @@ from database.utils.math.currency import (
__all__ = [ __all__ = [
"add_dinks", "add_dinks",
"claim_nightly", "claim_nightly",
"gamble_dinks",
"get_bank", "get_bank",
"get_nightly_data", "get_nightly_data",
"invest", "invest",
"upgrade_capacity", "upgrade_capacity",
"upgrade_interest", "upgrade_interest",
"upgrade_rob", "upgrade_rob",
"withdraw",
"NIGHTLY_AMOUNT", "NIGHTLY_AMOUNT",
] ]
@ -40,7 +42,7 @@ async def get_nightly_data(session: AsyncSession, user_id: int) -> NightlyData:
async def invest(session: AsyncSession, user_id: int, amount: Union[str, int]) -> int: async def invest(session: AsyncSession, user_id: int, amount: Union[str, int]) -> int:
"""Invest all your Dinks""" """Invest some of your Dinks"""
bank = await get_bank(session, user_id) bank = await get_bank(session, user_id)
if amount == "all": if amount == "all":
amount = bank.dinks amount = bank.dinks
@ -57,6 +59,22 @@ async def invest(session: AsyncSession, user_id: int, amount: Union[str, int]) -
return amount return amount
async def withdraw(session: AsyncSession, user_id: int, amount: Union[str, int]) -> int:
"""Withdraw your invested Dinks"""
bank = await get_bank(session, user_id)
if amount == "all":
amount = bank.invested
# Don't allow withdrawing more dinks than you own
amount = min(bank.invested, int(amount))
bank.dinks += amount
bank.invested -= amount
await session.commit()
return amount
async def add_dinks(session: AsyncSession, user_id: int, amount: int): async def add_dinks(session: AsyncSession, user_id: int, amount: int):
"""Increase the Dinks counter for a user""" """Increase the Dinks counter for a user"""
bank = await get_bank(session, user_id) bank = await get_bank(session, user_id)
@ -135,3 +153,20 @@ async def upgrade_rob(session: AsyncSession, user_id: int) -> int:
await session.commit() await session.commit()
return bank.rob_level return bank.rob_level
async def gamble_dinks(
session: AsyncSession, user_id: int, amount: Union[str, int], payout_factor: int, won: bool
) -> int:
"""Gamble some of your Dinks"""
bank = await get_bank(session, user_id)
if amount == "all":
amount = bank.dinks
amount = min(int(amount), bank.dinks)
sign = 1 if won else -1
factor = (payout_factor - 1) if won else 1
await add_dinks(session, user_id, sign * amount * factor)
return amount * factor

View File

@ -1,3 +1,4 @@
# flake8: noqa: E800
import typing import typing
import discord import discord
@ -38,7 +39,7 @@ class Currency(commands.Cog):
await crud.add_dinks(session, user.id, amount) await crud.add_dinks(session, user.id, amount)
plural = pluralize("Didier Dink", amount) plural = pluralize("Didier Dink", amount)
await ctx.reply( await ctx.reply(
f"**{ctx.author.display_name}** has awarded **{user.display_name}** **{amount}** {plural}.", f"{ctx.author.display_name} has awarded **{user.display_name}** with **{amount}** {plural}.",
mention_author=False, mention_author=False,
) )
@ -48,7 +49,8 @@ class Currency(commands.Cog):
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
bank = await crud.get_bank(session, ctx.author.id) bank = await crud.get_bank(session, ctx.author.id)
embed = discord.Embed(title=f"{ctx.author.display_name}'s Bank", colour=discord.Colour.blue()) embed = discord.Embed(title="Bank of Didier", colour=discord.Colour.blue())
embed.set_author(name=ctx.author.display_name)
if ctx.author.avatar is not None: if ctx.author.avatar is not None:
embed.set_thumbnail(url=ctx.author.avatar.url) embed.set_thumbnail(url=ctx.author.avatar.url)
@ -59,9 +61,9 @@ class Currency(commands.Cog):
await ctx.reply(embed=embed, mention_author=False) await ctx.reply(embed=embed, mention_author=False)
@bank.group( # type: ignore[arg-type] # @bank.group( # type: ignore[arg-type]
name="upgrade", aliases=["u", "upgrades"], case_insensitive=True, invoke_without_command=True # name="upgrade", aliases=["u", "upgrades"], case_insensitive=True, invoke_without_command=True
) # )
async def bank_upgrades(self, ctx: commands.Context): async def bank_upgrades(self, ctx: commands.Context):
"""List the upgrades you can buy & their prices.""" """List the upgrades you can buy & their prices."""
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
@ -81,7 +83,7 @@ class Currency(commands.Cog):
await ctx.reply(embed=embed, mention_author=False) await ctx.reply(embed=embed, mention_author=False)
@bank_upgrades.command(name="capacity", aliases=["c"]) # type: ignore[arg-type] # @bank_upgrades.command(name="capacity", aliases=["c"]) # type: ignore[arg-type]
async def bank_upgrade_capacity(self, ctx: commands.Context): async def bank_upgrade_capacity(self, ctx: commands.Context):
"""Upgrade the capacity level of your bank.""" """Upgrade the capacity level of your bank."""
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
@ -92,7 +94,7 @@ class Currency(commands.Cog):
await ctx.reply("You don't have enough Didier Dinks to do this.", mention_author=False) await ctx.reply("You don't have enough Didier Dinks to do this.", mention_author=False)
await self.client.reject_message(ctx.message) await self.client.reject_message(ctx.message)
@bank_upgrades.command(name="interest", aliases=["i"]) # type: ignore[arg-type] # @bank_upgrades.command(name="interest", aliases=["i"]) # type: ignore[arg-type]
async def bank_upgrade_interest(self, ctx: commands.Context): async def bank_upgrade_interest(self, ctx: commands.Context):
"""Upgrade the interest level of your bank.""" """Upgrade the interest level of your bank."""
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
@ -103,7 +105,7 @@ class Currency(commands.Cog):
await ctx.reply("You don't have enough Didier Dinks to do this.", mention_author=False) await ctx.reply("You don't have enough Didier Dinks to do this.", mention_author=False)
await self.client.reject_message(ctx.message) await self.client.reject_message(ctx.message)
@bank_upgrades.command(name="rob", aliases=["r"]) # type: ignore[arg-type] # @bank_upgrades.command(name="rob", aliases=["r"]) # type: ignore[arg-type]
async def bank_upgrade_rob(self, ctx: commands.Context): async def bank_upgrade_rob(self, ctx: commands.Context):
"""Upgrade the rob level of your bank.""" """Upgrade the rob level of your bank."""
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
@ -120,14 +122,14 @@ class Currency(commands.Cog):
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
bank = await crud.get_bank(session, ctx.author.id) bank = await crud.get_bank(session, ctx.author.id)
plural = pluralize("Didier Dink", bank.dinks) plural = pluralize("Didier Dink", bank.dinks)
await ctx.reply(f"**{ctx.author.display_name}** has **{bank.dinks}** {plural}.", mention_author=False) await ctx.reply(f"You have **{bank.dinks}** {plural}.", mention_author=False)
@commands.command(name="invest", aliases=["deposit", "dep"]) # type: ignore[arg-type] @commands.command(name="invest", aliases=["deposit", "dep", "i"]) # type: ignore[arg-type]
async def invest(self, ctx: commands.Context, amount: typing.Annotated[typing.Union[str, int], abbreviated_number]): async def invest(self, ctx: commands.Context, amount: typing.Annotated[typing.Union[str, int], abbreviated_number]):
"""Invest `amount` Didier Dinks into your bank. """Invest `amount` Didier Dinks into your bank.
The `amount`-argument can take both raw numbers, and abbreviations of big numbers. Additionally, passing The `amount`-argument can take both raw numbers, and abbreviations of big numbers. Additionally, passing
`all` as the value will invest all of your Didier Dinks. `all` or `*` as the value will invest all of your Didier Dinks.
Example usage: Example usage:
``` ```
@ -137,6 +139,9 @@ class Currency(commands.Cog):
didier invest 5.3b didier invest 5.3b
``` ```
""" """
if isinstance(amount, int) and amount <= 0:
return await ctx.reply("Amount of Didier Dinks to invest must be a strictly positive integer.")
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
invested = await crud.invest(session, ctx.author.id, amount) invested = await crud.invest(session, ctx.author.id, amount)
plural = pluralize("Didier Dink", invested) plural = pluralize("Didier Dink", invested)
@ -144,9 +149,24 @@ class Currency(commands.Cog):
if invested == 0: if invested == 0:
await ctx.reply("You don't have any Didier Dinks to invest.", mention_author=False) await ctx.reply("You don't have any Didier Dinks to invest.", mention_author=False)
else: else:
await ctx.reply( await ctx.reply(f"You have invested **{invested}** {plural}.", mention_author=False)
f"**{ctx.author.display_name}** has invested **{invested}** {plural}.", mention_author=False
) @commands.command(name="withdraw", aliases=["uninvest", "w"]) # type: ignore[arg-type]
async def withdraw(
self, ctx: commands.Context, amount: typing.Annotated[typing.Union[str, int], abbreviated_number]
):
"""Withdraw some of your invested Didier Dinks from your bank."""
if isinstance(amount, int) and amount <= 0:
return await ctx.reply("Amount of Didier Dinks to invest must be a strictly positive integer.")
async with self.client.postgres_session as session:
withdrawn = await crud.withdraw(session, ctx.author.id, amount)
plural = pluralize("Didier Dink", withdrawn)
if withdrawn == 0:
await ctx.reply("You don't have any Didier Dinks to withdraw.", mention_author=False)
else:
await ctx.reply(f"You have withdrawn **{withdrawn}** {plural}.", mention_author=False)
@commands.hybrid_command(name="nightly") # type: ignore[arg-type] @commands.hybrid_command(name="nightly") # type: ignore[arg-type]
async def nightly(self, ctx: commands.Context): async def nightly(self, ctx: commands.Context):
@ -154,7 +174,9 @@ class Currency(commands.Cog):
async with self.client.postgres_session as session: async with self.client.postgres_session as session:
try: try:
await crud.claim_nightly(session, ctx.author.id) await crud.claim_nightly(session, ctx.author.id)
await ctx.reply(f"You've claimed your daily **{crud.NIGHTLY_AMOUNT}** Didier Dinks.") await ctx.reply(
f"You've claimed your daily **{crud.NIGHTLY_AMOUNT}** Didier Dinks.", mention_author=False
)
except DoubleNightly: except DoubleNightly:
await ctx.reply( await ctx.reply(
"You've already claimed your Didier Nightly today.", mention_author=False, ephemeral=True "You've already claimed your Didier Nightly today.", mention_author=False, ephemeral=True

View File

@ -0,0 +1,73 @@
import random
from typing import Annotated, Optional, Union
from discord.ext import commands
from database.crud.currency import gamble_dinks
from didier import Didier
from didier.utils.discord.converters import abbreviated_number
from didier.utils.types.string import pluralize
class Gambling(commands.Cog):
"""Cog for various games"""
client: Didier
def __init__(self, client: Didier):
self.client = client
@commands.command(name="coinflip", aliases=["cf", "flip"]) # type: ignore[arg-type]
async def coinflip(
self,
ctx: commands.Context,
amount: Optional[Annotated[Union[str, int], abbreviated_number]] = None,
guess: Optional[str] = None,
):
"""Toss a coin, optionally wagering some Didier Dinks.
Passing an argument for `amount` but not `guess` will cause the guess to be randomized.
"""
result: str = random.choice(["heads", "tails"])
# No stakes
if amount is None:
return await ctx.reply(f"{result.capitalize()}!", mention_author=False)
if guess is None:
guess = random.choice(["heads", "tails"])
guess = guess.lower()
if guess not in (
"h",
"heads",
"t",
"tails",
):
return await ctx.reply('Guess must be one of "h", "heads", "t" or "tails".', mention_author=False)
if isinstance(amount, int) and amount <= 0:
return await ctx.reply(
"Amount of Didier Dinks to wager must be a strictly positive integer.", mention_author=False
)
won = guess[0] == result[0]
async with self.client.postgres_session as session:
received = await gamble_dinks(session, ctx.author.id, amount, 2, won)
if received == 0:
return await ctx.reply("You don't have any Didier Dinks to wager.", mention_author=False)
plural = pluralize("Didier Dink", received)
if won:
await ctx.reply(f"{result.capitalize()}! You won **{received}** {plural}!", mention_author=False)
else:
await ctx.reply(f"{result.capitalize()}! You lost **{received}** {plural}!", mention_author=False)
async def setup(client: Didier):
"""Load the cog"""
await client.add_cog(Gambling(client))

View File

@ -54,14 +54,55 @@ class Owner(commands.Cog):
"""Raise an exception for debugging purposes""" """Raise an exception for debugging purposes"""
raise Exception(message) raise Exception(message)
@commands.command(name="unload")
async def unload(self, ctx: commands.Context, *cogs: str):
"""Unload the cogs passed as an argument"""
unloaded = []
skipped = []
for cog in cogs:
try:
await self.client.unload_extension(f"didier.cogs.{cog}")
unloaded.append(cog)
except commands.ExtensionNotLoaded:
skipped.append(cog)
await self.client.confirm_message(ctx.message)
loaded_message = ", ".join(unloaded) if unloaded else "none"
skipped_message = ", ".join(skipped) if skipped else "none"
await ctx.reply(f"Successfully unloaded {loaded_message} (skipped {skipped_message}).", mention_author=False)
@commands.command(name="load")
async def load(self, ctx: commands.Context, *cogs: str):
"""Load the cogs passed as an argument"""
loaded = []
skipped = []
for cog in cogs:
try:
await self.client.load_extension(f"didier.cogs.{cog}")
loaded.append(cog)
except commands.ExtensionAlreadyLoaded:
skipped.append(cog)
await self.client.confirm_message(ctx.message)
loaded_message = ", ".join(loaded) if loaded else "none"
skipped_message = ", ".join(skipped) if skipped else "none"
await ctx.reply(f"Successfully loaded {loaded_message} (skipped {skipped_message}).", mention_author=False)
@commands.command(name="Reload") @commands.command(name="Reload")
async def reload(self, ctx: commands.Context, *cogs: str): async def reload(self, ctx: commands.Context, *cogs: str):
"""Reload the cogs passed as an argument""" """Reload the cogs passed as an argument"""
for cog in cogs: for cog in cogs:
try:
await self.client.reload_extension(f"didier.cogs.{cog}") await self.client.reload_extension(f"didier.cogs.{cog}")
except commands.ExtensionNotLoaded:
await self.client.load_extension(f"didier.cogs.{cog}")
await self.client.confirm_message(ctx.message) await self.client.confirm_message(ctx.message)
return await ctx.reply(f"Successfully reloaded {', '.join(cogs)}.", mention_author=False) await ctx.reply(f"Successfully reloaded {', '.join(cogs)}.", mention_author=False)
@commands.command(name="Sync") @commands.command(name="Sync")
async def sync( async def sync(

View File

@ -121,10 +121,6 @@ class Didier(commands.Bot):
# Allow checking against initial extensions more easily # Allow checking against initial extensions more easily
full_name = parent_path + file full_name = parent_path + file
# The currency cog is disabled
if "currency" in file:
continue
# Only take Python files, and ignore the ones starting with an underscore (like __init__ and __pycache__) # Only take Python files, and ignore the ones starting with an underscore (like __init__ and __pycache__)
# Also ignore the files that we have already loaded previously # Also ignore the files that we have already loaded previously
if file.endswith(".py") and not file.startswith("_") and not full_name.startswith(self.initial_extensions): if file.endswith(".py") and not file.startswith("_") and not full_name.startswith(self.initial_extensions):

View File

@ -14,7 +14,7 @@ def abbreviated_number(argument: str) -> Union[str, int]:
if not argument: if not argument:
raise ValueError raise ValueError
if argument.lower() == "all": if argument.lower() == "all" or argument == "*":
return "all" return "all"
if argument.isdecimal(): if argument.isdecimal():