Files
omnibot/lib/plugin_supervisor.ex
Alek Ratzloff 522c62a55c Finish plugin and routing overhaul, there's a new model in town:
* Plugins all derive from Omnibot.Plugin. There still is a base plugin,
  in case we want to have another plugin backend instead of a GenServer
* All plugins are monitored by a unique Plugin.Supervisor, which is in
  turn started by the PluginSupervisor (yes this is confusing, yes it
  needs to be renamed)
* Any other auxiliary child processes may be started through the
  Plugin.children/1 function.
* By default, plugins have a CfgState process which is an Agent that
  keeps track of the plugin's configuration and state
* Plugin API is now called through the GenServer backend for better
  synchronicity.
* Very few changes to the front-facing Plugin API, which is nice

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
2020-07-14 15:05:00 -07:00

63 lines
1.7 KiB
Elixir

defmodule Omnibot.PluginSupervisor do
@moduledoc false
use Supervisor
require Logger
alias Omnibot.State
def start_link(opts \\ []) do
Supervisor.start_link(__MODULE__, opts[:cfg], opts)
end
@impl true
def init(cfg) do
compile_files(cfg.plugin_paths || [])
# These are plugins that need to be loaded for core functionality of the bot
core = [
Omnibot.Core,
]
# Map the plugins in the configuration to the children
children =
for plug <- (core ++ cfg.plugins) do
{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({opts[:plugin], opts[:cfg]}) end)
Supervisor.init(children, strategy: :one_for_one)
end
defp compile_files([]), do: nil
defp compile_files([{path, opts} | plugin_paths]) do
case {File.exists?(path), File.dir?(path)} do
{_, true} -> compile_dir(path, opts[:recurse] || false)
{true, false} -> Code.require_file(path)
{_, _} -> Logger.error("plugin path '#{path}' does not exist, it will not be loaded")
end
compile_files(plugin_paths)
end
defp compile_files([path | plugin_paths]) do
compile_files([{path, []} | plugin_paths])
end
defp compile_dir(path, recurse) do
files =
File.ls!(path)
|> Enum.map(fn file -> {Path.join(path, file), [recurse: recurse]} end)
|> Enum.filter(fn {file, [recurse: recurse]} ->
(!File.dir?(file) || recurse) && File.exists?(file)
end)
compile_files(files)
end
end