EDA - Elixir Discord API

CIHex.pmHex DocsLicense: MIT

A complete, production-grade Discord library for Elixir. 21 API modules, 68+ event types, full voice with E2EE, automatic sharding, and 1200+ tests.

Why EDA?

Installation

def deps do
  [
    {:eda, "~> 0.1.2"}
  ]
end

Quick Start

1. Configure your bot

# config/config.exs
config :eda,
  token: System.get_env("DISCORD_TOKEN"),
  intents: [:guilds, :guild_messages, :message_content],
  consumer: MyBot.Consumer

2. Create a consumer

defmodule MyBot.Consumer do
  @behaviour EDA.Consumer

  @impl true
  def handle_event({:MESSAGE_CREATE, msg}) do
    if msg.content == "!ping" do
      EDA.API.Message.create(msg.channel_id, "Pong!")
    end
  end

  @impl true
  def handle_event({:READY, ready}) do
    IO.puts("Online as #{ready.user.username}!")
  end

  @impl true
  def handle_event(_event), do: :ok
end

3. Run

DISCORD_TOKEN="your_token" iex -S mix

REST API

# Messages
EDA.API.Message.create(channel_id, "Hello!")
EDA.API.Message.create(channel_id, content: "With embed", embeds: [%{title: "Hey", color: 0x5865F2}])

# Guilds & members
{:ok, guild} = EDA.API.Guild.get(guild_id)
{:ok, member} = EDA.API.Member.get(guild_id, user_id)
EDA.API.Role.add(guild_id, user_id, role_id)

# Slash commands
EDA.API.Command.create_global(app_id, %{name: "ping", description: "Pong!"})

# Reactions, threads, webhooks...
EDA.API.Reaction.create(channel_id, message_id, "🔥")
EDA.API.Thread.create(channel_id, %{name: "Discussion", auto_archive_duration: 1440})

Cache

EDA.Cache.me()                              # Bot user
EDA.Cache.get_guild(guild_id)               # Single guild
EDA.Cache.guilds()                          # All guilds
EDA.Cache.get_channel(channel_id)           # Single channel
EDA.Cache.channels_for_guild(guild_id)      # Guild channels
EDA.Cache.guild_count()                     # Stats

Configure cache admission per entity:

config :eda, :cache,
  policy: :all,           # :all | :none | MyPolicy | fn/3
  max_size: 10_000,       # Enable LRW eviction
  evict_interval: 60_000  # Eviction check interval (ms)

Events

Event Description
{:MESSAGE_CREATE, msg} Message created
{:INTERACTION_CREATE, interaction} Slash command / component / modal
{:GUILD_CREATE, guild} Guild available
{:GUILD_MEMBER_ADD, member} Member joined
{:VOICE_STATE_UPDATE, state} Voice state changed
{:CHANNEL_CREATE, channel} Channel created
{:THREAD_CREATE, thread} Thread created
{:AUTO_MODERATION_ACTION_EXECUTION, action} AutoMod triggered

Plus 60+ more — see HexDocs for the full list.

Gateway

config :eda,
  intents: [:guilds, :guild_messages, :message_content],
  # or :all, :nonprivileged
  encoding: :etf,      # :json (default) or :etf for binary encoding
  compress: true        # zlib transport compression

Sharding is automatic. EDA fetches the recommended shard count from Discord, launches shards with staggered timing, and tracks per-shard readiness. Override with:

config :eda, :gateway,
  shard_count: 4  # Fixed shard count

Architecture

EDA.Application
├── EDA.Cache.Supervisor
│   ├── EDA.Cache.Guild      (ETS)
│   ├── EDA.Cache.Channel    (ETS)
│   ├── EDA.Cache.User       (ETS)
│   ├── EDA.Cache.Member     (ETS)
│   ├── EDA.Cache.Role       (ETS)
│   ├── EDA.Cache.Presence   (ETS)
│   ├── EDA.Cache.VoiceState (ETS)
│   └── EDA.Cache.Evictor
├── EDA.HTTP.RateLimiter
└── EDA.Gateway.ShardSupervisor
    ├── EDA.Gateway.ShardManager
    ├── EDA.Gateway.ReadyTracker
    ├── EDA.Gateway.MemberChunker
    └── EDA.Gateway.Connection (per shard)

Documentation

Full documentation is available on HexDocs.

License

MIT — see LICENSE for details.

Contributing

Contributions are welcome! Open an issue or submit a pull request.