From 5817a95b5ee89480788832be35679dfcd2ed833b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 12 Nov 2013 23:43:43 +0100 Subject: Basic handling of modes, both ways --- src/bridge/bridge.cpp | 7 +++++++ src/irc/irc_channel.hpp | 1 - src/irc/irc_client.cpp | 43 ++++++++++++++++++++++++++++++++++++++++--- src/irc/irc_client.hpp | 19 +++++++++++++------ src/utils/split.cpp | 18 ++++++++++++++++++ src/utils/split.hpp | 10 +--------- src/xmpp/xmpp_component.cpp | 5 ++++- 7 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 src/utils/split.cpp (limited to 'src') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d292af3..0b26a7f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -4,6 +4,7 @@ #include #include +#include #include 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 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 diff --git a/src/irc/irc_channel.hpp b/src/irc/irc_channel.hpp index 3786697..c4b6d2c 100644 --- a/src/irc/irc_channel.hpp +++ b/src/irc/irc_channel.hpp @@ -26,7 +26,6 @@ public: private: std::unique_ptr self; std::vector> users; - IrcChannel(const IrcChannel&) = delete; IrcChannel(IrcChannel&&) = delete; IrcChannel& operator=(const IrcChannel&) = delete; diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp index 30b1204..0d8c614 100644 --- a/src/irc/irc_client.cpp +++ b/src/irc/irc_client.cpp @@ -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& arguments) +{ + std::vector 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] + "]"); +} diff --git a/src/irc/irc_client.hpp b/src/irc/irc_client.hpp index d9ea069..722f850 100644 --- a/src/irc/irc_client.hpp +++ b/src/irc/irc_client.hpp @@ -87,6 +87,10 @@ public: * Send the PART irc command */ 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& arguments); /** * Forward the server message received from IRC to the XMPP component */ @@ -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: diff --git a/src/utils/split.cpp b/src/utils/split.cpp new file mode 100644 index 0000000..82852ee --- /dev/null +++ b/src/utils/split.cpp @@ -0,0 +1,18 @@ +#include + +namespace utils +{ + std::vector split(const std::string &s, const char delim, const bool allow_empty) + { + std::vector 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; + } +} diff --git a/src/utils/split.hpp b/src/utils/split.hpp index 0067131..9fee90a 100644 --- a/src/utils/split.hpp +++ b/src/utils/split.hpp @@ -7,15 +7,7 @@ namespace utils { - std::vector split(const std::string &s, const char delim) - { - std::vector ret; - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) - ret.emplace_back(std::move(item)); - return ret; - } + std::vector split(const std::string &s, const char delim, const bool allow_empty=true); } #endif // SPLIT_INCLUDED diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp index e2063ba..c36a141 100644 --- a/src/xmpp/xmpp_component.cpp +++ b/src/xmpp/xmpp_component.cpp @@ -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); -- cgit v1.2.3