~singpolyma/biboumi

7a4cea426d0a07d577753ee008416e19eca6260d — louiz’ 4 years ago a43fb35
Reflect messages to XMPP only when they are actually sent
4 files changed, 45 insertions(+), 25 deletions(-)

M CHANGELOG.rst
M src/bridge/bridge.cpp
M src/irc/irc_client.cpp
M src/irc/irc_client.hpp
M CHANGELOG.rst => CHANGELOG.rst +2 -0
@@ 10,6 10,8 @@ Version 9.0
  ad-hoc configuration form on a server JID.
- Add a verify_certificate policy option that lets the admin disable
  certificate validation per-domain.
- Messages reflections are now properly cut if the body was cut before
  being to sent to IRC

Version 8.3 - 2018-06-01
========================

M src/bridge/bridge.cpp => src/bridge/bridge.cpp +20 -14
@@ 224,6 224,23 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body, std::
  bool first = true;
  for (const std::string& line: lines)
    {
      std::string uuid;
#ifdef USE_DATABASE
      const auto xmpp_body = this->make_xmpp_body(line);
      if (this->record_history)
        uuid = Database::store_muc_message(this->get_bare_jid(), iid.get_local(), iid.get_server(), std::chrono::system_clock::now(),
                                    std::get<0>(xmpp_body), irc->get_own_nick());
#endif
      if (!first || id.empty())
        id = utils::gen_uuid();

      MessageCallback mirror_to_all_resources = [this, iid, uuid, id](const IrcClient* irc, const IrcMessage& message) {
        const std::string& line = message.arguments[1];
        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, uuid, id);
      };

      if (line.substr(0, 5) == "/mode")
        {
          std::vector<std::string> args = utils::split(line.substr(5), ' ', false);


@@ 232,22 249,11 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body, std::
                                // XMPP user, that’s not a textual message.
        }
      else if (line.substr(0, 4) == "/me ")
        irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01");
        irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01",
                                  std::move(mirror_to_all_resources));
      else
        irc->send_channel_message(iid.get_local(), line);
        irc->send_channel_message(iid.get_local(), line, std::move(mirror_to_all_resources));

      std::string uuid;
#ifdef USE_DATABASE
      const auto xmpp_body = this->make_xmpp_body(line);
      if (this->record_history)
        uuid = Database::store_muc_message(this->get_bare_jid(), iid.get_local(), iid.get_server(), std::chrono::system_clock::now(),
                                    std::get<0>(xmpp_body), irc->get_own_nick());
#endif
      if (!first || id.empty())
        id = utils::gen_uuid();
      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, uuid, id);
      first = false;
    }
}

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +14 -7
@@ 398,8 398,10 @@ void IrcClient::parse_in_buffer(const size_t)
    }
}

void IrcClient::actual_send(const IrcMessage& message)
void IrcClient::actual_send(std::pair<IrcMessage, MessageCallback> message_pair)
{
  const IrcMessage& message = message_pair.first;
  const MessageCallback& callback = message_pair.second;
   log_debug("IRC SENDING: (", this->get_hostname(), ") ", message);
    std::string res;
    if (!message.prefix.empty())


@@ 417,14 419,18 @@ void IrcClient::actual_send(const IrcMessage& message)
      }
    res += "\r\n";
    this->send_data(std::move(res));

    if (callback)
      callback(this, message);
 }

void IrcClient::send_message(IrcMessage message, bool throttle)
void IrcClient::send_message(IrcMessage message, MessageCallback callback, bool throttle)
{
  auto message_pair = std::make_pair(std::move(message), std::move(callback));
  if (this->tokens_bucket.use_token() || !throttle)
    this->actual_send(message);
    this->actual_send(std::move(message_pair));
  else
    message_queue.push_back(std::move(message));
    message_queue.push_back(std::move(message_pair));
}

void IrcClient::send_raw(const std::string& txt)


@@ 475,7 481,7 @@ void IrcClient::send_topic_command(const std::string& chan_name, const std::stri

void IrcClient::send_quit_command(const std::string& reason)
{
  this->send_message(IrcMessage("QUIT", {reason}), false);
  this->send_message(IrcMessage("QUIT", {reason}), {}, false);
}

void IrcClient::send_join_command(const std::string& chan_name, const std::string& password)


@@ 494,7 500,8 @@ void IrcClient::send_join_command(const std::string& chan_name, const std::strin
  this->start();
}

bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body)
bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body,
                                     MessageCallback callback)
{
  IrcChannel* channel = this->get_channel(chan_name);
  if (!channel->joined)


@@ 517,7 524,7 @@ bool IrcClient::send_channel_message(const std::string& chan_name, const std::st
                         ::strlen(":!@ PRIVMSG ") - chan_name.length() - ::strlen(" :\r\n");
  const auto lines = cut(body, line_size);
  for (const auto& line: lines)
    this->send_message(IrcMessage("PRIVMSG", {chan_name, line}));
    this->send_message(IrcMessage("PRIVMSG", {chan_name, line}), callback);
  return true;
}


M src/irc/irc_client.hpp => src/irc/irc_client.hpp +9 -4
@@ 21,6 21,10 @@
#include <set>
#include <utils/tokens_bucket.hpp>

class IrcClient;

using MessageCallback = std::function<void(const IrcClient*, const IrcMessage&)>;

class Bridge;

/**


@@ 86,9 90,9 @@ public:
   * (actually, into our out_buf and signal the poller that we want to wach
   * for send events to be ready)
   */
  void send_message(IrcMessage message, bool throttle=true);
  void send_message(IrcMessage message, MessageCallback callback={}, bool throttle=true);
  void send_raw(const std::string& txt);
  void actual_send(const IrcMessage& message);
  void actual_send(std::pair<IrcMessage, MessageCallback> message_pair);
  /**
   * Send the PONG irc command
   */


@@ 117,7 121,8 @@ public:
   * Send a PRIVMSG command for a channel
   * Return true if the message was actually sent
   */
  bool send_channel_message(const std::string& chan_name, const std::string& body);
  bool send_channel_message(const std::string& chan_name, const std::string& body,
                            MessageCallback callback);
  /**
   * Send a PRIVMSG command for an user
   */


@@ 336,7 341,7 @@ private:
  /**
   * Where messaged are stored when they are throttled.
   */
  std::deque<IrcMessage> message_queue{};
  std::deque<std::pair<IrcMessage, MessageCallback>> message_queue{};
  /**
   * The list of joined channels, indexed by name
   */