Skip to content

Commit e8bd6bf

Browse files
committed
docs: add example
1 parent 0cf224d commit e8bd6bf

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

mix.exs

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ defmodule Crux.Gateway.MixProject do
4848
end
4949

5050
defp docs() do
51-
[formatter: "html"]
51+
[
52+
formatter: "html",
53+
extras: [
54+
"pages/EXAMPLES.md"
55+
]
56+
]
5257
end
5358

5459
defp aliases() do

pages/EXAMPLES.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Examples
2+
3+
## Small Everything
4+
5+
A simple example of Crux.Gateway in combination with Crux.Rest and Crux.Structures,
6+
although with small adjustments this would work fine without.
7+
8+
### Application Supervisor
9+
The first component: The Application Supervisor,
10+
the gateway can be started at whatever supervisor level however.
11+
12+
```elixir
13+
defmodule MyApp.Application do
14+
use Application
15+
16+
def start(_, _) do
17+
children = [
18+
{MyApp.Rest, token: MyApp.token!()}, # Assuming that MyApp.Rest is a module using Crux.Rest
19+
{Crux.Gateway, &gateway_config/0}, # This function is evaluated once when Crux.Gateway is started
20+
MyApp.ConsumerSupervisor
21+
]
22+
23+
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
24+
Supervisor.init(children, opts)
25+
end
26+
27+
defp gateway_config() do
28+
%{url: url, shards: shards, session_start_limit: %{max_concurrency: max_concurrency}} =
29+
MyApp.Rest.get_gateway_bot!()
30+
31+
%{
32+
max_concurrency: max_concurrency,
33+
intents: Crux.Structs.Intents.resolve(:guild_messages),
34+
name: MyApp.Gateway,
35+
token: MyApp.token!(),
36+
url: url,
37+
shards: for(shard_id <- 0..(shards - 1), do: {shard_id, shards})
38+
}
39+
end
40+
end
41+
```
42+
43+
### Consumer Supervisor
44+
45+
The second component: The Consumer Supervisor for gateway dispatches.
46+
47+
This is pretty much just boilerplate code:
48+
```elixir
49+
defmodule MyApp.ConsumerSupervisor do
50+
use ConsumerSupervisor
51+
52+
def start_link(arg) do
53+
ConsumerSupervisor.start_link(__MODULE__, arg, name: __MODULE__)
54+
end
55+
56+
def init(_arg) do
57+
pids =
58+
MyApp.Gateway
59+
|> Crux.Gateway.producers()
60+
|> Map.values()
61+
62+
opts = [strategy: :one_for_one, subscribe_to: pids]
63+
ConsumerSupervisor.init([MyApp.Consumer], opts)
64+
end
65+
end
66+
```
67+
68+
### Consumer
69+
70+
The third and last component: The consumer.
71+
72+
This module is actually handling the incoming gateway dispatches.
73+
This small example is just replying with `Pong!` whenever a non-bot user sends `!ping` in any channel.
74+
75+
```elixir
76+
defmodule MyApp.Consumer do
77+
require Logger
78+
79+
def child_spec(_arg) do
80+
%{
81+
id: __MODULE__,
82+
start: {__MODULE__, :start_link, []},
83+
restart: :temporary # or :transient, if you want the process to restart on crashes
84+
}
85+
end
86+
87+
def start_link({type, data, shard}) do
88+
Task.start_link(
89+
__MODULE__,
90+
:handle_event,
91+
[type, data, shard]
92+
)
93+
end
94+
95+
def handle_event(:READY, data, _shard) do
96+
Logger.info("Ready as #{data.user.username}##{data.user.discriminator} (#{data.user.id})")
97+
end
98+
99+
# Ignore bots, like a good bot.
100+
def handle_event(:MESSAGE_CREATE, %{author: %{bot: true}}, _shard), do: :ok
101+
102+
def handle_event(:MESSAGE_CREATE, %{channel_id: channel_id, content: "!ping"}, _shard) do
103+
MyApp.Rest.create_message(channel_id, content: "Pong!")
104+
end
105+
106+
# Catch-all clause to avoid the process crashing on other events.
107+
def handle_event(_type, _data, _shard), do: :ok
108+
end
109+
```

0 commit comments

Comments
 (0)