diff options
author | Jordan Bracco <href@random.sh> | 2022-12-20 00:21:54 +0000 |
---|---|---|
committer | Jordan Bracco <href@random.sh> | 2022-12-20 19:29:41 +0100 |
commit | 2d83df8b32bff7f0028923bb5b64dc0b55f20d03 (patch) | |
tree | 1207e67b5b15f540963db05e7be89f3ca950e724 /lib/lsg_matrix | |
parent | Nola rename, the end. pt 6. Refs T77. (diff) |
Nola rename: The Big Move, Refs T77
Diffstat (limited to 'lib/lsg_matrix')
-rw-r--r-- | lib/lsg_matrix/matrix.ex | 169 | ||||
-rw-r--r-- | lib/lsg_matrix/plug.ex | 25 | ||||
-rw-r--r-- | lib/lsg_matrix/room.ex | 196 |
3 files changed, 0 insertions, 390 deletions
diff --git a/lib/lsg_matrix/matrix.ex b/lib/lsg_matrix/matrix.ex deleted file mode 100644 index 9334816..0000000 --- a/lib/lsg_matrix/matrix.ex +++ /dev/null @@ -1,169 +0,0 @@ -defmodule Nola.Matrix do - require Logger - alias Polyjuice.Client - - @behaviour MatrixAppService.Adapter.Room - @behaviour MatrixAppService.Adapter.Transaction - @behaviour MatrixAppService.Adapter.User - @env Mix.env - - def dets(part) do - (Nola.data_path() <> "/matrix-#{to_string(part)}.dets") |> String.to_charlist() - end - - def setup() do - {:ok, _} = :dets.open_file(dets(:rooms), []) - {:ok, _} = :dets.open_file(dets(:room_aliases), []) - {:ok, _} = :dets.open_file(dets(:users), []) - :ok - end - - def myself?("@_dev:random.sh"), do: true - def myself?("@_bot:random.sh"), do: true - def myself?("@_dev."<>_), do: true - def myself?("@_bot."<>_), do: true - def myself?(_), do: false - - def mxc_to_http(mxc = "mxc://"<>_) do - uri = URI.parse(mxc) - %URI{uri | scheme: "https", path: "/_matrix/media/r0/download/#{uri.authority}#{uri.path}"} - |> URI.to_string() - end - - def get_or_create_matrix_user(id) do - if mxid = lookup_user(id) do - mxid - else - opts = [ - type: "m.login.application_service", - inhibit_login: true, - device_id: "APP_SERVICE", - initial_device_display_name: "Application Service", - username: if(@env == :dev, do: "_dev.#{id}", else: "_bot.#{id}") - ] - Logger.debug("Registering user for #{id}") - {:ok, %{"user_id" => mxid}} = Polyjuice.Client.LowLevel.register(client(), opts) - :dets.insert(dets(:users), {id, mxid}) - end - end - - def lookup_user(id) do - case :dets.lookup(dets(:users), id) do - [{_, matrix_id}] -> matrix_id - _ -> nil - end - end - - def user_name("@"<>name) do - [username, _] = String.split(name, ":", parts: 2) - username - end - - def application_childs() do - import Supervisor.Spec - [ - supervisor(Nola.Matrix.Room.Supervisor, [], [name: IRC.PuppetConnection.Supervisor]), - ] - end - - def after_start() do - rooms = :dets.foldl(fn({id, _, _, _}, acc) -> [id | acc] end, [], dets(:rooms)) - for room <- rooms, do: Nola.Matrix.Room.start(room) - end - - def lookup_room(room) do - case :dets.lookup(dets(:rooms), room) do - [{_, network, channel, opts}] -> {:ok, Map.merge(opts, %{network: network, channel: channel})} - _ -> {:error, :no_such_room} - end - end - - def lookup_room_alias(room_alias) do - case :dets.lookup(dets(:room_aliases), room_alias) do - [{_, room_id}] -> {:ok, room_id} - _ -> {:error, :no_such_room_alias} - end - end - - def lookup_or_create_room(room_alias) do - case lookup_room_alias(room_alias) do - {:ok, room_id} -> {:ok, room_id} - {:error, :no_such_room_alias} -> create_room(room_alias) - end - end - - def create_room(room_alias) do - Logger.debug("Matrix: creating room #{inspect room_alias}") - localpart = localpart(room_alias) - with {:ok, network, channel} <- extract_network_channel_from_localpart(localpart), - %IRC.Connection{} <- IRC.Connection.get_network(network, channel), - room = [visibility: :public, room_alias_name: localpart, name: if(network == "random", do: channel, else: "#{network}/#{channel}")], - {:ok, %{"room_id" => room_id}} <- Client.Room.create_room(client(), room) do - Logger.info("Matrix: created room #{room_alias} #{room_id}") - :dets.insert(dets(:rooms), {room_id, network, channel, %{}}) - :dets.insert(dets(:room_aliases), {room_alias, room_id}) - {:ok, room_id} - else - nil -> {:error, :no_such_network_channel} - error -> error - end - end - - def localpart(room_alias) do - [<<"#", localpart :: binary>>, _] = String.split(room_alias, ":", parts: 2) - localpart - end - - def extract_network_channel_from_localpart(localpart) do - s = localpart - |> String.replace("dev.", "") - |> String.split("/", parts: 2) - - case s do - [network, channel] -> {:ok, network, channel} - [channel] -> {:ok, "random", channel} - _ -> {:error, :invalid_localpart} - end - end - - @impl MatrixAppService.Adapter.Room - def query_alias(room_alias) do - case lookup_or_create_room(room_alias) do - {:ok, room_id} -> - Nola.Matrix.Room.start(room_id) - :ok - error -> error - end - end - - @impl MatrixAppService.Adapter.Transaction - def new_event(event = %MatrixAppService.Event{}) do - Logger.debug("New matrix event: #{inspect event}") - if event.room_id do - Nola.Matrix.Room.start_and_send_matrix_event(event.room_id, event) - end - :noop - end - - @impl MatrixAppService.Adapter.User - def query_user(user_id) do - Logger.warn("Matrix lookup user: #{inspect user_id}") - :error - end - - def client(opts \\ []) do - base_url = Application.get_env(:matrix_app_service, :base_url) - access_token = Application.get_env(:matrix_app_service, :access_token) - default_opts = [ - access_token: access_token, - device_id: "APP_SERVICE", - application_service: true, - user_id: nil - ] - opts = Keyword.merge(default_opts, opts) - - Polyjuice.Client.LowLevel.create(base_url, opts) - end - - -end diff --git a/lib/lsg_matrix/plug.ex b/lib/lsg_matrix/plug.ex deleted file mode 100644 index c64ed11..0000000 --- a/lib/lsg_matrix/plug.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule Nola.Matrix.Plug do - - defmodule Auth do - def init(state) do - state - end - - def call(conn, _) do - hs = Application.get_env(:matrix_app_service, :homeserver_token) - MatrixAppServiceWeb.AuthPlug.call(conn, hs) - end - end - - defmodule SetConfig do - def init(state) do - state - end - - def call(conn, _) do - config = Application.get_all_env(:matrix_app_service) - MatrixAppServiceWeb.SetConfigPlug.call(conn, config) - end - end - -end diff --git a/lib/lsg_matrix/room.ex b/lib/lsg_matrix/room.ex deleted file mode 100644 index c790760..0000000 --- a/lib/lsg_matrix/room.ex +++ /dev/null @@ -1,196 +0,0 @@ -defmodule Nola.Matrix.Room do - require Logger - alias Nola.Matrix - alias Polyjuice.Client - import Matrix, only: [client: 0, client: 1, user_name: 1, myself?: 1] - - defmodule Supervisor do - use DynamicSupervisor - - def start_link() do - DynamicSupervisor.start_link(__MODULE__, [], name: __MODULE__) - end - - def start_child(room_id) do - spec = %{id: room_id, start: {Nola.Matrix.Room, :start_link, [room_id]}, restart: :transient} - DynamicSupervisor.start_child(__MODULE__, spec) - end - - @impl true - def init(_init_arg) do - DynamicSupervisor.init( - strategy: :one_for_one, - max_restarts: 10, - max_seconds: 1 - ) - end - end - - def start(room_id) do - __MODULE__.Supervisor.start_child(room_id) - end - - def start_link(room_id) do - GenServer.start_link(__MODULE__, [room_id], name: name(room_id)) - end - - def start_and_send_matrix_event(room_id, event) do - pid = if pid = whereis(room_id) do - pid - else - case __MODULE__.start(room_id) do - {:ok, pid} -> pid - {:error, {:already_started, pid}} -> pid - :ignore -> nil - end - end - if(pid, do: send(pid, {:matrix_event, event})) - end - - def whereis(room_id) do - {:global, name} = name(room_id) - case :global.whereis_name(name) do - :undefined -> nil - pid -> pid - end - end - - def name(room_id) do - {:global, {__MODULE__, room_id}} - end - - def init([room_id]) do - case Matrix.lookup_room(room_id) do - {:ok, state} -> - Logger.metadata(matrix_room: room_id) - - {:ok, _} = Registry.register(IRC.PubSub, "#{state.network}:events", plugin: __MODULE__) - for t <- ["messages", "triggers", "outputs", "events"] do - {:ok, _} = Registry.register(IRC.PubSub, "#{state.network}/#{state.channel}:#{t}", plugin: __MODULE__) - end - - state = state - |> Map.put(:id, room_id) - Logger.info("Started Matrix room #{room_id}") - {:ok, state, {:continue, :update_state}} - error -> - Logger.info("Received event for nonexistent room #{inspect room_id}: #{inspect error}") - :ignore - end - end - - def handle_continue(:update_state, state) do - {:ok, s} = Client.Room.get_state(client(), state.id) - members = Enum.reduce(s, [], fn(s, acc) -> - if s["type"] == "m.room.member" do - if s["content"]["membership"] == "join" do - [s["user_id"] | acc] - else - # XXX: The user left, remove from IRC.Memberships ? - acc - end - else - acc - end - end) - |> Enum.filter(& &1) - - for m <- members, do: IRC.UserTrack.joined(state.id, %{network: "matrix", nick: m, user: m, host: "matrix."}, [], true) - - accounts = IRC.UserTrack.channel(state.network, state.channel) - |> Enum.filter(& &1) - |> Enum.map(fn(tuple) -> IRC.UserTrack.User.from_tuple(tuple).account end) - |> Enum.uniq() - |> Enum.each(fn(account_id) -> - introduce_irc_account(account_id, state) - end) - - {:noreply, state} - end - - def handle_info({:irc, :text, message}, state), do: handle_irc(message, state) - def handle_info({:irc, :out, message}, state), do: handle_irc(message, state) - def handle_info({:irc, :trigger, _, message}, state), do: handle_irc(message, state) - def handle_info({:irc, :event, event}, state), do: handle_irc(event, state) - def handle_info({:matrix_event, event}, state) do - if myself?(event.user_id) do - {:noreply, state} - else - handle_matrix(event, state) - end - end - - def handle_irc(message = %IRC.Message{account: account}, state) do - unless Map.get(message.meta, :puppet) && Map.get(message.meta, :from) == self() do - opts = if Map.get(message.meta, :self) || is_nil(account) do - [] - else - mxid = Matrix.get_or_create_matrix_user(account.id) - [user_id: mxid] - end - Client.Room.send_message(client(opts),state.id, message.text) - end - {:noreply, state} - end - - def handle_irc(%{type: :join, account_id: account_id}, state) do - introduce_irc_account(account_id, state) - {:noreply, state} - end - - def handle_irc(%{type: quit_or_part, account_id: account_id}, state) when quit_or_part in [:quit, :part] do - mxid = Matrix.get_or_create_matrix_user(account_id) - Client.Room.leave(client(user_id: mxid), state.id) - {:noreply, state} - end - - - def handle_irc(event, state) do - Logger.warn("Skipped irc event #{inspect event}") - {:noreply, state} - end - - def handle_matrix(event = %{type: "m.room.member", user_id: user_id, content: %{"membership" => "join"}}, state) do - _account = get_account(event, state) - IRC.UserTrack.joined(state.id, %{network: "matrix", nick: user_id, user: user_id, host: "matrix."}, [], true) - {:noreply, state} - end - - def handle_matrix(event = %{type: "m.room.member", user_id: user_id, content: %{"membership" => "leave"}}, state) do - IRC.UserTrack.parted(state.id, %{network: "matrix", nick: user_id}) - {:noreply, state} - end - - def handle_matrix(event = %{type: "m.room.message", user_id: user_id, content: %{"msgtype" => "m.text", "body" => text}}, state) do - IRC.send_message_as(get_account(event, state), state.network, state.channel, text, true) - {:noreply, state} - end - - def handle_matrix(event, state) do - Logger.warn("Skipped matrix event #{inspect event}") - {:noreply, state} - end - - def get_account(%{user_id: user_id}, %{id: id}) do - IRC.Account.find_by_nick("matrix", user_id) - end - - defp introduce_irc_account(account_id, state) do - mxid = Matrix.get_or_create_matrix_user(account_id) - account = IRC.Account.get(account_id) - user = IRC.UserTrack.find_by_account(state.network, account) - base_nick = if(user, do: user.nick, else: account.name) - case Client.Profile.put_displayname(client(user_id: mxid), base_nick) do - :ok -> :ok - error -> - Logger.warn("Failed to update profile for #{mxid}: #{inspect error}") - end - case Client.Room.join(client(user_id: mxid), state.id) do - {:ok, _} -> :ok - error -> - Logger.warn("Failed to join room for #{mxid}: #{inspect error}") - end - :ok - end - -end |