diff options
Diffstat (limited to 'lib/irc/base_client.ex')
-rw-r--r-- | lib/irc/base_client.ex | 170 |
1 files changed, 0 insertions, 170 deletions
diff --git a/lib/irc/base_client.ex b/lib/irc/base_client.ex deleted file mode 100644 index 8da45be..0000000 --- a/lib/irc/base_client.ex +++ /dev/null @@ -1,170 +0,0 @@ -defmodule Irc.BaseClient do - @behaviour :gen_statem - require Logger - alias Irc.Parser.Line - alias Irc.Connection - require Irc.Parser.Numeric - import Irc.Parser.Numeric - - @moduledoc """ - Extensible fully-featured IRC client. - - ## Behaviour - - The BaseClient requires a callback module. You can check out `Irc.Client`. - - ## Capabs - - IRCv3 Capabs are handled by separates modules. - """ - - @internal {:next_event, :internal, nil} - - defstruct [:conn, :conn_mon, :module, :modstate, :args, :nick, :modes, :info, :error] - - def callback_mode, do: [:state_functions, :state_enter] - - @type event ::event_connected | event_nick | event_modes | event_line | event_down - - @type event_connected :: {:connected, Connection.Info.t} - @type event_nick :: {:nick, prev_nick :: String.t, new_nick :: String.t} - @type event_modes :: {:modes, changes :: String.t, prev :: list, modes :: list} - @type event_line :: {:line, line :: Irc.Parser.Line.t} - @type event_down :: {:down, Connection.error, delay :: integer} - - @type modstate :: any - @type handle_return :: {:ok, modstate()} - @type handle_call_return :: {:reply, any(), modstate()} | {:noreply, modstate()} - - @callback init(Keyword.t) :: {:ok, modstate} | any - @callback handle_event(event(), modstate()) :: handle_return() - @callback handle_info(any(), modstate()) :: handle_return() - @callback handle_cast(any(), modstate()) :: handle_return() - @callback handle_call(any(), reference(), modstate()) :: handle_call_return() - @callback stop(Connection.error, modstate) :: any() - - @type start_opt :: Connection.start_opt - | {:module, module()} - | {:conn_statem_opts, [:gen_statem.start_opt]} - @type start_ret :: {:ok, pid} | {:error, Connection.error} | :gen_statem.start_ret - - @spec start(Connection.nick, Connection.host, [start_opt], [:gen_statem.start_opt]) :: start_ret - def start(nick, host, opts \\ [], start_opts \\ []) do - :gen_statem.start(__MODULE__, [nick, host, prepare_args(opts)], start_opts) - end - - @spec start_link(Connection.nick, Connection.host, [start_opt], [:gen_statem.start_opt]) :: start_ret - def start_link(nick, host, opts \\ [], start_opts \\ []) do - :gen_statem.start_link(__MODULE__, [nick, host, prepare_args(opts)], start_opts) - end - - - @doc false - def init([args]) do - capabs = ["account-notify", "away-notify"] - args = args - |> Keyword.put(:capabs, capabs) - with \ - {:ok, conn} <- Connection.start(Keyword.get(args, :nick), Keyword.get(args, :host), args, Keyword.get(args, :conn_statem_opts, [])), - conn_mon <- Process.monitor(conn), - {:ok, module} <- Keyword.fetch(args, :module), - {:ok, modstate} <- module.init(args) - do - data = %__MODULE__{ - conn: conn, conn_mon: conn_mon, - module: module, modstate: modstate, - args: args - } - {:ok, :disconnected, data} - else - error -> {:stop, error} - end - end - - def disconnected(:enter, :connected, data) do - Logger.debug "#{inspect data} disconnected: #{inspect data.error}" - :keep_state_and_data - end - - def disconnected(:info, msg = {:irc_conn_up, _, info}, data) do - data = run_handler_event({:connected, info}, data) - {:next_state, :connected, %__MODULE__{data | nick: info.nick, info: info, modes: info.modes, error: nil}} - end - - def disconnected(type, content, data) do - handle_common(:disconnected, type, content, data) - end - - def connected(:enter, _, data) do - Logger.debug "#{inspect data} UP" - :keep_state_and_data - end - - def connected(:info, msg = {:irc_conn_nick, _, prev_nick, new_nick}, data) do - data = run_handler_event({:nick, prev_nick, new_nick}, data) - {:keep_state, %__MODULE__{data | nick: new_nick}} - end - - def connected(:info, msg = {:irc_conn_modes, _, changes, prev, modes}, data) do - data = run_handler_event({:modes, changes, prev, modes}, data) - {:keep_state, %__MODULE__{data | modes: modes}} - end - - def connected(:info, {:irc_conn_down, _, reason, delay}, data) do - data = run_handler_event({:down, reason, delay}, data) - {:next_state, :disconnected, %__MODULE__{data | error: reason}} - end - - # TODO: REMOVE? - def connected(:info, {:irc_conn_line, _, line}, data) do - data = run_handler_event({:line, line}, data) - :keep_state_and_data - end - - def connected(type, content, data) do - handle_common(:connected, type, content, data) - end - - # TODO: Callback stop? - def error(:internal, reason, data) do - Logger.error "#{inspect data}: #{inspect reason}" - data.module.stop(reason, data.modstate) - {:stop, :normal} - end - - def handle_common(_, :info, {:irc_conn_error, _, reason}, data) do - {:next_state, :error, data, {:next_event, :internal, reason}} - end - - def handle_common(_, :enter, _, _) do - :keep_state_and_data - end - - def terminate(reason, state, data) do - Logger.error("#{inspect(data)} terminating in #{inspect(state)}: #{inspect reason}") - end - - def code_change(_old_vsn, old_state, old_data, _extra) do - {:ok, old_state, old_data} - end - - defp prepare_args(args) do - args - end - - defp run_handler_event(event, data) do - case data.module.handle_event(event, data.modstate) do - {:ok, modstate} -> %__MODULE__{data | modstate: modstate} - :ok -> data - end - end - - defimpl Inspect, for: __MODULE__ do - import Inspect.Algebra - def inspect(struct, _opts) do - concat(["#Irc.Client<", inspect(self()), ">"]) - end - end - - -end |