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