mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 18:49:03 -04:00
Add m_clearchan which removes users from a channel without sending n*(n+1)/2 QUIT messages
This commit is contained in:
parent
3fef0ed889
commit
7acb4ced20
@ -373,7 +373,7 @@ SAJOIN SAPART SAMODE SATOPIC SAKICK
|
||||
|
||||
KILL SAQUIT GLINE ZLINE QLINE
|
||||
KLINE RLINE ELINE CBAN SHUN
|
||||
FILTER OJOIN
|
||||
FILTER OJOIN CLEARCHAN
|
||||
|
||||
CONNECT SQUIT RCONNECT RSQUIT
|
||||
|
||||
@ -754,6 +754,16 @@ Reloads the specified core command.">
|
||||
|
||||
Closes all unregistered connections to the local server.">
|
||||
|
||||
<helpop key="clearchan" value="/CLEARCHAN <channel> [<KILL|KICK|G|Z>] [<reason>]
|
||||
|
||||
Quits or kicks all non-opers from a channel, optionally G/Z-Lines them.
|
||||
Useful for quickly nuking bot channels.
|
||||
|
||||
The default method, KILL, simply disconnects the victims from the server,
|
||||
while methods G and Z also add G/Z-Lines for all the targets.
|
||||
|
||||
When used, the victims won't see each other getting kicked or quitting.">
|
||||
|
||||
######################
|
||||
# User/Channel Modes #
|
||||
######################
|
||||
|
@ -61,7 +61,7 @@ SAJOIN SAPART SAMODE SATOPIC SAKICK
|
||||
|
||||
KILL SAQUIT GLINE ZLINE QLINE
|
||||
KLINE RLINE ELINE CBAN SHUN
|
||||
FILTER
|
||||
FILTER CLEARCHAN
|
||||
|
||||
CONNECT SQUIT RCONNECT RSQUIT
|
||||
|
||||
|
@ -456,6 +456,11 @@
|
||||
# To use, CHGNAME must be in one of your oper class blocks.
|
||||
#<module name="m_chgname.so">
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# Clear chan module: Allows opers to masskick, masskill or mass-G/ZLine
|
||||
# all users on a channel using /CLEARCHAN.
|
||||
#<module name="m_clearchan.so">
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# Cloaking module: Adds usermode +x and cloaking support.
|
||||
# Relies on the module m_md5.so being loaded.
|
||||
|
@ -40,7 +40,7 @@
|
||||
chanmodes="*">
|
||||
|
||||
<class name="ServerLink" commands="CONNECT SQUIT CONNECT MKPASSWD ALLTIME SWHOIS CLOSE JUMPSERVER LOCKSERV" usermodes="*" chanmodes="*" privs="servers/auspex">
|
||||
<class name="BanControl" commands="KILL GLINE KLINE ZLINE QLINE ELINE TLINE RLINE CHECK NICKLOCK SHUN CLONES CBAN" usermodes="*" chanmodes="*">
|
||||
<class name="BanControl" commands="KILL GLINE KLINE ZLINE QLINE ELINE TLINE RLINE CHECK NICKLOCK SHUN CLONES CBAN CLEARCHAN" usermodes="*" chanmodes="*">
|
||||
<class name="OperChat" commands="WALLOPS GLOBOPS SETIDLE" usermodes="*" chanmodes="*" privs="users/mass-message">
|
||||
<class name="HostCloak" commands="SETHOST SETIDENT SETNAME CHGHOST CHGIDENT" usermodes="*" chanmodes="*" privs="users/auspex">
|
||||
|
||||
|
217
src/modules/m_clearchan.cpp
Normal file
217
src/modules/m_clearchan.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* InspIRCd -- Internet Relay Chat Daemon
|
||||
*
|
||||
* Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
|
||||
*
|
||||
* This file is part of InspIRCd. InspIRCd is free software: you can
|
||||
* redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "xline.h"
|
||||
|
||||
class CommandClearChan : public Command
|
||||
{
|
||||
public:
|
||||
Channel* activechan;
|
||||
|
||||
CommandClearChan(Module* Creator)
|
||||
: Command(Creator, "CLEARCHAN", 1, 3)
|
||||
{
|
||||
syntax = "<channel> [<KILL|KICK|G|Z>] [<reason>]";
|
||||
flags_needed = 'o';
|
||||
|
||||
// Stop the linking mod from forwarding ENCAP'd CLEARCHAN commands, see below why
|
||||
force_manual_route = true;
|
||||
}
|
||||
|
||||
CmdResult Handle(const std::vector<std::string>& parameters, User* user)
|
||||
{
|
||||
Channel* chan = activechan = ServerInstance->FindChan(parameters[0]);
|
||||
if (!chan)
|
||||
{
|
||||
user->WriteNotice("The channel " + parameters[0] + " does not exist.");
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
// See what method the oper wants to use, default to KILL
|
||||
std::string method("KILL");
|
||||
if (parameters.size() > 1)
|
||||
{
|
||||
method = parameters[1];
|
||||
std::transform(method.begin(), method.end(), method.begin(), ::toupper);
|
||||
}
|
||||
|
||||
XLineFactory* xlf = NULL;
|
||||
bool kick = (method == "KICK");
|
||||
if ((!kick) && (method != "KILL"))
|
||||
{
|
||||
if ((method != "Z") && (method != "G"))
|
||||
{
|
||||
user->WriteNotice("Invalid method for clearing " + chan->name);
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
xlf = ServerInstance->XLines->GetFactory(method);
|
||||
if (!xlf)
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
const std::string reason = parameters.size() > 2 ? parameters.back() : "Clearing " + chan->name;
|
||||
|
||||
if (!user->server->IsSilentULine())
|
||||
ServerInstance->SNO->WriteToSnoMask((IS_LOCAL(user) ? 'a' : 'A'), user->nick + " has cleared \002" + chan->name + "\002 (" + method + "): " + reason);
|
||||
|
||||
user->WriteNotice("Clearing \002" + chan->name + "\002 (" + method + "): " + reason);
|
||||
|
||||
{
|
||||
// Route this command manually so it is sent before the QUITs we are about to generate.
|
||||
// The idea is that by the time our QUITs reach the next hop, it has already removed all their
|
||||
// clients from the channel, meaning victims on other servers won't see the victims on this
|
||||
// server quitting.
|
||||
std::vector<std::string> eparams;
|
||||
eparams.push_back(chan->name);
|
||||
eparams.push_back(method);
|
||||
eparams.push_back(":");
|
||||
eparams.back().append(reason);
|
||||
ServerInstance->PI->BroadcastEncap(this->name, eparams, user, user);
|
||||
}
|
||||
|
||||
// Attach to the appropriate hook so we're able to hide the QUIT/KICK messages
|
||||
Implementation hook = (kick ? I_OnUserKick : I_OnBuildNeighborList);
|
||||
ServerInstance->Modules->Attach(hook, creator);
|
||||
|
||||
std::string mask;
|
||||
// Now remove all local non-opers from the channel
|
||||
const UserMembList* users = chan->GetUsers();
|
||||
for (UserMembCIter i = users->begin(); i != users->end(); )
|
||||
{
|
||||
User* curr = i->first;
|
||||
++i;
|
||||
|
||||
if (!IS_LOCAL(curr) || curr->IsOper())
|
||||
continue;
|
||||
|
||||
// If kicking users, remove them and skip the QuitUser()
|
||||
if (kick)
|
||||
{
|
||||
chan->KickUser(ServerInstance->FakeClient, curr, reason);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are banning users then create the XLine and add it
|
||||
if (xlf)
|
||||
{
|
||||
XLine* xline;
|
||||
try
|
||||
{
|
||||
mask = ((method[0] == 'Z') ? curr->GetIPString() : "*@" + curr->host);
|
||||
xline = xlf->Generate(ServerInstance->Time(), 60*60, user->nick, reason, mask);
|
||||
}
|
||||
catch (ModuleException& ex)
|
||||
{
|
||||
// Nothing, move on to the next user
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ServerInstance->XLines->AddLine(xline, user))
|
||||
delete xline;
|
||||
}
|
||||
|
||||
ServerInstance->Users->QuitUser(curr, reason);
|
||||
}
|
||||
|
||||
ServerInstance->Modules->Detach(hook, creator);
|
||||
if (xlf)
|
||||
ServerInstance->XLines->ApplyLines();
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleClearChan : public Module
|
||||
{
|
||||
CommandClearChan cmd;
|
||||
|
||||
public:
|
||||
ModuleClearChan()
|
||||
: cmd(this)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
// Only attached while we are working; don't react to events otherwise
|
||||
ServerInstance->Modules->DetachAll(this);
|
||||
}
|
||||
|
||||
void OnBuildNeighborList(User* source, IncludeChanList& include, std::map<User*, bool>& exception) CXX11_OVERRIDE
|
||||
{
|
||||
bool found = false;
|
||||
for (IncludeChanList::iterator i = include.begin(); i != include.end(); ++i)
|
||||
{
|
||||
if ((*i)->chan == cmd.activechan)
|
||||
{
|
||||
// Don't show the QUIT to anyone in the channel by default
|
||||
include.erase(i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const UserMembList* users = cmd.activechan->GetUsers();
|
||||
for (UserMembCIter i = users->begin(); i != users->end(); ++i)
|
||||
{
|
||||
LocalUser* curr = IS_LOCAL(i->first);
|
||||
if (!curr)
|
||||
continue;
|
||||
|
||||
if (curr->IsOper())
|
||||
{
|
||||
// If another module has removed the channel we're working on from the list of channels
|
||||
// to consider for sending the QUIT to then don't add exceptions for opers, because the
|
||||
// module before us doesn't want them to see it or added the exceptions already.
|
||||
// If there is a value for this oper in excepts already, this won't overwrite it.
|
||||
if (found)
|
||||
exception.insert(std::make_pair(curr, true));
|
||||
continue;
|
||||
}
|
||||
else if (!include.empty() && curr->chans.size() > 1)
|
||||
{
|
||||
// This is a victim and potentially has another common channel with the user quitting,
|
||||
// add a negative exception overwriting the previous value, if any.
|
||||
exception[curr] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnUserKick(User* source, Membership* memb, const std::string& reason, CUList& excepts) CXX11_OVERRIDE
|
||||
{
|
||||
// Hide the KICK from all non-opers
|
||||
User* leaving = memb->user;
|
||||
const UserMembList* users = memb->chan->GetUsers();
|
||||
for (UserMembCIter i = users->begin(); i != users->end(); ++i)
|
||||
{
|
||||
User* curr = i->first;
|
||||
if ((IS_LOCAL(curr)) && (!curr->IsOper()) && (curr != leaving))
|
||||
excepts.insert(curr);
|
||||
}
|
||||
}
|
||||
|
||||
Version GetVersion() CXX11_OVERRIDE
|
||||
{
|
||||
return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass-G/ZLine users on a channel", VF_VENDOR|VF_OPTCOMMON);
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(ModuleClearChan)
|
Loading…
x
Reference in New Issue
Block a user