Handle KICK in irc channel, both ways
This commit is contained in:
@@ -122,6 +122,13 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick)
|
|||||||
irc->send_nick_command(new_nick);
|
irc->send_nick_command(new_nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason)
|
||||||
|
{
|
||||||
|
IrcClient* irc = this->get_irc_client(iid.server);
|
||||||
|
if (irc)
|
||||||
|
irc->send_kick_command(iid.chan, target, reason);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -180,3 +187,8 @@ std::string Bridge::get_own_nick(const Iid& iid)
|
|||||||
return irc->get_own_nick();
|
return irc->get_own_nick();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author)
|
||||||
|
{
|
||||||
|
this->xmpp->kick_user(iid.chan + "%" + iid.server, target, reason, author, this->user_jid);
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public:
|
|||||||
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);
|
void send_irc_nick_change(const Iid& iid, const std::string& new_nick);
|
||||||
|
void send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
**
|
**
|
||||||
@@ -76,6 +77,7 @@ public:
|
|||||||
* true) changed his nick to new_nick
|
* 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);
|
void send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self);
|
||||||
|
void kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Misc
|
* Misc
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ void IrcClient::send_nick_command(const std::string& nick)
|
|||||||
this->send_message(IrcMessage("NICK", {nick}));
|
this->send_message(IrcMessage("NICK", {nick}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IrcClient::send_kick_command(const std::string& chan_name, const std::string& target, const std::string& reason)
|
||||||
|
{
|
||||||
|
this->send_message(IrcMessage("KICK", {chan_name, target, reason}));
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -311,6 +316,21 @@ void IrcClient::on_nick(const IrcMessage& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IrcClient::on_kick(const IrcMessage& message)
|
||||||
|
{
|
||||||
|
const std::string target = message.arguments[1];
|
||||||
|
const std::string reason = message.arguments[2];
|
||||||
|
const std::string chan_name = message.arguments[0];
|
||||||
|
IrcChannel* channel = this->get_channel(chan_name);
|
||||||
|
if (channel->get_self()->nick == target)
|
||||||
|
channel->joined = false;
|
||||||
|
IrcUser author(message.prefix);
|
||||||
|
Iid iid;
|
||||||
|
iid.chan = chan_name;
|
||||||
|
iid.server = this->hostname;
|
||||||
|
this->bridge->kick_muc_user(std::move(iid), target, reason, author.nick);
|
||||||
|
}
|
||||||
|
|
||||||
void IrcClient::on_mode(const IrcMessage& message)
|
void IrcClient::on_mode(const IrcMessage& message)
|
||||||
{
|
{
|
||||||
const std::string target = message.arguments[0];
|
const std::string target = message.arguments[0];
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ public:
|
|||||||
* Send the MODE irc command
|
* Send the MODE irc command
|
||||||
*/
|
*/
|
||||||
void send_mode_command(const std::string& chan_name, const std::vector<std::string>& arguments);
|
void send_mode_command(const std::string& chan_name, const std::vector<std::string>& arguments);
|
||||||
|
/**
|
||||||
|
* Send the KICK irc command
|
||||||
|
*/
|
||||||
|
void send_kick_command(const std::string& chan_name, const std::string& target, const std::string& reason);
|
||||||
/**
|
/**
|
||||||
* Forward the server message received from IRC to the XMPP component
|
* Forward the server message received from IRC to the XMPP component
|
||||||
*/
|
*/
|
||||||
@@ -124,6 +128,7 @@ public:
|
|||||||
void on_welcome_message(const IrcMessage& message);
|
void on_welcome_message(const IrcMessage& message);
|
||||||
void on_part(const IrcMessage& message);
|
void on_part(const IrcMessage& message);
|
||||||
void on_nick(const IrcMessage& message);
|
void on_nick(const IrcMessage& message);
|
||||||
|
void on_kick(const IrcMessage& message);
|
||||||
void on_mode(const IrcMessage& message);
|
void on_mode(const IrcMessage& message);
|
||||||
/**
|
/**
|
||||||
* A mode towards our own user is received (note, that is different from a
|
* A mode towards our own user is received (note, that is different from a
|
||||||
@@ -194,6 +199,7 @@ static const std::unordered_map<std::string, irc_callback_t> irc_callbacks = {
|
|||||||
{"NICK", &IrcClient::on_nick},
|
{"NICK", &IrcClient::on_nick},
|
||||||
{"MODE", &IrcClient::on_mode},
|
{"MODE", &IrcClient::on_mode},
|
||||||
{"PING", &IrcClient::send_pong_command},
|
{"PING", &IrcClient::send_pong_command},
|
||||||
|
{"KICK", &IrcClient::on_kick},
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IRC_CLIENT_INCLUDED
|
#endif // IRC_CLIENT_INCLUDED
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#define COMPONENT_NS "jabber:component:accept"
|
#define COMPONENT_NS "jabber:component:accept"
|
||||||
#define MUC_NS "http://jabber.org/protocol/muc"
|
#define MUC_NS "http://jabber.org/protocol/muc"
|
||||||
#define MUC_USER_NS MUC_NS"#user"
|
#define MUC_USER_NS MUC_NS"#user"
|
||||||
|
#define MUC_ADMIN_NS MUC_NS"#admin"
|
||||||
#define DISCO_NS "http://jabber.org/protocol/disco"
|
#define DISCO_NS "http://jabber.org/protocol/disco"
|
||||||
#define DISCO_ITEMS_NS DISCO_NS"#items"
|
#define DISCO_ITEMS_NS DISCO_NS"#items"
|
||||||
#define DISCO_INFO_NS DISCO_NS"#info"
|
#define DISCO_INFO_NS DISCO_NS"#info"
|
||||||
@@ -36,6 +37,8 @@ XmppComponent::XmppComponent(const std::string& hostname, const std::string& sec
|
|||||||
std::bind(&XmppComponent::handle_presence, this,std::placeholders::_1));
|
std::bind(&XmppComponent::handle_presence, this,std::placeholders::_1));
|
||||||
this->stanza_handlers.emplace(COMPONENT_NS":message",
|
this->stanza_handlers.emplace(COMPONENT_NS":message",
|
||||||
std::bind(&XmppComponent::handle_message, this,std::placeholders::_1));
|
std::bind(&XmppComponent::handle_message, this,std::placeholders::_1));
|
||||||
|
this->stanza_handlers.emplace(COMPONENT_NS":iq",
|
||||||
|
std::bind(&XmppComponent::handle_iq, this,std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
XmppComponent::~XmppComponent()
|
XmppComponent::~XmppComponent()
|
||||||
@@ -201,6 +204,46 @@ void XmppComponent::handle_message(const Stanza& stanza)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmppComponent::handle_iq(const Stanza& stanza)
|
||||||
|
{
|
||||||
|
Bridge* bridge = this->get_user_bridge(stanza["from"]);
|
||||||
|
Jid to(stanza["to"]);
|
||||||
|
std::string type;
|
||||||
|
try {
|
||||||
|
type = stanza["type"];
|
||||||
|
}
|
||||||
|
catch (const AttributeNotFound&)
|
||||||
|
{ return; }
|
||||||
|
if (type == "set")
|
||||||
|
{
|
||||||
|
XmlNode* query;
|
||||||
|
if ((query = stanza.get_child(MUC_ADMIN_NS":query")))
|
||||||
|
{
|
||||||
|
XmlNode* child;
|
||||||
|
if ((child = query->get_child(MUC_ADMIN_NS":item")))
|
||||||
|
{
|
||||||
|
std::string nick;
|
||||||
|
std::string role;
|
||||||
|
try {
|
||||||
|
nick = (*child)["nick"];
|
||||||
|
role = (*child)["role"];
|
||||||
|
}
|
||||||
|
catch (const AttributeNotFound&)
|
||||||
|
{ return; }
|
||||||
|
if (!nick.empty() && role == "none")
|
||||||
|
{
|
||||||
|
std::string reason;
|
||||||
|
XmlNode* reason_el = child->get_child(MUC_ADMIN_NS":reason");
|
||||||
|
if (reason_el)
|
||||||
|
reason = reason_el->get_inner();
|
||||||
|
Iid iid(to.local);
|
||||||
|
bridge->send_irc_kick(iid, nick, reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bridge* XmppComponent::get_user_bridge(const std::string& user_jid)
|
Bridge* XmppComponent::get_user_bridge(const std::string& user_jid)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -360,3 +403,39 @@ void XmppComponent::send_nick_change(const std::string& muc_name, const std::str
|
|||||||
else
|
else
|
||||||
this->send_user_join(muc_name, new_nick, jid_to);
|
this->send_user_join(muc_name, new_nick, jid_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmppComponent::kick_user(const std::string& muc_name,
|
||||||
|
const std::string& target,
|
||||||
|
const std::string& txt,
|
||||||
|
const std::string& author,
|
||||||
|
const std::string& jid_to)
|
||||||
|
{
|
||||||
|
Stanza presence("presence");
|
||||||
|
presence["from"] = muc_name + "@" + this->served_hostname + "/" + target;
|
||||||
|
presence["to"] = jid_to;
|
||||||
|
presence["type"] = "unavailable";
|
||||||
|
XmlNode x("x");
|
||||||
|
x["xmlns"] = MUC_USER_NS;
|
||||||
|
XmlNode item("item");
|
||||||
|
item["affiliation"] = "none";
|
||||||
|
item["role"] = "none";
|
||||||
|
XmlNode actor("actor");
|
||||||
|
actor["nick"] = author;
|
||||||
|
actor["jid"] = author; // backward compatibility with old clients
|
||||||
|
actor.close();
|
||||||
|
item.add_child(std::move(actor));
|
||||||
|
XmlNode reason("reason");
|
||||||
|
reason.set_inner(txt);
|
||||||
|
reason.close();
|
||||||
|
item.add_child(std::move(reason));
|
||||||
|
item.close();
|
||||||
|
x.add_child(std::move(item));
|
||||||
|
XmlNode status("status");
|
||||||
|
status["code"] = "307";
|
||||||
|
status.close();
|
||||||
|
x.add_child(std::move(status));
|
||||||
|
x.close();
|
||||||
|
presence.add_child(std::move(x));
|
||||||
|
presence.close();
|
||||||
|
this->send_stanza(presence);
|
||||||
|
}
|
||||||
|
|||||||
@@ -83,12 +83,21 @@ public:
|
|||||||
* Indicate that a participant changed his nick
|
* 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);
|
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);
|
||||||
|
/**
|
||||||
|
* An user is kicked from a room
|
||||||
|
*/
|
||||||
|
void kick_user(const std::string& muc_name,
|
||||||
|
const std::string& target,
|
||||||
|
const std::string& reason,
|
||||||
|
const std::string& author,
|
||||||
|
const std::string& jid_to);
|
||||||
/**
|
/**
|
||||||
* Handle the various stanza types
|
* Handle the various stanza types
|
||||||
*/
|
*/
|
||||||
void handle_handshake(const Stanza& stanza);
|
void handle_handshake(const Stanza& stanza);
|
||||||
void handle_presence(const Stanza& stanza);
|
void handle_presence(const Stanza& stanza);
|
||||||
void handle_message(const Stanza& stanza);
|
void handle_message(const Stanza& stanza);
|
||||||
|
void handle_iq(const Stanza& stanza);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user