summaryrefslogtreecommitdiff
path: root/lib/irc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/irc')
-rw-r--r--lib/irc/connection.ex24
-rw-r--r--lib/irc/puppet_connection.ex48
-rw-r--r--lib/irc/user_track.ex43
3 files changed, 78 insertions, 37 deletions
diff --git a/lib/irc/connection.ex b/lib/irc/connection.ex
index eff5930..a0cdc27 100644
--- a/lib/irc/connection.ex
+++ b/lib/irc/connection.ex
@@ -113,7 +113,6 @@ defmodule IRC.Connection do
spec = [{{:_, :"$1", :_, :_, :_, :_, :_, :_, :_, :_, :_},
[{:==, :"$1", {:const, network}}], [:"$_"]}]
results = Enum.map(:dets.select(dets(), spec), fn(object) -> from_tuple(object) end)
- |> IO.inspect()
if channel do
Enum.find(results, fn(conn) -> Enum.member?(conn.channels, channel) end)
else
@@ -277,14 +276,17 @@ defmodule IRC.Connection do
# Received something in a channel
def handle_info({:received, text, sender, chan}, state) do
- reply_fun = fn(text) -> irc_reply(state, {chan, sender}, text) end
- account = IRC.Account.lookup(sender)
- message = %IRC.Message{at: NaiveDateTime.utc_now(), text: text, network: network(state), account: account, sender: sender, channel: chan, replyfun: reply_fun, trigger: extract_trigger(text)}
- message = case IRC.UserTrack.messaged(message) do
- :ok -> message
- {:ok, message} -> message
+ user = IRC.UserTrack.find_by_nick(network(state), sender.nick)
+ if !Map.get(user.options, :puppet) do
+ reply_fun = fn(text) -> irc_reply(state, {chan, sender}, text) end
+ account = IRC.Account.lookup(sender)
+ message = %IRC.Message{at: NaiveDateTime.utc_now(), text: text, network: network(state), account: account, sender: sender, channel: chan, replyfun: reply_fun, trigger: extract_trigger(text)}
+ message = case IRC.UserTrack.messaged(message) do
+ :ok -> message
+ {:ok, message} -> message
+ end
+ publish(message, ["#{message.network}/#{chan}:messages"])
end
- publish(message, ["#{message.network}/#{chan}:messages"])
{:noreply, state}
end
@@ -443,13 +445,9 @@ defmodule IRC.Connection do
|> List.flatten()
outputs = for line <- lines do
ExIRC.Client.msg(client, :privmsg, target, line)
- {:irc, :out, %IRC.Message{network: network, channel: target, text: line, sender: %ExIRC.SenderInfo{nick: state.conn.nick}, at: NaiveDateTime.utc_now()}}
+ {:irc, :out, %IRC.Message{network: network, channel: target, text: line, sender: %ExIRC.SenderInfo{nick: state.conn.nick}, at: NaiveDateTime.utc_now(), meta: %{self: true}}}
end
for f <- outputs, do: dispatch(["irc:outputs", "#{network}/#{target}:outputs"], f)
- case :global.whereis_name({LSG.TelegramRoom, network, target}) do
- pid when is_pid(pid) -> send(pid, {:raw, text})
- _ -> :ok
- end
end
defp irc_reply(%{client: client}, {target, %{nick: nick}}, {:kick, reason}) do
diff --git a/lib/irc/puppet_connection.ex b/lib/irc/puppet_connection.ex
index 59bce1b..da6cc93 100644
--- a/lib/irc/puppet_connection.ex
+++ b/lib/irc/puppet_connection.ex
@@ -35,7 +35,7 @@ defmodule IRC.PuppetConnection do
end
def send_message(account = %IRC.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}, channel, text) do
- GenServer.cast(name(account_id, connection_id), {:send_message, channel, text})
+ GenServer.cast(name(account_id, connection_id), {:send_message, self(), channel, text})
end
def start_and_send_message(account = %IRC.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}, channel, text) do
@@ -49,7 +49,7 @@ defmodule IRC.PuppetConnection do
else
pid
end
- GenServer.cast(pid, {:send_message, channel, text})
+ GenServer.cast(pid, {:send_message, self(), channel, text})
end
def start(account = %IRC.Account{}, connection = %IRC.Connection{}) do
@@ -103,11 +103,11 @@ defmodule IRC.PuppetConnection do
{:noreply, %{state | buffer: []}}
end
- def handle_cast(cast = {:send_message, channel, text}, state = %{connected: false, buffer: buffer}) do
+ def handle_cast(cast = {:send_message, _pid, _channel, _text}, state = %{connected: false, buffer: buffer}) do
{:noreply, %{state | buffer: [cast | buffer]}}
end
- def handle_cast({:send_message, channel, text}, state = %{connected: true}) do
+ def handle_cast({:send_message, pid, channel, text}, state = %{connected: true}) do
channels = if !Enum.member?(state.channels, channel) do
ExIRC.Client.join(state.client, channel)
[channel | state.channels]
@@ -116,6 +116,20 @@ defmodule IRC.PuppetConnection do
end
ExIRC.Client.msg(state.client, :privmsg, channel, text)
+ meta = %{puppet: true, from: pid}
+ account = IRC.Account.get(state.account_id)
+ nick = make_nick(state)
+ sender = %ExIRC.SenderInfo{network: state.network, nick: suffix_nick(nick), user: nick, host: "puppet."}
+ reply_fun = fn(text) ->
+ IRC.Connection.broadcast_message(state.network, channel, text)
+ end
+ message = %IRC.Message{at: NaiveDateTime.utc_now(), text: text, network: state.network, account: account, sender: sender, channel: channel, replyfun: reply_fun, trigger: IRC.Connection.extract_trigger(text), meta: meta}
+ message = case IRC.UserTrack.messaged(message) do
+ :ok -> message
+ {:ok, message} -> message
+ end
+ IRC.Connection.publish(message, ["#{message.network}/#{channel}:messages"])
+
idle = if length(state.buffer) == 0 do
:erlang.cancel_timer(state.idle)
:erlang.send_after(@max_idle, self(), :idle)
@@ -147,11 +161,8 @@ defmodule IRC.PuppetConnection do
def handle_info({:connected, server, port}, state) do
Logger.info("#{inspect(self())} Connected to #{server}:#{port} #{inspect state}")
{_, backoff} = :backoff.succeed(state.backoff)
- account = IRC.Account.get(state.account_id)
- user = IRC.UserTrack.find_by_account(state.network, account)
- base_nick = if(user, do: user.nick, else: account.name)
- nick = "#{base_nick}[p]"
- ExIRC.Client.logon(state.client, "", nick, base_nick, "#{base_nick}'s puppet")
+ base_nick = make_nick(state)
+ ExIRC.Client.logon(state.client, "", suffix_nick(base_nick), base_nick, "#{base_nick}'s puppet")
{:noreply, %{state | backoff: backoff, connected_server: server, connected_port: port}}
end
@@ -159,6 +170,8 @@ defmodule IRC.PuppetConnection do
def handle_info(:logged_in, state) do
Logger.info("#{inspect(self())} Logged in")
{_, backoff} = :backoff.succeed(state.backoff)
+ # Create an UserTrack entry for the client so it's authenticated to the right account_id already.
+ IRC.UserTrack.connected(state.network, suffix_nick(make_nick(state)), make_nick(state), "puppet.", state.account_id, %{puppet: true})
{:noreply, %{state | backoff: backoff}}
end
@@ -176,4 +189,21 @@ defmodule IRC.PuppetConnection do
{:noreply, state}
end
+ def make_nick(state) do
+ account = IRC.Account.get(state.account_id)
+ user = IRC.UserTrack.find_by_account(state.network, account)
+ base_nick = if(user, do: user.nick, else: account.name)
+ clean_nick = case String.split(base_nick, ":", parts: 2) do
+ ["@"<>nick, _] -> nick
+ [nick] -> nick
+ end
+ clean_nick
+ end
+
+ if Mix.env == :dev do
+ def suffix_nick(nick), do: "#{nick}[d]"
+ else
+ def suffix_nick(nick), do: "#{nick}[p]"
+ end
+
end
diff --git a/lib/irc/user_track.ex b/lib/irc/user_track.ex
index 4b1ee67..1b51266 100644
--- a/lib/irc/user_track.ex
+++ b/lib/irc/user_track.ex
@@ -20,7 +20,7 @@ defmodule IRC.UserTrack do
def clear_network(network) do
op(fn(ets) ->
spec = [
- {{:_, :"$1", :_, :_, :_, :_, :_, :_, :_, :_, :_},
+ {{:_, :"$1", :_, :_, :_, :_, :_, :_, :_, :_, :_, :_},
[
{:==, :"$1", {:const, network}}
], [:"$_"]}
@@ -61,22 +61,22 @@ defmodule IRC.UserTrack do
defmodule Id, do: use EntropyString
defmodule User do
- defstruct [:id, :account, :network, :nick, {:nicks, []}, :username, :host, :realname, {:privileges, %{}}, {:last_active, %{}}]
+ defstruct [:id, :account, :network, :nick, {:nicks, []}, :username, :host, :realname, {:privileges, %{}}, {:last_active, %{}}, {:options, %{}}]
def to_tuple(u = %__MODULE__{}) do
- {u.id || IRC.UserTrack.Id.large_id, u.network, u.account, String.downcase(u.nick), u.nick, u.nicks || [], u.username, u.host, u.realname, u.privileges, u.last_active}
+ {u.id || IRC.UserTrack.Id.large_id, u.network, u.account, String.downcase(u.nick), u.nick, u.nicks || [], u.username, u.host, u.realname, u.privileges, u.last_active, u.options}
end
#tuple size: 11
- def from_tuple({id, network, account, _downcased_nick, nick, nicks, username, host, realname, privs, last_active}) do
- struct = %__MODULE__{id: id, account: account, network: network, nick: nick, nicks: nicks, username: username, host: host, realname: realname, privileges: privs, last_active: last_active}
+ def from_tuple({id, network, account, _downcased_nick, nick, nicks, username, host, realname, privs, last_active, opts}) do
+ struct = %__MODULE__{id: id, account: account, network: network, nick: nick, nicks: nicks, username: username, host: host, realname: realname, privileges: privs, last_active: last_active, options: opts}
end
end
def find_by_account(%IRC.Account{id: id}) do
#iex(15)> :ets.fun2ms(fn(obj = {_, net, acct, _, _, _, _, _, _}) when net == network and acct == account -> obj end)
spec = [
- {{:_, :_, :"$2", :_, :_, :_, :_, :_, :_, :_, :_},
+ {{:_, :_, :"$2", :_, :_, :_, :_, :_, :_, :_, :_, :_},
[
{:==, :"$2", {:const, id}}
], [:"$_"]}
@@ -91,7 +91,7 @@ defmodule IRC.UserTrack do
def find_by_account(network, %IRC.Account{id: id}) do
#iex(15)> :ets.fun2ms(fn(obj = {_, net, acct, _, _, _, _, _, _}) when net == network and acct == account -> obj end)
spec = [
- {{:_, :"$1", :"$2", :_, :_, :_, :_, :_, :_, :_, :_},
+ {{:_, :"$1", :"$2", :_, :_, :_, :_, :_, :_, :_, :_, :_},
[
{:andalso, {:==, :"$1", {:const, network}},
{:==, :"$2", {:const, id}}}
@@ -100,7 +100,10 @@ defmodule IRC.UserTrack do
case :ets.select(@ets, spec) do
results = [_r | _] ->
results
- |> Enum.sort_by(fn({_, _, _, _, _, _, _, _, _, _, actives}) ->
+ |> Enum.reject(fn({_, net, _, _, _, _, _, _, _, _, actives, opts}) -> net == "matrix" end)
+ |> Enum.reject(fn({_, net, _, _, _, _, _, _, _, _, actives, opts}) -> net == "telegram" end)
+ |> Enum.reject(fn({_, _, _, _, _, _, _, _, _, _, actives, opts}) -> Map.get(opts, :puppet) end)
+ |> Enum.sort_by(fn({_, _, _, _, _, _, _, _, _, _, actives, _}) ->
Map.get(actives, nil)
end, {:desc, NaiveDateTime})
|> List.first
@@ -117,14 +120,14 @@ defmodule IRC.UserTrack do
def merge_account(old_id, new_id) do
#iex(15)> :ets.fun2ms(fn(obj = {_, net, acct, _, _, _, _, _, _}) when net == network and acct == account -> obj end)
spec = [
- {{:_, :_, :"$1", :_, :_, :_, :_, :_, :_, :_, :_},
+ {{:_, :_, :"$1", :_, :_, :_, :_, :_, :_, :_, :_, :_},
[
{:==, :"$1", {:const, old_id}}
], [:"$_"]}
]
- Enum.each(:ets.select(@ets, spec), fn({id, net, _, downcased_nick, nick, nicks, username, host, realname, privs, active}) ->
+ Enum.each(:ets.select(@ets, spec), fn({id, net, _, downcased_nick, nick, nicks, username, host, realname, privs, active, opts}) ->
Storage.op(fn(ets) ->
- :ets.insert(@ets, {id, net, new_id, downcased_nick, nick, nicks, username, host, realname, privs, active})
+ :ets.insert(@ets, {id, net, new_id, downcased_nick, nick, nicks, username, host, realname, privs, active, opts})
end)
end)
end
@@ -139,7 +142,7 @@ defmodule IRC.UserTrack do
end
def find_by_nick(network, nick) do
- case :ets.match(@ets, {:"$1", network, :_, String.downcase(nick), :_, :_, :_, :_, :_, :_, :_}) do
+ case :ets.match(@ets, {:"$1", network, :_, String.downcase(nick), :_, :_, :_, :_, :_, :_, :_, :_}) do
[[id]] -> lookup(id)
_ ->
nil
@@ -165,13 +168,24 @@ defmodule IRC.UserTrack do
end
def channel(network, channel) do
- Enum.filter(to_list(), fn({_, network, _, _, _, _, _, _, _, channels, _}) ->
+ Enum.filter(to_list(), fn({_, network, _, _, _, _, _, _, _, channels, _, _}) ->
Map.get(channels, channel)
end)
end
# TODO
- def connected(sender = %{nick: nick}) do
+ def connected(network, nick, user, host, account_id, opts \\ %{}) do
+ if account = IRC.Account.get(account_id) do
+ user = %User{id: IRC.UserTrack.Id.large_id, account: account_id, network: network, nick: nick, username: user, host: host, privileges: %{}, options: opts}
+ Storage.op(fn(ets) ->
+ :ets.insert(ets, User.to_tuple(user))
+ end)
+
+ IRC.Connection.publish_event(network, %{type: :connect, user_id: user.id, account_id: user.account})
+ :ok
+ else
+ :error
+ end
end
def joined(c, s), do: joined(c,s,[])
@@ -302,5 +316,4 @@ defmodule IRC.UserTrack do
defp userchans(%{privileges: privileges}) do
for({chan, _} <- privileges, do: chan)
end
-
end