]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_kicknorejoin.cpp
Some more text fixes and improvements (#1618).
[user/henk/code/inspircd.git] / src / modules / m_kicknorejoin.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
6  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
7  *   Copyright (C) 2006-2007 Robin Burchell <robin+git@viroteck.net>
8  *   Copyright (C) 2006 John Brooks <john.brooks@dereferenced.net>
9  *   Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
10  *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
11  *
12  * This file is part of InspIRCd.  InspIRCd is free software: you can
13  * redistribute it and/or modify it under the terms of the GNU General Public
14  * License as published by the Free Software Foundation, version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24
25
26 #include "inspircd.h"
27 #include "modules/invite.h"
28
29 enum
30 {
31         // From RFC 2182.
32         ERR_UNAVAILRESOURCE = 437
33 };
34
35
36 class KickRejoinData
37 {
38         struct KickedUser
39         {
40                 std::string uuid;
41                 time_t expire;
42
43                 KickedUser(User* user, unsigned int Delay)
44                         : uuid(user->uuid)
45                         , expire(ServerInstance->Time() + Delay)
46                 {
47                 }
48         };
49
50         typedef std::vector<KickedUser> KickedList;
51
52         mutable KickedList kicked;
53
54  public:
55         const unsigned int delay;
56
57         KickRejoinData(unsigned int Delay) : delay(Delay) { }
58
59         bool canjoin(LocalUser* user) const
60         {
61                 for (KickedList::iterator i = kicked.begin(); i != kicked.end(); )
62                 {
63                         KickedUser& rec = *i;
64                         if (rec.expire > ServerInstance->Time())
65                         {
66                                 if (rec.uuid == user->uuid)
67                                         return false;
68                                 ++i;
69                         }
70                         else
71                         {
72                                 // Expired record, remove.
73                                 stdalgo::vector::swaperase(kicked, i);
74                                 if (kicked.empty())
75                                         break;
76                         }
77                 }
78                 return true;
79         }
80
81         void add(User* user)
82         {
83                 // One user can be in the list multiple times if the user gets kicked, force joins
84                 // (skipping OnUserPreJoin) and gets kicked again, but that's okay because canjoin()
85                 // works correctly in this case as well
86                 kicked.push_back(KickedUser(user, delay));
87         }
88 };
89
90 /** Handles channel mode +J
91  */
92 class KickRejoin : public ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >
93 {
94         const unsigned int max;
95  public:
96         KickRejoin(Module* Creator)
97                 : ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >(Creator, "kicknorejoin", 'J')
98                 , max(60)
99         {
100         }
101
102         ModeAction OnSet(User* source, Channel* channel, std::string& parameter) CXX11_OVERRIDE
103         {
104                 unsigned int v = ConvToNum<unsigned int>(parameter);
105                 if (v <= 0)
106                 {
107                         source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
108                         return MODEACTION_DENY;
109                 }
110
111                 if (IS_LOCAL(source) && v > max)
112                         v = max;
113
114                 ext.set(channel, new KickRejoinData(v));
115                 return MODEACTION_ALLOW;
116         }
117
118         void SerializeParam(Channel* chan, const KickRejoinData* krd, std::string& out)
119         {
120                 out.append(ConvToStr(krd->delay));
121         }
122
123         std::string GetModuleSettings() const
124         {
125                 return ConvToStr(max);
126         }
127 };
128
129 class ModuleKickNoRejoin : public Module
130 {
131         KickRejoin kr;
132         Invite::API invapi;
133
134 public:
135         ModuleKickNoRejoin()
136                 : kr(this)
137                 , invapi(this)
138         {
139         }
140
141         ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
142         {
143                 if (chan)
144                 {
145                         const KickRejoinData* data = kr.ext.get(chan);
146                         if ((data) && !invapi->IsInvited(user, chan) && (!data->canjoin(user)))
147                         {
148                                 user->WriteNumeric(ERR_UNAVAILRESOURCE, chan, InspIRCd::Format("You must wait %u seconds after being kicked to rejoin (+J is set)", data->delay));
149                                 return MOD_RES_DENY;
150                         }
151                 }
152                 return MOD_RES_PASSTHRU;
153         }
154
155         void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) CXX11_OVERRIDE
156         {
157                 if ((!IS_LOCAL(memb->user)) || (source == memb->user))
158                         return;
159
160                 KickRejoinData* data = kr.ext.get(memb->chan);
161                 if (data)
162                 {
163                         data->add(memb->user);
164                 }
165         }
166
167         Version GetVersion() CXX11_OVERRIDE
168         {
169                 return Version("Provides channel mode +J, delays rejoins after kicks", VF_VENDOR | VF_COMMON, kr.GetModuleSettings());
170         }
171 };
172
173 MODULE_INIT(ModuleKickNoRejoin)