group controller & real supervision hierarchy

master
cynic 3 years ago
parent c95bf3d817
commit f3e1c22f1a
  1. 69
      lib/ircked_elixir/chat_group.ex
  2. 40
      lib/ircked_elixir/chatter.ex
  3. 2
      lib/ircked_elixir/chatter/state.ex
  4. 10
      lib/ircked_elixir/overseer.ex

@ -0,0 +1,69 @@
defmodule IrckedElixir.ChatGroup do
use GenServer
alias IrckedElixir.Chatter.Message, as: Message
alias IrckedElixir.Chatter.Privmsg, as: Privmsg
@server_address "localhost"
@server_port 6667
@base_nick "functism"
@chatters 3
@impl true
def init(chatters) do
1..@chatters
|> Enum.to_list
|> Enum.map(
fn n ->
%{
id: "chatter"<>to_string(n),
start: {IrckedElixir.Chatter, :start_link, [%IrckedElixir.Chatter.State{ip: @server_address, port: @server_port, nick: @base_nick <> to_string(n), reporter: n == 1}]}
}
end
)
|> Enum.each(
fn child ->
DynamicSupervisor.start_child(IrckedElixir.DynamicSupervisor, child)
end
)
{:ok, chatters}
end
@impl true
def handle_info({:checkin, nick, chatter}, chatters) do
chatters = Map.put(chatters, nick, chatter)
{:noreply, chatters}
end
def handle_info({:report, msg}, chatters) do
case msg.command do
"PRIVMSG" ->
pm = Privmsg.parse(msg)
IO.puts(inspect pm)
case pm.body do
".cunny" -> send_all(chatters, pm.to, "cunny!")
_ -> ""
end
"" -> ""
_ -> IO.puts(inspect msg)
end
{:noreply, chatters}
end
def start_link(chatters) do
GenServer.start_link(__MODULE__, chatters, name: :chatgroup)
end
def send_all(chatters, to, body) do
chatters
|> Map.keys
|> Enum.each(
fn chatter ->
send(String.to_atom(chatter), {:sendprivmsg, to, body})
IO.puts("LOL, "<>inspect(chatter))
end
)
end
end

@ -6,36 +6,40 @@ defmodule IrckedElixir.Chatter do
@impl true @impl true
def init(starting_state) do def init(starting_state) do
{:ok, socket} = :gen_tcp.connect(to_charlist(starting_state.ip), starting_state.port, [:binary, active: false]) {:ok, socket} = :gen_tcp.connect(to_charlist(starting_state.ip), starting_state.port, [:binary, active: true])
IO.puts(inspect starting_state)
starting_state = %{starting_state | sock: socket} starting_state = %{starting_state | sock: socket}
IO.puts(inspect starting_state)
IO.puts(inspect socket)
:gen_tcp.send(socket, ["USER ", starting_state.nick, " 0 * :", starting_state.nick, "\r\n"]) :gen_tcp.send(socket, ["USER ", starting_state.nick, " 0 * :", starting_state.nick, "\r\n"])
:gen_tcp.send(socket, ["NICK ", starting_state.nick, "\r\n"]) :gen_tcp.send(socket, ["NICK ", starting_state.nick, "\r\n"])
send(self(), {:run, starting_state}) send(:chatgroup, {:checkin, starting_state.nick, self()})
{:ok, starting_state} {:ok, starting_state}
end end
@impl true @impl true
def handle_info({:sendmsg, to, body}, state) do def handle_info({:tcp, _, data}, state) do
Privmsg.construct(state.nick, to, body).message |> Message.send(state.sock) String.split(data, "\r\n") |> Enum.each(fn raw -> handle(Message.parse(raw), state) end)
{:noreply, state} {:noreply, state}
end end
@impl true def handle_info({:tcp_closed, _}, state) do
def handle_info({:run, start_state}, _state) do {:stop, :normal, state}
run(start_state) end
{:noreply, start_state}
def handle_info({:tcp_error, _}, state) do
{:stop, :normal, state}
end
def handle_info({:sendprivmsg, to, body}, state) do
Privmsg.construct(state.nick, to, body).message |> Message.send(state.sock)
{:noreply, state}
end end
def start_link(starting_state) do def start_link(starting_state) do
GenServer.start_link(__MODULE__, starting_state) GenServer.start_link(__MODULE__, starting_state, name: starting_state.nick |> String.to_atom)
end end
def sendmsg(to, body) do def sendpm(to, body) do
send(self(), {:sendmsg, to, body}) send(self(), {:sendprivmsg, to, body})
end end
def run(state) do def run(state) do
@ -45,20 +49,20 @@ defmodule IrckedElixir.Chatter do
end end
def handle(msg, state) do def handle(msg, state) do
if state.reporter do
send(:chatgroup, {:report, msg})
end
case msg.command do case msg.command do
"PING" -> Message.construct("", "PONG", msg.parameters) |> Message.send(state.sock) "PING" -> Message.construct("", "PONG", msg.parameters) |> Message.send(state.sock)
"001" -> Message.construct("", "JOIN", ["#qrs"]) |> Message.send(state.sock) "001" -> Message.construct("", "JOIN", ["#qrs"]) |> Message.send(state.sock)
"PRIVMSG" -> "PRIVMSG" ->
pm = Privmsg.parse(msg) pm = Privmsg.parse(msg)
IO.puts(inspect pm)
case pm.body do case pm.body do
".bots" -> Privmsg.construct("functism", pm.to, "https://github.com/kurisufriend/ircked_elixir").message |> Message.send(state.sock)
".hello" -> Privmsg.construct("functism", pm.to, "hai").message |> Message.send(state.sock)
_ -> "" _ -> ""
end end
"" -> "" "" -> ""
_ -> IO.puts(inspect msg) _ -> ""
end end
end end
end end

@ -1,3 +1,3 @@
defmodule IrckedElixir.Chatter.State do defmodule IrckedElixir.Chatter.State do
defstruct ip: "", port: 0, nick: "", sock: nil defstruct ip: "", port: 0, nick: "", sock: nil, reporter: false
end end

@ -1,18 +1,16 @@
defmodule IrckedElixir.Overseer do defmodule IrckedElixir.Overseer do
use Supervisor use Supervisor
@server_address "localhost"
@server_port 6667
@base_nick "functism"
@chatters 20
def start_link(opts) do def start_link(opts) do
Supervisor.start_link(__MODULE__, :ok, opts) Supervisor.start_link(__MODULE__, :ok, opts)
end end
@impl true @impl true
def init(:ok) do def init(:ok) do
children = 1..@chatters |> Enum.to_list |> Enum.map(fn n -> %{id: "chatter"<>to_string(n), start: {IrckedElixir.Chatter, :start_link, [%IrckedElixir.Chatter.State{ip: @server_address, port: @server_port, nick: @base_nick <> to_string(n)}]}} end) children = [
{DynamicSupervisor, strategy: :one_for_one, name: IrckedElixir.DynamicSupervisor},
{IrckedElixir.ChatGroup, %{}}
]
Supervisor.init(children, strategy: :one_for_one) Supervisor.init(children, strategy: :one_for_one)
end end
end end

Loading…
Cancel
Save