Discord permission flags and calculator.
Computes effective permissions for a member at guild or channel level, following Discord's official algorithm with the 3-tier overwrite cascade.
Features
- Correct 3-tier overwrite cascade: @everyone → roles (merged) → member
- Access gates: returns
0if VIEW_CHANNEL is missing, or if VOICE_CONNECT is missing on voice/stage channels has_permission?/3: one-call convenience for permission checks- Pure bitwise hot path: no atom-list conversion during calculation
- All 50+ Discord permissions up to date (bit 52)
- Nil-safe: returns
{:error, reason}instead of crashing on missing data
Usage
# Check if a member can manage messages in a channel
EDA.Permission.has_permission?(guild_id, user_id, channel_id, :manage_messages)
# Get all effective permissions in a channel
{:ok, bitset} = EDA.Permission.in_channel(guild_id, user_id, channel_id)
perms = EDA.Permission.to_list(bitset)
# Guild-level permissions
{:ok, bitset} = EDA.Permission.in_guild(guild_id, user_id)
Summary
Functions
Returns the bitset with all permissions set.
Returns all known permission flag atoms.
Returns the flag atom for a bit value, or :error.
Checks if a specific flag is set in a bitset.
Checks if a member has a specific permission at guild level.
Checks if a member has a specific permission in a channel.
Computes effective channel-level permissions for a member.
Computes effective guild-level permissions for a member.
Returns the bit value for a permission flag.
Converts a list of flag atoms to a combined bitset.
Converts a bitset to a list of flag atoms. Unknown bits are skipped.
Types
@type bitset() :: non_neg_integer()
@type flag() ::
:create_instant_invite
| :kick_members
| :ban_members
| :administrator
| :manage_channels
| :manage_guild
| :add_reactions
| :view_audit_log
| :priority_speaker
| :stream
| :view_channel
| :send_messages
| :send_tts_messages
| :manage_messages
| :embed_links
| :attach_files
| :read_message_history
| :mention_everyone
| :use_external_emojis
| :view_guild_insights
| :connect
| :speak
| :mute_members
| :deafen_members
| :move_members
| :use_vad
| :change_nickname
| :manage_nicknames
| :manage_roles
| :manage_webhooks
| :manage_guild_expressions
| :use_application_commands
| :request_to_speak
| :manage_events
| :manage_threads
| :create_public_threads
| :create_private_threads
| :use_external_stickers
| :send_messages_in_threads
| :use_embedded_activities
| :moderate_members
| :view_creator_monetization_analytics
| :use_soundboard
| :create_guild_expressions
| :create_events
| :use_external_sounds
| :send_voice_messages
| :set_voice_channel_status
| :send_polls
| :use_external_apps
| :pin_messages
| :bypass_slowmode
Functions
@spec all() :: bitset()
Returns the bitset with all permissions set.
@spec all_flags() :: [flag()]
Returns all known permission flag atoms.
Returns the flag atom for a bit value, or :error.
Checks if a specific flag is set in a bitset.
Checks if a member has a specific permission at guild level.
Checks if a member has a specific permission in a channel.
Convenience function — most common use case for bots.
Computes effective channel-level permissions for a member.
Returns {:ok, bitset} or {:error, reason}.
Algorithm (matches Discord's official spec + JDA)
- Owner → ALL_PERMISSIONS
- Compute guild base permissions
- ADMINISTRATOR → ALL_PERMISSIONS (skips all overwrites)
- Apply 3-tier overwrite cascade: a. @everyone role overwrite b. All role overwrites (merged via OR, then applied) c. Member-specific overwrite (highest priority)
- Access gate: no VIEW_CHANNEL → 0
- Access gate: voice/stage channel + no CONNECT → 0
Computes effective guild-level permissions for a member.
Returns {:ok, bitset} or {:error, reason}.
Algorithm
- Guild owner → ALL_PERMISSIONS
- OR all role permission bits together
- If ADMINISTRATOR is set → ALL_PERMISSIONS
Returns the bit value for a permission flag.
Converts a list of flag atoms to a combined bitset.
Converts a bitset to a list of flag atoms. Unknown bits are skipped.