summaryrefslogtreecommitdiff
path: root/lib/irc/base_client.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/irc/base_client.ex')
-rw-r--r--lib/irc/base_client.ex170
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