Skip to content

Permission system

This bot uses a multi-layered custom permission system (not Discord's built-in role permissions), implemented in utils.py. It supports two sources, config.yaml + perm.yaml, with config.yaml always taking precedence.

Permission tiers

TierBasisDescription
Adminconfig.yaml > admins.usersOnly the admins defined in the config file; has all permissions
ModServer administrator + mods.users + mods.guilds + dynamic permissionsMod commands + rate-limit exemption

Inclusion relationships

text
config admins   →  Admin (all permissions)
server admins   →  Mod (mod command permissions, excluding admin-only)
config mods     →  Mod
perm.yaml       →  Mod (appended dynamic rules)
  • Admin = only the admins.users list
  • Mod = server admins + config admins + config mods + perm.yaml dynamic rules

Admin commands such as /sync, /reload, and /emoji update are only available to config admins; server admins cannot use them.

List matching rules

Each entry in admins.users / mods.users / mods.guilds[*] can be:

  • A user ID (a number, e.g. 123456789012345678)
  • A username (a string, e.g. "wyf9")
  • A numeric string is also matched as an ID
python
def matches_identity(user, values):
    for value in values:
        if user.id == value or user.name == value:
            return True
        if isinstance(value, str) and value.isdigit() and user.id == int(value):
            return True
    return False

WARNING

Username matching is based on the Discord global username (user.name), not the server nickname (display_name). It is recommended to prefer user IDs to avoid ambiguity.

Declarative permission control

A command's handler method declares the required permission level via the @u.requires(...) decorator:

python
@u.requires(u.Permission.MOD)
async def _handle_lock(self, source, channel=None): ...

The Permission level enum:

LevelMeaning
Permission.EVERYONEAvailable to everyone
Permission.MODRequires mod (includes admin)
Permission.ADMINRequires admin (server admin / config admin)

It also supports passing a custom decision function (module, user, guild) -> bool, such as the allowlist check of the Voice module.

When a permission check fails, the bot replies with :x: **You don't have permission to use this command** :x: (a temporary message deleted after 10 seconds) and aborts execution.

Quick reference of required permissions per command

CommandRequired permission
random / uuid / to-fileEveryone (subject to rate limiting)
/e / /emoji infoEveryone (subject to rate limiting)
delete / clear-message / move-channelMod
/lock now / /lock unlock / /lock plan / /lock unplanMod
/vc join / /vc leaveAllowlisted user or Mod (see Voice module)
/emoji updateAdmin (config admins only)
/syncAdmin (config admins only)
/reloadAdmin (config admins only)
/perm add / /perm rm / /perm showAdmin (config admins only)

Global rate limit

All commands have a global rate-limit fallback of 10 reqs / 10s. Admins are not subject to rate limiting.

Released under the MIT License