]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_watch.cpp
Change watchlist to a list of pointers, can operate and iterate much faster
[user/henk/code/inspircd.git] / src / modules / m_watch.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 #include <stdio.h>
20 #include <string>
21 #include <vector>
22 #include "users.h"
23 #include "channels.h"
24 #include "modules.h"
25 #include "helperfuncs.h"
26 #include "hashcomp.h"
27
28 /* $ModDesc: Provides support for the /watch command */
29
30 static Server *Srv;
31
32 class watchentry : public classbase
33 {
34  public:
35         userrec* watcher;
36         std::string target;
37 };
38
39 typedef std::vector<watchentry*> watchlist;
40 watchlist watches;
41
42 class cmd_watch : public command_t
43 {
44  public:
45         cmd_watch() : command_t("WATCH",0,0)
46         {
47                 this->source = "m_watch.so";
48         }
49
50         void Handle (const char** parameters, int pcnt, userrec *user)
51         {
52                 if (!pcnt)
53                 {
54                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
55                         {
56                                 watchentry* a = (watchentry*)(*q);
57                                 if (a->watcher == user)
58                                 {
59                                         userrec* targ = Srv->FindNick(a->target);
60                                         if (targ)
61                                         {
62                                                 WriteServ(user->fd,"604 %s %s %s %s %lu :is online",user->nick,targ->nick,targ->ident,targ->dhost,targ->age);
63                                         }
64                                 }
65                         }
66                         WriteServ(user->fd,"607 %s :End of WATCH list",user->nick);
67                 }
68                 else if (pcnt > 0)
69                 {
70                         for (int x = 0; x < pcnt; x++)
71                         {
72                                 const char *nick = parameters[x];
73                                 if (!strcasecmp(nick,"C"))
74                                 {
75                                         // watch clear
76                                         bool done = false;
77                                         while (!done)
78                                         {
79                                                 done = true;
80                                                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
81                                                 {
82                                                         watchentry* a = (watchentry*)(*q);
83                                                         if (a->watcher == user)
84                                                         {
85                                                                 done = false;
86                                                                 watches.erase(q);
87                                                                 delete a;
88                                                                 break;
89                                                         }
90                                                 }
91                                         }
92                                 }
93                                 else if (!strcasecmp(nick,"L"))
94                                 {
95                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
96                                         {
97                                                 watchentry* a = (watchentry*)(*q);
98                                                 if (a->watcher == user)
99                                                 {
100                                                         userrec* targ = Srv->FindNick(a->target);
101                                                         if (targ)
102                                                         {
103                                                                 WriteServ(user->fd,"604 %s %s %s %s %lu :is online",user->nick,targ->nick,targ->ident,targ->dhost,targ->age);
104                                                         }
105                                                 }
106                                         }
107                                         WriteServ(user->fd,"607 %s :End of WATCH list",user->nick);
108                                 }
109                                 else if (!strcasecmp(nick,"S"))
110                                 {
111                                         std::string list = "";
112                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
113                                         {
114                                                 watchentry* a = (watchentry*)(*q);
115                                                 if (a->watcher == user)
116                                                 {
117                                                         list.append(" ").append(a->target);
118                                                 }
119                                         }
120                                         char* l = (char*)list.c_str();
121                                         if (*l == ' ')
122                                                 l++;
123                                         WriteServ(user->fd,"606 %s :%s",user->nick,l);
124                                         WriteServ(user->fd,"607 %s :End of WATCH S",user->nick);
125                                 }
126                                 else if (nick[0] == '-')
127                                 {
128                                         // removing an item from the list
129                                         nick++;
130                                         irc::string n1 = nick;
131                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
132                                         {
133                                                 watchentry* b = (watchentry*)(*q);
134                                                 if (b->watcher == user)
135                                                 {
136                                                         irc::string n2 = b->target.c_str();
137                                                         userrec* a = Srv->FindNick(b->target);
138                                                         if (a)
139                                                         {
140                                                                 WriteServ(user->fd,"602 %s %s %s %s %lu :stopped watching",user->nick,a->nick,a->ident,a->dhost,a->age);
141                                                         }
142                                                         else
143                                                         {
144                                                                  WriteServ(user->fd,"602 %s %s * * 0 :stopped watching",user->nick,b->target.c_str());
145                                                         }
146                                                         if (n1 == n2)
147                                                         {
148                                                                 watches.erase(q);
149                                                                 delete b;
150                                                                 break;
151                                                         }
152                                                 }
153                                         }
154                                 }
155                                 else if (nick[0] == '+')
156                                 {
157                                         nick++;
158                                         irc::string n1 = nick;
159                                         bool exists = false;
160                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
161                                         {
162                                                 watchentry* a = (watchentry*)(*q);
163                                                 if (a->watcher == user)
164                                                 {
165                                                         irc::string n2 = a->target.c_str();
166                                                         if (n1 == n2)
167                                                         {
168                                                                 // already on watch list
169                                                                 exists = true;
170                                                         }
171                                                 }
172                                         }
173                                         if (!exists)
174                                         {
175                                                 watchentry* w = new watchentry();
176                                                 w->watcher = user;
177                                                 w->target = nick;
178                                                 watches.push_back(w);
179                                                 log(DEBUG,"*** Added %s to watchlist of %s",nick,user->nick);
180                                         }
181                                         userrec* a = Srv->FindNick(nick);
182                                         if (a)
183                                         {
184                                                 WriteServ(user->fd,"604 %s %s %s %s %lu :is online",user->nick,a->nick,a->ident,a->dhost,a->age);
185                                         }
186                                         else
187                                         {
188                                                 WriteServ(user->fd,"605 %s %s * * 0 :is offline",user->nick,nick);
189                                         }
190                                 }
191                         }
192                 }
193                 return;
194         }
195 };
196
197 class Modulewatch : public Module
198 {
199         cmd_watch* mycommand;
200  public:
201
202         Modulewatch(Server* Me)
203                 : Module::Module(Me)
204         {
205                 Srv = Me;
206                 mycommand = new cmd_watch();
207                 Srv->AddCommand(mycommand);
208         }
209
210         void Implements(char* List)
211         {
212                 List[I_OnUserQuit] = List[I_OnGlobalConnect] = List[I_OnUserPostNick] = List[I_On005Numeric] = 1;
213         }
214
215         virtual void OnUserQuit(userrec* user, const std::string &reason)
216         {
217                 log(DEBUG,"*** WATCH: On global quit: user %s",user->nick);
218                 irc::string n2 = user->nick;
219                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
220                 {
221                         watchentry* a = (watchentry*)(*q);
222                         irc::string n1 = a->target.c_str();
223                         if (n1 == n2)
224                         {
225                                 log(DEBUG,"*** WATCH: On global quit: user %s is in notify of %s",user->nick,a->watcher->nick);
226                                 WriteServ(a->watcher->fd,"601 %s %s %s %s %lu :went offline",a->watcher->nick,user->nick,user->ident,user->dhost,time(NULL));
227                         }
228                 }
229                 bool done = false;
230                 while (!done)
231                 {
232                         done = true;
233                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
234                         {
235                                 watchentry* a = (watchentry*)(*q);
236                                 if (a->watcher == user)
237                                 {
238                                         done = false;
239                                         watches.erase(q);
240                                         delete a;
241                                         break;
242                                 }
243                         }
244                 }
245         }
246
247         virtual void OnGlobalConnect(userrec* user)
248         {
249                 irc::string n2 = user->nick;
250                 log(DEBUG,"*** WATCH: On global connect: user %s",user->nick);
251                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
252                 {
253                         watchentry* a = (watchentry*)(*q);
254                         irc::string n1 = a->target.c_str();
255                         if (n1 == n2)
256                         {
257                                 log(DEBUG,"*** WATCH: On global connect: user %s is in notify of %s",user->nick,a->watcher->nick);
258                                 WriteServ(a->watcher->fd,"600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
259                         }
260                 }
261         }
262
263         virtual void OnUserPostNick(userrec* user, const std::string &oldnick)
264         {
265                 irc::string n2 = oldnick.c_str();
266                 irc::string n3 = user->nick;
267                 log(DEBUG,"*** WATCH: On global nickchange: old nick: %s new nick: %s",oldnick.c_str(),user->nick);
268                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
269                 {
270                         watchentry* a = (watchentry*)(*q);
271                         irc::string n1 = a->target.c_str();
272                         // changed from a nick on the watchlist to one that isnt
273                         if (n1 == n2)
274                         {
275                                 log(DEBUG,"*** WATCH: On global nickchange: old nick %s was on notify list of %s",oldnick.c_str(),a->watcher->nick);
276                                 WriteServ(a->watcher->fd,"601 %s %s %s %s %lu :went offline",a->watcher->nick,oldnick.c_str(),user->ident,user->dhost,time(NULL));
277                         }
278                         else if (n1 == n3)
279                         {
280                                 // changed from a nick not on notify to one that is
281                                 log(DEBUG,"*** WATCH: On global nickchange: new nick %s is on notify list of %s",user->nick,a->watcher->nick);
282                                 WriteServ(a->watcher->fd,"600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
283                         }
284                 }
285         }       
286
287         virtual void On005Numeric(std::string &output)
288         {
289                 // we don't really have a limit...
290                 output = output + " WATCH=999";
291         }
292         
293         virtual ~Modulewatch()
294         {
295         }
296         
297         virtual Version GetVersion()
298         {
299                 return Version(1,0,0,1,VF_VENDOR);
300         }
301 };
302
303
304 class ModulewatchFactory : public ModuleFactory
305 {
306  public:
307         ModulewatchFactory()
308         {
309         }
310         
311         ~ModulewatchFactory()
312         {
313         }
314         
315         virtual Module * CreateModule(Server* Me)
316         {
317                 return new Modulewatch(Me);
318         }
319         
320 };
321
322
323 extern "C" void * init_module( void )
324 {
325         return new ModulewatchFactory;
326 }
327