2012-04-19 20:58:29 +02:00
|
|
|
/*
|
|
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2021-12-30 18:52:08 +00:00
|
|
|
* Copyright (C) 2018 A_D
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2014 Daniel Vassdal <shutter@canternet.org>
|
2020-04-24 10:23:47 +01:00
|
|
|
* Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2012-2015 Attila Molnar <attilamolnar@hush.com>
|
|
|
|
* Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
|
|
|
|
* Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
|
2012-04-19 20:58:29 +02:00
|
|
|
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
|
|
|
|
* Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2006, 2010 Craig Edwards <brain@inspircd.org>
|
2021-03-05 02:04:16 +00:00
|
|
|
* Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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.
|
2007-07-16 17:30:04 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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/>.
|
2007-07-16 17:30:04 +00:00
|
|
|
*/
|
|
|
|
|
2012-04-19 20:58:29 +02:00
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
#include "inspircd.h"
|
2018-09-23 14:12:05 +02:00
|
|
|
#include "modules/invite.h"
|
2007-07-16 17:30:04 +00:00
|
|
|
|
2021-10-04 17:07:51 +01:00
|
|
|
class KickRejoinData final
|
2014-02-15 14:38:24 +01:00
|
|
|
{
|
2021-10-04 17:07:51 +01:00
|
|
|
struct KickedUser final
|
2015-01-23 15:50:18 +01:00
|
|
|
{
|
|
|
|
std::string uuid;
|
|
|
|
time_t expire;
|
|
|
|
|
|
|
|
KickedUser(User* user, unsigned int Delay)
|
|
|
|
: uuid(user->uuid)
|
|
|
|
, expire(ServerInstance->Time() + Delay)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<KickedUser> KickedList;
|
|
|
|
|
|
|
|
mutable KickedList kicked;
|
2015-01-23 15:46:03 +01:00
|
|
|
|
2022-01-25 13:59:42 +00:00
|
|
|
public:
|
2015-01-23 15:46:03 +01:00
|
|
|
const unsigned int delay;
|
2014-02-15 14:38:24 +01:00
|
|
|
|
|
|
|
KickRejoinData(unsigned int Delay) : delay(Delay) { }
|
2015-01-23 15:46:03 +01:00
|
|
|
|
|
|
|
bool canjoin(LocalUser* user) const
|
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
for (KickedList::iterator i = kicked.begin(); i != kicked.end(); )
|
2015-01-23 15:46:03 +01:00
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
KickedUser& rec = *i;
|
|
|
|
if (rec.expire > ServerInstance->Time())
|
2015-01-23 15:46:03 +01:00
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
if (rec.uuid == user->uuid)
|
2015-01-23 15:46:03 +01:00
|
|
|
return false;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Expired record, remove.
|
2015-01-23 15:50:18 +01:00
|
|
|
stdalgo::vector::swaperase(kicked, i);
|
|
|
|
if (kicked.empty())
|
|
|
|
break;
|
2015-01-23 15:46:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void add(User* user)
|
|
|
|
{
|
2015-01-23 15:50:18 +01:00
|
|
|
// One user can be in the list multiple times if the user gets kicked, force joins
|
|
|
|
// (skipping OnUserPreJoin) and gets kicked again, but that's okay because canjoin()
|
|
|
|
// works correctly in this case as well
|
2021-03-30 19:44:07 +01:00
|
|
|
kicked.emplace_back(user, delay);
|
2015-01-23 15:46:03 +01:00
|
|
|
}
|
2014-02-15 14:38:24 +01:00
|
|
|
};
|
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
/** Handles channel mode +J
|
|
|
|
*/
|
2021-10-01 05:39:12 +01:00
|
|
|
class KickRejoin final
|
|
|
|
: public ParamMode<KickRejoin, SimpleExtItem<KickRejoinData>>
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2022-01-25 13:59:42 +00:00
|
|
|
public:
|
2021-05-09 22:45:40 +01:00
|
|
|
const unsigned int max = 60;
|
|
|
|
|
2013-02-18 19:56:05 +01:00
|
|
|
KickRejoin(Module* Creator)
|
2014-02-15 14:38:24 +01:00
|
|
|
: ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >(Creator, "kicknorejoin", 'J')
|
2009-11-15 18:26:44 +00:00
|
|
|
{
|
2019-06-12 21:46:07 +01:00
|
|
|
syntax = "<seconds>";
|
2009-11-15 18:26:44 +00:00
|
|
|
}
|
2007-07-16 17:30:04 +00:00
|
|
|
|
2019-01-25 02:52:11 +00:00
|
|
|
ModeAction OnSet(User* source, Channel* channel, std::string& parameter) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2018-12-12 20:34:46 +00:00
|
|
|
unsigned int v = ConvToNum<unsigned int>(parameter);
|
2014-02-15 14:38:24 +01:00
|
|
|
if (v <= 0)
|
2018-01-27 13:05:14 +00:00
|
|
|
{
|
|
|
|
source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
|
2014-02-15 14:38:24 +01:00
|
|
|
return MODEACTION_DENY;
|
2018-01-27 13:05:14 +00:00
|
|
|
}
|
2013-02-18 19:56:05 +01:00
|
|
|
|
2018-12-12 20:34:46 +00:00
|
|
|
if (IS_LOCAL(source) && v > max)
|
2014-02-15 14:38:24 +01:00
|
|
|
v = max;
|
2013-02-18 19:56:05 +01:00
|
|
|
|
2021-03-17 13:12:24 +00:00
|
|
|
ext.Set(channel, v);
|
2013-02-18 19:56:05 +01:00
|
|
|
return MODEACTION_ALLOW;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
2014-02-15 14:38:24 +01:00
|
|
|
|
|
|
|
void SerializeParam(Channel* chan, const KickRejoinData* krd, std::string& out)
|
|
|
|
{
|
|
|
|
out.append(ConvToStr(krd->delay));
|
|
|
|
}
|
2007-07-16 17:30:04 +00:00
|
|
|
};
|
|
|
|
|
2021-10-01 04:37:03 +01:00
|
|
|
class ModuleKickNoRejoin final
|
|
|
|
: public Module
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2009-09-02 00:43:04 +00:00
|
|
|
KickRejoin kr;
|
2018-09-23 14:12:05 +02:00
|
|
|
Invite::API invapi;
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2007-07-16 17:30:04 +00:00
|
|
|
public:
|
2009-09-26 14:13:13 +00:00
|
|
|
ModuleKickNoRejoin()
|
2020-04-11 14:00:48 +01:00
|
|
|
: Module(VF_VENDOR | VF_COMMON, "Adds channel mode J (kicknorejoin) which prevents users from rejoining after being kicked from a channel.")
|
2020-04-09 18:57:50 +01:00
|
|
|
, kr(this)
|
2018-09-23 14:12:05 +02:00
|
|
|
, invapi(this)
|
2012-10-13 03:12:29 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-05-23 01:53:34 +01:00
|
|
|
ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven, bool override) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2021-05-23 01:53:34 +01:00
|
|
|
if (!override && chan)
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2021-03-17 05:58:47 +00:00
|
|
|
const KickRejoinData* data = kr.ext.Get(chan);
|
2018-09-23 14:12:05 +02:00
|
|
|
if ((data) && !invapi->IsInvited(user, chan) && (!data->canjoin(user)))
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2020-04-14 00:23:09 +01:00
|
|
|
user->WriteNumeric(ERR_UNAVAILRESOURCE, chan->name, InspIRCd::Format("You must wait %u seconds after being kicked to rejoin (+J is set)", data->delay));
|
2015-01-23 15:46:03 +01:00
|
|
|
return MOD_RES_DENY;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-02 00:49:36 +00:00
|
|
|
return MOD_RES_PASSTHRU;
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2019-01-25 02:52:11 +00:00
|
|
|
void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2014-02-15 14:38:24 +01:00
|
|
|
if ((!IS_LOCAL(memb->user)) || (source == memb->user))
|
|
|
|
return;
|
|
|
|
|
2021-03-17 05:58:47 +00:00
|
|
|
KickRejoinData* data = kr.ext.Get(memb->chan);
|
2014-02-15 14:38:24 +01:00
|
|
|
if (data)
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2015-01-23 15:46:03 +01:00
|
|
|
data->add(memb->user);
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-11 11:35:23 +00:00
|
|
|
|
2021-05-09 22:45:40 +01:00
|
|
|
void GetLinkData(LinkData& data, std::string& compatdata) override
|
2007-07-16 17:30:04 +00:00
|
|
|
{
|
2022-04-07 14:02:39 +01:00
|
|
|
data["max-time"] = compatdata = ConvToStr(kr.max);
|
2007-07-16 17:30:04 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_INIT(ModuleKickNoRejoin)
|