~singpolyma/biboumi

5817a95b5ee89480788832be35679dfcd2ed833b — Florent Le Coz 10 years ago b60cbda
Basic handling of modes, both ways
M CMakeLists.txt => CMakeLists.txt +1 -1
@@ 70,7 70,7 @@ target_link_libraries(xmpp bridge network utils
file(GLOB source_bridge
  src/bridge/*.[hc]pp)
add_library(bridge STATIC ${source_bridge})
target_link_libraries(bridge xmpp irc)
target_link_libraries(bridge xmpp irc utils)

#
## Main executable

M src/bridge/bridge.cpp => src/bridge/bridge.cpp +7 -0
@@ 4,6 4,7 @@
#include <network/poller.hpp>
#include <utils/encoding.hpp>

#include <utils/split.hpp>
#include <iostream>

static const char* action_prefix = "\01ACTION ";


@@ 83,6 84,12 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body)
      std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl;
      return;
    }
  if (body.substr(0, 6) == "/mode ")
    {
      std::vector<std::string> args = utils::split(body.substr(6), ' ', false);
      irc->send_mode_command(iid.chan, args);
      return;
    }
  if (body.substr(0, 4) == "/me ")
    irc->send_channel_message(iid.chan, action_prefix + body.substr(4) + "\01");
  else

M src/irc/irc_channel.hpp => src/irc/irc_channel.hpp +0 -1
@@ 26,7 26,6 @@ public:
private:
  std::unique_ptr<IrcUser> self;
  std::vector<std::unique_ptr<IrcUser>> users;

  IrcChannel(const IrcChannel&) = delete;
  IrcChannel(IrcChannel&&) = delete;
  IrcChannel& operator=(const IrcChannel&) = delete;

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +40 -3
@@ 162,9 162,15 @@ void IrcClient::send_part_command(const std::string& chan_name, const std::strin
{
  IrcChannel* channel = this->get_channel(chan_name);
  if (channel->joined == true)
    {
      this->send_message(IrcMessage("PART", {chan_name, status_message}));
    }
    this->send_message(IrcMessage("PART", {chan_name, status_message}));
}

void IrcClient::send_mode_command(const std::string& chan_name, const std::vector<std::string>& arguments)
{
  std::vector<std::string> args(arguments);
  args.insert(args.begin(), chan_name);
  IrcMessage m("MODE", std::move(args));
  this->send_message(std::move(m));
}

void IrcClient::send_pong_command(const IrcMessage& message)


@@ 325,3 331,34 @@ void IrcClient::on_nick(const IrcMessage& message)
    }
}

void IrcClient::on_mode(const IrcMessage& message)
{
  const std::string target = message.arguments[0];
  if (target[0] == '&' || target[0] == '#' ||
      target[0] == '!' || target[0] == '+')
    this->on_channel_mode(message);
  else
    this->on_user_mode(message);
}

void IrcClient::on_channel_mode(const IrcMessage& message)
{
  // For now, just transmit the modes so the user can know what happens
  // TODO, actually interprete the mode.
  Iid iid;
  iid.chan = message.arguments[0];
  iid.server = this->hostname;
  IrcUser user(message.prefix);
  this->bridge->send_message(iid, "", std::string("Mode ") + iid.chan +
                                      " [" + message.arguments[1] +
                                      (message.arguments.size() > 2 ? (" " + message.arguments[2]): "")
                                      + "] by " + user.nick,
                             true);
}

void IrcClient::on_user_mode(const IrcMessage& message)
{
  this->bridge->send_xmpp_message(this->hostname, "",
                                  std::string("User mode for ") + message.arguments[0] +
                                  " is [" + message.arguments[1] + "]");
}

M src/irc/irc_client.hpp => src/irc/irc_client.hpp +13 -6
@@ 88,6 88,10 @@ public:
   */
  void send_part_command(const std::string& chan_name, const std::string& status_message);
  /**
   * Send the MODE irc command
   */
  void send_mode_command(const std::string& chan_name, const std::vector<std::string>& arguments);
  /**
   * Forward the server message received from IRC to the XMPP component
   */
  void forward_server_message(const IrcMessage& message);


@@ 118,17 122,20 @@ public:
   * When a message 001 is received, join the rooms we wanted to join, and set our actual nickname
   */
  void on_welcome_message(const IrcMessage& message);
  /**
   * When a PART message is received
   */
  void on_part(const IrcMessage& message);
  void on_nick(const IrcMessage& message);
  void on_mode(const IrcMessage& message);
  /**
   * When a NICK message is received
   * A mode towards our own user is received (note, that is different from a
   * channel mode towards or own nick, see
   * http://tools.ietf.org/html/rfc2812#section-3.1.5 VS #section-3.2.3)
   */
  void on_nick(const IrcMessage& message);
  void on_user_mode(const IrcMessage& message);
  /**
   * When a QUIT message is received
   * A mode towards a channel. Note that this can change the mode of the
   * channel itself or an IrcUser in it.
   */
  void on_channel_mode(const IrcMessage& message);
  void on_quit(const IrcMessage& message);

private:

A src/utils/split.cpp => src/utils/split.cpp +18 -0
@@ 0,0 1,18 @@
#include <utils/split.hpp>

namespace utils
{
  std::vector<std::string> split(const std::string &s, const char delim, const bool allow_empty)
  {
    std::vector<std::string> ret;
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
      {
        if (item.empty() && !allow_empty)
          continue ;
        ret.emplace_back(std::move(item));
      }
    return ret;
  }
}

M src/utils/split.hpp => src/utils/split.hpp +1 -9
@@ 7,15 7,7 @@

namespace utils
{
  std::vector<std::string> split(const std::string &s, const char delim)
  {
    std::vector<std::string> ret;
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
      ret.emplace_back(std::move(item));
    return ret;
  }
  std::vector<std::string> split(const std::string &s, const char delim, const bool allow_empty=true);
}

#endif // SPLIT_INCLUDED

M src/xmpp/xmpp_component.cpp => src/xmpp/xmpp_component.cpp +4 -1
@@ 294,7 294,10 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
{
  Stanza message("message");
  message["to"] = jid_to;
  message["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
  if (!nick.empty())
    message["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
  else // Message from the room itself
    message["from"] = muc_name + "@" + this->served_hostname;
  message["type"] = "groupchat";
  XmlNode body("body");
  body.set_inner(body_str);