diff options
Diffstat (limited to '')
-rw-r--r-- | lib/matrix/room.ex | 161 |
1 files changed, 108 insertions, 53 deletions
diff --git a/lib/matrix/room.ex b/lib/matrix/room.ex index e2965a5..b3921f6 100644 --- a/lib/matrix/room.ex +++ b/lib/matrix/room.ex @@ -12,7 +12,12 @@ defmodule Nola.Matrix.Room do end def start_child(room_id) do - spec = %{id: room_id, start: {Nola.Matrix.Room, :start_link, [room_id]}, restart: :transient} + spec = %{ + id: room_id, + start: {Nola.Matrix.Room, :start_link, [room_id]}, + restart: :transient + } + DynamicSupervisor.start_child(__MODULE__, spec) end @@ -35,20 +40,23 @@ defmodule Nola.Matrix.Room do 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 + 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 - 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 @@ -65,45 +73,62 @@ defmodule Nola.Matrix.Room do Logger.metadata(matrix_room: room_id) {:ok, _} = Registry.register(Nola.PubSub, "#{state.network}:events", plugin: __MODULE__) + for t <- ["messages", "triggers", "outputs", "events"] do - {:ok, _} = Registry.register(Nola.PubSub, "#{state.network}/#{state.channel}:#{t}", plugin: __MODULE__) + {:ok, _} = + Registry.register(Nola.PubSub, "#{state.network}/#{state.channel}:#{t}", + plugin: __MODULE__ + ) end - state = state - |> Map.put(:id, room_id) + 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}") + 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] + + 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 Nola.Memberships ? + acc + end else - # XXX: The user left, remove from Nola.Memberships ? acc end - else - acc - end - end) - |> Enum.filter(& &1) - - for m <- members, do: Nola.UserTrack.joined(state.id, %{network: "matrix", nick: m, user: m, host: "matrix."}, [], true) - - accounts = Nola.UserTrack.channel(state.network, state.channel) - |> Enum.filter(& &1) - |> Enum.map(fn(tuple) -> Nola.UserTrack.User.from_tuple(tuple).account end) - |> Enum.uniq() - |> Enum.each(fn(account_id) -> - introduce_irc_account(account_id, state) - end) + end) + |> Enum.filter(& &1) + + for m <- members, + do: + Nola.UserTrack.joined( + state.id, + %{network: "matrix", nick: m, user: m, host: "matrix."}, + [], + true + ) + + accounts = + Nola.UserTrack.channel(state.network, state.channel) + |> Enum.filter(& &1) + |> Enum.map(fn tuple -> Nola.UserTrack.User.from_tuple(tuple).account end) + |> Enum.uniq() + |> Enum.each(fn account_id -> + introduce_irc_account(account_id, state) + end) {:noreply, state} end @@ -112,6 +137,7 @@ defmodule Nola.Matrix.Room do 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} @@ -122,14 +148,17 @@ defmodule Nola.Matrix.Room do def handle_irc(message = %Nola.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) + 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 @@ -138,36 +167,56 @@ defmodule Nola.Matrix.Room do {:noreply, state} end - def handle_irc(%{type: quit_or_part, account_id: account_id}, state) when quit_or_part in [:quit, :part] do + 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}") + 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 + def handle_matrix( + event = %{type: "m.room.member", user_id: user_id, content: %{"membership" => "join"}}, + state + ) do _account = get_account(event, state) - Nola.UserTrack.joined(state.id, %{network: "matrix", nick: user_id, user: user_id, host: "matrix."}, [], true) + + Nola.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 + def handle_matrix( + event = %{type: "m.room.member", user_id: user_id, content: %{"membership" => "leave"}}, + state + ) do Nola.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 + def handle_matrix( + event = %{ + type: "m.room.message", + user_id: user_id, + content: %{"msgtype" => "m.text", "body" => text} + }, + state + ) do Nola.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}") + Logger.warn("Skipped matrix event #{inspect(event)}") {:noreply, state} end @@ -180,17 +229,23 @@ defmodule Nola.Matrix.Room do account = Nola.Account.get(account_id) user = Nola.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 + :ok -> + :ok + error -> - Logger.warn("Failed to update profile for #{mxid}: #{inspect 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 + {:ok, _} -> + :ok + error -> - Logger.warn("Failed to join room for #{mxid}: #{inspect error}") + Logger.warn("Failed to join room for #{mxid}: #{inspect(error)}") end + :ok end - end |