import types import contextlib import asyncio import logging from redbot.core import commands log = logging.getLogger("redbot.cogs.permissions.resolvers") async def val_if_check_is_valid(*, ctx: commands.Context, check: object, level: str) -> bool: """ Returns the value from a check if it is valid """ val = None # let's not spam the console with improperly made 3rd party checks try: if asyncio.iscoroutinefunction(check): val = await check(ctx, level=level) else: val = check(ctx, level=level) except Exception as e: # but still provide a way to view it (run with debug flag) log.debug(str(e)) return val def resolve_models(*, ctx: commands.Context, models: dict) -> bool: """ Resolves models in order. """ cmd_name = ctx.command.qualified_name cog_name = ctx.cog.__class__.__name__ resolved = None to_iter = (("commands", cmd_name), ("cogs", cog_name)) for model_name, ctx_attr in to_iter: if ctx_attr in models.get(model_name, {}): blacklist = models[model_name][ctx_attr].get("deny", []) whitelist = models[model_name][ctx_attr].get("allow", []) resolved = resolve_lists(ctx=ctx, whitelist=whitelist, blacklist=blacklist) if resolved is not None: return resolved resolved = models[model_name][ctx_attr].get("default", None) if resolved is not None: return resolved return None def resolve_lists(*, ctx: commands.Context, whitelist: list, blacklist: list) -> bool: """ resolves specific lists """ voice_channel = None with contextlib.suppress(Exception): voice_channel = ctx.author.voice.voice_channel entries = [x.id for x in (ctx.author, voice_channel, ctx.channel) if x] roles = sorted(ctx.author.roles, reverse=True) if ctx.guild else [] entries.extend([x.id for x in roles]) # entries now contains the following (in order) (if applicable) # author.id # author.voice.voice_channel.id # channel.id # role.id for each role (highest to lowest) # (implicitly) guild.id because # the @everyone role shares an id with the guild for entry in entries: if entry in whitelist: return True if entry in blacklist: return False return None