diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index b123f63..003288d 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -225,6 +225,7 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body, std:: return ; if (irc->has_capability("draft/multiline") + && lines.size() > 1 // /me and /mode cannot be multi lined && lines[0].substr(0, 5) != "/mode" && lines[0].substr(0, 4) != "/me ") @@ -241,13 +242,6 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body, std:: if (id.empty()) id = utils::gen_uuid(); - IrcChannel* channel = irc->get_channel(iid.get_local()); - if (!channel->joined) - { - log_warning("Cannot send message to channel ", iid.get_local(), ", it is not joined"); - return; - } - std::vector messages; for (const std::string& line: lines) { @@ -467,6 +461,41 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::vector lines = utils::split(body, '\n', true); if (lines.empty()) return ; + + if (irc->has_capability("draft/multiline") + && lines.size() > 1 + // /me and /mode cannot be multi lined + && lines[0].substr(0, 5) != "/mode" + && lines[0].substr(0, 4) != "/me ") + { + std::basic_string uuid = utils::gen_uuid(); + std::vector messages; + for (const std::string &line : lines) { + constexpr auto max_username_size = 10; + constexpr auto max_hostname_size = 63; + const auto line_size = 512 - 1 - ::strlen("batch=") - uuid.length() - 1 - + ::strlen("draft/multiline-concat") - 1 - + irc->get_own_nick().size() - max_username_size - + max_hostname_size - ::strlen(":!@ PRIVMSG ") - + iid.get_local().length() - ::strlen(" :\r\n"); + const auto privmsgs = cut(line, line_size); + bool first = true; + for (const auto &privmsg : privmsgs) { + if (first) { + messages.push_back(IrcMessage({}, std::string(), "PRIVMSG", + {iid.get_local(), privmsg})); + first = false; + } else + messages.push_back(IrcMessage({{"draft/multiline-concat", {}}}, + std::string(), "PRIVMSG", + {iid.get_local(), privmsg})); + } + } + irc->send_batch(uuid, "draft/multiline", {iid.get_local()}, messages, + [](const IrcClient *, const IrcMessage &) {}); + return; + } + for (const std::string& line: lines) { if (line.substr(0, 4) == "/me ") diff --git a/tests/end_to_end/scenarios/multiline_message.py b/tests/end_to_end/scenarios/multiline_message.py index e26bc90..1e8ab1a 100644 --- a/tests/end_to_end/scenarios/multiline_message.py +++ b/tests/end_to_end/scenarios/multiline_message.py @@ -52,5 +52,15 @@ scenario = ( ["/message[@from='#foo%{irc_server_one}/{nick_one}'][@id='the-message-id'][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='a\nb\nc']"], ["/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='a\nb\nc']"], - ) + ), + + # Send a multi-line private message, to a in-room JID + send_stanza("a\nb\nc"), + # Message is received with a server-wide JID + expect_stanza("/message[@from='{lower_nick_one}%{irc_server_one}'][@to='{jid_two}'][@type='chat']/body[text()='a\nb\nc']"), + + # Send a multi-line private message, to a server-wide JID + send_stanza("a\nb\nc"), + # Message is received with a server-wide JID + expect_stanza("/message[@from='{lower_nick_one}%{irc_server_one}'][@to='{jid_two}'][@type='chat']/body[text()='a\nb\nc']"), )