Change IRC modes when receiving an affiliation/role change request
fix #2946
This commit is contained in:
@@ -183,6 +183,72 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bridge::forward_affiliation_role_change(const Iid& iid, const std::string& nick,
|
||||||
|
const std::string& affiliation,
|
||||||
|
const std::string& role)
|
||||||
|
{
|
||||||
|
IrcClient* irc = this->get_irc_client(iid.get_server());
|
||||||
|
if (!irc)
|
||||||
|
return;
|
||||||
|
IrcChannel* chan = irc->get_channel(iid.get_local());
|
||||||
|
if (!chan || !chan->joined)
|
||||||
|
return;
|
||||||
|
IrcUser* user = chan->find_user(nick);
|
||||||
|
if (!user)
|
||||||
|
return;
|
||||||
|
// For each affiliation or role, we have a “maximal” mode that we want to
|
||||||
|
// set. We must remove any superior mode at the same time. For example if
|
||||||
|
// the user already has +o mode, and we set its affiliation to member, we
|
||||||
|
// remove the +o mode, and add +v. For each “superior” mode (for example,
|
||||||
|
// for +v, the superior modes are 'h', 'a', 'o' and 'q') we check if that
|
||||||
|
// user has it, and if yes we remove that mode
|
||||||
|
|
||||||
|
std::size_t nb = 1; // the number of times the nick must be
|
||||||
|
// repeated in the argument list
|
||||||
|
std::string modes; // The string of modes to
|
||||||
|
// add/remove. For example "+v-aoh"
|
||||||
|
std::vector<char> modes_to_remove; // List of modes to check for removal
|
||||||
|
if (affiliation == "none")
|
||||||
|
{
|
||||||
|
modes = "";
|
||||||
|
nb = 0;
|
||||||
|
modes_to_remove = {'v', 'h', 'o', 'a', 'q'};
|
||||||
|
}
|
||||||
|
else if (affiliation == "member")
|
||||||
|
{
|
||||||
|
modes = "+v";
|
||||||
|
modes_to_remove = {'h', 'o', 'a', 'q'};
|
||||||
|
}
|
||||||
|
else if (role == "moderator")
|
||||||
|
{
|
||||||
|
modes = "+h";
|
||||||
|
modes_to_remove = {'o', 'a', 'q'};
|
||||||
|
}
|
||||||
|
else if (affiliation == "admin")
|
||||||
|
{
|
||||||
|
modes = "+o";
|
||||||
|
modes_to_remove = {'a', 'q'};
|
||||||
|
}
|
||||||
|
else if (affiliation == "owner")
|
||||||
|
{
|
||||||
|
modes = "+a";
|
||||||
|
modes_to_remove = {'q'};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
for (const char mode: modes_to_remove)
|
||||||
|
if (user->modes.find(mode) != user->modes.end())
|
||||||
|
{
|
||||||
|
modes += "-"s + mode;
|
||||||
|
nb++;
|
||||||
|
}
|
||||||
|
if (modes.empty())
|
||||||
|
return;
|
||||||
|
std::vector<std::string> args(nb, nick);
|
||||||
|
args.insert(args.begin(), modes);
|
||||||
|
irc->send_mode_command(iid.get_local(), args);
|
||||||
|
}
|
||||||
|
|
||||||
void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type)
|
void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type)
|
||||||
{
|
{
|
||||||
if (iid.get_local().empty() || iid.get_server().empty())
|
if (iid.get_local().empty() || iid.get_server().empty())
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ public:
|
|||||||
void send_irc_version_request(const std::string& irc_hostname, const std::string& target,
|
void send_irc_version_request(const std::string& irc_hostname, const std::string& target,
|
||||||
const std::string& iq_id, const std::string& to_jid,
|
const std::string& iq_id, const std::string& to_jid,
|
||||||
const std::string& from_jid);
|
const std::string& from_jid);
|
||||||
|
void forward_affiliation_role_change(const Iid& iid, const std::string& nick,
|
||||||
|
const std::string& affiliation, const std::string& role);
|
||||||
/**
|
/**
|
||||||
* Directly send a CTCP PING request to the IRC user
|
* Directly send a CTCP PING request to the IRC user
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -481,14 +481,20 @@ void XmppComponent::handle_iq(const Stanza& stanza)
|
|||||||
{
|
{
|
||||||
std::string nick = child->get_tag("nick");
|
std::string nick = child->get_tag("nick");
|
||||||
std::string role = child->get_tag("role");
|
std::string role = child->get_tag("role");
|
||||||
if (!nick.empty() && role == "none")
|
std::string affiliation = child->get_tag("affiliation");
|
||||||
|
if (!nick.empty())
|
||||||
|
{
|
||||||
|
Iid iid(to.local);
|
||||||
|
if (role == "none")
|
||||||
{ // This is a kick
|
{ // This is a kick
|
||||||
std::string reason;
|
std::string reason;
|
||||||
XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS);
|
XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS);
|
||||||
if (reason_el)
|
if (reason_el)
|
||||||
reason = reason_el->get_inner();
|
reason = reason_el->get_inner();
|
||||||
Iid iid(to.local);
|
|
||||||
bridge->send_irc_kick(iid, nick, reason, id, from);
|
bridge->send_irc_kick(iid, nick, reason, id, from);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bridge->forward_affiliation_role_change(iid, nick, affiliation, role);
|
||||||
stanza_error.disable();
|
stanza_error.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user