~singpolyma/biboumi

096a4e3bafe6e2d238e4592f57f22f19f363fcbd — Florent Le Coz 10 years ago f0d9273
Handle nick changes, both ways
M src/bridge/bridge.cpp => src/bridge/bridge.cpp +29 -3
@@ 59,10 59,15 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname)
    }
}

void Bridge::join_irc_channel(const Iid& iid, const std::string& username)
bool Bridge::join_irc_channel(const Iid& iid, const std::string& username)
{
  IrcClient* irc = this->get_irc_client(iid.server, username);
  irc->send_join_command(iid.chan);
  if (irc->is_channel_joined(iid.chan) == false)
    {
      irc->send_join_command(iid.chan);
      return true;
    }
  return false;
}

void Bridge::send_channel_message(const Iid& iid, const std::string& body)


@@ 103,6 108,13 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message)
    irc->send_part_command(iid.chan, status_message);
}

void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick)
{
  IrcClient* irc = this->get_irc_client(iid.server);
  if (irc)
    irc->send_nick_command(new_nick);
}

void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc)
{
  std::string utf8_body = this->sanitize_for_xmpp(body);


@@ 118,11 130,17 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st
    this->xmpp->send_message(iid.chan + "%" + iid.server, utf8_body, this->user_jid);
}

void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self)
void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self)
{
  this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->sanitize_for_xmpp(message), this->user_jid, self);
}

void Bridge::send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self)
{
  this->xmpp->send_nick_change(std::move(iid.chan) + "%" + std::move(iid.server),
                               old_nick, new_nick, this->user_jid, self);
}

void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg)
{
  std::string body;


@@ 147,3 165,11 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam
{
  this->xmpp->send_topic(chan_name + "%" + hostname, this->sanitize_for_xmpp(topic), this->user_jid);
}

std::string Bridge::get_own_nick(const Iid& iid)
{
  IrcClient* irc = this->get_irc_client(iid.server);
  if (irc)
    return irc->get_own_nick();
  return "";
}

M src/bridge/bridge.hpp => src/bridge/bridge.hpp +17 -2
@@ 30,10 30,15 @@ public:
   **
   **/

  void join_irc_channel(const Iid& iid, const std::string& username);
  /**
   * Try to join an irc_channel, does nothing and return true if the channel
   * was already joined.
   */
  bool join_irc_channel(const Iid& iid, const std::string& username);
  void send_channel_message(const Iid& iid, const std::string& body);
  void send_private_message(const Iid& iid, const std::string& body);
  void leave_irc_channel(Iid&& iid, std::string&& status_message);
  void send_irc_nick_change(const Iid& iid, const std::string& new_nick);

  /***
   **


@@ 65,7 70,17 @@ public:
  /**
   * Send an unavailable presence from this participant
   */
  void send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self);
  void send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self);
  /**
   * Send presences to indicate that an user old_nick (ourself if self ==
   * true) changed his nick to new_nick
   */
  void send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self);

  /**
   * Misc
   */
  std::string get_own_nick(const Iid& iid);

private:
  /**

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +39 -6
@@ 53,6 53,12 @@ IrcChannel* IrcClient::get_channel(const std::string& name)
    }
}

bool IrcClient::is_channel_joined(const std::string& name)
{
  IrcChannel* client = this->get_channel(name);
  return client->joined;
}

std::string IrcClient::get_own_nick() const
{
  return this->current_nick;


@@ 91,6 97,8 @@ void IrcClient::parse_in_buffer()
        this->on_part(message);
      else if (message.command == "QUIT")
        this->on_quit(message);
      else if (message.command == "NICK")
        this->on_nick(message);
    }
}



@@ 128,11 136,9 @@ void IrcClient::send_nick_command(const std::string& nick)
void IrcClient::send_join_command(const std::string& chan_name)
{
  if (this->welcomed == false)
    {
      this->channels_to_join.push_back(chan_name);
      return ;
    }
  this->send_message(IrcMessage("JOIN", {chan_name}));
    this->channels_to_join.push_back(chan_name);
  else
    this->send_message(IrcMessage("JOIN", {chan_name}));
}

bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body)


@@ 288,7 294,34 @@ void IrcClient::on_quit(const IrcMessage& message)
          Iid iid;
          iid.chan = chan_name;
          iid.server = this->hostname;
          this->bridge->send_muc_leave(std::move(iid), std::move(nick), std::move(txt), false);
          this->bridge->send_muc_leave(std::move(iid), std::move(nick), txt, false);
        }
    }
}

void IrcClient::on_nick(const IrcMessage& message)
{
  const std::string new_nick = message.arguments[0];
  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.chan = chan_name;
          iid.server = this->hostname;
          bool self = channel->get_self()->nick == old_nick;
          this->bridge->send_nick_change(std::move(iid), old_nick, new_nick, self);
          user->nick = new_nick;
          if (self)
            {
              channel->get_self()->nick = new_nick;
              this->current_nick = new_nick;
            }
        }
    }
}


M src/irc/irc_client.hpp => src/irc/irc_client.hpp +9 -1
@@ 45,6 45,10 @@ public:
   */
  IrcChannel* get_channel(const std::string& name);
  /**
   * Returns true if the channel is joined
   */
  bool is_channel_joined(const std::string& name);
  /**
   * Return our own nick
   */
  std::string get_own_nick() const;


@@ 67,7 71,7 @@ public:
   */
  void send_nick_command(const std::string& username);
  /**
   * Send the JOIN irc command
   * Send the JOIN irc command.
   */
  void send_join_command(const std::string& chan_name);
  /**


@@ 119,6 123,10 @@ public:
   */
  void on_part(const IrcMessage& message);
  /**
   * When a NICK message is received
   */
  void on_nick(const IrcMessage& message);
  /**
   * When a QUIT message is received
   */
  void on_quit(const IrcMessage& message);

M src/xmpp/xmpp_component.cpp => src/xmpp/xmpp_component.cpp +41 -1
@@ 167,7 167,13 @@ void XmppComponent::handle_presence(const Stanza& stanza)
  if (!iid.chan.empty() && !iid.chan.empty())
    { // presence toward a MUC that corresponds to an irc channel
      if (type.empty())
        bridge->join_irc_channel(iid, to.resource);
        {
          const std::string own_nick = bridge->get_own_nick(iid);
          if (!own_nick.empty() && own_nick != to.resource)
            bridge->send_irc_nick_change(iid, to.resource);
          else
            bridge->join_irc_channel(iid, to.resource);
        }
      else if (type == "unavailable")
        {
          XmlNode* status = stanza.get_child(MUC_USER_NS":status");


@@ 317,3 323,37 @@ void XmppComponent::send_muc_leave(std::string&& muc_name, std::string&& nick, s
  presence.close();
  this->send_stanza(presence);
}

void XmppComponent::send_nick_change(const std::string& muc_name, const std::string& old_nick, const std::string& new_nick, const std::string& jid_to, const bool self)
{
  Stanza presence("presence");
  presence["to"] = jid_to;
  presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick;
  presence["type"] = "unavailable";
  XmlNode x("x");
  x["xmlns"] = MUC_USER_NS;
  XmlNode item("item");
  item["nick"] = new_nick;
  item.close();
  x.add_child(std::move(item));
  XmlNode status("status");
  status["code"] = "303";
  status.close();
  x.add_child(std::move(status));
  if (self)
    {
      XmlNode status2("status");
      status2["code"] = "110";
      status2.close();
      x.add_child(std::move(status2));
    }
  x.close();
  presence.add_child(std::move(x));
  presence.close();
  this->send_stanza(presence);

  if (self)
    this->send_self_join(muc_name, new_nick, jid_to);
  else
    this->send_user_join(muc_name, new_nick, jid_to);
}

M src/xmpp/xmpp_component.hpp => src/xmpp/xmpp_component.hpp +4 -0
@@ 80,6 80,10 @@ public:
   */
  void send_muc_leave(std::string&& muc_name, std::string&& nick, std::string&& message, const std::string& jid_to, const bool self);
  /**
   * Indicate that a participant changed his nick
   */
  void send_nick_change(const std::string& muc_name, const std::string& old_nick, const std::string& new_nick, const std::string& jid_to, const bool self);
  /**
   * Handle the various stanza types
   */
  void handle_handshake(const Stanza& stanza);