2020-06-12 17:29:35 -04:00
|
|
|
defmodule Omnibot.Irc do
|
|
|
|
|
require Logger
|
|
|
|
|
alias Omnibot.Irc.Msg
|
2020-08-11 15:23:53 -07:00
|
|
|
alias Omnibot.Config
|
2020-06-12 17:29:35 -04:00
|
|
|
use GenServer
|
|
|
|
|
|
|
|
|
|
## Client API
|
|
|
|
|
|
2020-08-11 12:48:28 -07:00
|
|
|
def start_link(opts) do
|
|
|
|
|
{cfg, opts} = Keyword.pop!(opts, :cfg)
|
|
|
|
|
GenServer.start_link(__MODULE__, cfg, opts)
|
2020-06-12 17:29:35 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def send_msg(irc, msg) do
|
|
|
|
|
GenServer.cast(irc, {:send_msg, msg})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def send_msg(irc, command, params) when is_list(params) do
|
2020-08-11 12:48:28 -07:00
|
|
|
GenServer.cast(irc, {:send_msg, command, params})
|
2020-06-12 17:29:35 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def send_msg(irc, command, param), do: send_msg(irc, command, [param])
|
|
|
|
|
|
|
|
|
|
def send_to(irc, channel, text), do: send_msg(irc, "PRIVMSG", [channel, text])
|
|
|
|
|
|
|
|
|
|
def join(irc, channel), do: send_msg(irc, "JOIN", channel)
|
|
|
|
|
|
|
|
|
|
def part(irc, channel), do: send_msg(irc, "PART", channel)
|
|
|
|
|
|
2020-08-11 12:48:28 -07:00
|
|
|
def cfg(irc), do: GenServer.call(irc, :cfg)
|
|
|
|
|
|
2020-08-12 15:31:40 -07:00
|
|
|
defp route_msg(irc, cfg, :connect) do
|
|
|
|
|
handle_msg(irc, cfg.plugins, :connect)
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-11 15:23:53 -07:00
|
|
|
defp route_msg(irc, cfg, msg) do
|
|
|
|
|
plugins = Config.channel_plugins(cfg, Msg.channel(msg))
|
2020-08-12 15:31:40 -07:00
|
|
|
handle_msg(irc, plugins, msg)
|
|
|
|
|
end
|
2020-06-14 18:00:31 -04:00
|
|
|
|
2020-08-12 15:31:40 -07:00
|
|
|
defp handle_msg(irc, plugins, msg) do
|
2020-06-14 18:00:31 -04:00
|
|
|
Task.Supervisor.async_stream_nolink(
|
|
|
|
|
Omnibot.RouterSupervisor,
|
2020-07-02 18:30:46 -07:00
|
|
|
plugins,
|
2020-07-12 12:19:14 -07:00
|
|
|
# Spin up tasks to handle messages in case handle_msg() hangs
|
|
|
|
|
fn {plugin, _plug_cfg} -> plugin.handle_msg(irc, msg) end,
|
2020-06-14 18:00:31 -04:00
|
|
|
timeout: 30_000,
|
|
|
|
|
on_timeout: :kill_task
|
|
|
|
|
) |> Stream.run()
|
2020-06-13 18:11:18 -04:00
|
|
|
end
|
|
|
|
|
|
2020-06-12 17:29:35 -04:00
|
|
|
## Server callbacks
|
|
|
|
|
|
|
|
|
|
@impl true
|
2020-08-11 12:48:28 -07:00
|
|
|
def init(cfg) do
|
2020-06-12 17:29:35 -04:00
|
|
|
_ssl = cfg.ssl
|
|
|
|
|
|
|
|
|
|
{:ok, socket} =
|
|
|
|
|
:gen_tcp.connect(to_charlist(cfg.server), cfg.port, [:binary, active: false, packet: :line])
|
|
|
|
|
|
|
|
|
|
# Wait for first message
|
|
|
|
|
send_msg(self(), "NICK", cfg.nick)
|
|
|
|
|
send_msg(self(), "USER", [cfg.user, "0", "*", cfg.real])
|
2020-06-13 21:47:46 -04:00
|
|
|
:inet.setopts(socket, active: true)
|
2020-06-12 17:29:35 -04:00
|
|
|
|
2020-08-12 15:31:40 -07:00
|
|
|
route_msg(self(), cfg, :connect)
|
2020-08-11 12:48:28 -07:00
|
|
|
{:ok, {socket, cfg}}
|
2020-06-12 17:29:35 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
defp write(socket, msg) do
|
|
|
|
|
msg = String.Chars.to_string(msg)
|
|
|
|
|
Logger.debug(">>> #{msg}")
|
|
|
|
|
:gen_tcp.send(socket, "#{msg}\r\n")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@impl true
|
2020-08-11 12:48:28 -07:00
|
|
|
def handle_cast({:send_msg, command, params}, state = {socket, cfg}) do
|
|
|
|
|
msg = Config.msg(cfg, command, params)
|
|
|
|
|
write(socket, msg)
|
|
|
|
|
{:noreply, state}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
|
def handle_cast({:send_msg, msg}, state = {socket, _cfg}) do
|
2020-06-12 17:29:35 -04:00
|
|
|
write(socket, msg)
|
2020-08-11 12:48:28 -07:00
|
|
|
{:noreply, state}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
|
def handle_call(:cfg, _from, state = {_socket, cfg}) do
|
|
|
|
|
{:reply, cfg, state}
|
2020-06-12 17:29:35 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@impl true
|
2020-08-11 15:23:53 -07:00
|
|
|
def handle_info({:tcp, _info_socket, line}, state = {_socket, cfg}) do
|
2020-06-12 17:29:35 -04:00
|
|
|
Logger.debug(String.trim(line))
|
|
|
|
|
msg = Msg.parse(line)
|
|
|
|
|
|
|
|
|
|
# Send the message to the router
|
2020-08-11 15:23:53 -07:00
|
|
|
route_msg(self(), cfg, msg)
|
2020-07-18 14:09:17 -07:00
|
|
|
|
2020-08-11 12:48:28 -07:00
|
|
|
{:noreply, state}
|
2020-06-12 17:29:35 -04:00
|
|
|
end
|
|
|
|
|
end
|