[Bank] Allow Bot Owner/Guild Owners to remove invalid users from the bank (#2845)

* Add command to remove dead members from bank

* Add a global check

* Added a FIXME so `bank_local_clean` is updated once bulk-update is implemented
Added a brief warning to warn devs not to use the `_get_base_group` as it can mess up their config files
Removed a redundant existence check

* Updated  commit to reflect changes requested in review

* Updated  commit to reflect changes requested in review

* 🤦

* Return command to run with user id so we don't worry about safeguarding the command agaisn't invalid formats

* Braaaainnn

Removed aliases that used old naming scheme

* TL:DR  Added global bank support, and rework permissions

Renamed `bank_local_clean` to `bank_prune`
Added support for global banks to `bank_prune`
`bank_prune` will now raise `BankPruneError` if trying to prune a local bank and `guild` is not supplied

Renamed `cleanup` subgroup to `prune`
`prune` subgroup will have 3 commands:
  `user`   :  Deletes the bank account for the specified member : Accepts `Union[discord.Member, discord.User, int]`
  `global` :  Prune global bank accounts for all users who no longer share a server with the bot
  `local`  :  Prune local bank accounts for all users who are no longer in the guild

Changed check for `prune` subgroup to be `@check_global_setting_admin()`
[p]bank prune local  : Can be run by Guild owners only
[p]bank prune global : Can be run by Bot Owner only
[p]bank prune user   : Can be run by Admins, Guild owners and Bot Owner

* Yikes ... Updated kwarg name

* Fixed unexpected unindent: docstring of redbot.core.bank.bank_prune:14:Field list ends without a blank line

* ...

* 3rd time lucky?

* 4th time lucky?

* Fix Docstring

* Initial commit to address review by Flame

* Updated code to reflect Flame's comments

* Skip pruning of unavailable guilds

* Fixed typo in string

* *sigh* black is the bane of my existence

* addressed Flames commends
Fixed [p]bank prune user, When run via DM it will now return an error message to the user (Thanks jack1142)

* Time to get some sleep

* 'DM' > 'DMs' in string

* Add towncrier entries

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

* Update to reflect Flame's review

Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
This commit is contained in:
Draper
2019-08-30 22:35:25 +01:00
committed by Michael H
parent ef3ac77bd8
commit 7959e0c916
6 changed files with 158 additions and 2 deletions

View File

@@ -8,6 +8,8 @@ import discord
from redbot.core.utils.chat_formatting import humanize_number
from . import Config, errors, commands
from .i18n import Translator
from .bot import Red
from .errors import BankPruneError
_ = Translator("Bank API", __file__)
@@ -33,6 +35,7 @@ __all__ = [
"set_max_balance",
"cost",
"AbortPurchase",
"bank_prune",
]
_MAX_BALANCE = 2 ** 63 - 1
@@ -365,6 +368,59 @@ async def wipe_bank(guild: Optional[discord.Guild] = None) -> None:
await _conf.clear_all_members(guild)
async def bank_prune(bot: Red, guild: discord.Guild = None, user_id: int = None) -> None:
"""Prune bank accounts from the bank.
Parameters
----------
bot : Red
The bot.
guild : discord.Guild
The guild to prune. This is required if the bank is set to local.
user_id : int
The id of the user whose account will be pruned.
If supplied this will prune only this user's bank account
otherwise it will prune all invalid users from the bank.
Raises
------
BankPruneError
If guild is :code:`None` and the bank is Local.
"""
global_bank = await is_global()
if global_bank:
_guilds = [g for g in bot.guilds if not g.unavailable and g.large and not g.chunked]
_uguilds = [g for g in bot.guilds if g.unavailable]
group = _conf._get_base_group(_conf.USER)
else:
if guild is None:
raise BankPruneError("'guild' can't be None when pruning a local bank")
_guilds = [guild] if not guild.unavailable and guild.large else []
_uguilds = [guild] if guild.unavailable else []
group = _conf._get_base_group(_conf.MEMBER, str(guild.id))
if user_id is None:
await bot.request_offline_members(*_guilds)
accounts = await group.all()
tmp = accounts.copy()
members = bot.get_all_members() if global_bank else guild.members
user_list = {str(m.id) for m in members if m.guild not in _uguilds}
async with group.all() as bank_data: # FIXME: use-config-bulk-update
if user_id is None:
for acc in tmp:
if acc not in user_list:
del bank_data[acc]
else:
user_id = str(user_id)
if user_id in bank_data:
del bank_data[user_id]
async def get_leaderboard(positions: int = None, guild: discord.Guild = None) -> List[tuple]:
"""
Gets the bank's leaderboard

View File

@@ -883,6 +883,12 @@ class Config:
self.custom_groups[group_identifier] = identifier_count
def _get_base_group(self, category: str, *primary_keys: str) -> Group:
"""
.. warning::
:code:`Config._get_base_group()` should not be used to get config groups as
this is not a safe operation. Using this could end up corrupting your config file.
"""
# noinspection PyTypeChecker
pkey_len, is_custom = ConfigCategory.get_pkey_info(category, self.custom_groups)
identifier_data = IdentifierData(
cog_name=self.cog_name,

View File

@@ -51,6 +51,10 @@ class BalanceTooHigh(BankError, OverflowError):
)
class BankPruneError(BankError):
"""Raised when trying to prune a local bank and no server is specified."""
class MissingExtraRequirements(RedError):
"""Raised when an extra requirement is missing but required."""