diff --git a/lib/irc/handler.ex b/lib/irc/handler.ex index d1aadbc..16aac76 100644 --- a/lib/irc/handler.ex +++ b/lib/irc/handler.ex @@ -1072,10 +1072,9 @@ defmodule M51.IrcConn.Handler do fn _room_id, room -> commands = room.members - |> Stream.map(fn {user_id, _member} -> + |> Stream.map(fn {user_id, member} -> [local_name, hostname] = String.split(user_id, ":", parts: 2) - # TODO: pick the most common display name of the user instead - gecos = user_id + gecos = member.display_name || user_id # RPL_WHOREPLY make_numeric.("352", [ target, @@ -1097,9 +1096,9 @@ defmodule M51.IrcConn.Handler do else # target is a nick [local_name, hostname] = String.split(target, ":", parts: 2) + display_name = M51.MatrixClient.State.user_display_name(matrix_state, target) - # TODO: pick the most common display name instead - gecos = target + gecos = display_name send_batch.( [ @@ -1133,10 +1132,10 @@ defmodule M51.IrcConn.Handler do end [local_name, hostname] -> - [member: memberships] = M51.MatrixClient.State.user(matrix_state, target) + memberships = M51.MatrixClient.State.user_memberships(matrix_state, target) + display_name = M51.MatrixClient.State.user_display_name(matrix_state, target) - # TODO: pick the most common display name instead - gecos = target + gecos = display_name overhead = make_numeric.("353", [target, ""]) |> M51.Irc.Command.format() |> byte_size() @@ -1148,7 +1147,6 @@ defmodule M51.IrcConn.Handler do channel_commands = memberships - |> Map.keys() |> Enum.map(fn room_id -> M51.MatrixClient.State.room_irc_channel(matrix_state, room_id) end) diff --git a/lib/matrix_client/state.ex b/lib/matrix_client/state.ex index 58d8334..4a35cce 100644 --- a/lib/matrix_client/state.ex +++ b/lib/matrix_client/state.ex @@ -95,7 +95,8 @@ defmodule M51.MatrixClient.State do room = Map.get(state.rooms, room_id, @emptyroom) if Map.has_key?(room.members, userid) do - {true, state} + # User may have changed their display-name, so update the member list + {true, update_in(state.rooms[room_id].members[userid], fn _ -> member end)} else room = %{room | members: Map.put(room.members, userid, member)} {false, %{state | rooms: Map.put(state.rooms, room_id, room)}} @@ -120,18 +121,32 @@ defmodule M51.MatrixClient.State do end @doc """ - Returns [member: %{room_id => %M51.Matrix.RoomMember{...}}] + Returns the user's current display name. This is the same across all rooms + they're in, but not guaranteed to be unique vs. other users. + + If the user has no known display name (i.e. membership set is empty), just + returns the userid. + """ + def user_display_name(pid, user_id) do + Agent.get(pid, fn state -> + state.rooms + |> Stream.filter(fn {_room_id, room} -> Map.has_key?(room.members, user_id) end) + |> Stream.map(fn {_room_id, room} -> room.members[user_id].display_name end) + # Matrix display names are per-user, so we just pick an arbitrary channel + # that they're in and fish it out of the userlist. + # TODO: store a user_id to user info map separately from the channels? + |> Enum.at(0, user_id) + end) + end + + @doc """ + Returns a list of room_ids that the user is a member in. """ - def user(pid, user_id) do + def user_memberships(pid, user_id) do Agent.get(pid, fn state -> - [ - member: - state.rooms - |> Map.to_list() - |> Enum.map(fn {room_id, room} -> {room_id, Map.get(room.members, user_id)} end) - |> Enum.filter(fn {_room_id, member} -> member != nil end) - |> Map.new() - ] + state.rooms + |> Enum.filter(fn {_room_id, room} -> Map.has_key?(room.members, user_id) end) + |> Enum.map(fn {room_id, _room} -> room_id end) end) end diff --git a/test/irc/handler_test.exs b/test/irc/handler_test.exs index 4c33d21..9dbd041 100644 --- a/test/irc/handler_test.exs +++ b/test/irc/handler_test.exs @@ -762,7 +762,7 @@ defmodule M51.IrcConn.HandlerTest do assert line == "@label=l2 BATCH +#{batch_id} :labeled-response\r\n" assert_line( - "@batch=#{batch_id} :server. 352 foo:example.org #existing_room:example.org user1 example.org * user1:example.org H :0 user1:example.org\r\n" + "@batch=#{batch_id} :server. 352 foo:example.org #existing_room:example.org user1 example.org * user1:example.org H :0 user one\r\n" ) assert_line( @@ -788,7 +788,7 @@ defmodule M51.IrcConn.HandlerTest do send(handler, cmd("WHO #existing_room:example.org")) assert_line( - ":server. 352 foo:example.org #existing_room:example.org user1 example.org * user1:example.org H :0 user1:example.org\r\n" + ":server. 352 foo:example.org #existing_room:example.org user1 example.org * user1:example.org H :0 user one\r\n" ) assert_line( @@ -826,7 +826,7 @@ defmodule M51.IrcConn.HandlerTest do assert line == "@label=l1 BATCH +#{batch_id} :labeled-response\r\n" assert_line( - "@batch=#{batch_id} :server. 311 foo:example.org user1:example.org user1 example.org * :user1:example.org\r\n" + "@batch=#{batch_id} :server. 311 foo:example.org user1:example.org user1 example.org * :user one\r\n" ) assert_line(