summaryrefslogtreecommitdiff
path: root/lib/irc
diff options
context:
space:
mode:
authorJordan Bracco <href@random.sh>2022-12-20 02:47:33 +0000
committerJordan Bracco <href@random.sh>2022-12-20 19:29:41 +0100
commit2127553ad058bfa688feb73097e604a8fb5a1899 (patch)
tree3246c31aef0f6c3a110376de21265a6f5d02c597 /lib/irc
parentIRC.PubSub -> Nola.PubSub, refs T77 (diff)
Rename IRC.Account to Nola.Account, refs T77
Diffstat (limited to 'lib/irc')
-rw-r--r--lib/irc/account.ex263
-rw-r--r--lib/irc/connection.ex10
-rw-r--r--lib/irc/membership.ex10
-rw-r--r--lib/irc/nola_irc.ex2
-rw-r--r--lib/irc/puppet_connection.ex18
-rw-r--r--lib/irc/user_track.ex16
6 files changed, 28 insertions, 291 deletions
diff --git a/lib/irc/account.ex b/lib/irc/account.ex
deleted file mode 100644
index a39733c..0000000
--- a/lib/irc/account.ex
+++ /dev/null
@@ -1,263 +0,0 @@
-defmodule IRC.Account do
- alias IRC.UserTrack.User
-
- @moduledoc """
- Account registry....
-
- Maps a network predicate:
- * `{net, {:nick, nickname}}`
- * `{net, {:account, account}}`
- * `{net, {:mask, user@host}}`
- to an unique identifier, that can be shared over multiple networks.
-
- If a predicate cannot be found for an existing account, a new account will be made in the database.
-
- To link two existing accounts from different network onto a different one, a merge operation is provided.
-
- """
-
- # FIXME: Ensure uniqueness of name?
-
- @derive {Poison.Encoder, except: [:token]}
- defstruct [:id, :name, :token]
- @type t :: %__MODULE__{id: id(), name: String.t()}
- @type id :: String.t()
-
- defimpl Inspect, for: __MODULE__ do
- import Inspect.Algebra
-
- def inspect(%{id: id, name: name}, opts) do
- concat(["#IRC.Account[", id, " ", name, "]"])
- end
- end
-
- def file(base) do
- to_charlist(Nola.data_path() <> "/account_#{base}.dets")
- end
-
- defp from_struct(%__MODULE__{id: id, name: name, token: token}) do
- {id, name, token}
- end
-
- defp from_tuple({id, name, token}) do
- %__MODULE__{id: id, name: name, token: token}
- end
-
- def start_link() do
- GenServer.start_link(__MODULE__, [], [name: __MODULE__])
- end
-
- def init(_) do
- {:ok, accounts} = :dets.open_file(file("db"), [])
- {:ok, meta} = :dets.open_file(file("meta"), [])
- {:ok, predicates} = :dets.open_file(file("predicates"), [{:type, :set}])
- {:ok, %{accounts: accounts, meta: meta, predicates: predicates}}
- end
-
- def get(id) do
- case :dets.lookup(file("db"), id) do
- [account] -> from_tuple(account)
- _ -> nil
- end
- end
-
- def get_by_name(name) do
- spec = [{{:_, :"$1", :_}, [{:==, :"$1", {:const, name}}], [:"$_"]}]
- case :dets.select(file("db"), spec) do
- [account] -> from_tuple(account)
- _ -> nil
- end
- end
-
- def get_meta(%__MODULE__{id: id}, key, default \\ nil) do
- case :dets.lookup(file("meta"), {id, key}) do
- [{_, value}] -> (value || default)
- _ -> default
- end
- end
-
- @spec find_meta_accounts(String.t()) :: [{account :: t(), value :: String.t()}, ...]
- @doc "Find all accounts that have a meta of `key`."
- def find_meta_accounts(key) do
- spec = [{{{:"$1", :"$2"}, :"$3"}, [{:==, :"$2", {:const, key}}], [{{:"$1", :"$3"}}]}]
- for {id, val} <- :dets.select(file("meta"), spec), do: {get(id), val}
- end
-
- @doc "Find an account given a specific meta `key` and `value`."
- @spec find_meta_account(String.t(), String.t()) :: t() | nil
- def find_meta_account(key, value) do
- #spec = [{{{:"$1", :"$2"}, :"$3"}, [:andalso, {:==, :"$2", {:const, key}}, {:==, :"$3", {:const, value}}], [:"$1"]}]
- spec = [{{{:"$1", :"$2"}, :"$3"}, [{:andalso, {:==, :"$2", {:const, key}}, {:==, {:const, value}, :"$3"}}], [:"$1"]}]
- case :dets.select(file("meta"), spec) do
- [id] -> get(id)
- _ -> nil
- end
- end
-
- def get_all_meta(%__MODULE__{id: id}) do
- spec = [{{{:"$1", :"$2"}, :"$3"}, [{:==, :"$1", {:const, id}}], [{{:"$2", :"$3"}}]}]
- :dets.select(file("meta"), spec)
- end
-
- def put_user_meta(account = %__MODULE__{}, key, value) do
- put_meta(account, "u:"<>key, value)
- end
-
- def put_meta(%__MODULE__{id: id}, key, value) do
- :dets.insert(file("meta"), {{id, key}, value})
- end
-
- def delete_meta(%__MODULE__{id: id}, key) do
- :dets.delete(file("meta"), {id, key})
- end
-
- def all_accounts() do
- :dets.traverse(file("db"), fn(obj) -> {:continue, from_tuple(obj)} end)
- end
-
- def all_predicates() do
- :dets.traverse(file("predicates"), fn(obj) -> {:continue, obj} end)
- end
-
- def all_meta() do
- :dets.traverse(file("meta"), fn(obj) -> {:continue, obj} end)
- end
-
- def merge_account(old_id, new_id) do
- if old_id != new_id do
- spec = [{{:"$1", :"$2"}, [{:==, :"$2", {:const, old_id}}], [:"$1"]}]
- predicates = :dets.select(file("predicates"), spec)
- for pred <- predicates, do: :ok = :dets.insert(file("predicates"), {pred, new_id})
- spec = [{{{:"$1", :"$2"}, :"$3"}, [{:==, :"$1", {:const, old_id}}], [{{:"$2", :"$3"}}]}]
- metas = :dets.select(file("meta"), spec)
- for {k,v} <- metas do
- :dets.delete(file("meta"), {{old_id, k}})
- :ok = :dets.insert(file("meta"), {{new_id, k}, v})
- end
- :dets.delete(file("db"), old_id)
- IRC.Membership.merge_account(old_id, new_id)
- IRC.UserTrack.merge_account(old_id, new_id)
- IRC.Connection.dispatch("account", {:account_change, old_id, new_id})
- IRC.Connection.dispatch("conn", {:account_change, old_id, new_id})
- end
- :ok
- end
-
- @doc "Find an account by a logged in user"
- def find_by_nick(network, nick) do
- do_lookup(%ExIRC.SenderInfo{nick: nick, network: network}, false)
- end
-
- @doc "Always find an account by nickname, even if offline. Uses predicates and then account name."
- def find_always_by_nick(network, chan, nick) do
- with \
- nil <- find_by_nick(network, nick),
- nil <- do_lookup(%User{network: network, nick: nick}, false),
- nil <- get_by_name(nick)
- do
- nil
- else
- %__MODULE__{} = account ->
- memberships = IRC.Membership.of_account(account)
- if Enum.any?(memberships, fn({net, ch}) -> (net == network) or (chan && chan == ch) end) do
- account
- else
- nil
- end
- end
- end
-
- def find(something) do
- do_lookup(something, false)
- end
-
- def lookup(something, make_default \\ true) do
- account = do_lookup(something, make_default)
- if account && Map.get(something, :nick) do
- IRC.Connection.dispatch("account", {:account_auth, Map.get(something, :nick), account.id})
- end
- account
- end
-
- def handle_info(_, state) do
- {:noreply, state}
- end
-
- def handle_cast(_, state) do
- {:noreply, state}
- end
-
- def handle_call(_, _, state) do
- {:noreply, state}
- end
-
- def terminate(_, state) do
- for {_, dets} <- state do
- :dets.sync(dets)
- :dets.close(dets)
- end
- end
-
- defp do_lookup(message = %IRC.Message{account: account_id}, make_default) when is_binary(account_id) do
- get(account_id)
- end
-
- defp do_lookup(sender = %ExIRC.Who{}, make_default) do
- if user = IRC.UserTrack.find_by_nick(sender) do
- lookup(user, make_default)
- else
- #FIXME this will never work with continued lookup by other methods as Who isn't compatible
- lookup_by_nick(sender, :dets.lookup(file("predicates"), {sender.network,{:nick, sender.nick}}), make_default)
- end
- end
-
- defp do_lookup(sender = %ExIRC.SenderInfo{}, make_default) do
- lookup(IRC.UserTrack.find_by_nick(sender), make_default)
- end
-
- defp do_lookup(user = %User{account: id}, make_default) when is_binary(id) do
- get(id)
- end
-
- defp do_lookup(user = %User{network: server, nick: nick}, make_default) do
- lookup_by_nick(user, :dets.lookup(file("predicates"), {server,{:nick, nick}}), make_default)
- end
-
- defp do_lookup(nil, _) do
- nil
- end
-
- defp lookup_by_nick(_, [{_, id}], _make_default) do
- get(id)
- end
-
- defp lookup_by_nick(user, _, make_default) do
- #authenticate_by_host(user)
- if make_default, do: new_account(user), else: nil
- end
-
- def new_account(nick) do
- id = EntropyString.large_id()
- :dets.insert(file("db"), {id, nick, EntropyString.token()})
- get(id)
- end
-
- def new_account(%{nick: nick, network: server}) do
- id = EntropyString.large_id()
- :dets.insert(file("db"), {id, nick, EntropyString.token()})
- :dets.insert(file("predicates"), {{server, {:nick, nick}}, id})
- get(id)
- end
-
- def update_account_name(account = %__MODULE__{id: id}, name) do
- account = %__MODULE__{account | name: name}
- :dets.insert(file("db"), from_struct(account))
- get(id)
- end
-
- def get_predicates(%__MODULE__{} = account) do
- spec = [{{:"$1", :"$2"}, [{:==, :"$2", {:const, account.id}}], [:"$1"]}]
- :dets.select(file("predicates"), spec)
- end
-
-end
diff --git a/lib/irc/connection.ex b/lib/irc/connection.ex
index 4472466..49f5774 100644
--- a/lib/irc/connection.ex
+++ b/lib/irc/connection.ex
@@ -293,7 +293,7 @@ defmodule IRC.Connection do
else
if !Map.get(user.options, :puppet) do
reply_fun = fn(text) -> irc_reply(state, {chan, sender}, text) end
- account = IRC.Account.lookup(sender)
+ account = Nola.Account.lookup(sender)
message = %IRC.Message{id: FlakeId.get(), transport: :irc, at: NaiveDateTime.utc_now(), text: text, network: state.network,
account: account, sender: sender, channel: chan, replyfun: reply_fun,
trigger: extract_trigger(text)}
@@ -310,7 +310,7 @@ defmodule IRC.Connection do
# Received a private message
def handle_info({:received, text, sender}, state) do
reply_fun = fn(text) -> irc_reply(state, {sender.nick, sender}, text) end
- account = IRC.Account.lookup(sender)
+ account = Nola.Account.lookup(sender)
message = %IRC.Message{id: FlakeId.get(), transport: :irc, text: text, network: state.network, at: NaiveDateTime.utc_now(),
account: account, sender: sender, replyfun: reply_fun, trigger: extract_trigger(text)}
message = case IRC.UserTrack.messaged(message) do
@@ -322,7 +322,7 @@ defmodule IRC.Connection do
end
## -- Broadcast
- def handle_info({:broadcast, net, account = %IRC.Account{}, message}, state) do
+ def handle_info({:broadcast, net, account = %Nola.Account{}, message}, state) do
if net == state.conn.network do
user = IRC.UserTrack.find_by_account(net, account)
if user do
@@ -350,7 +350,7 @@ defmodule IRC.Connection do
priv = if operator, do: [:operator], else: []
# Don't touch -- on WHO the bot joined, not the users.
IRC.UserTrack.joined(channel, who, priv, false)
- account = IRC.Account.lookup(who)
+ account = Nola.Account.lookup(who)
if account do
{:account, who.network, channel, who.nick, account.id}
end
@@ -367,7 +367,7 @@ defmodule IRC.Connection do
def handle_info({:joined, channel, sender}, state) do
IRC.UserTrack.joined(channel, sender, [])
- account = IRC.Account.lookup(sender)
+ account = Nola.Account.lookup(sender)
if account do
dispatch("account", {:account, sender.network, channel, sender.nick, account.id})
end
diff --git a/lib/irc/membership.ex b/lib/irc/membership.ex
index b727dfd..25a0cfc 100644
--- a/lib/irc/membership.ex
+++ b/lib/irc/membership.ex
@@ -19,7 +19,7 @@ defmodule IRC.Membership do
{:ok, dets}
end
- def of_account(%IRC.Account{id: id}) do
+ def of_account(%Nola.Account{id: id}) do
spec = [{{{:"$1", :"$2", :"$3"}, :_}, [{:==, :"$1", {:const, id}}], [{{:"$2", :"$3"}}]}]
:dets.select(dets(), spec)
end
@@ -33,11 +33,11 @@ defmodule IRC.Membership do
end)
end
- def touch(%IRC.Account{id: id}, network, channel) do
+ def touch(%Nola.Account{id: id}, network, channel) do
:dets.insert(dets(), {{id, network, channel}, NaiveDateTime.utc_now()})
end
def touch(account_id, network, channel) do
- if account = IRC.Account.get(account_id) do
+ if account = Nola.Account.get(account_id) do
touch(account, network, channel)
end
end
@@ -91,7 +91,7 @@ defmodule IRC.Membership do
:dets.select(dets(), spec)
end
- def friends(account = %IRC.Account{id: id}) do
+ def friends(account = %Nola.Account{id: id}) do
for({net, chan} <- of_account(account), do: members(net, chan))
|> List.flatten()
|> Enum.uniq()
@@ -116,7 +116,7 @@ defmodule IRC.Membership do
defp expand(network, list) do
for id <- list do
- if account = IRC.Account.get(id) do
+ if account = Nola.Account.get(id) do
user = IRC.UserTrack.find_by_account(network, account)
nick = if(user, do: user.nick, else: account.name)
{account, user, nick}
diff --git a/lib/irc/nola_irc.ex b/lib/irc/nola_irc.ex
index dde99af..2d355d3 100644
--- a/lib/irc/nola_irc.ex
+++ b/lib/irc/nola_irc.ex
@@ -13,7 +13,7 @@ defmodule Nola.IRC do
[
worker(Registry, [[keys: :duplicate, name: IRC.ConnectionPubSub]], id: :registr_irc_conn),
worker(IRC.Membership, []),
- worker(IRC.Account, []),
+ worker(Nola.Account, []),
worker(IRC.UserTrack.Storage, []),
worker(Nola.Plugins.Account, []),
supervisor(Nola.Plugins.Supervisor, [], [name: Nola.Plugins.Supervisor]),
diff --git a/lib/irc/puppet_connection.ex b/lib/irc/puppet_connection.ex
index 91a26b3..fd0a98e 100644
--- a/lib/irc/puppet_connection.ex
+++ b/lib/irc/puppet_connection.ex
@@ -12,7 +12,7 @@ defmodule IRC.PuppetConnection do
DynamicSupervisor.start_link(__MODULE__, [], name: __MODULE__)
end
- def start_child(%IRC.Account{id: account_id}, %IRC.Connection{id: connection_id}) do
+ def start_child(%Nola.Account{id: account_id}, %IRC.Connection{id: connection_id}) do
spec = %{id: {account_id, connection_id}, start: {IRC.PuppetConnection, :start_link, [account_id, connection_id]}, restart: :transient}
DynamicSupervisor.start_child(__MODULE__, spec)
end
@@ -27,7 +27,7 @@ defmodule IRC.PuppetConnection do
end
end
- def whereis(account = %IRC.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}) do
+ def whereis(account = %Nola.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}) do
{:global, name} = name(account_id, connection_id)
case :global.whereis_name(name) do
:undefined -> nil
@@ -35,11 +35,11 @@ defmodule IRC.PuppetConnection do
end
end
- def send_message(account = %IRC.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}, channel, text) do
+ def send_message(account = %Nola.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}, channel, text) do
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
+ def start_and_send_message(account = %Nola.Account{id: account_id}, connection = %IRC.Connection{id: connection_id}, channel, text) do
{:global, name} = name(account_id, connection_id)
pid = whereis(account, connection)
pid = if !pid do
@@ -53,7 +53,7 @@ defmodule IRC.PuppetConnection do
GenServer.cast(pid, {:send_message, self(), channel, text})
end
- def start(account = %IRC.Account{}, connection = %IRC.Connection{}) do
+ def start(account = %Nola.Account{}, connection = %IRC.Connection{}) do
IRC.PuppetConnection.Supervisor.start_child(account, connection)
end
@@ -66,7 +66,7 @@ defmodule IRC.PuppetConnection do
end
def init([account_id, connection_id]) do
- account = %IRC.Account{} = IRC.Account.get(account_id)
+ account = %Nola.Account{} = Nola.Account.get(account_id)
connection = %IRC.Connection{} = IRC.Connection.lookup(connection_id)
Logger.metadata(puppet_conn: account.id <> "@" <> connection.id)
backoff = :backoff.init(@min_backoff, @max_backoff)
@@ -78,7 +78,7 @@ defmodule IRC.PuppetConnection do
def handle_continue(:connect, state) do
#ipv6 = if @env == :prod do
# subnet = Nola.Subnet.assign(state.account_id)
- # IRC.Account.put_meta(IRC.Account.get(state.account_id), "subnet", subnet)
+ # Nola.Account.put_meta(Nola.Account.get(state.account_id), "subnet", subnet)
# ip = Pfx.host(subnet, 1)
# {:ok, ipv6} = :inet_parse.ipv6_address(to_charlist(ip))
# System.cmd("add-ip6", [ip])
@@ -146,7 +146,7 @@ defmodule IRC.PuppetConnection do
ExIRC.Client.msg(state.client, :privmsg, channel, text)
meta = %{puppet: true, from: pid}
- account = IRC.Account.get(state.account_id)
+ account = Nola.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) ->
@@ -219,7 +219,7 @@ defmodule IRC.PuppetConnection do
end
def make_nick(state) do
- account = IRC.Account.get(state.account_id)
+ account = Nola.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
diff --git a/lib/irc/user_track.ex b/lib/irc/user_track.ex
index 1efa523..3f144d5 100644
--- a/lib/irc/user_track.ex
+++ b/lib/irc/user_track.ex
@@ -73,7 +73,7 @@ defmodule IRC.UserTrack do
end
end
- def find_by_account(%IRC.Account{id: id}) do
+ def find_by_account(%Nola.Account{id: id}) do
#iex(15)> :ets.fun2ms(fn(obj = {_, net, acct, _, _, _, _, _, _}) when net == network and acct == account -> obj end)
spec = [
{{:_, :_, :"$2", :_, :_, :_, :_, :_, :_, :_, :_, :_},
@@ -90,7 +90,7 @@ defmodule IRC.UserTrack do
nil
end
- def find_by_account(network, %IRC.Account{id: id}) do
+ def find_by_account(network, %Nola.Account{id: id}) do
#iex(15)> :ets.fun2ms(fn(obj = {_, net, acct, _, _, _, _, _, _}) when net == network and acct == account -> obj end)
spec = [
{{:_, :"$1", :"$2", :_, :_, :_, :_, :_, :_, :_, :_, :_},
@@ -178,7 +178,7 @@ defmodule IRC.UserTrack do
# TODO
def connected(network, nick, user, host, account_id, opts \\ %{}) do
- if account = IRC.Account.get(account_id) do
+ if account = Nola.Account.get(account_id) do
user = if user = find_by_nick(network, nick) do
user
else
@@ -207,7 +207,7 @@ defmodule IRC.UserTrack do
else
user = %User{id: IRC.UserTrack.Id.large_id, network: sender.network, nick: nick, username: uname, host: host, privileges: %{channel => privileges}}
- account = IRC.Account.lookup(user).id
+ account = Nola.Account.lookup(user).id
user = %User{user | account: account}
end
user = touch_struct(user, channel)
@@ -239,10 +239,10 @@ defmodule IRC.UserTrack do
def messaged(%IRC.Message{network: network, account: account, channel: chan, sender: %{nick: nick}} = m) do
{user, account} = if user = find_by_nick(network, nick) do
- {touch_struct(user, chan), account || IRC.Account.lookup(user)}
+ {touch_struct(user, chan), account || Nola.Account.lookup(user)}
else
user = %User{network: network, nick: nick, privileges: %{}}
- account = IRC.Account.lookup(user)
+ account = Nola.Account.lookup(user)
{%User{user | account: account.id}, account}
end
Storage.insert(User.to_tuple(user))
@@ -256,9 +256,9 @@ defmodule IRC.UserTrack do
def renamed(network, old_nick, new_nick) do
if user = find_by_nick(network, old_nick) do
- old_account = IRC.Account.lookup(user)
+ old_account = Nola.Account.lookup(user)
user = %User{user | nick: new_nick, nicks: [old_nick|user.nicks]}
- account = IRC.Account.lookup(user, false) || old_account
+ account = Nola.Account.lookup(user, false) || old_account
user = %User{user | nick: new_nick, account: account.id, nicks: [old_nick|user.nicks]}
Storage.insert(User.to_tuple(user))
channels = for {channel, _} <- user.privileges, do: channel