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