Add Omnibot.Module
Modules can easily be defined with `use Omnibot.Module`. Omnibot.Contrib.Fortune has been updated to use this. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
defmodule Omnibot.Contrib.Fortune do
|
defmodule Omnibot.Contrib.Fortune do
|
||||||
use GenServer
|
use Omnibot.Module
|
||||||
alias Omnibot.Irc
|
|
||||||
require Logger
|
|
||||||
|
|
||||||
@fortunes [
|
@fortunes [
|
||||||
"Reply hazy, try again",
|
"Reply hazy, try again",
|
||||||
@@ -21,10 +19,6 @@ defmodule Omnibot.Contrib.Fortune do
|
|||||||
|
|
||||||
## Client API
|
## Client API
|
||||||
|
|
||||||
def start_link(opts) do
|
|
||||||
GenServer.start_link(__MODULE__, opts[:cfg], opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
def privmsg(module, channel, nick, line) do
|
def privmsg(module, channel, nick, line) do
|
||||||
GenServer.cast(module, {:privmsg, {channel, nick, line}})
|
GenServer.cast(module, {:privmsg, {channel, nick, line}})
|
||||||
end
|
end
|
||||||
@@ -32,26 +26,11 @@ defmodule Omnibot.Contrib.Fortune do
|
|||||||
## Server callbacks
|
## Server callbacks
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def init(cfg) do
|
def on_channel_msg(channel, nick, line) do
|
||||||
#Logger.debug("Starting fortune module")
|
if line == "!fortune" do
|
||||||
#IO.inspect(self())
|
|
||||||
{:ok, cfg}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_call(:unload, _from, cfg) do
|
|
||||||
Logger.info("Unloading")
|
|
||||||
{:reply, :ok, cfg}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_cast({:privmsg, {channel, nick, line}}, cfg) do
|
|
||||||
if IO.inspect(line) == "!fortune" do
|
|
||||||
fortune = Enum.random(@fortunes)
|
fortune = Enum.random(@fortunes)
|
||||||
reply = "#{nick}: #{fortune}"
|
reply = "#{nick}: #{fortune}"
|
||||||
Irc.send_to(Irc, channel, reply)
|
Irc.send_to(channel, reply)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:noreply, cfg}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,12 +22,16 @@ defmodule Omnibot.Irc do
|
|||||||
|
|
||||||
def send_msg(irc, command, param), do: send_msg(irc, command, [param])
|
def send_msg(irc, command, param), do: send_msg(irc, command, [param])
|
||||||
|
|
||||||
|
def send_to(channel, text), do: send_to(__MODULE__, channel, text)
|
||||||
def send_to(irc, channel, text), do: send_msg(irc, "PRIVMSG", [channel, text])
|
def send_to(irc, channel, text), do: send_msg(irc, "PRIVMSG", [channel, text])
|
||||||
|
|
||||||
|
def join(channel), do: join(__MODULE__, channel)
|
||||||
def join(irc, channel), do: send_msg(irc, "JOIN", channel)
|
def join(irc, channel), do: send_msg(irc, "JOIN", channel)
|
||||||
|
|
||||||
|
def part(channel), do: part(__MODULE__, channel)
|
||||||
def part(irc, channel), do: send_msg(irc, "PART", channel)
|
def part(irc, channel), do: send_msg(irc, "PART", channel)
|
||||||
|
|
||||||
|
def sync_channels(), do: sync_channels(__MODULE__)
|
||||||
def sync_channels(irc), do: GenServer.cast(irc, :sync_channels)
|
def sync_channels(irc), do: GenServer.cast(irc, :sync_channels)
|
||||||
|
|
||||||
## Server callbacks
|
## Server callbacks
|
||||||
|
|||||||
72
lib/module.ex
Normal file
72
lib/module.ex
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
defmodule Omnibot.Module do
|
||||||
|
defmacro __using__([]) do
|
||||||
|
quote do
|
||||||
|
use GenServer
|
||||||
|
alias Omnibot.{Irc, Module}
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@behaviour Module
|
||||||
|
|
||||||
|
## Client API
|
||||||
|
|
||||||
|
def start_link(opts) do
|
||||||
|
GenServer.start_link(__MODULE__, opts[:cfg], opts ++ [name: __MODULE__])
|
||||||
|
end
|
||||||
|
|
||||||
|
def msg(msg), do: GenServer.cast(__MODULE__, msg)
|
||||||
|
def msg(module, msg), do: GenServer.cast(module, {:msg, msg})
|
||||||
|
|
||||||
|
## Server callbacks
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def init(cfg), do: {:ok, cfg}
|
||||||
|
|
||||||
|
@impl Module
|
||||||
|
def on_msg(msg) do
|
||||||
|
route_msg(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
def route_msg(msg) do
|
||||||
|
nick = msg.prefix.nick
|
||||||
|
case String.upcase(msg.command) do
|
||||||
|
"PRIVMSG" -> [channel | text] = msg.params
|
||||||
|
on_channel_msg(channel, nick, Enum.join(text, " "))
|
||||||
|
"JOIN" -> [channel | _] = msg.params
|
||||||
|
on_join(channel, nick)
|
||||||
|
"PART" -> [channel | _] = msg.params
|
||||||
|
on_part(channel, nick)
|
||||||
|
"KICK" -> [channel | _] = msg.params
|
||||||
|
on_kick(channel, nick)
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Module
|
||||||
|
def on_channel_msg(_channel, _nick, _line), do: nil
|
||||||
|
|
||||||
|
@impl Module
|
||||||
|
def on_join(_channel, _nick), do: nil
|
||||||
|
|
||||||
|
@impl Module
|
||||||
|
def on_part(_channel, _nick), do: nil
|
||||||
|
|
||||||
|
@impl Module
|
||||||
|
def on_kick(_channel, _nick), do: nil
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_cast({:msg, msg}, cfg) do
|
||||||
|
on_msg(msg)
|
||||||
|
{:noreply, cfg}
|
||||||
|
end
|
||||||
|
|
||||||
|
defoverridable Module
|
||||||
|
defoverridable GenServer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@callback on_msg(msg :: %Omnibot.Irc.Msg{}) :: any
|
||||||
|
@callback on_channel_msg(channel :: String.t, nick :: String.t, line :: String.t) :: any
|
||||||
|
@callback on_join(channel :: String.t, nick :: String.t) :: any
|
||||||
|
@callback on_part(channel :: String.t, nick :: String.t) :: any
|
||||||
|
@callback on_kick(channel :: String.t, nick :: String.t) :: any
|
||||||
|
end
|
||||||
@@ -3,6 +3,19 @@ defmodule Omnibot.Router do
|
|||||||
alias Omnibot.{Config, Irc, Irc.Msg, State}
|
alias Omnibot.{Config, Irc, Irc.Msg, State}
|
||||||
|
|
||||||
def route(irc, msg) do
|
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
|
case String.upcase(msg.command) do
|
||||||
"PRIVMSG" -> handle(irc, :privmsg, msg)
|
"PRIVMSG" -> handle(irc, :privmsg, msg)
|
||||||
"JOIN" -> handle(irc, :join, msg)
|
"JOIN" -> handle(irc, :join, msg)
|
||||||
@@ -15,15 +28,12 @@ defmodule Omnibot.Router do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def handle(_irc, :privmsg, msg) do
|
def handle(_irc, :privmsg, msg) do
|
||||||
# TODO : get channel, pass along to modules
|
[channel | _params] = msg.params
|
||||||
[channel | params] = msg.params
|
|
||||||
line = Enum.join(params, " ")
|
|
||||||
nick = msg.prefix.nick
|
|
||||||
|
|
||||||
# Find modules that want this message
|
# Find modules that want this message
|
||||||
State.cfg()
|
State.cfg()
|
||||||
|> Config.channel_modules(channel)
|
|> Config.channel_modules(channel)
|
||||||
|> Enum.each(fn {module, _} -> module.privmsg(module, channel, nick, line) end)
|
|> Enum.each(fn {module, _} -> module.msg(module, msg) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(_irc, :join, %Msg {prefix: %Msg.Prefix{nick: nick}, params: [channel | _]}) do
|
def handle(_irc, :join, %Msg {prefix: %Msg.Prefix{nick: nick}, params: [channel | _]}) do
|
||||||
|
|||||||
Reference in New Issue
Block a user