WIP: Move Config.all_channels/0 and Config.channel_modules/1 logic into State; add State.add_loaded_module/2
The problem: When we're going through the list of modules to send messages to based on the channels they're a part of, it was being done so through the config. Since the config doesn't (and shouldn't) list all of the core modules that get included, any core modules that were loaded and running under the ModuleSupervisor would not get included in the router's attempt to send messages to a module. Now, the Config.all_channels and Config.channel_modules functions live in State, and State has a new "add_loaded_module" function where loaded modules are registered. The aforementioned moved functions will use this as the "source of truth" when deciding where to send messages for modules to handle. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
58
lib/state.ex
58
lib/state.ex
@@ -2,7 +2,7 @@ defmodule Omnibot.State do
|
||||
use GenServer
|
||||
|
||||
@enforce_keys [:cfg]
|
||||
defstruct [:cfg, channels: MapSet.new()]
|
||||
defstruct [:cfg, channels: MapSet.new(), module_map: %{}]
|
||||
|
||||
## Client API
|
||||
|
||||
@@ -21,6 +21,21 @@ defmodule Omnibot.State do
|
||||
GenServer.call(state, :cfg)
|
||||
end
|
||||
|
||||
@doc "Adds a loaded module to the default state."
|
||||
def add_loaded_module(module), do: add_loaded_module(__MODULE__, module)
|
||||
|
||||
@doc "Adds a loaded module to the given state."
|
||||
def add_loaded_module(state, {module, cfg}), do: GenServer.cast(state, {:add_loaded_module, {module, cfg}})
|
||||
|
||||
@doc "Adds a loaded module to the given state."
|
||||
def add_loaded_module(state, module), do: add_loaded_module(state, {module, []})
|
||||
|
||||
@doc "Gets all loaded modules from the default state."
|
||||
def loaded_modules(), do: loaded_modules(__MODULE__)
|
||||
|
||||
@doc "Gets all loaded modules from the given state."
|
||||
def loaded_modules(state), do: GenServer.call(state, :loaded_modules)
|
||||
|
||||
@doc "Gets all channels that the bot is present in from the default State process."
|
||||
def channels(), do: channels(__MODULE__)
|
||||
|
||||
@@ -45,6 +60,34 @@ defmodule Omnibot.State do
|
||||
GenServer.cast(state, {:remove_channel, channel})
|
||||
end
|
||||
|
||||
def all_channels(), do: all_channels(__MODULE__)
|
||||
|
||||
def all_channels(state) do
|
||||
loaded_modules(state) |> Enum.flat_map(
|
||||
fn {_, cfg} ->
|
||||
case cfg[:channels] do
|
||||
:all -> []
|
||||
nil -> []
|
||||
channels -> channels
|
||||
end
|
||||
end)
|
||||
|> MapSet.new()
|
||||
|> MapSet.to_list()
|
||||
end
|
||||
|
||||
def channel_modules(channel), do: channel_modules(__MODULE__, channel)
|
||||
|
||||
@doc ~S"""
|
||||
Gets a list of all `{module, mod_cfg}` from the given State that are both
|
||||
loaded, and listening to the given channel.
|
||||
"""
|
||||
def channel_modules(state, channel) do
|
||||
loaded_modules(state) |> Enum.filter(
|
||||
fn {_, cfg} ->
|
||||
cfg[:channels] == :all or Enum.member?(cfg[:channels] || [], channel)
|
||||
end)
|
||||
end
|
||||
|
||||
## Server API
|
||||
|
||||
@impl true
|
||||
@@ -61,7 +104,18 @@ defmodule Omnibot.State do
|
||||
def handle_call(:channels, _from, state) do
|
||||
{:reply, state.channels, state}
|
||||
end
|
||||
|
||||
|
||||
@impl true
|
||||
def handle_call(:loaded_modules, _from, state) do
|
||||
{:reply, state.module_map, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast({:add_loaded_module, {module, cfg}}, state) do
|
||||
state = %{state | module_map: Map.put(state.module_map, module, cfg)}
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast({:add_channel, channel}, state) do
|
||||
{:noreply, %{state | channels: state.channels |> MapSet.put(channel)}}
|
||||
|
||||
Reference in New Issue
Block a user