Handle nick changes, both ways
This commit is contained in:
+29
-3
@@ -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);
|
IrcClient* irc = this->get_irc_client(iid.server, username);
|
||||||
irc->send_join_command(iid.chan);
|
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)
|
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);
|
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)
|
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);
|
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);
|
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);
|
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)
|
void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg)
|
||||||
{
|
{
|
||||||
std::string body;
|
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);
|
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 "";
|
||||||
|
}
|
||||||
|
|||||||
+17
-2
@@ -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_channel_message(const Iid& iid, const std::string& body);
|
||||||
void send_private_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 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
|
* 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:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|||||||
+39
-6
@@ -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
|
std::string IrcClient::get_own_nick() const
|
||||||
{
|
{
|
||||||
return this->current_nick;
|
return this->current_nick;
|
||||||
@@ -91,6 +97,8 @@ void IrcClient::parse_in_buffer()
|
|||||||
this->on_part(message);
|
this->on_part(message);
|
||||||
else if (message.command == "QUIT")
|
else if (message.command == "QUIT")
|
||||||
this->on_quit(message);
|
this->on_quit(message);
|
||||||
|
else if (message.command == "NICK")
|
||||||
|
this->on_nick(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,11 +136,9 @@ void IrcClient::send_nick_command(const std::string& nick)
|
|||||||
void IrcClient::send_join_command(const std::string& chan_name)
|
void IrcClient::send_join_command(const std::string& chan_name)
|
||||||
{
|
{
|
||||||
if (this->welcomed == false)
|
if (this->welcomed == false)
|
||||||
{
|
this->channels_to_join.push_back(chan_name);
|
||||||
this->channels_to_join.push_back(chan_name);
|
else
|
||||||
return ;
|
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)
|
bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body)
|
||||||
@@ -288,7 +294,34 @@ void IrcClient::on_quit(const IrcMessage& message)
|
|||||||
Iid iid;
|
Iid iid;
|
||||||
iid.chan = chan_name;
|
iid.chan = chan_name;
|
||||||
iid.server = this->hostname;
|
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
|
* Return the channel with this name, create it if it does not yet exist
|
||||||
*/
|
*/
|
||||||
IrcChannel* get_channel(const std::string& name);
|
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
|
* Return our own nick
|
||||||
*/
|
*/
|
||||||
@@ -67,7 +71,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void send_nick_command(const std::string& username);
|
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);
|
void send_join_command(const std::string& chan_name);
|
||||||
/**
|
/**
|
||||||
@@ -118,6 +122,10 @@ public:
|
|||||||
* When a PART message is received
|
* When a PART message is received
|
||||||
*/
|
*/
|
||||||
void on_part(const IrcMessage& message);
|
void on_part(const IrcMessage& message);
|
||||||
|
/**
|
||||||
|
* When a NICK message is received
|
||||||
|
*/
|
||||||
|
void on_nick(const IrcMessage& message);
|
||||||
/**
|
/**
|
||||||
* When a QUIT message is received
|
* When a QUIT message is received
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -167,7 +167,13 @@ void XmppComponent::handle_presence(const Stanza& stanza)
|
|||||||
if (!iid.chan.empty() && !iid.chan.empty())
|
if (!iid.chan.empty() && !iid.chan.empty())
|
||||||
{ // presence toward a MUC that corresponds to an irc channel
|
{ // presence toward a MUC that corresponds to an irc channel
|
||||||
if (type.empty())
|
if (type.empty())
|
||||||
bridge->join_irc_channel(iid, to.resource);
|
{
|
||||||
|
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")
|
else if (type == "unavailable")
|
||||||
{
|
{
|
||||||
XmlNode* status = stanza.get_child(MUC_USER_NS":status");
|
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();
|
presence.close();
|
||||||
this->send_stanza(presence);
|
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
|
* 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);
|
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
|
* Handle the various stanza types
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user