~singpolyma/biboumi

663d4ad54a014b2ced62610098a6f5676f813d10 — louiz’ 6 years ago 6bbab9d
Forward mediated invitations (XMPP to IRC only)
M doc/biboumi.1.rst => doc/biboumi.1.rst +15 -0
@@ 339,6 339,21 @@ Notices
Notices are received exactly like private messages.  It is not possible to
send a notice.

Invitations
-----------

Biboumi forwards the mediated invitations to the target nick.  If the user
wishes to invite the user “FooBar” into a room, they can invite one of the
following “JIDs” (one of them is not a JID, actually):

- foobar%anything@anything
- anything@anything/FooBar
- FooBar

Note that the “anything” part are simply ignored because they have no
meaning for the IRC server: we already know which IRC server is targeted
using the JID of the target channel.

Kicks and bans
--------------


M src/bridge/bridge.cpp => src/bridge/bridge.cpp +16 -0
@@ 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)

M src/bridge/bridge.hpp => src/bridge/bridge.hpp +2 -0
@@ 105,6 105,8 @@ public:
  void on_gateway_ping(const std::string& irc_hostname, const std::string& iq_id, const std::string& to_jid,
                       const std::string& from_jid);

  void send_irc_invitation(const Iid& iid, const std::string to);

  /***
   **
   ** From IRC to XMPP.

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +13 -2
@@ 64,6 64,8 @@ static const std::unordered_map<std::string,
  {"432", {&IrcClient::on_erroneous_nickname, {2, 0}}},
  {"433", {&IrcClient::on_nickname_conflict, {2, 0}}},
  {"438", {&IrcClient::on_nickname_change_too_fast, {2, 0}}},
  {"443", {&IrcClient::on_useronchannel, {3, 0}}},
  {"ERR_USERONCHANNEL", {&IrcClient::on_useronchannel, {3, 0}}},
  {"001", {&IrcClient::on_welcome_message, {1, 0}}},
  {"PART", {&IrcClient::on_part, {1, 0}}},
  {"ERROR", {&IrcClient::on_error, {1, 0}}},


@@ 95,7 97,6 @@ static const std::unordered_map<std::string,
  {"436", {&IrcClient::on_generic_error, {2, 0}}},
  {"441", {&IrcClient::on_generic_error, {2, 0}}},
  {"442", {&IrcClient::on_generic_error, {2, 0}}},
  {"443", {&IrcClient::on_generic_error, {2, 0}}},
  {"444", {&IrcClient::on_generic_error, {2, 0}}},
  {"446", {&IrcClient::on_generic_error, {2, 0}}},
  {"451", {&IrcClient::on_generic_error, {2, 0}}},


@@ 429,6 430,11 @@ void IrcClient::send_list_command()
  this->send_message(IrcMessage("LIST", {}));
}

void IrcClient::send_invitation(const std::string& chan_name, const std::string& nick)
{
  this->send_message(IrcMessage("INVITE", {nick, chan_name}));
}

void IrcClient::send_topic_command(const std::string& chan_name, const std::string& topic)
{
  this->send_message(IrcMessage("TOPIC", {chan_name, topic}));


@@ 803,7 809,6 @@ void IrcClient::on_nickname_change_too_fast(const IrcMessage& message)
                                      "", txt);
  }
}

void IrcClient::on_generic_error(const IrcMessage& message)
{
  const std::string error_msg = message.arguments.size() >= 3 ?


@@ 811,6 816,12 @@ void IrcClient::on_generic_error(const IrcMessage& message)
  this->send_gateway_message(message.arguments[1] + ": " + error_msg, message.prefix);
}

void IrcClient::on_useronchannel(const IrcMessage& message)
{
  this->send_gateway_message(message.arguments[1] + " " + message.arguments[3] + " "
                             + message.arguments[2]);
}

void IrcClient::on_welcome_message(const IrcMessage& message)
{
  this->current_nick = message.arguments[0];

M src/irc/irc_client.hpp => src/irc/irc_client.hpp +5 -0
@@ 129,6 129,7 @@ public:
   * Send the LIST irc command
   */
  void send_list_command();
  void send_invitation(const std::string& chan_name, const std::string& nick);
  void send_topic_command(const std::string& chan_name, const std::string& topic);
  /**
   * Send the QUIT irc command


@@ 235,6 236,10 @@ public:
   */
  void on_nickname_change_too_fast(const IrcMessage& message);
  /**
   * An error when we try to invite a user already in the channel
   */
  void on_useronchannel(const IrcMessage& message);
  /**
   * Handles most errors from the server by just forwarding the message to the user.
   */
  void on_generic_error(const IrcMessage& message);

M src/xmpp/biboumi_component.cpp => src/xmpp/biboumi_component.cpp +13 -0
@@ 254,6 254,19 @@ void BiboumiComponent::handle_message(const Stanza& stanza)
            }
        }
    }
  else if (type == "normal" && iid.type == Iid::Type::Channel)
    {
      if (const XmlNode* x = stanza.get_child("x", MUC_USER_NS))
        if (const XmlNode* invite = x->get_child("invite", MUC_USER_NS))
          {
            const auto invite_to = invite->get_tag("to");
            if (!invite_to.empty())
              {
                bridge->send_irc_invitation(iid, invite_to);
              }
          }

    }
  else if (iid.type == Iid::Type::User)
    this->send_invalid_user_error(to.local, from);
  } catch (const IRCNotConnected& ex)