From 0d2dd71de5292895f69d5f08b000e03e928bdd34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 8 Aug 2016 20:49:00 +0200 Subject: =?UTF-8?q?Don=E2=80=99t=20use=20!=20as=20the=20separator=20for=20?= =?UTF-8?q?nicknames,=20use=20%=20instead?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s now easier to use. The distinction between a nick and a channel name is based on the first character (by default it's '#' and '&'). The user doesn’t have to worry about which separator to use anymore. fix #3066 --- src/bridge/bridge.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 17d3ec6..ac61dbc 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -133,7 +133,7 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) } } -IrcClient* Bridge::find_irc_client(const std::string& hostname) +IrcClient* Bridge::find_irc_client(const std::string& hostname) const { try { @@ -470,7 +470,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s const std::string& iq_id, const std::string& to_jid, const std::string& from_jid) { - Iid iid(nick + "!" + irc_hostname); + Iid iid(nick, irc_hostname, Iid::Type::User); this->send_private_message(iid, "\01PING " + iq_id + "\01"); irc_responder_callback_t cb = [this, nick=utils::tolower(nick), iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool @@ -541,7 +541,7 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std const std::string& iq_id, const std::string& to_jid, const std::string& from_jid) { - Iid iid(target + "!" + irc_hostname); + Iid iid(target, irc_hostname, Iid::Type::User); this->send_private_message(iid, "\01VERSION\01"); // TODO, add a timer to remove that waiting iq if the server does not // respond with a matching command before n seconds @@ -590,7 +590,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st const auto it = this->preferred_user_from.find(iid.get_local()); if (it != this->preferred_user_from.end()) { - const auto chan_name = Iid(Jid(it->second).local).get_local(); + const auto chan_name = Iid(Jid(it->second).local, {}).get_local(); for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, iid.get_server()}]) this->xmpp.send_message(it->second, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource, "chat", true); @@ -653,7 +653,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho else body = msg; - const auto encoding = in_encoding_for(*this, {from}); + const auto encoding = in_encoding_for(*this, {from, this}); for (const auto& resource: this->resources_in_server[from]) { this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource, "chat"); @@ -696,7 +696,7 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam { std::string encoded_chan_name(chan_name); xep0106::encode(encoded_chan_name); - const auto encoding = in_encoding_for(*this, {encoded_chan_name + '%' + hostname}); + const auto encoding = in_encoding_for(*this, {encoded_chan_name, hostname, Iid::Type::Channel}); this->xmpp.send_topic(encoded_chan_name + utils::empty_if_fixed_server( "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid + "/" + resource, who); @@ -741,7 +741,7 @@ void Bridge::send_iq_version_request(const std::string& nick, const std::string& { const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_iq_version_request(utils::tolower(nick) + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); + this->xmpp.send_iq_version_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, @@ -753,7 +753,7 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Forward to the first resource (arbitrary, based on the “order” of the std::set) only const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_ping_request(utils::tolower(nick) + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); + this->xmpp.send_ping_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); } void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) @@ -776,7 +776,7 @@ void Bridge::remove_all_preferred_from_jid_of_room(const std::string& channel_na { for (auto it = this->preferred_user_from.begin(); it != this->preferred_user_from.end();) { - Iid iid(Jid(it->second).local); + Iid iid(Jid(it->second).local, {}); if (iid.get_local() == channel_name) it = this->preferred_user_from.erase(it); else @@ -806,6 +806,14 @@ std::unordered_map>& Bridge::get_irc_cli return this->irc_clients; } +std::set Bridge::get_chantypes(const std::string& hostname) const +{ + IrcClient* irc = this->find_irc_client(hostname); + if (!irc) + return {'#', '&'}; + return irc->get_chantypes(); +} + void Bridge::add_resource_to_chan(const Bridge::ChannelKey& channel, const std::string& resource) { auto it = this->resources_in_chan.find(channel); -- cgit v1.2.3 From 8ec823be4fc587abb7282a06a12f9df9c37810d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 12 Aug 2016 16:39:19 +0200 Subject: Save received and sent messages into the database --- src/bridge/bridge.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ac61dbc..1812611 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -224,6 +224,11 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01"); else irc->send_channel_message(iid.get_local(), line); + + const auto xmpp_body = this->make_xmpp_body(line); + Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), + std::get<0>(xmpp_body), irc->get_own_nick()); + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), this->user_jid + "/" + resource); @@ -578,10 +583,15 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st const auto encoding = in_encoding_for(*this, iid); if (muc) { + const auto xmpp_body = this->make_xmpp_body(body, encoding); + Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), + std::get<0>(xmpp_body), nick); + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) { this->xmpp.send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource); + } } else -- cgit v1.2.3 From 787563722c36bc63223655d337d98caac82dc44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sat, 13 Aug 2016 01:46:11 +0200 Subject: Only save the messages into the db if we are actually using a db --- src/bridge/bridge.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 1812611..23fc71d 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -225,10 +225,11 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) else irc->send_channel_message(iid.get_local(), line); +#ifdef USE_DATABASE const auto xmpp_body = this->make_xmpp_body(line); Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), std::get<0>(xmpp_body), irc->get_own_nick()); - +#endif for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), this->user_jid + "/" + resource); @@ -583,10 +584,11 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st const auto encoding = in_encoding_for(*this, iid); if (muc) { +#ifdef USE_DATABASE const auto xmpp_body = this->make_xmpp_body(body, encoding); Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), std::get<0>(xmpp_body), nick); - +#endif for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) { this->xmpp.send_muc_message(std::to_string(iid), nick, -- cgit v1.2.3 From 663d4ad54a014b2ced62610098a6f5676f813d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 16 Aug 2016 15:59:00 +0200 Subject: Forward mediated invitations (XMPP to IRC only) --- src/bridge/bridge.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 23fc71d..8323c77 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -543,6 +543,22 @@ void Bridge::on_gateway_ping(const std::string& irc_hostname, const std::string& "", true); } +void Bridge::send_irc_invitation(const Iid& iid, const std::string to) +{ + IrcClient* irc = this->get_irc_client(iid.get_server()); + Jid to_jid(to); + std::string target_nick; + // Many ways to address a nick: + // A jid (ANY jid…) with a resource + if (!to_jid.resource.empty()) + target_nick = to_jid.resource; + else if (!to_jid.local.empty()) // A jid with a iid with a local part + target_nick = Iid(to_jid.local, {}).get_local(); + else + target_nick = to; // Not a jid, just the nick + irc->send_invitation(iid.get_local(), target_nick); +} + void Bridge::send_irc_version_request(const std::string& irc_hostname, const std::string& target, const std::string& iq_id, const std::string& to_jid, const std::string& from_jid) -- cgit v1.2.3 From 5406de35a39c935a19460da06bf3dcd3948a00d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 17 Aug 2016 20:44:00 +0200 Subject: On a client error, do not QUIT, just make the resource leave all channels This should fix #3205 --- src/bridge/bridge.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 8323c77..f6fefd9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -60,6 +60,20 @@ void Bridge::shutdown(const std::string& exit_message) } } +void Bridge::remove_resource(const std::string& resource, + const std::string& part_message) +{ + const auto resources_in_chan_copy = this->resources_in_chan; + for (const auto& chan_pair: resources_in_chan_copy) + { + const ChannelKey& channel_key = chan_pair.first; + const std::set& resources = chan_pair.second; + if (resources.count(resource)) + this->leave_irc_channel({std::get<0>(channel_key), std::get<1>(channel_key), {}}, + part_message, resource); + } +} + void Bridge::clean() { auto it = this->irc_clients.begin(); @@ -330,7 +344,7 @@ void Bridge::send_raw_message(const std::string& hostname, const std::string& bo irc->send_raw(body); } -void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message, const std::string& resource) +void Bridge::leave_irc_channel(Iid&& iid, const std::string& status_message, const std::string& resource) { IrcClient* irc = this->get_irc_client(iid.get_server()); const auto key = iid.to_tuple(); -- cgit v1.2.3 From 4c8fb9a0e314db88dec1f105144aadafc5796ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 17 Aug 2016 03:42:40 +0200 Subject: Forward IRC invites to XMPP --- src/bridge/bridge.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index f6fefd9..f69da77 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -798,6 +798,12 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& this->xmpp.send_ping_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); } +void Bridge::send_xmpp_invitation(const Iid& iid, const std::string& author) +{ + for (const auto& resource: this->resources_in_server[iid.get_server()]) + this->xmpp.send_invitation(std::to_string(iid), this->user_jid + "/" + resource, author); +} + void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) { auto it = this->preferred_user_from.find(nick); -- cgit v1.2.3 From d1626c929f1d313c2f0f85b7d8b756a8d488d1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 22 Aug 2016 00:44:17 +0200 Subject: When joining a channel, send the most recent history found in the database --- src/bridge/bridge.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index f69da77..11393d4 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -744,6 +744,26 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam } +void Bridge::send_room_history(const std::string& hostname, const std::string& chan_name) +{ + for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) + this->send_room_history(hostname, chan_name, resource); +} + +void Bridge::send_room_history(const std::string& hostname, const std::string& chan_name, const std::string& resource) +{ +#ifdef USE_DATABASE + const auto coptions = Database::get_irc_channel_options_with_server_and_global_default(this->user_jid, hostname, chan_name); + const auto lines = Database::get_muc_logs(this->user_jid, chan_name, hostname, coptions.maxHistoryLength.value()); + for (const auto& line: lines) + { + const auto seconds = line.date.value().timeStamp(); + this->xmpp.send_history_message(chan_name + "%" + hostname, line.nick.value(), line.body.value(), + this->user_jid + "/" + resource, seconds); + } +#endif +} + std::string Bridge::get_own_nick(const Iid& iid) { IrcClient* irc = this->find_irc_client(iid.get_server()); -- cgit v1.2.3 From 38a4bcb2d2fd9bb535801a0209d614206204a460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 22 Aug 2016 00:47:55 +0200 Subject: Only save messages coming from real MUC participants in the database Not messages coming from the room, for example --- src/bridge/bridge.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 11393d4..ad1a45e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -616,8 +616,9 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st { #ifdef USE_DATABASE const auto xmpp_body = this->make_xmpp_body(body, encoding); - Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), - std::get<0>(xmpp_body), nick); + if (!nick.empty()) + Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), + std::get<0>(xmpp_body), nick); #endif for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) { -- cgit v1.2.3 From cfebca4d7c46959fc490cb9c72363d4ac3ee0c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 23 Aug 2016 00:11:51 +0200 Subject: Only save the logs if recordHistory global config option is true --- src/bridge/bridge.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ad1a45e..9b91474 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -32,6 +32,10 @@ Bridge::Bridge(const std::string& user_jid, BiboumiComponent& xmpp, std::shared_ xmpp(xmpp), poller(poller) { +#ifdef USE_DATABASE + const auto options = Database::get_global_options(this->user_jid); + this->set_record_history(options.recordHistory.value()); +#endif } /** @@ -241,8 +245,9 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) #ifdef USE_DATABASE const auto xmpp_body = this->make_xmpp_body(line); - Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), - std::get<0>(xmpp_body), irc->get_own_nick()); + if (this->record_history) + Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), + std::get<0>(xmpp_body), irc->get_own_nick()); #endif for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), @@ -616,7 +621,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st { #ifdef USE_DATABASE const auto xmpp_body = this->make_xmpp_body(body, encoding); - if (!nick.empty()) + if (!nick.empty() && this->record_history) Database::store_muc_message(this->get_bare_jid(), iid, std::chrono::system_clock::now(), std::get<0>(xmpp_body), nick); #endif @@ -971,7 +976,6 @@ void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::strin { if (user->nick != self->nick) { - log_debug(user->nick); this->send_user_join(iid.get_server(), iid.get_encoded_local(), user.get(), user->get_most_significant_mode(irc->get_sorted_user_modes()), false, resource); @@ -982,3 +986,10 @@ void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::strin true, resource); this->send_topic(iid.get_server(), iid.get_encoded_local(), channel->topic, channel->topic_author, resource); } + +#ifdef USE_DATABASE +void Bridge::set_record_history(const bool val) +{ + this->record_history = val; +} +#endif \ No newline at end of file -- cgit v1.2.3 From 1ffc3677536fd2978c5f4a77fc6148e80ff1256b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 23 Aug 2016 02:30:40 +0200 Subject: Send the muc history when a second (or more) resource joins a room --- src/bridge/bridge.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9b91474..e24383e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -984,6 +984,7 @@ void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::strin this->send_user_join(iid.get_server(), iid.get_encoded_local(), self, self->get_most_significant_mode(irc->get_sorted_user_modes()), true, resource); + this->send_room_history(iid.get_server(), iid.get_local(), resource); this->send_topic(iid.get_server(), iid.get_encoded_local(), channel->topic, channel->topic_author, resource); } -- cgit v1.2.3 From 93ebf45f3050681f94497aac889d30885a503a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 20 Sep 2016 19:02:12 +0200 Subject: Make history messages work with fixed_irc_server fix #3209 --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index e24383e..2fc466a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -764,7 +764,7 @@ void Bridge::send_room_history(const std::string& hostname, const std::string& c for (const auto& line: lines) { const auto seconds = line.date.value().timeStamp(); - this->xmpp.send_history_message(chan_name + "%" + hostname, line.nick.value(), line.body.value(), + this->xmpp.send_history_message(chan_name + utils::empty_if_fixed_server("%" + hostname), line.nick.value(), line.body.value(), this->user_jid + "/" + resource, seconds); } #endif -- cgit v1.2.3 From 35fc5d6f290eeccd6d2f7267eed7355ed59d356e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 21 Sep 2016 20:38:14 +0200 Subject: Some little style/typo fixes --- src/bridge/bridge.cpp | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 2fc466a..d4c2b2a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -498,7 +498,8 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s Iid iid(nick, irc_hostname, Iid::Type::User); this->send_private_message(iid, "\01PING " + iq_id + "\01"); - irc_responder_callback_t cb = [this, nick=utils::tolower(nick), iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool + irc_responder_callback_t cb = [this, nick=utils::tolower(nick), iq_id, to_jid, irc_hostname, from_jid] + (const std::string& hostname, const IrcMessage& message) -> bool { if (irc_hostname != hostname || message.arguments.size() < 2) return false; @@ -586,7 +587,8 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std this->send_private_message(iid, "\01VERSION\01"); // TODO, add a timer to remove that waiting iq if the server does not // respond with a matching command before n seconds - irc_responder_callback_t cb = [this, target, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool + irc_responder_callback_t cb = [this, target, iq_id, to_jid, irc_hostname, from_jid] + (const std::string& hostname, const IrcMessage& message) -> bool { if (irc_hostname != hostname) return false; @@ -659,15 +661,16 @@ void Bridge::send_presence_error(const Iid& iid, const std::string& nick, this->xmpp.send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, error_code, text); } -void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self, const std::string& resource) +void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self, + const std::string& resource) { if (!resource.empty()) - this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + resource, - self); + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), + this->user_jid + "/" + resource, self); else for (const auto& res: this->resources_in_chan[iid.to_tuple()]) - this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + res, - self); + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), + this->user_jid + "/" + res, self); IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); @@ -730,7 +733,8 @@ void Bridge::send_user_join(const std::string& hostname, const std::string& chan affiliation, role, this->user_jid + "/" + resource, self); } -void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic, const std::string& who) +void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic, + const std::string& who) { for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) { @@ -764,7 +768,8 @@ void Bridge::send_room_history(const std::string& hostname, const std::string& c for (const auto& line: lines) { const auto seconds = line.date.value().timeStamp(); - this->xmpp.send_history_message(chan_name + utils::empty_if_fixed_server("%" + hostname), line.nick.value(), line.body.value(), + this->xmpp.send_history_message(chan_name + utils::empty_if_fixed_server("%" + hostname), line.nick.value(), + line.body.value(), this->user_jid + "/" + resource, seconds); } #endif @@ -775,7 +780,7 @@ std::string Bridge::get_own_nick(const Iid& iid) IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc) return irc->get_own_nick(); - return ""; + return {}; } size_t Bridge::active_clients() const @@ -791,8 +796,9 @@ void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::stri void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) - this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid + "/" + resource, "cancel", "conflict", "409", ""); + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) + this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid + "/" + resource, + "cancel", "conflict", "409", ""); } void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) @@ -802,14 +808,16 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) - this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid + "/" + resource); + this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, + this->user_jid + "/" + resource); } void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) { const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_iq_version_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); + this->xmpp.send_iq_version_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), + this->user_jid + "/" + *resources.begin()); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, @@ -821,7 +829,8 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Forward to the first resource (arbitrary, based on the “order” of the std::set) only const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_ping_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); + this->xmpp.send_ping_request(utils::tolower(nick) + "%" + utils::empty_if_fixed_server(hostname), + this->user_jid + "/" + *resources.begin(), utils::revstr(id)); } void Bridge::send_xmpp_invitation(const Iid& iid, const std::string& author) -- cgit v1.2.3 From 07e2209596a1fbcc1d6f97d68bfda8e2add19ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 22 Sep 2016 00:00:13 +0200 Subject: Add the missing & for 3 std::string function arguments --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d4c2b2a..d16875f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -563,7 +563,7 @@ void Bridge::on_gateway_ping(const std::string& irc_hostname, const std::string& "", true); } -void Bridge::send_irc_invitation(const Iid& iid, const std::string to) +void Bridge::send_irc_invitation(const Iid& iid, const std::string& to) { IrcClient* irc = this->get_irc_client(iid.get_server()); Jid to_jid(to); -- cgit v1.2.3 From 76a8189b46177eb78eee12d1cb3266f282acd380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 3 Oct 2016 00:58:21 +0200 Subject: Implement result-set-management for LIST queries ref #2948 --- src/bridge/bridge.cpp | 181 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 150 insertions(+), 31 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d16875f..8849ef9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -10,6 +9,7 @@ #include #include #include +#include "result_set_management.hpp" using namespace std::string_literals; @@ -386,45 +386,164 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) irc->send_nick_command(new_nick); } -void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq_id, - const std::string& to_jid) +void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq_id, const std::string& to_jid, + ResultSetInfo rs_info) { - IrcClient* irc = this->get_irc_client(iid.get_server()); + auto& list = channel_list_cache[iid.get_server()]; - irc->send_list_command(); + // We fetch the list from the IRC server only if we have a complete + // cached list that needs to be invalidated (that is, when the request + // doesn’t have a after or before, or when the list is empty). + // If the list is not complete, this means that a request is already + // ongoing, so we just need to add the callback. + // By default the list is complete and empty. + if (list.complete && + (list.channels.empty() || (rs_info.after.empty() && rs_info.before.empty()))) + { + IrcClient* irc = this->get_irc_client(iid.get_server()); + irc->send_list_command(); + + // Add a callback that will populate our list + list.channels.clear(); + list.complete = false; + irc_responder_callback_t cb = [this, iid](const std::string& irc_hostname, + const IrcMessage& message) -> bool + { + if (irc_hostname != iid.get_server()) + return false; - std::vector list; + auto& list = channel_list_cache[iid.get_server()]; + + if (message.command == "263" || message.command == "RPL_TRYAGAIN" || message.command == "ERR_TOOMANYMATCHES" + || message.command == "ERR_NOSUCHSERVER") + { + list.complete = true; + return true; + } + else if (message.command == "322" || message.command == "RPL_LIST") + { // Add element to list + if (message.arguments.size() == 4) + { + list.channels.emplace_back(message.arguments[1] + utils::empty_if_fixed_server("%" + iid.get_server()), + message.arguments[2], message.arguments[3]); + } + return false; + } + else if (message.command == "323" || message.command == "RPL_LISTEND") + { // Send the iq response with the content of the list + list.complete = true; + return true; + } + return false; + }; - irc_responder_callback_t cb = [this, iid, iq_id, to_jid, list=std::move(list)](const std::string& irc_hostname, - const IrcMessage& message) mutable -> bool + this->add_waiting_irc(std::move(cb)); + } + + // If the list is complete, we immediately send the answer. + // Otherwise, we install a callback, that will populate our list and send + // the answer when we can. + if (list.complete) { - if (irc_hostname != iid.get_server()) + this->send_matching_channel_list(list, rs_info, iq_id, to_jid, std::to_string(iid)); + } + else + { + // Add a callback to answer the request as soon as we can + irc_responder_callback_t cb = [this, iid, iq_id, to_jid, + rs_info=std::move(rs_info)](const std::string& irc_hostname, + const IrcMessage& message) -> bool + { + if (irc_hostname != iid.get_server()) + return false; + + if (message.command == "263" || message.command == "RPL_TRYAGAIN" || message.command == "ERR_TOOMANYMATCHES" + || message.command == "ERR_NOSUCHSERVER") + { + std::string text; + if (message.arguments.size() >= 2) + text = message.arguments[1]; + this->xmpp.send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "wait", "service-unavailable", text, false); + return true; + } + else if (message.command == "322" || message.command == "RPL_LIST") + { + auto& list = channel_list_cache[iid.get_server()]; + const auto res = this->send_matching_channel_list(list, rs_info, iq_id, to_jid, std::to_string(iid)); + log_debug("We added a new channel in our list, can we send the result? ", std::boolalpha, res); + return res; + } + else if (message.command == "323" || message.command == "RPL_LISTEND") + { // Send the iq response with the content of the list + auto& list = channel_list_cache[iid.get_server()]; + this->send_matching_channel_list(list, rs_info, iq_id, to_jid, std::to_string(iid)); + return true; + } return false; - if (message.command == "263" || message.command == "RPL_TRYAGAIN" || - message.command == "ERR_TOOMANYMATCHES" || message.command == "ERR_NOSUCHSERVER") + }; + + this->add_waiting_irc(std::move(cb)); + } +} + +bool Bridge::send_matching_channel_list(const ChannelList& channel_list, const ResultSetInfo& rs_info, + const std::string& id, const std::string& to_jid, const std::string& from) +{ + auto begin = channel_list.channels.begin(); + auto end = channel_list.channels.begin(); + if (channel_list.complete) + { + begin = std::find_if(channel_list.channels.begin(), channel_list.channels.end(), [this, &rs_info](const ListElement& element) + { + return rs_info.after == element.channel + "@" + this->xmpp.get_served_hostname(); + }); + if (begin == channel_list.channels.end()) + begin = channel_list.channels.begin(); + else + begin = std::next(begin); + end = std::find_if(channel_list.channels.begin(), channel_list.channels.end(), [this, &rs_info](const ListElement& element) + { + return rs_info.before == element.channel + "@" + this->xmpp.get_served_hostname(); + }); + if (rs_info.max >= 0) { - std::string text; - if (message.arguments.size() >= 2) - text = message.arguments[1]; - this->xmpp.send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, - "wait", "service-unavailable", text, false); - return true; + if (std::distance(begin, end) >= rs_info.max) + end = begin + rs_info.max; } - else if (message.command == "322" || message.command == "RPL_LIST") - { // Add element to list - if (message.arguments.size() == 4) - list.emplace_back(message.arguments[1], message.arguments[2], - message.arguments[3]); - return false; + } + else + { + if (rs_info.after.empty() && rs_info.before.empty() && rs_info.max < 0) + return false; + if (!rs_info.after.empty()) + { + begin = std::find_if(channel_list.channels.begin(), channel_list.channels.end(), [this, &rs_info](const ListElement& element) + { + return rs_info.after == element.channel + "@" + this->xmpp.get_served_hostname(); + }); + if (begin == channel_list.channels.end()) + return false; + begin = std::next(begin); } - else if (message.command == "323" || message.command == "RPL_LISTEND") - { // Send the iq response with the content of the list - this->xmpp.send_iq_room_list_result(iq_id, to_jid, std::to_string(iid), list); - return true; + if (!rs_info.before.empty()) + { + end = std::find_if(channel_list.channels.begin(), channel_list.channels.end(), [this, &rs_info](const ListElement& element) + { + return rs_info.before == element.channel + "@" + this->xmpp.get_served_hostname(); + }); + if (end == channel_list.channels.end()) + return false; } - return false; - }; - this->add_waiting_irc(std::move(cb)); + if (rs_info.max >= 0) + { + if (std::distance(begin, end) < rs_info.max) + return false; + else + end = begin + rs_info.max; + } + } + this->xmpp.send_iq_room_list_result(id, to_jid, from, channel_list, begin, end, rs_info); + return true; } void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason, @@ -1002,4 +1121,4 @@ void Bridge::set_record_history(const bool val) { this->record_history = val; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 729078a238e563d071f7905e01d3029a880fd479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 3 Oct 2016 01:11:54 +0200 Subject: Add missing include file --- src/bridge/bridge.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 8849ef9..65171a9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -10,6 +10,7 @@ #include #include #include "result_set_management.hpp" +#include using namespace std::string_literals; -- cgit v1.2.3 From 28f1dd76548fc9a7de3920d938903f68cdfffe0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 3 Oct 2016 21:35:16 +0200 Subject: Make version requests work with global user JIDs as well fix #3210 --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 65171a9..7724ba7 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -713,7 +713,7 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std if (irc_hostname != hostname) return false; IrcUser user(message.prefix); - if (message.command == "NOTICE" && user.nick == target && + if (message.command == "NOTICE" && utils::tolower(user.nick) == utils::tolower(target) && message.arguments.size() >= 2 && message.arguments[1].substr(0, 9) == "\01VERSION ") { // remove the "\01VERSION " and the "\01" parts from the string -- cgit v1.2.3 From 3620d533ee88a8804317d2745320c0186192ddaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 5 Oct 2016 00:17:22 +0200 Subject: Avoid sending PART command for unjoined channels fix #3205 --- src/bridge/bridge.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 7724ba7..fb7ea42 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -360,7 +360,15 @@ void Bridge::leave_irc_channel(Iid&& iid, const std::string& status_message, con const auto resources = this->number_of_resources_in_chan(key); if (resources == 1) { - irc->send_part_command(iid.get_local(), status_message); + // Do not send a PART message if we actually are not in that channel + // or if we already sent a PART but we are just waiting for the + // acknowledgment from the server + IrcChannel* channel = irc->get_channel(iid.get_local()); + if (channel->joined && !channel->parting) + { + irc->send_part_command(iid.get_local(), status_message); + channel->parting = true; + } // Since there are no resources left in that channel, we don't // want to receive private messages using this room's JID this->remove_all_preferred_from_jid_of_room(iid.get_local()); -- cgit v1.2.3 From 8ac8d2b2425d19eb995a36efa808b664979e358f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 7 Oct 2016 23:28:40 +0200 Subject: Correctly set status="110" in the presence for the target of a kick --- src/bridge/bridge.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index fb7ea42..ab42876 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -916,10 +916,11 @@ size_t Bridge::active_clients() const return this->irc_clients.size(); } -void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) +void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author, + const bool self) { for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) - this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid + "/" + resource); + this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid + "/" + resource, self); } void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) -- cgit v1.2.3 From dfc0793ef2fec12d2613b53b27f1a7f85dae2688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 11 Oct 2016 00:43:46 +0200 Subject: Include a private and no-copy nodes in private to avoid carbon duplication --- src/bridge/bridge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ab42876..9300d45 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -771,13 +771,13 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st const auto chan_name = Iid(Jid(it->second).local, {}).get_local(); for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, iid.get_server()}]) this->xmpp.send_message(it->second, this->make_xmpp_body(body, encoding), - this->user_jid + "/" + resource, "chat", true); + this->user_jid + "/" + resource, "chat", true, true); } else { for (const auto& resource: this->resources_in_server[iid.get_server()]) this->xmpp.send_message(std::to_string(iid), this->make_xmpp_body(body, encoding), - this->user_jid + "/" + resource, "chat", false); + this->user_jid + "/" + resource, "chat", false, true); } } } @@ -835,7 +835,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho const auto encoding = in_encoding_for(*this, {from, this}); for (const auto& resource: this->resources_in_server[from]) { - this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource, "chat"); + this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource, "chat", false, false); } } -- cgit v1.2.3 From 00eb18bae8cf62d49f4b5d42aed8507fcca3c03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 23 Oct 2016 23:58:03 +0200 Subject: Refactor channel->parting to a new location --- src/bridge/bridge.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9300d45..ac69ebc 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -365,10 +365,7 @@ void Bridge::leave_irc_channel(Iid&& iid, const std::string& status_message, con // acknowledgment from the server IrcChannel* channel = irc->get_channel(iid.get_local()); if (channel->joined && !channel->parting) - { - irc->send_part_command(iid.get_local(), status_message); - channel->parting = true; - } + irc->send_part_command(iid.get_local(), status_message); // Since there are no resources left in that channel, we don't // want to receive private messages using this room's JID this->remove_all_preferred_from_jid_of_room(iid.get_local()); -- cgit v1.2.3 From c3bb9fe2e2c2a0b2773e9b9824c4e675448b862f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 23 Oct 2016 23:59:21 +0200 Subject: Handle forced-join by just sending an invitation fix #3116 --- src/bridge/bridge.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ac69ebc..67eb805 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -839,8 +839,19 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const IrcUser* user, const char user_mode, const bool self) { - for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) - this->send_user_join(hostname, chan_name, user, user_mode, self, resource); + const auto resources = this->resources_in_chan[ChannelKey{chan_name, hostname}]; + if (self && resources.empty()) + { // This was a forced join: no client ever asked to join this room, + // but the server tells us we are in that room anyway. XMPP can’t + // do that, so we invite all the resources to join that channel. + const Iid iid(chan_name, hostname, Iid::Type::Channel); + this->send_xmpp_invitation(iid, ""); + } + else + { + for (const auto& resource: resources) + this->send_user_join(hostname, chan_name, user, user_mode, self, resource); + } } void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, -- cgit v1.2.3 From c70301e503fdb887387a54fcf5284d593e65d837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 2 Nov 2016 21:25:26 +0100 Subject: Fix the presences sent, when multiple resources join the virtual channel fix #3216 --- src/bridge/bridge.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 67eb805..a0ecc6e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -177,16 +177,23 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const { // Join the dummy channel if (irc->is_welcomed()) { - if (irc->get_dummy_channel().joined) + if (res_in_chan) return false; // Immediately simulate a message coming from the IRC server saying that we // joined the channel - const IrcMessage join_message(irc->get_nick(), "JOIN", {""}); - irc->on_channel_join(join_message); - const IrcMessage end_join_message(std::string(iid.get_server()), "366", - {irc->get_nick(), - "", "End of NAMES list"}); - irc->on_channel_completely_joined(end_join_message); + if (irc->get_dummy_channel().joined) + { + this->generate_channel_join_for_resource(iid, resource); + } + else + { + const IrcMessage join_message(irc->get_nick(), "JOIN", {""}); + irc->on_channel_join(join_message); + const IrcMessage end_join_message(std::string(iid.get_server()), "366", + {irc->get_nick(), + "", "End of NAMES list"}); + irc->on_channel_completely_joined(end_join_message); + } } else { -- cgit v1.2.3