]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_kicknorejoin.cpp
Templated GetExt
[user/henk/code/inspircd.git] / src / modules / m_kicknorejoin.cpp
1 #include <time.h>
2 #include <map>
3 #include <vector>
4 #include <sstream>
5 #include "users.h"
6 #include "channels.h"
7 #include "modules.h"
8 #include "helperfuncs.h"
9 #include "inspircd.h"
10
11 /* $ModDesc: Provides channel mode +J (delay rejoin after kick) */
12
13 inline int strtoint(const std::string &str)
14 {
15         std::istringstream ss(str);
16         int result;
17         ss >> result;
18         return result;
19 }
20
21 typedef std::map<userrec*, time_t> delaylist;
22
23 class KickRejoin : public ModeHandler
24 {
25  public:
26         KickRejoin() : ModeHandler('J', 1, 0, false, MODETYPE_CHANNEL, false) { }
27
28         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
29         {
30                 if (!adding)
31                 {
32                         // Taking the mode off, we need to clean up.
33                         delaylist* dl = (delaylist*)channel->GetExt("norejoinusers");
34
35                         if (dl)
36                         {
37                                 DELETE(dl);
38                                 channel->Shrink("norejoinusers");
39                         }
40                 }
41                 if ((!adding) || (atoi(parameter.c_str()) > 0))
42                 {
43                         parameter = ConvToStr(atoi(parameter.c_str()));
44                         channel->SetModeParam('J', parameter.c_str(), adding);
45                         channel->SetMode('J', adding);
46                         return MODEACTION_ALLOW;
47                 }
48                 else
49                 {
50                         return MODEACTION_DENY;
51                 }
52         }
53 };
54
55 class ModuleKickNoRejoin : public Module
56 {
57         Server *Srv;
58         KickRejoin* kr;
59         
60 public:
61  
62         ModuleKickNoRejoin(Server* Me)
63                 : Module::Module(Me)
64         {
65                 Srv = Me;
66                 kr = new KickRejoin();
67                 Srv->AddMode(kr, 'J');
68         }
69
70         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname)
71         {
72                 if (chan)
73                 {
74                         delaylist* dl = (delaylist*)chan->GetExt("norejoinusers");
75                         log(DEBUG, "m_kicknorejoin.so: tried to grab delay list");
76                         
77                         if (dl)
78                         {
79                                 log(DEBUG, "m_kicknorejoin.so: got delay list, iterating over it");
80                                 std::vector<userrec*> itemstoremove;
81                         
82                                 for (delaylist::iterator iter = dl->begin(); iter != dl->end(); iter++)
83                                 {
84                                         log(DEBUG, "m_kicknorejoin.so:\t[%s] => %d", iter->first->nick, iter->second);
85                                         if (iter->second > time(NULL))
86                                         {
87                                                 log(DEBUG, "m_kicknorejoin.so: still inside time slot");
88                                                 if (iter->first == user)                                        
89                                                 {
90                                                         log(DEBUG, "m_kicknorejoin.so: and we have the right user");
91                                                         WriteServ(user->fd, "495 %s %s :You cannot rejoin this channel yet after being kicked (+J)", user->nick, chan->name);
92                                                         return 1;
93                                                 }
94                                         }
95                                         else
96                                         {
97                                                 // Expired record, remove.
98                                                 log(DEBUG, "m_kicknorejoin.so: record expired");
99                                                 itemstoremove.push_back(iter->first);
100                                         }
101                                 }
102                                 
103                                 for (unsigned int i = 0; i < itemstoremove.size(); i++)
104                                         dl->erase(itemstoremove[i]);
105                                                                                                                                         
106                                 if (!dl->size())
107                                 {
108                                         // Now it's empty..
109                                                 DELETE(dl);
110                                                 chan->Shrink("norejoinusers");
111                                         }
112                                 }
113                         }
114                         return 0;
115                 }
116                 
117                 virtual void OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
118                 {
119                         if (chan->IsModeSet('J') && (source != user))
120                         {
121                                 delaylist* dl = (delaylist*)chan->GetExt("norejoinusers");
122                                 
123                                 if (!dl)
124                                 {
125                                         dl = new delaylist;
126                                         chan->Extend("norejoinusers", (char*)dl);
127                                 }
128                                 
129                                 log(DEBUG, "m_kicknorejoin.so: setting record for %s, %d second delay", user->nick, strtoint(chan->GetModeParameter('J')));
130                                 (*dl)[user] = time(NULL) + strtoint(chan->GetModeParameter('J'));
131                         }
132                 }
133                 
134                 virtual void OnChannelDelete(chanrec* chan)
135                 {
136                         delaylist* dl = (delaylist*)chan->GetExt("norejoinusers");
137                         
138                         if (dl)
139                         {
140                                 DELETE(dl);
141                         chan->Shrink("norejoinusers");
142                 }
143         }
144         
145         virtual void OnCleanup(int target_type, void* item)
146         {
147                 if(target_type == TYPE_CHANNEL)
148                         OnChannelDelete((chanrec*)item);
149         }
150
151         virtual void Implements(char* List)
152         {
153                 List[I_OnCleanup] = List[I_On005Numeric] = List[I_OnChannelDelete] = List[I_OnUserPreJoin] = List[I_OnUserKick] = 1;
154         }
155
156         virtual void On005Numeric(std::string &output)
157         {
158                 InsertMode(output, "J", 3);
159         }
160
161         virtual ~ModuleKickNoRejoin()
162         {
163                 DELETE(kr);
164         }
165         
166         virtual Version GetVersion()
167         {
168                 return Version(1, 0, 0, 0, VF_STATIC | VF_VENDOR);
169         }
170 };
171
172
173 class ModuleKickNoRejoinFactory : public ModuleFactory
174 {
175  public:
176         ModuleKickNoRejoinFactory()
177         {
178         }
179         
180         ~ModuleKickNoRejoinFactory()
181         {
182         }
183         
184         virtual Module * CreateModule(Server* Me)
185         {
186                 return new ModuleKickNoRejoin(Me);
187         }
188         
189 };
190
191
192 extern "C" void * init_module( void )
193 {
194         return new ModuleKickNoRejoinFactory;
195 }
196