mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-08 12:18:54 -05:00
[V3 Permissions] Don't rely on load order to be consistent (#1760)
* Modifies permissions re #1758 * requested changes in
This commit is contained in:
parent
0d193d3e9e
commit
5de5a519c3
@ -32,60 +32,9 @@ class Permissions:
|
||||
def __init__(self, bot: Red):
|
||||
self.bot = bot
|
||||
self.config = Config.get_conf(self, identifier=78631113035100160, force_registration=True)
|
||||
self._before = []
|
||||
self._after = []
|
||||
self.config.register_global(owner_models={})
|
||||
self.config.register_guild(owner_models={})
|
||||
|
||||
def add_check(self, check_obj: object, before_or_after: str):
|
||||
"""
|
||||
Adds a check to the check ordering
|
||||
|
||||
checks should be a function taking 2 arguments:
|
||||
ctx: commands.Context
|
||||
level: str
|
||||
|
||||
and returning:
|
||||
None: do not interfere
|
||||
True: command should be allowed even if they dont
|
||||
have role or perm requirements for the check
|
||||
False: command should be blocked
|
||||
|
||||
before_or_after:
|
||||
Should literally be a str equaling 'before' or 'after'
|
||||
This should be based on if this should take priority
|
||||
over set rules or not
|
||||
|
||||
3rd party cogs adding checks using this should only allow
|
||||
the owner to add checks before, and ensure only the owner
|
||||
can add checks recieving the level 'owner'
|
||||
|
||||
3rd party cogs should keep a copy of of any checks they registered
|
||||
and deregister then on unload
|
||||
"""
|
||||
|
||||
if before_or_after == "before":
|
||||
self._before.append(check_obj)
|
||||
elif before_or_after == "after":
|
||||
self._after.append(check_obj)
|
||||
else:
|
||||
raise TypeError("RTFM")
|
||||
|
||||
def remove_check(self, check_obj: object, before_or_after: str):
|
||||
"""
|
||||
Removes a previously registered check object
|
||||
|
||||
3rd party cogs should keep a copy of of any checks they registered
|
||||
and deregister then on unload
|
||||
"""
|
||||
|
||||
if before_or_after == "before":
|
||||
self._before.remove(check_obj)
|
||||
elif before_or_after == "after":
|
||||
self._after.remove(check_obj)
|
||||
else:
|
||||
raise TypeError("RTFM")
|
||||
|
||||
async def __global_check(self, ctx):
|
||||
"""
|
||||
Yes, this is needed on top of hooking into checks.py
|
||||
@ -126,7 +75,13 @@ class Permissions:
|
||||
roles = sorted(ctx.author.roles, reverse=True) if ctx.guild else []
|
||||
entries.extend([x.id for x in roles])
|
||||
|
||||
for check in self._before:
|
||||
before = [
|
||||
getattr(cog, "_{0.__class__.__name__}__red_permissions_before".format(cog), None)
|
||||
for cog in ctx.bot.cogs.values()
|
||||
]
|
||||
for check in before:
|
||||
if check is None:
|
||||
continue
|
||||
override = await val_if_check_is_valid(check=check, ctx=ctx, level=level)
|
||||
if override is not None:
|
||||
return override
|
||||
@ -137,7 +92,11 @@ class Permissions:
|
||||
if override is not None:
|
||||
return override
|
||||
|
||||
for check in self._after:
|
||||
after = [
|
||||
getattr(cog, "_{0.__class__.__name__}__red_permissions_after".format(cog), None)
|
||||
for cog in ctx.bot.cogs.values()
|
||||
]
|
||||
for check in after:
|
||||
override = await val_if_check_is_valid(check=check, ctx=ctx, level=level)
|
||||
if override is not None:
|
||||
return override
|
||||
|
||||
@ -12,21 +12,10 @@ async def val_if_check_is_valid(*, ctx: commands.Context, check: object, level:
|
||||
Returns the value from a check if it is valid
|
||||
"""
|
||||
|
||||
# Non staticmethods should not be run without their parent
|
||||
# class, even if the parent class did not deregister them
|
||||
if check.__module__ is None:
|
||||
pass
|
||||
elif isinstance(check, types.FunctionType):
|
||||
if (
|
||||
next(filter(lambda x: check.__module__ == x.__module__, ctx.bot.cogs.values()), None)
|
||||
is None
|
||||
):
|
||||
return None
|
||||
|
||||
val = None
|
||||
# let's not spam the console with improperly made 3rd party checks
|
||||
try:
|
||||
if asyncio.iscoroutine(check) or asyncio.iscoroutinefunction(check):
|
||||
if asyncio.iscoroutinefunction(check):
|
||||
val = await check(ctx, level=level)
|
||||
else:
|
||||
val = check(ctx, level=level)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user