diff options
author | 2019-09-26 18:25:04 -0700 | |
---|---|---|
committer | 2019-10-01 18:25:30 -0700 | |
commit | 689d203475cb68b1eb85afe6e44c688197c56a9b (patch) | |
tree | 470f097b0f0ac1744882c84419c4af5a237bb97a | |
parent | Make respect_role_hierarchy a decorator (diff) |
Support positional target arg for respect_role_hierarchy
* Add some logging
-rw-r--r-- | bot/decorators.py | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/bot/decorators.py b/bot/decorators.py index a44d62afa..d8a9494d2 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -3,7 +3,7 @@ import random from asyncio import Lock, sleep from contextlib import suppress from functools import wraps -from typing import Any, Callable, Container, Optional +from typing import Any, Callable, Container, Optional, Union from weakref import WeakValueDictionary from discord import Colour, Embed, Member @@ -144,20 +144,33 @@ def redirect_output(destination_channel: int, bypass_roles: Container[int] = Non return wrap -def respect_role_hierarchy(target_arg_name: str = "user") -> Callable: +def respect_role_hierarchy(target_arg: Union[int, str] = 0) -> Callable: """ Ensure the highest role of the invoking member is greater than that of the target member. If the condition fails, a warning is sent to the invoking context. A target which is not an instance of discord.Member will always pass. + A value of 0 (i.e. position 0) for `target_arg` corresponds to the argument which comes after + `ctx`. If the target argument is a kwarg, its name can instead be given. + This decorator must go before (below) the `command` decorator. """ def wrap(func: Callable) -> Callable: @wraps(func) async def inner(self: Callable, ctx: Context, *args, **kwargs) -> Any: - target = kwargs[target_arg_name] + try: + target = kwargs[target_arg] + except KeyError: + try: + target = args[target_arg] + except IndexError: + log.error(f"Could not find target member argument at position {target_arg}") + except TypeError: + log.error(f"Could not find target member kwarg with key {target_arg!r}") + if not isinstance(target, Member): + log.trace("The target is not a discord.Member; skipping role hierarchy check.") return await func(self, ctx, *args, **kwargs) cmd = ctx.command.name |