Skip to content

Track display names and include them in WHOIS and WHO #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions lib/irc/handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.(
[
Expand Down Expand Up @@ -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()
Expand All @@ -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)
Expand Down
37 changes: 26 additions & 11 deletions lib/matrix_client/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)}}
Expand All @@ -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

Expand Down
6 changes: 3 additions & 3 deletions test/irc/handler_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand Down