diff --git a/lib/config.ex b/lib/config.ex index 904cb7b..91faf7e 100644 --- a/lib/config.ex +++ b/lib/config.ex @@ -17,7 +17,10 @@ defmodule Omnibot.Config do Gets all channels that the bot should join via its modules. """ def all_channels(cfg) do - Enum.flat_map(cfg.modules, fn {_, [channels: channels]} -> channels end) + Enum.flat_map(cfg.modules, fn + {_, [channels: :all]} -> [] + {_, [channels: channels]} -> channels + end) |> MapSet.new() |> MapSet.to_list() end @@ -28,7 +31,9 @@ defmodule Omnibot.Config do """ def channel_modules(cfg, channel) do cfg.modules - |> Enum.filter(fn {_, cfg} -> Enum.member?(cfg[:channels] || [], channel) end) + |> Enum.filter(fn {_, cfg} -> + cfg[:channels] == :all or Enum.member?(cfg[:channels] || [], channel) + end) end def msg_prefix(cfg) do diff --git a/lib/core/join.ex b/lib/core/join.ex new file mode 100644 index 0000000..f5340db --- /dev/null +++ b/lib/core/join.ex @@ -0,0 +1,11 @@ +defmodule Omnibot.Core.Join do + use Omnibot.Module + alias Omnibot.State + + def on_join(channel, nick) do + cfg = State.cfg() + if nick == cfg.nick do + State.add_channel(channel) + end + end +end diff --git a/lib/irc/msg.ex b/lib/irc/msg.ex index ee6f97d..c4f7f6c 100644 --- a/lib/irc/msg.ex +++ b/lib/irc/msg.ex @@ -65,6 +65,17 @@ defmodule Omnibot.Irc.Msg do params: params, } end + + @doc "Gets the channel that the given message is targeting, if any." + def channel(msg) do + case String.upcase(msg.command) do + "PRIVMSG" -> Enum.at(msg.params, 0) + "JOIN" -> Enum.at(msg.params, 0) + "PART" -> Enum.at(msg.params, 0) + "KICK" -> Enum.at(msg.params, 0) + _ -> nil + end + end end defimpl String.Chars, for: Irc.Msg.Prefix do diff --git a/lib/module.ex b/lib/module.ex index a296a27..54dbf9c 100644 --- a/lib/module.ex +++ b/lib/module.ex @@ -1,7 +1,7 @@ defmodule Omnibot.Module do defmodule Hooks do defmacro __before_compile__(_env) do - quote do + quote generated: true do @impl true def on_channel_msg(_channel, _nick, _line), do: nil diff --git a/lib/router.ex b/lib/router.ex index 8c8a5b2..599ed4a 100644 --- a/lib/router.ex +++ b/lib/router.ex @@ -2,70 +2,48 @@ defmodule Omnibot.Router do require Logger alias Omnibot.{Config, Irc, Irc.Msg, State} - def route(irc, msg) do - # TODO - consider removing this check and specific handling into the `use Omnibot.Module` block - # PROS: - # - Don't have to determine message command twice (first here, second in Omnibot.Module) - # - Allows for much more powerful modules. JOIN, PART, KICK, etc handlers would be modules themselves - # - This is an extremely big win IMO - # - # CONS: - # - All routed functionality needs to be in a module - # - This may get a little old - # - A failed command could cause important messages to be missed (?) - # - Do messages in a named PID's mailbox persist after that PID goes away? My guess is "no" - # - To get around this, there could be a mailbox for "special" commands, probably using ETS - # - case String.upcase(msg.command) do - "PRIVMSG" -> handle(irc, :privmsg, msg) - "JOIN" -> handle(irc, :join, msg) - "KICK" -> handle(irc, :kick, msg) - "PART" -> handle(irc, :part, msg) - "PING" -> handle(irc, :ping, msg) - "001" -> handle(irc, :welcome, msg) - _ -> nil - end - end - - def handle(_irc, :privmsg, msg) do - [channel | _params] = msg.params - - # Find modules that want this message + def route(_irc, msg) do + channel = Msg.channel(msg) State.cfg() |> Config.channel_modules(channel) |> Enum.each(fn {module, _} -> module.on_msg(msg) end) end - def handle(_irc, :join, %Msg {prefix: %Msg.Prefix{nick: nick}, params: [channel | _]}) do - cfg = State.cfg() - if nick == cfg.nick do - State.add_channel(channel) - end - end + #def handle(_irc, :privmsg, msg) do + # [channel | _params] = msg.params - def handle(irc, :kick, %Msg {params: [channel, who | _]}) do - cfg = State.cfg() - if who == cfg.nick do - State.remove_channel(State, channel) - # sync_channels here because this is a state that we (should) not have put ourselves into - Irc.sync_channels(irc) - end - end + # # Find modules that want this message + # State.cfg() + # |> Config.channel_modules(channel) + # |> Enum.each(fn {module, _} -> module.on_msg(msg) end) + #end - def handle(_irc, :part, %Msg {prefix: %Msg.Prefix{nick: nick}, params: [channel | _]}) do - cfg = State.cfg() - if nick == cfg.nick do - State.remove_channel(State, channel) - end - end + #def handle(_irc, :join, msg: %Msg {params: [channel | _]}) do + # State.cfg() + # |> Config.channel_modules(channel) + # |> Enum.each(fn {module, _} -> module.on_join(msg) end) + #end - def handle(irc, :ping, msg) do - cfg = State.cfg() - reply = Config.msg(cfg, "PONG", msg.params) - Irc.send_msg(irc, reply) - end + #def handle(irc, :kick, msg: %Msg {params: [channel | _]}) do + # State.cfg() + # |> Config.channel_modules(channel) + # |> Enum.each(fn {module, _} -> module.on_kick(msg) end) + #end - def handle(irc, :welcome, _msg) do - Irc.sync_channels(irc) - end + #def handle(_irc, :part, %Msg {prefix: %Msg.Prefix{nick: nick}, params: [channel | _]}) do + # cfg = State.cfg() + # if nick == cfg.nick do + # State.remove_channel(State, channel) + # end + #end + + #def handle(irc, :ping, msg) do + # cfg = State.cfg() + # reply = Config.msg(cfg, "PONG", msg.params) + # Irc.send_msg(irc, reply) + #end + + #def handle(irc, :welcome, _msg) do + # Irc.sync_channels(irc) + #end end