make chatters GenServers instead of runaway Tasks

(so they can keep their own state!)
master
cynic 3 years ago
parent 27b4b33d4b
commit c95bf3d817
  1. 59
      lib/ircked_elixir/chatter.ex
  2. 2
      lib/ircked_elixir/chatter/state.ex
  3. 2
      lib/ircked_elixir/overseer.ex

@ -1,32 +1,59 @@
defmodule IrckedElixir.Chatter do
use GenServer
alias IrckedElixir.Chatter.Message, as: Message
alias IrckedElixir.Chatter.Privmsg, as: Privmsg
def start(server, port, nick) do
{:ok, socket} = :gen_tcp.connect(to_charlist(server), port, [:binary, active: false])
:gen_tcp.send(socket, ["USER ", nick, " 0 * :", nick, "\r\n"])
:gen_tcp.send(socket, ["NICK ", nick, "\r\n"])
@impl true
def init(starting_state) do
{:ok, socket} = :gen_tcp.connect(to_charlist(starting_state.ip), starting_state.port, [:binary, active: false])
IO.puts(inspect starting_state)
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, ["NICK ", starting_state.nick, "\r\n"])
send(self(), {:run, starting_state})
{:ok, starting_state}
end
@impl true
def handle_info({:sendmsg, to, body}, state) do
Privmsg.construct(state.nick, to, body).message |> Message.send(state.sock)
{:noreply, state}
end
@impl true
def handle_info({:run, start_state}, _state) do
run(start_state)
{:noreply, start_state}
end
run(socket)
def start_link(starting_state) do
GenServer.start_link(__MODULE__, starting_state)
end
def run(socket) do
{:ok, data} = :gen_tcp.recv(socket, 0)
String.split(data, "\r\n") |> Enum.each(fn raw -> handle(Message.parse(raw), socket) end)
run(socket)
def sendmsg(to, body) do
send(self(), {:sendmsg, to, body})
end
def send(socket, to, body) do
Privmsg.construct("functism", to, body).message |> Message.send(socket)
def run(state) do
{:ok, data} = :gen_tcp.recv(state.sock, 0)
String.split(data, "\r\n") |> Enum.each(fn raw -> handle(Message.parse(raw), state) end)
run(state)
end
def handle(msg, socket) do
def handle(msg, state) do
case msg.command do
"PING" -> Message.construct("", "PONG", msg.parameters) |> Message.send(socket)
"001" -> Message.construct("", "JOIN", ["#qrs"]) |> Message.send(socket)
"PING" -> Message.construct("", "PONG", msg.parameters) |> Message.send(state.sock)
"001" -> Message.construct("", "JOIN", ["#qrs"]) |> Message.send(state.sock)
"PRIVMSG" ->
pm = Privmsg.parse(msg)
IO.puts(inspect pm)
case pm.body do
".bots" -> Privmsg.construct("functism", pm.to, "https://github.com/kurisufriend/ircked_elixir").message |> Message.send(socket)
".hello" -> Privmsg.construct("functism", pm.to, "hai").message |> Message.send(socket)
".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

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

@ -12,7 +12,7 @@ defmodule IrckedElixir.Overseer do
@impl true
def init(:ok) do
children = 1..@chatters |> Enum.to_list |> Enum.map(fn n -> %{id: "chatter"<>to_string(n), start: {Task, :start_link, [fn -> IrckedElixir.Chatter.start(@server_address, @server_port, @base_nick <> to_string(n)) end]}} end)
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)
Supervisor.init(children, strategy: :one_for_one)
end
end

Loading…
Cancel
Save