summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/biboumi.1.rst15
-rw-r--r--src/bridge/bridge.cpp16
-rw-r--r--src/bridge/bridge.hpp2
-rw-r--r--src/irc/irc_client.cpp15
-rw-r--r--src/irc/irc_client.hpp5
-rw-r--r--src/xmpp/biboumi_component.cpp13
6 files changed, 64 insertions, 2 deletions
diff --git a/doc/biboumi.1.rst b/doc/biboumi.1.rst
index d4c21d9..783788f 100644
--- a/doc/biboumi.1.rst
+++ b/doc/biboumi.1.rst
@@ -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
--------------
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
index 23fc71d..8323c77 100644
--- a/src/bridge/bridge.cpp
+++ b/src/bridge/bridge.cpp
@@ -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)
diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp
index d7b2a5c..a1ff3ad 100644
--- a/src/bridge/bridge.hpp
+++ b/src/bridge/bridge.hpp
@@ -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.
diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp
index d00b6ee..6d4df4a 100644
--- a/src/irc/irc_client.cpp
+++ b/src/irc/irc_client.cpp
@@ -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];
diff --git a/src/irc/irc_client.hpp b/src/irc/irc_client.hpp
index fa35e65..6fa40ce 100644
--- a/src/irc/irc_client.hpp
+++ b/src/irc/irc_client.hpp
@@ -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);
diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp
index a0222f5..e7549df 100644
--- a/src/xmpp/biboumi_component.cpp
+++ b/src/xmpp/biboumi_component.cpp
@@ -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)