~singpolyma/biboumi

5990a8bf8ae622f075a7e2a12b2f5ac0cab8713b — louiz’ 7 years ago c3bb9fe
Correctly handle the nick change inside the virtual channel
2 files changed, 63 insertions(+), 22 deletions(-)

M src/irc/irc_client.cpp
M tests/end_to_end/__main__.py
M src/irc/irc_client.cpp => src/irc/irc_client.cpp +30 -21
@@ 931,29 931,38 @@ void IrcClient::on_quit(const IrcMessage& message)

void IrcClient::on_nick(const IrcMessage& message)
{
  const std::string new_nick = message.arguments[0];
  const std::string new_nick = IrcUser(message.arguments[0]).nick;
  const std::string current_nick = IrcUser(message.prefix).nick;
  const auto change_nick_func = [&](const std::string& chan_name, const IrcChannel* channel)
  {
    IrcUser* user;
    if (channel->get_self() && channel->get_self()->nick == current_nick)
      user = channel->get_self();
    else
      user = channel->find_user(current_nick);
    if (user)
      {
        std::string old_nick = user->nick;
        Iid iid(chan_name, this->hostname, Iid::Type::Channel);
        const bool self = channel->get_self()->nick == old_nick;
        const char user_mode = user->get_most_significant_mode(this->sorted_user_modes);
        this->bridge.send_nick_change(std::move(iid), old_nick, new_nick, user_mode, self);
        user->nick = new_nick;
        if (self)
          {
            channel->get_self()->nick = new_nick;
            this->current_nick = new_nick;
          }
      }
  };

  if (this->get_dummy_channel().joined)
    {
      change_nick_func("", &this->get_dummy_channel());
    }
  for (auto it = this->channels.begin(); it != this->channels.end(); ++it)
    {
      const std::string chan_name = it->first;
      IrcChannel* channel = it->second.get();
      IrcUser* user = channel->find_user(message.prefix);
      if (user)
        {
          std::string old_nick = user->nick;
          Iid iid;
          iid.set_local(chan_name);
          iid.set_server(this->hostname);
          iid.type = Iid::Type::Channel;
          const bool self = channel->get_self()->nick == old_nick;
          const char user_mode = user->get_most_significant_mode(this->sorted_user_modes);
          this->bridge.send_nick_change(std::move(iid), old_nick, new_nick, user_mode, self);
          user->nick = new_nick;
          if (self)
            {
              channel->get_self()->nick = new_nick;
              this->current_nick = new_nick;
            }
        }
      change_nick_func(it->first, it->second.get());
    }
}


M tests/end_to_end/__main__.py => tests/end_to_end/__main__.py +33 -1
@@ 482,7 482,7 @@ if __name__ == '__main__':
                             ),
                     partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
                 ]),
        Scenario("virtual_channel_join",
        Scenario("virtual_channel",
                 [
                     handshake_sequence(),
                     partial(send_stanza,


@@ 494,6 494,38 @@ if __name__ == '__main__':
                             ),
                     partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
                     connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
                     partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
                     partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_one}']"),
                     partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Closing Link: localhost (Client Quit)']"),
                     partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Connection closed.']"),
                 ]),
        Scenario("irc_server_disconnection",
                 [
                     handshake_sequence(),
                     partial(send_stanza,
                             "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
                     connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
                     partial(expect_stanza,
                             ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
                              "/presence/muc_user:x/muc_user:status[@code='110']")
                             ),
                     partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
                     connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),

                     partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),

                     partial(expect_unordered, [
                         ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='{nick_two}']",
                          "/presence/muc_user:x/muc_user:status[@code='110']",
                          "/presence/muc_user:x/muc_user:status[@code='303']"),
                         ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']",
                          "/presence/muc_user:x/muc_user:status[@code='110']"),
                         ]),

                     partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
                     partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}']"),
                     partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Closing Link: localhost (Client Quit)']"),
                     partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Connection closed.']"),
                 ]),
        Scenario("channel_join_with_two_users",
                 [