Packages

An elixir library for creating discord bots.

Current section

Files

Jump to
discord_elixir lib discord_elixir.ex
Raw

lib/discord_elixir.ex

defmodule Discord do
defmacro __using__(_) do
quote do
@behaviour :websocket_client_handler
require Logger
import Discord
import DiscordElixir.Sending
def start_link(token, wss_client \\ :websocket_client, rest_client \\ HTTPotion) do
case DiscordElixir.Gateway.start(token) do
{:ok, gateway_url} ->
state = %{
token: token,
wss_client: wss_client,
gateway: gateway_url,
start_pid: self(),
rest_api_url: "https://discordapp.com/api",
rest_client: rest_client
}
bot_name_task = Task.async(fn -> DiscordElixir.Sending.bot_name(state) end)
url = String.to_char_list(gateway_url)
bot_name = Task.await(bot_name_task)
state = Map.put(state, :bot_name, bot_name)
wss_client.start_link(url, __MODULE__, state)
receive do
{:ok, discord} ->
discord = Map.delete(discord, :start_pid)
{:ok, discord}
_ ->
{:error}
end
end
end
def init(discord, socket) do
discord = Map.put(discord, :socket, socket)
identify(identification(discord), discord)
{:ok, discord}
end
def identify(id, discord) do
discord.wss_client.send({:text, Poison.encode!(id)}, discord.socket)
end
def identification(discord) do
identification = %{
token: discord.token,
compress: "true",
properties: %{
"$os" => "elixir",
"$browser" => "elixir_bot",
"$device" => "elixir",
"$referrer" => "",
"$referring_domain" => ""
}
}
%{
op: 2,
d: identification
}
end
def websocket_info(message, _connection, state) do
try do
handle_info(message, state)
rescue
e -> handle_exception(e)
end
end
def websocket_terminate(_message, _conn, state) do
handle_disconnect(state)
end
def handle_message(%{"t" => "READY", "d" => %{"heartbeat_interval" => heartbeat_interval}}, _conn, state) do
DiscordElixir.Heartbeat.start_heartbeat(state, heartbeat_interval)
handle_connect(state)
{:ok, state}
end
def handle_message(message = %{"t" => "GUILD_CREATE"}, _conn, state) do
state = store_channels(message, state)
send state.start_pid, {:ok, state}
{:ok, state}
end
def store_channels(%{"d" => %{"channels" => channels}}, state) do
channels =
channels
|> Enum.filter(fn chan -> chan["type"] == "text" end)
|> Enum.map(fn chan -> %{id: chan["id"], name: chan["name"]} end)
Map.put(state, :channels, channels)
end
def handle_message(message, _conn, state) do
case message do
%{"t" => "MESSAGE_CREATE", "d" => %{"content" => _content}} ->
message
|> add_channel_name(state)
|> format_message
|> handle_chat_message(state)
{:ok, state}
_ ->
{:ok, state}
end
end
def format_message(message) do
%{
author: message["d"]["author"]["username"],
content: message["d"]["content"],
channel_name: message["channel_name"],
}
end
def websocket_handle({:text, message}, conn, state) do
{:ok, new_state} = message |> convert_message |> handle_message(conn,state)
{:ok, new_state}
end
def handle_exception(e) do
IO.inspect "exception"
end
def convert_message(string_message) do
message_map = Poison.Parser.parse!(string_message)
end
def add_channel_name(message, state) do
Map.put(message, "channel_name",
Enum.find(state.channels, fn channel -> Map.get(channel, :id) == message["d"]["channel_id"] end) |> Map.get(:name)
)
end
def handle_chat_message(_message, _state), do: :ok
def handle_disconnect(_state), do: :ok
def handle_info(_message, _state), do: :ok
def handle_connect(state), do: :ok
defoverridable [ handle_chat_message: 2, handle_disconnect: 1, handle_info: 2, handle_connect: 1 ]
end
end
end