]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_watch.cpp
WHEEEEE!!!!!
[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                 syntax = "[C|L|S]|[+|-<nick>]";
49         }
50
51         void Handle (const char** parameters, int pcnt, userrec *user)
52         {
53                 if (!pcnt)
54                 {
55                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
56                         {
57                                 watchentry* a = (watchentry*)(*q);
58                                 if (a->watcher == user)
59                                 {
60                                         userrec* targ = Srv->FindNick(a->target);
61                                         if (targ)
62                                         {
63                                                 user->WriteServ("604 %s %s %s %s %lu :is online",user->nick,targ->nick,targ->ident,targ->dhost,targ->age);
64                                         }
65                                 }
66                         }
67                         user->WriteServ("607 %s :End of WATCH list",user->nick);
68                 }
69                 else if (pcnt > 0)
70                 {
71                         for (int x = 0; x < pcnt; x++)
72                         {
73                                 const char *nick = parameters[x];
74                                 if (!strcasecmp(nick,"C"))
75                                 {
76                                         // watch clear
77                                         bool done = false;
78                                         while (!done)
79                                         {
80                                                 done = true;
81                                                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
82                                                 {
83                                                         watchentry* a = (watchentry*)(*q);
84                                                         if (a->watcher == user)
85                                                         {
86                                                                 done = false;
87                                                                 watches.erase(q);
88                                                                 delete a;
89                                                                 break;
90                                                         }
91                                                 }
92                                         }
93                                 }
94                                 else if (!strcasecmp(nick,"L"))
95                                 {
96                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
97                                         {
98                                                 watchentry* a = (watchentry*)(*q);
99                                                 if (a->watcher == user)
100                                                 {
101                                                         userrec* targ = Srv->FindNick(a->target);
102                                                         if (targ)
103                                                         {
104                                                                 user->WriteServ("604 %s %s %s %s %lu :is online",user->nick,targ->nick,targ->ident,targ->dhost,targ->age);
105                                                         }
106                                                 }
107                                         }
108                                         user->WriteServ("607 %s :End of WATCH list",user->nick);
109                                 }
110                                 else if (!strcasecmp(nick,"S"))
111                                 {
112                                         std::string list = "";
113                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
114                                         {
115                                                 watchentry* a = (watchentry*)(*q);
116                                                 if (a->watcher == user)
117                                                 {
118                                                         list.append(" ").append(a->target);
119                                                 }
120                                         }
121                                         char* l = (char*)list.c_str();
122                                         if (*l == ' ')
123                                                 l++;
124                                         user->WriteServ("606 %s :%s",user->nick,l);
125                                         user->WriteServ("607 %s :End of WATCH S",user->nick);
126                                 }
127                                 else if (nick[0] == '-')
128                                 {
129                                         // removing an item from the list
130                                         nick++;
131                                         irc::string n1 = nick;
132                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
133                                         {
134                                                 watchentry* b = (watchentry*)(*q);
135                                                 if (b->watcher == user)
136                                                 {
137                                                         irc::string n2 = b->target.c_str();
138                                                         userrec* a = Srv->FindNick(b->target);
139                                                         if (a)
140                                                         {
141                                                                 user->WriteServ("602 %s %s %s %s %lu :stopped watching",user->nick,a->nick,a->ident,a->dhost,a->age);
142                                                         }
143                                                         else
144                                                         {
145                                                                  user->WriteServ("602 %s %s * * 0 :stopped watching",user->nick,b->target.c_str());
146                                                         }
147                                                         if (n1 == n2)
148                                                         {
149                                                                 watches.erase(q);
150                                                                 delete b;
151                                                                 break;
152                                                         }
153                                                 }
154                                         }
155                                 }
156                                 else if (nick[0] == '+')
157                                 {
158                                         nick++;
159                                         irc::string n1 = nick;
160                                         bool exists = false;
161                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
162                                         {
163                                                 watchentry* a = (watchentry*)(*q);
164                                                 if (a->watcher == user)
165                                                 {
166                                                         irc::string n2 = a->target.c_str();
167                                                         if (n1 == n2)
168                                                         {
169                                                                 // already on watch list
170                                                                 exists = true;
171                                                         }
172                                                 }
173                                         }
174                                         if (!exists)
175                                         {
176                                                 watchentry* w = new watchentry();
177                                                 w->watcher = user;
178                                                 w->target = nick;
179                                                 watches.push_back(w);
180                                                 log(DEBUG,"*** Added %s to watchlist of %s",nick,user->nick);
181                                         }
182                                         userrec* a = Srv->FindNick(nick);
183                                         if (a)
184                                         {
185                                                 user->WriteServ("604 %s %s %s %s %lu :is online",user->nick,a->nick,a->ident,a->dhost,a->age);
186                                         }
187                                         else
188                                         {
189                                                 user->WriteServ("605 %s %s * * 0 :is offline",user->nick,nick);
190                                         }
191                                 }
192                         }
193                 }
194                 return;
195         }
196 };
197
198 class Modulewatch : public Module
199 {
200         cmd_watch* mycommand;
201  public:
202
203         Modulewatch(Server* Me)
204                 : Module::Module(Me)
205         {
206                 Srv = Me;
207                 mycommand = new cmd_watch();
208                 Srv->AddCommand(mycommand);
209         }
210
211         void Implements(char* List)
212         {
213                 List[I_OnUserQuit] = List[I_OnGlobalConnect] = List[I_OnUserPostNick] = List[I_On005Numeric] = 1;
214         }
215
216         virtual void OnUserQuit(userrec* user, const std::string &reason)
217         {
218                 log(DEBUG,"*** WATCH: On global quit: user %s",user->nick);
219                 irc::string n2 = user->nick;
220                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
221                 {
222                         watchentry* a = (watchentry*)(*q);
223                         irc::string n1 = a->target.c_str();
224                         if (n1 == n2)
225                         {
226                                 log(DEBUG,"*** WATCH: On global quit: user %s is in notify of %s",user->nick,a->watcher->nick);
227                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,user->nick,user->ident,user->dhost,time(NULL));
228                         }
229                 }
230                 bool done = false;
231                 while (!done)
232                 {
233                         done = true;
234                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
235                         {
236                                 watchentry* a = (watchentry*)(*q);
237                                 if (a->watcher == user)
238                                 {
239                                         done = false;
240                                         watches.erase(q);
241                                         delete a;
242                                         break;
243                                 }
244                         }
245                 }
246         }
247
248         virtual void OnGlobalConnect(userrec* user)
249         {
250                 irc::string n2 = user->nick;
251                 log(DEBUG,"*** WATCH: On global connect: user %s",user->nick);
252                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
253                 {
254                         watchentry* a = (watchentry*)(*q);
255                         irc::string n1 = a->target.c_str();
256                         if (n1 == n2)
257                         {
258                                 log(DEBUG,"*** WATCH: On global connect: user %s is in notify of %s",user->nick,a->watcher->nick);
259                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
260                         }
261                 }
262         }
263
264         virtual void OnUserPostNick(userrec* user, const std::string &oldnick)
265         {
266                 irc::string n2 = oldnick.c_str();
267                 irc::string n3 = user->nick;
268                 log(DEBUG,"*** WATCH: On global nickchange: old nick: %s new nick: %s",oldnick.c_str(),user->nick);
269                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
270                 {
271                         watchentry* a = (watchentry*)(*q);
272                         irc::string n1 = a->target.c_str();
273                         // changed from a nick on the watchlist to one that isnt
274                         if (n1 == n2)
275                         {
276                                 log(DEBUG,"*** WATCH: On global nickchange: old nick %s was on notify list of %s",oldnick.c_str(),a->watcher->nick);
277                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,oldnick.c_str(),user->ident,user->dhost,time(NULL));
278                         }
279                         else if (n1 == n3)
280                         {
281                                 // changed from a nick not on notify to one that is
282                                 log(DEBUG,"*** WATCH: On global nickchange: new nick %s is on notify list of %s",user->nick,a->watcher->nick);
283                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
284                         }
285                 }
286         }       
287
288         virtual void On005Numeric(std::string &output)
289         {
290                 // we don't really have a limit...
291                 output = output + " WATCH=999";
292         }
293         
294         virtual ~Modulewatch()
295         {
296         }
297         
298         virtual Version GetVersion()
299         {
300                 return Version(1,0,0,1,VF_VENDOR);
301         }
302 };
303
304
305 class ModulewatchFactory : public ModuleFactory
306 {
307  public:
308         ModulewatchFactory()
309         {
310         }
311         
312         ~ModulewatchFactory()
313         {
314         }
315         
316         virtual Module * CreateModule(Server* Me)
317         {
318                 return new Modulewatch(Me);
319         }
320         
321 };
322
323
324 extern "C" void * init_module( void )
325 {
326         return new ModulewatchFactory;
327 }
328