Commit 096a4e3b authored by louiz’'s avatar louiz’

Handle nick changes, both ways

parent f0d9273d
......@@ -59,10 +59,15 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname)
}
}
void Bridge::join_irc_channel(const Iid& iid, const std::string& username)
bool Bridge::join_irc_channel(const Iid& iid, const std::string& username)
{
IrcClient* irc = this->get_irc_client(iid.server, username);
if (irc->is_channel_joined(iid.chan) == false)
{
irc->send_join_command(iid.chan);
return true;
}
return false;
}
void Bridge::send_channel_message(const Iid& iid, const std::string& body)
......@@ -103,6 +108,13 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message)
irc->send_part_command(iid.chan, status_message);
}
void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick)
{
IrcClient* irc = this->get_irc_client(iid.server);
if (irc)
irc->send_nick_command(new_nick);
}
void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc)
{
std::string utf8_body = this->sanitize_for_xmpp(body);
......@@ -118,11 +130,17 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st
this->xmpp->send_message(iid.chan + "%" + iid.server, utf8_body, this->user_jid);
}
void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self)
void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self)
{
this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->sanitize_for_xmpp(message), this->user_jid, self);
}
void Bridge::send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self)
{
this->xmpp->send_nick_change(std::move(iid.chan) + "%" + std::move(iid.server),
old_nick, new_nick, this->user_jid, self);
}
void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg)
{
std::string body;
......@@ -147,3 +165,11 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam
{
this->xmpp->send_topic(chan_name + "%" + hostname, this->sanitize_for_xmpp(topic), this->user_jid);
}
std::string Bridge::get_own_nick(const Iid& iid)
{
IrcClient* irc = this->get_irc_client(iid.server);
if (irc)
return irc->get_own_nick();
return "";
}
......@@ -30,10 +30,15 @@ public:
**
**/
void join_irc_channel(const Iid& iid, const std::string& username);
/**
* Try to join an irc_channel, does nothing and return true if the channel
* was already joined.
*/
bool join_irc_channel(const Iid& iid, const std::string& username);
void send_channel_message(const Iid& iid, const std::string& body);
void send_private_message(const Iid& iid, const std::string& body);
void leave_irc_channel(Iid&& iid, std::string&& status_message);
void send_irc_nick_change(const Iid& iid, const std::string& new_nick);
/***
**
......@@ -65,7 +70,17 @@ public:
/**
* Send an unavailable presence from this participant
*/
void send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self);
void send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self);
/**
* Send presences to indicate that an user old_nick (ourself if self ==
* true) changed his nick to new_nick
*/
void send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self);
/**
* Misc
*/
std::string get_own_nick(const Iid& iid);
private:
/**
......
......@@ -53,6 +53,12 @@ IrcChannel* IrcClient::get_channel(const std::string& name)
}
}
bool IrcClient::is_channel_joined(const std::string& name)
{
IrcChannel* client = this->get_channel(name);
return client->joined;
}
std::string IrcClient::get_own_nick() const
{
return this->current_nick;
......@@ -91,6 +97,8 @@ void IrcClient::parse_in_buffer()
this->on_part(message);
else if (message.command == "QUIT")
this->on_quit(message);
else if (message.command == "NICK")
this->on_nick(message);
}
}
......@@ -128,10 +136,8 @@ void IrcClient::send_nick_command(const std::string& nick)
void IrcClient::send_join_command(const std::string& chan_name)
{
if (this->welcomed == false)
{
this->channels_to_join.push_back(chan_name);
return ;
}
else
this->send_message(IrcMessage("JOIN", {chan_name}));
}
......@@ -288,7 +294,34 @@ void IrcClient::on_quit(const IrcMessage& message)
Iid iid;
iid.chan = chan_name;
iid.server = this->hostname;
this->bridge->send_muc_leave(std::move(iid), std::move(nick), std::move(txt), false);
this->bridge->send_muc_leave(std::move(iid), std::move(nick), txt, false);
}
}
}
void IrcClient::on_nick(const IrcMessage& message)
{
const std::string new_nick = message.arguments[0];
for (auto it = this->channels.begin(); it != this->channels.end(); ++it)
{
const std::string chan_name = it->first;
IrcChannel* channel = it->second.get();
IrcUser* user = channel->find_user(message.prefix);
if (user)
{
std::string old_nick = user->nick;
Iid iid;
iid.chan = chan_name;
iid.server = this->hostname;
bool self = channel->get_self()->nick == old_nick;
this->bridge->send_nick_change(std::move(iid), old_nick, new_nick, self);
user->nick = new_nick;
if (self)
{
channel->get_self()->nick = new_nick;
this->current_nick = new_nick;
}
}
}
}
......@@ -44,6 +44,10 @@ public:
* Return the channel with this name, create it if it does not yet exist
*/
IrcChannel* get_channel(const std::string& name);
/**
* Returns true if the channel is joined
*/
bool is_channel_joined(const std::string& name);
/**
* Return our own nick
*/
......@@ -67,7 +71,7 @@ public:
*/
void send_nick_command(const std::string& username);
/**
* Send the JOIN irc command
* Send the JOIN irc command.
*/
void send_join_command(const std::string& chan_name);
/**
......@@ -118,6 +122,10 @@ public:
* When a PART message is received
*/
void on_part(const IrcMessage& message);
/**
* When a NICK message is received
*/
void on_nick(const IrcMessage& message);
/**
* When a QUIT message is received
*/
......
......@@ -167,7 +167,13 @@ void XmppComponent::handle_presence(const Stanza& stanza)
if (!iid.chan.empty() && !iid.chan.empty())
{ // presence toward a MUC that corresponds to an irc channel
if (type.empty())
{
const std::string own_nick = bridge->get_own_nick(iid);
if (!own_nick.empty() && own_nick != to.resource)
bridge->send_irc_nick_change(iid, to.resource);
else
bridge->join_irc_channel(iid, to.resource);
}
else if (type == "unavailable")
{
XmlNode* status = stanza.get_child(MUC_USER_NS":status");
......@@ -317,3 +323,37 @@ void XmppComponent::send_muc_leave(std::string&& muc_name, std::string&& nick, s
presence.close();
this->send_stanza(presence);
}
void XmppComponent::send_nick_change(const std::string& muc_name, const std::string& old_nick, const std::string& new_nick, const std::string& jid_to, const bool self)
{
Stanza presence("presence");
presence["to"] = jid_to;
presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick;
presence["type"] = "unavailable";
XmlNode x("x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
item["nick"] = new_nick;
item.close();
x.add_child(std::move(item));
XmlNode status("status");
status["code"] = "303";
status.close();
x.add_child(std::move(status));
if (self)
{
XmlNode status2("status");
status2["code"] = "110";
status2.close();
x.add_child(std::move(status2));
}
x.close();
presence.add_child(std::move(x));
presence.close();
this->send_stanza(presence);
if (self)
this->send_self_join(muc_name, new_nick, jid_to);
else
this->send_user_join(muc_name, new_nick, jid_to);
}
......@@ -79,6 +79,10 @@ public:
* Send an unavailable presence for this nick
*/
void send_muc_leave(std::string&& muc_name, std::string&& nick, std::string&& message, const std::string& jid_to, const bool self);
/**
* Indicate that a participant changed his nick
*/
void send_nick_change(const std::string& muc_name, const std::string& old_nick, const std::string& new_nick, const std::string& jid_to, const bool self);
/**
* Handle the various stanza types
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment