Adds the full README (quickstart, interaction styles, privileged intents, cache, REST, slash registration, event semantics, Nostrum porting guide, reliability design), an examples/echo_bot.exs Mix.install script, ex_doc config in mix.exs, and rewrites Dexcord.Gateway's moduledoc to describe the finished reliability behavior instead of stale Phase 0-1 scope notes.
89 lines
2.7 KiB
Elixir
89 lines
2.7 KiB
Elixir
# Dexcord example bot: raw events, a prefix command, and a slash command.
|
|
#
|
|
# Run it from the repo root with:
|
|
#
|
|
# DISCORD_TOKEN=your-bot-token elixir examples/echo_bot.exs
|
|
#
|
|
# Optionally set DEV_GUILD_ID to a guild id to register the `/ping` slash
|
|
# command to that guild only (instant propagation, good for development).
|
|
# Without it, the command registers globally (propagation can take ~1h).
|
|
#
|
|
# What it demonstrates:
|
|
#
|
|
# * `intents: :all` - every documented gateway intent, including the
|
|
# privileged ones. If you see a 4014 (disallowed intents) error in the
|
|
# logs, enable SERVER MEMBERS / PRESENCE / MESSAGE CONTENT under
|
|
# Bot -> Privileged Gateway Intents in the Discord Developer Portal (see
|
|
# the README's "Privileged intents" section).
|
|
# * A raw `Dexcord.Handler` that logs every `MESSAGE_CREATE` and sets the
|
|
# bot's presence on `READY`.
|
|
# * A `!ping` prefix command via `Dexcord.Prefix.Router`.
|
|
# * A `/ping` slash command that responds ephemerally.
|
|
#
|
|
# This script does not connect to Discord on its own - it only starts if you
|
|
# provide a real DISCORD_TOKEN and run it, at which point it connects for
|
|
# real and stays running until you stop it (Ctrl-C twice).
|
|
|
|
Mix.install([
|
|
{:dexcord, path: Path.expand("..", __DIR__)}
|
|
])
|
|
|
|
defmodule EchoBot.Commands do
|
|
@moduledoc false
|
|
use Dexcord.Prefix.Router
|
|
|
|
def handle_command("ping", _args, msg) do
|
|
Dexcord.Api.create_message(msg["channel_id"], "pong")
|
|
end
|
|
end
|
|
|
|
defmodule EchoBot.Slash do
|
|
@moduledoc false
|
|
use Dexcord.Slash
|
|
|
|
def commands do
|
|
[%{name: "ping", description: "Replies with pong (only you can see it)."}]
|
|
end
|
|
|
|
def handle_interaction("ping", interaction) do
|
|
Dexcord.Slash.respond(interaction, %{content: "pong", ephemeral: true})
|
|
end
|
|
end
|
|
|
|
defmodule EchoBot.Handler do
|
|
@moduledoc false
|
|
use Dexcord.Handler
|
|
|
|
def handle_event({:READY, data}) do
|
|
IO.puts("Ready as #{get_in(data, ["user", "username"])}")
|
|
|
|
Dexcord.update_presence(%{
|
|
"since" => nil,
|
|
"activities" => [%{"name" => "!ping / /ping", "type" => 0}],
|
|
"status" => "online",
|
|
"afk" => false
|
|
})
|
|
end
|
|
|
|
def handle_event({:MESSAGE_CREATE, msg}) do
|
|
IO.puts("#{get_in(msg, ["author", "username"])}: #{msg["content"]}")
|
|
Dexcord.Prefix.dispatch(msg, prefix: "!", to: EchoBot.Commands)
|
|
end
|
|
end
|
|
|
|
token = System.fetch_env!("DISCORD_TOKEN")
|
|
dev_guild_id = System.get_env("DEV_GUILD_ID")
|
|
|
|
children = [
|
|
{Dexcord,
|
|
token: token,
|
|
handler: EchoBot.Handler,
|
|
intents: :all,
|
|
slash: EchoBot.Slash,
|
|
slash_guild_ids: if(dev_guild_id, do: [dev_guild_id])}
|
|
]
|
|
|
|
{:ok, _supervisor} =
|
|
Supervisor.start_link(children, strategy: :one_for_one, name: EchoBot.Supervisor)
|
|
|
|
Process.sleep(:infinity)
|