Skip to content

Commit

Permalink
Implement draft/no-implicit-names
Browse files Browse the repository at this point in the history
  • Loading branch information
progval committed Aug 14, 2023
1 parent 6cec824 commit 5a92f46
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 26 deletions.
3 changes: 3 additions & 0 deletions lib/irc/handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ defmodule M51.IrcConn.Handler do
# https://github.com/progval/ircv3-specifications/blob/redaction/extensions/message-redaction.md
"draft/message-redaction" => {:message_redaction, nil},

# https://github.com/ircv3/ircv3-specifications/pull/527
"draft/no-implicit-names" => {:no_implicit_names, nil},

# https://ircv3.net/specs/extensions/sasl-3.1
"sasl" => {:sasl, "PLAIN"},

Expand Down
52 changes: 28 additions & 24 deletions lib/matrix_client/poller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,7 @@ defmodule M51.MatrixClient.Poller do
state = M51.IrcConn.Supervisor.matrix_state(sup_pid)
nick = M51.IrcConn.State.nick(irc_state)
channel = M51.MatrixClient.State.room_irc_channel(state, room_id)
capabilities = M51.IrcConn.State.capabilities(irc_state)
send_join = make_send_function(sup_pid, event, write)
send_nonjoin = make_send_function(sup_pid, nil, write)

Expand Down Expand Up @@ -1265,31 +1266,34 @@ defmodule M51.MatrixClient.Poller do
end
end

# send RPL_NAMREPLY
overhead = make_numeric.("353", ["=", channel, ""]) |> M51.Irc.Command.format() |> byte_size()

# note for later: if we ever implement prefixes, make sure to add them
# *after* calling nick2nuh; we don't want to have prefixes in the username part.
M51.MatrixClient.State.room_members(state, room_id)
|> Enum.map(fn {user_id, _member} ->
nuh = nick2nuh(user_id)
# M51.Irc.Command does not escape " " in trailing
String.replace(nuh, " ", "\\s") <> " "
end)
|> Enum.sort()
|> M51.Irc.WordWrap.join_tokens(512 - overhead)
|> Enum.map(fn line ->
line = line |> String.trim_trailing()

if line != "" do
# RPL_NAMREPLY
send_numeric.("353", ["=", channel, line])
end
end)
|> Enum.filter(fn line -> line != nil end)
if !Enum.member?(capabilities, :no_implicit_names) do
# send RPL_NAMREPLY
overhead =
make_numeric.("353", ["=", channel, ""]) |> M51.Irc.Command.format() |> byte_size()

# note for later: if we ever implement prefixes, make sure to add them
# *after* calling nick2nuh; we don't want to have prefixes in the username part.
M51.MatrixClient.State.room_members(state, room_id)
|> Enum.map(fn {user_id, _member} ->
nuh = nick2nuh(user_id)
# M51.Irc.Command does not escape " " in trailing
String.replace(nuh, " ", "\\s") <> " "
end)
|> Enum.sort()
|> M51.Irc.WordWrap.join_tokens(512 - overhead)
|> Enum.map(fn line ->
line = line |> String.trim_trailing()

if line != "" do
# RPL_NAMREPLY
send_numeric.("353", ["=", channel, line])
end
end)
|> Enum.filter(fn line -> line != nil end)

# RPL_ENDOFNAMES
send_numeric.("366", [channel, "End of /NAMES list"])
# RPL_ENDOFNAMES
send_numeric.("366", [channel, "End of /NAMES list"])
end
end

defp close_renamed_channel(
Expand Down
4 changes: 2 additions & 2 deletions test/irc/handler_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ defmodule M51.IrcConn.HandlerTest do
use ExUnit.Case, async: false
doctest M51.IrcConn.Handler

@cap_ls_302 ":server. CAP * LS :account-tag batch draft/account-registration=before-connect draft/channel-rename draft/chathistory draft/message-redaction draft/multiline=max-bytes=8192 draft/sasl-ir echo-message extended-join labeled-response message-tags sasl=PLAIN server-time soju.im/account-required standard-replies userhost-in-names\r\n"
@cap_ls ":server. CAP * LS :account-tag batch draft/account-registration draft/channel-rename draft/chathistory draft/message-redaction draft/multiline draft/sasl-ir echo-message extended-join labeled-response message-tags sasl server-time soju.im/account-required standard-replies userhost-in-names\r\n"
@cap_ls_302 ":server. CAP * LS :account-tag batch draft/account-registration=before-connect draft/channel-rename draft/chathistory draft/message-redaction draft/multiline=max-bytes=8192 draft/no-implicit-names draft/sasl-ir echo-message extended-join labeled-response message-tags sasl=PLAIN server-time soju.im/account-required standard-replies userhost-in-names\r\n"
@cap_ls ":server. CAP * LS :account-tag batch draft/account-registration draft/channel-rename draft/chathistory draft/message-redaction draft/multiline draft/no-implicit-names draft/sasl-ir echo-message extended-join labeled-response message-tags sasl server-time soju.im/account-required standard-replies userhost-in-names\r\n"
@isupport "CASEMAPPING=rfc3454 CLIENTTAGDENY=*,-draft/react,-draft/reply CHANLIMIT= CHANTYPES=#! CHATHISTORY=100 MAXTARGETS=1 MSGREFTYPES=msgid PREFIX= TARGMAX=JOIN:1,PART:1 UTF8ONLY :are supported by this server\r\n"

setup do
Expand Down
59 changes: 59 additions & 0 deletions test/matrix_client/poller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,65 @@ defmodule M51.MatrixClient.PollerTest do
end
end)

test "new room with draft/no-implicit-names" do
M51.IrcConn.State.add_capabilities(:process_ircconn_state, [
:no_implicit_names,
])

state_events1 = [
%{
"content" => %{"alias" => "#test1:example.org"},
"event_id" => "$event1",
"origin_server_ts" => 1_632_644_251_623,
"sender" => "@nick:example.org",
"state_key" => "",
"type" => "m.room.canonical_alias",
"unsigned" => %{}
}
]

state_events2 = [
%{
"content" => %{"alias" => "#test2:example.org"},
"event_id" => "$event2",
"origin_server_ts" => 1_632_644_251_623,
"sender" => "@nick:example.org",
"state_key" => "",
"type" => "m.room.canonical_alias",
"unsigned" => %{}
}
]

M51.MatrixClient.Poller.handle_events(self(), true, %{
"rooms" => %{
"join" => %{
"!testid1:example.org" => %{"state" => %{"events" => state_events1}}
}
}
})

assert_line(":mynick:example.com!mynick@example.com JOIN :#test1:example.org\r\n")
assert_line(":server. 331 mynick:example.com #test1:example.org :No topic is set\r\n")

assert_last_line()

# Need to send more messages from the poller to make sure there really isn't any
# message left

M51.MatrixClient.Poller.handle_events(self(), true, %{
"rooms" => %{
"join" => %{
"!testid2:example.org" => %{"state" => %{"events" => state_events2}}
}
}
})

assert_line(":mynick:example.com!mynick@example.com JOIN :#test2:example.org\r\n")
assert_line(":server. 331 mynick:example.com #test2:example.org :No topic is set\r\n")

assert_last_line()
end

test "invalid room renaming" do
M51.IrcConn.State.add_capabilities(:process_ircconn_state, [
:channel_rename,
Expand Down

0 comments on commit 5a92f46

Please sign in to comment.