WIP: Move to using modules for implementing core behavior
Since modules can now intercept all messages in the channels they're listening for, it'd be cool to have modules handling things like making sure the Omnibot.State stays updated as appropriate, and that pings are ponged, etc. This will probably deprecate the router, since it's been reduced to a single function call, but we'll see about that. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
11
lib/core/join.ex
Normal file
11
lib/core/join.ex
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user