[Bank] Allow bank managers to set the maximum allowed balance in the bank (#2926)

* Removes `MAX_BALANCE` from bank, user `bank.get_max_balance()` now
`[p]bankset maxbal` can be used to set the maximum bank balance

Signed-off-by: Guy <guyreis96@gmail.com>

* Removes `MAX_BALANCE` from bank, user `bank.get_max_balance()` now
`[p]bankset maxbal` can be used to set the maximum bank balance

Signed-off-by: Guy <guyreis96@gmail.com>

* Removes `MAX_BALANCE` from bank, user `bank.get_max_balance()` now
`[p]bankset maxbal` can be used to set the maximum bank balance

Signed-off-by: Guy <guyreis96@gmail.com>

* Rename method 🤦

Signed-off-by: Guy <guyreis96@gmail.com>

* Updated this to be aware of #2925

Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>

* Addressed Flames review + Fixed 1 bug in errors.py + `[p]leaderboard` and `[p]bank balance` will set the users balance to max balance if the bank maxbal is lower than the previous user balance

Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>

* Missed this clarification

Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>

* address Flames review

Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
This commit is contained in:
Draper
2019-08-30 02:05:31 +01:00
committed by Michael H
parent b490942bcd
commit e04eed4a89
6 changed files with 159 additions and 26 deletions

View File

@@ -12,7 +12,6 @@ from .i18n import Translator
_ = Translator("Bank API", __file__)
__all__ = [
"MAX_BALANCE",
"Account",
"get_balance",
"set_balance",
@@ -30,20 +29,28 @@ __all__ = [
"set_currency_name",
"get_default_balance",
"set_default_balance",
"get_max_balance",
"set_max_balance",
"cost",
"AbortPurchase",
]
MAX_BALANCE = 2 ** 63 - 1
_MAX_BALANCE = 2 ** 63 - 1
_DEFAULT_GLOBAL = {
"is_global": False,
"bank_name": "Twentysix bank",
"currency": "credits",
"default_balance": 100,
"max_balance": _MAX_BALANCE,
}
_DEFAULT_GUILD = {"bank_name": "Twentysix bank", "currency": "credits", "default_balance": 100}
_DEFAULT_GUILD = {
"bank_name": "Twentysix bank",
"currency": "credits",
"default_balance": 100,
"max_balance": _MAX_BALANCE,
}
_DEFAULT_MEMBER = {"name": "", "balance": 0, "created_at": 0}
@@ -186,10 +193,11 @@ async def set_balance(member: discord.Member, amount: int) -> int:
"""
if amount < 0:
raise ValueError("Not allowed to have negative balance.")
if amount > MAX_BALANCE:
max_bal = await get_max_balance(member.guild)
if amount > max_bal:
currency = await get_currency_name(member.guild)
raise errors.BalanceTooHigh(
user=member.display_name, max_balance=MAX_BALANCE, currency_name=currency
user=member.display_name, max_balance=max_bal, currency_name=currency
)
if await is_global():
group = _conf.user(member)
@@ -329,10 +337,12 @@ async def transfer_credits(from_: discord.Member, to: discord.Member, amount: in
)
)
if await get_balance(to) + amount > MAX_BALANCE:
max_bal = await get_max_balance(to.guild)
if await get_balance(to) + amount > max_bal:
currency = await get_currency_name(to.guild)
raise errors.BalanceTooHigh(
user=to.display_name, max_balance=MAX_BALANCE, currency_name=currency
user=to.display_name, max_balance=max_bal, currency_name=currency
)
await withdraw_credits(from_, amount)
@@ -635,6 +645,75 @@ async def set_currency_name(name: str, guild: discord.Guild = None) -> str:
return name
async def get_max_balance(guild: discord.Guild = None) -> int:
"""Get the max balance for the bank.
Parameters
----------
guild : `discord.Guild`, optional
The guild to get the max balance for (required if bank is
guild-specific).
Returns
-------
int
The maximum allowed balance.
Raises
------
RuntimeError
If the bank is guild-specific and guild was not provided.
"""
if await is_global():
return await _conf.max_balance()
elif guild is not None:
return await _conf.guild(guild).max_balance()
else:
raise RuntimeError("Guild must be provided.")
async def set_max_balance(amount: int, guild: discord.Guild = None) -> int:
"""Set the maximum balance for the bank.
Parameters
----------
amount : int
The new maximum balance.
guild : `discord.Guild`, optional
The guild to set the max balance for (required if bank is
guild-specific).
Returns
-------
int
The new maximum balance.
Raises
------
RuntimeError
If the bank is guild-specific and guild was not provided.
ValueError
If the amount is less than 0 or higher than 2 ** 63 - 1.
"""
if not (0 < amount <= _MAX_BALANCE):
raise ValueError(
"Amount must be greater than zero and less than {max}.".format(
max=humanize_number(_MAX_BALANCE, override_locale="en_US")
)
)
if await is_global():
await _conf.max_balance.set(amount)
elif guild is not None:
await _conf.guild(guild).max_balance.set(amount)
else:
raise RuntimeError(
"Guild must be provided if setting the maximum balance of a guild-specific bank."
)
return amount
async def get_default_balance(guild: discord.Guild = None) -> int:
"""Get the current default balance amount.
@@ -684,12 +763,18 @@ async def set_default_balance(amount: int, guild: discord.Guild = None) -> int:
RuntimeError
If the bank is guild-specific and guild was not provided.
ValueError
If the amount is invalid.
If the amount is less than 0 or higher than the max allowed balance.
"""
amount = int(amount)
if amount < 0:
raise ValueError("Amount must be greater than zero.")
max_bal = await get_max_balance(guild)
if not (0 < amount <= max_bal):
raise ValueError(
"Amount must be greater than zero and less than {max}.".format(
max=humanize_number(max_bal, override_locale="en_US")
)
)
if await is_global():
await _conf.default_balance.set(amount)
@@ -714,7 +799,7 @@ def cost(amount: int):
You can intentionally refund by raising `AbortPurchase`
(this error will be consumed and not show to users)
Other exceptions will propogate and will be handled by Red's (and/or
Other exceptions will propagate and will be handled by Red's (and/or
any other configured) error handling.
"""
if not isinstance(amount, int) or amount < 0: