diff --git a/lib/contrib/markov/markov.ex b/lib/contrib/markov/markov.ex index d18415f..ee769d2 100644 --- a/lib/contrib/markov/markov.ex +++ b/lib/contrib/markov/markov.ex @@ -6,7 +6,7 @@ defmodule Omnibot.Contrib.Markov do @default_config path: "markov", order: 2, save_every: 5 * 60 @impl true - def children(cfg, _state) do + def children(cfg) do [{Task, fn -> Stream.timer(cfg[:save_every] * 1000) |> Stream.cycle() diff --git a/lib/contrib/wordbot/wordbot.ex b/lib/contrib/wordbot/wordbot.ex index 0971ec6..de88229 100644 --- a/lib/contrib/wordbot/wordbot.ex +++ b/lib/contrib/wordbot/wordbot.ex @@ -5,23 +5,8 @@ defmodule Omnibot.Contrib.Wordbot do @default_config wordbot_source: "words.txt", wordbot_db: "wordbot.db", words_per_round: 300, hours_per_round: 5 - #def start_link(opts) do - #Supervisor.start_link(__MODULE__, opts[:cfg], opts) - #end - - #@impl true - #def init(cfg) do - # children = [ - # {Task.Supervisor, name: Omnibot.Contrib.Wordbot.Watchers, strategy: :one_for_one}, - # Wordbot.Db.child_spec(cfg[:wordbot_db]), - # {Wordbot.Bot, cfg: cfg, name: Omnibot.Contrib.Wordbot.Bot}, - # ] - - # Supervisor.init(children, strategy: :one_for_all) - #end - @impl true - def children(cfg, _state) do + def children(cfg) do [ {Task.Supervisor, name: Omnibot.Contrib.Wordbot.Watchers, strategy: :one_for_one}, Wordbot.Db.child_spec(cfg[:wordbot_db]), diff --git a/lib/plugin/base.ex b/lib/plugin/base.ex index cbfcc6d..1e4f290 100644 --- a/lib/plugin/base.ex +++ b/lib/plugin/base.ex @@ -19,6 +19,11 @@ defmodule Omnibot.Plugin.Base do @impl true def on_init(_cfg), do: nil + @impl true + def on_msg(irc, msg) do + route_msg(irc, msg) + end + @impl true def default_config(), do: @default_config @@ -33,11 +38,6 @@ defmodule Omnibot.Plugin.Base do @behaviour Plugin.Base - @impl Plugin.Base - def on_msg(irc, msg) do - route_msg(irc, msg) - end - defp route_msg(irc, %Irc.Msg {prefix: nil}), do: nil defp route_msg(irc, msg) do diff --git a/lib/plugin/plugin.ex b/lib/plugin/plugin.ex index ae1abc5..e9b3d42 100644 --- a/lib/plugin/plugin.ex +++ b/lib/plugin/plugin.ex @@ -14,21 +14,24 @@ defmodule Omnibot.Plugin do def state(pid), do: Agent.get(pid, fn {_, state} -> state end) - def update_state(pid, fun, timeout \\ 5000), - do: Agent.update(pid, &{&1, apply(fun, [&1])}, timeout) + def update_state(pid, fun, timeout \\ 5000) do + Agent.update(pid, fn {cfg, state} -> {cfg, apply(fun, [state])} end, timeout) + #Agent.update(pid, &{&1, apply(fun, [&1])}, timeout) + end end defmacro __using__(opts) do opts = opts ++ @default_opts - quote do - use Supervisor + quote generated: true do + use GenServer use Omnibot.Plugin.Base ## Client API def start_link(opts) do - Supervisor.start_link(__MODULE__, {opts[:cfg], opts[:state]}, opts) + {cfg, opts} = Keyword.pop(opts, :cfg) + GenServer.start_link(__MODULE__, cfg, opts) end def cfg() do @@ -48,30 +51,37 @@ defmodule Omnibot.Plugin do GenServer.cast(__MODULE__, {:handle_msg, irc, msg}) end - @impl Omnibot.Plugin - def children(_cfg, _state), do: [] - ## Server callbacks - @impl Supervisor - def init({cfg, state}) do - base_children = [ - {Omnibot.Plugin.CfgState, cfg: cfg, state: state, name: __MODULE__.CfgState}, - ] - children = - (if unquote(opts[:include_base]), do: base_children, else: []) ++ children(cfg, state) - Supervisor.init(children, unquote(opts[:opts])) + @impl GenServer + def init(_cfg) do + {:ok, nil} end + @impl GenServer def handle_cast({:handle_msg, irc, msg}, state) do on_msg(irc, msg) {:noreply, state} end + defp base_children(cfg, state) when unquote(opts[:include_base]) do + [ + {Omnibot.Plugin.CfgState, cfg: cfg, state: state, name: __MODULE__.CfgState}, + {__MODULE__, name: __MODULE__}, + ] + end + + defp base_children(_cfg, _state), do: [] + + @impl Omnibot.Plugin + def children(cfg), do: [] + + def plugin_children(cfg, state), do: base_children(cfg, state) ++ children(cfg) + @behaviour Omnibot.Plugin defoverridable Omnibot.Plugin end end - @callback children(cfg :: [atom: any], state :: any) :: [atom | {atom, [atom: any]} | {atom, any, [atom: any]}] + @callback children(cfg :: [atom: any]) :: [atom | {atom, [atom: any]} | {atom, any, [atom: any]}] end diff --git a/lib/plugin/supervisor.ex b/lib/plugin/supervisor.ex new file mode 100644 index 0000000..6fd3ef1 --- /dev/null +++ b/lib/plugin/supervisor.ex @@ -0,0 +1,28 @@ +defmodule Omnibot.Plugin.Supervisor do + use Supervisor + + def start_link(opts) do + {plugin, opts} = Keyword.pop(opts, :plugin) + {cfg, opts} = Keyword.pop(opts, :cfg) + start_link(plugin, cfg, opts) + end + + def start_link(plugin, cfg, opts) when is_atom(plugin) do + Supervisor.start_link(__MODULE__, {plugin, cfg}, opts) + end + + def child_spec(arg) do + id = Module.concat(arg[:plugin], Plugin.Supervisor) + %{ + id: id, + start: {__MODULE__, :start_link, [arg]}, + } + end + + @impl true + def init({plugin, cfg}) when is_atom(plugin) do + state = plugin.on_init(cfg) + children = IO.inspect(plugin.plugin_children(cfg, state)) + Supervisor.init(children, strategy: :one_for_one) + end +end diff --git a/lib/plugin_supervisor.ex b/lib/plugin_supervisor.ex index e0e40de..c9617a4 100644 --- a/lib/plugin_supervisor.ex +++ b/lib/plugin_supervisor.ex @@ -21,14 +21,15 @@ defmodule Omnibot.PluginSupervisor do # Map the plugins in the configuration to the children children = for plug <- (core ++ cfg.plugins) do - case plug do - {name, cfg} -> {name, cfg: cfg ++ name.default_config(), name: name} - name -> {name, cfg: name.default_config(), name: name} + {name, cfg} = case plug do + {name, cfg} -> {name, cfg ++ name.default_config()} + name -> {name, name.default_config()} end + {Omnibot.Plugin.Supervisor, plugin: name, cfg: cfg} end # Add each child to the "loaded plugins" list in the State - Enum.each(children, fn {plugin, opts} -> State.add_loaded_plugin({plugin, opts[:cfg]}) end) + Enum.each(children, fn {_plugin, opts} -> State.add_loaded_plugin({opts[:plugin], opts[:cfg]}) end) Supervisor.init(children, strategy: :one_for_one) end