]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_kicknorejoin.cpp
Merge pull request #1084 from SaberUK/insp20+fix-parallel-debug-install
[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
28 /* $ModDesc: Provides channel mode +J (delay rejoin after kick) */
29
30 typedef std::map<std::string, time_t> delaylist;
31
32 /** Handles channel mode +J
33  */
34 class KickRejoin : public ModeHandler
35 {
36  public:
37         unsigned int max;
38         SimpleExtItem<delaylist> ext;
39         KickRejoin(Module* Creator)
40                 : ModeHandler(Creator, "kicknorejoin", 'J', PARAM_SETONLY, MODETYPE_CHANNEL)
41                 , ext("norejoinusers", Creator)
42         {
43         }
44
45         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
46         {
47                 if (adding)
48                 {
49                         int v = ConvToInt(parameter);
50                         if (v <= 0)
51                                 return MODEACTION_DENY;
52                         if (parameter == channel->GetModeParameter(this))
53                                 return MODEACTION_DENY;
54
55                         if ((IS_LOCAL(source) && ((unsigned int)v > max)))
56                                 v = max;
57
58                         parameter = ConvToStr(v);
59                         channel->SetModeParam(this, parameter);
60                 }
61                 else
62                 {
63                         if (!channel->IsModeSet(this))
64                                 return MODEACTION_DENY;
65
66                         ext.unset(channel);
67                         channel->SetModeParam(this, "");
68                 }
69                 return MODEACTION_ALLOW;
70         }
71 };
72
73 class ModuleKickNoRejoin : public Module
74 {
75         KickRejoin kr;
76
77 public:
78
79         ModuleKickNoRejoin()
80                 : kr(this)
81         {
82         }
83
84         void init()
85         {
86                 ServerInstance->Modules->AddService(kr);
87                 ServerInstance->Modules->AddService(kr.ext);
88                 Implementation eventlist[] = { I_OnUserPreJoin, I_OnUserKick, I_OnRehash };
89                 ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
90                 OnRehash(NULL);
91         }
92
93         void OnRehash(User* user)
94         {
95                 kr.max = ServerInstance->Duration(ServerInstance->Config->ConfValue("kicknorejoin")->getString("maxtime"));
96                 if (!kr.max)
97                         kr.max = 30*60;
98         }
99
100         ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
101         {
102                 if (chan)
103                 {
104                         delaylist* dl = kr.ext.get(chan);
105                         if (dl)
106                         {
107                                 for (delaylist::iterator iter = dl->begin(); iter != dl->end(); )
108                                 {
109                                         if (iter->second > ServerInstance->Time())
110                                         {
111                                                 if (iter->first == user->uuid)
112                                                 {
113                                                         std::string modeparam = chan->GetModeParameter(&kr);
114                                                         user->WriteNumeric(ERR_DELAYREJOIN, "%s %s :You must wait %s seconds after being kicked to rejoin (+J)",
115                                                                 user->nick.c_str(), chan->name.c_str(), modeparam.c_str());
116                                                         return MOD_RES_DENY;
117                                                 }
118                                                 ++iter;
119                                         }
120                                         else
121                                         {
122                                                 // Expired record, remove.
123                                                 dl->erase(iter++);
124                                         }
125                                 }
126
127                                 if (dl->empty())
128                                         kr.ext.unset(chan);
129                         }
130                 }
131                 return MOD_RES_PASSTHRU;
132         }
133
134         void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts)
135         {
136                 if (memb->chan->IsModeSet(&kr) && (IS_LOCAL(memb->user)) && (source != memb->user))
137                 {
138                         delaylist* dl = kr.ext.get(memb->chan);
139                         if (!dl)
140                         {
141                                 dl = new delaylist;
142                                 kr.ext.set(memb->chan, dl);
143                         }
144                         (*dl)[memb->user->uuid] = ServerInstance->Time() + ConvToInt(memb->chan->GetModeParameter(&kr));
145                 }
146         }
147
148         ~ModuleKickNoRejoin()
149         {
150         }
151
152         Version GetVersion()
153         {
154                 return Version("Channel mode to delay rejoin after kick", VF_VENDOR);
155         }
156 };
157
158
159 MODULE_INIT(ModuleKickNoRejoin)