From 7c671499350e22f8bfba2f72b9827aa5b200f7b0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Nov 2013 23:17:48 +0100 Subject: Implement part and join, both ways --- src/irc/irc_channel.cpp | 24 ++++++++++++++++++++++ src/irc/irc_channel.hpp | 2 ++ src/irc/irc_client.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++------- src/irc/irc_client.hpp | 10 ++++++++- src/irc/irc_user.cpp | 8 ++++++-- 5 files changed, 88 insertions(+), 10 deletions(-) (limited to 'src/irc') diff --git a/src/irc/irc_channel.cpp b/src/irc/irc_channel.cpp index 223305b..6daf708 100644 --- a/src/irc/irc_channel.cpp +++ b/src/irc/irc_channel.cpp @@ -22,3 +22,27 @@ IrcUser* IrcChannel::get_self() const { return this->self.get(); } + +IrcUser* IrcChannel::find_user(const std::string& name) +{ + IrcUser user(name); + for (const auto& u: this->users) + { + if (u->nick == user.nick) + return u.get(); + } + return nullptr; +} + +void IrcChannel::remove_user(const IrcUser* user) +{ + for (auto it = this->users.begin(); it != this->users.end(); ++it) + { + IrcUser* u = it->get(); + if (u->nick == user->nick) + { + this->users.erase(it); + break ; + } + } +} diff --git a/src/irc/irc_channel.hpp b/src/irc/irc_channel.hpp index da0f298..3786697 100644 --- a/src/irc/irc_channel.hpp +++ b/src/irc/irc_channel.hpp @@ -20,6 +20,8 @@ public: void set_self(const std::string& name); IrcUser* get_self() const; IrcUser* add_user(const std::string& name); + IrcUser* find_user(const std::string& name); + void remove_user(const IrcUser* user); private: std::unique_ptr self; diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp index cf57bd7..e3d7653 100644 --- a/src/irc/irc_client.cpp +++ b/src/irc/irc_client.cpp @@ -76,7 +76,7 @@ void IrcClient::parse_in_buffer() message.command == "372") this->forward_server_message(message); else if (message.command == "JOIN") - this->on_self_channel_join(message); + this->on_channel_join(message); else if (message.command == "PRIVMSG") this->on_channel_message(message); else if (message.command == "353") @@ -87,6 +87,8 @@ void IrcClient::parse_in_buffer() this->on_channel_completely_joined(message); else if (message.command == "001") this->on_welcome_message(message); + else if (message.command == "PART") + this->on_part(message); } } @@ -128,9 +130,7 @@ void IrcClient::send_join_command(const std::string& chan_name) this->channels_to_join.push_back(chan_name); return ; } - IrcChannel* channel = this->get_channel(chan_name); - if (channel->joined == false) - this->send_message(IrcMessage("JOIN", {chan_name})); + this->send_message(IrcMessage("JOIN", {chan_name})); } bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body) @@ -145,6 +145,15 @@ bool IrcClient::send_channel_message(const std::string& chan_name, const std::st return true; } +void IrcClient::send_part_command(const std::string& chan_name, const std::string& status_message) +{ + IrcChannel* channel = this->get_channel(chan_name); + if (channel->joined == true) + { + this->send_message(IrcMessage("PART", {chan_name, status_message})); + } +} + void IrcClient::send_pong_command(const IrcMessage& message) { const std::string id = message.arguments[0]; @@ -175,12 +184,21 @@ void IrcClient::set_and_forward_user_list(const IrcMessage& message) } } -void IrcClient::on_self_channel_join(const IrcMessage& message) +void IrcClient::on_channel_join(const IrcMessage& message) { const std::string chan_name = message.arguments[0]; IrcChannel* channel = this->get_channel(chan_name); - channel->joined = true; - channel->set_self(message.prefix); + const std::string nick = message.prefix; + if (channel->joined == false) + { + channel->joined = true; + channel->set_self(nick); + } + else + { + IrcUser* user = channel->add_user(nick); + this->bridge->send_user_join(this->hostname, chan_name, user->nick); + } } void IrcClient::on_channel_message(const IrcMessage& message) @@ -217,3 +235,25 @@ void IrcClient::on_welcome_message(const IrcMessage& message) this->send_join_command(chan_name); this->channels_to_join.clear(); } + +void IrcClient::on_part(const IrcMessage& message) +{ + const std::string chan_name = message.arguments[0]; + IrcChannel* channel = this->get_channel(chan_name); + std::string txt; + if (message.arguments.size() >= 2) + txt = message.arguments[1]; + const IrcUser* user = channel->find_user(message.prefix); + if (user) + { + std::string nick = user->nick; + channel->remove_user(user); + Iid iid; + iid.chan = chan_name; + iid.server = this->hostname; + bool self = channel->get_self()->nick == nick; + this->bridge->send_muc_leave(std::move(iid), std::move(nick), std::move(txt), self); + if (self) + channel->joined = false; + } +} diff --git a/src/irc/irc_client.hpp b/src/irc/irc_client.hpp index 50f3781..e58ffbc 100644 --- a/src/irc/irc_client.hpp +++ b/src/irc/irc_client.hpp @@ -75,6 +75,10 @@ public: * Return true if the message was actually sent */ bool send_channel_message(const std::string& chan_name, const std::string& body); + /** + * Send the PART irc command + */ + void send_part_command(const std::string& chan_name, const std::string& status_message); /** * Forward the server message received from IRC to the XMPP component */ @@ -88,7 +92,7 @@ public: * Remember our nick and host, when we are joined to the channel. The list * of user comes after so we do not send the self-presence over XMPP yet. */ - void on_self_channel_join(const IrcMessage& message); + void on_channel_join(const IrcMessage& message); /** * When a channel message is received */ @@ -106,6 +110,10 @@ 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); private: /** diff --git a/src/irc/irc_user.cpp b/src/irc/irc_user.cpp index fc853bc..afe8623 100644 --- a/src/irc/irc_user.cpp +++ b/src/irc/irc_user.cpp @@ -7,14 +7,18 @@ IrcUser::IrcUser(const std::string& name) const std::string::size_type sep = name.find("!"); if (sep == std::string::npos) { - if (name[0] == '@' || name[0] == '+') + if (name[0] == '~' || name[0] == '&' + || name[0] == '@' || name[0] == '%' + || name[0] == '+') this->nick = name.substr(1); else this->nick = name; } else { - if (name[0] == '@' || name[0] == '+') + if (name[0] == '~' || name[0] == '&' + || name[0] == '@' || name[0] == '%' + || name[0] == '+') this->nick = name.substr(1, sep); else this->nick = name.substr(0, sep); -- cgit v1.2.3