]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_watch.cpp
FindNick, FindChan, ChanModes, UserList, CountInvisible, PurgeEmptyChannels, GetClass...
[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 #include "inspircd.h"
28
29 /* $ModDesc: Provides support for the /watch command */
30
31 static Server *Srv;
32 extern InspIRCd* ServerInstance;
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() : command_t("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                                         irc::string n1 = nick;
134                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
135                                         {
136                                                 watchentry* b = (watchentry*)(*q);
137                                                 if (b->watcher == user)
138                                                 {
139                                                         irc::string n2 = b->target.c_str();
140                                                         userrec* a = ServerInstance->FindNick(b->target);
141                                                         if (a)
142                                                         {
143                                                                 user->WriteServ("602 %s %s %s %s %lu :stopped watching",user->nick,a->nick,a->ident,a->dhost,a->age);
144                                                         }
145                                                         else
146                                                         {
147                                                                  user->WriteServ("602 %s %s * * 0 :stopped watching",user->nick,b->target.c_str());
148                                                         }
149                                                         if (n1 == n2)
150                                                         {
151                                                                 watches.erase(q);
152                                                                 delete b;
153                                                                 break;
154                                                         }
155                                                 }
156                                         }
157                                 }
158                                 else if (nick[0] == '+')
159                                 {
160                                         nick++;
161                                         irc::string n1 = nick;
162                                         bool exists = false;
163                                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
164                                         {
165                                                 watchentry* a = (watchentry*)(*q);
166                                                 if (a->watcher == user)
167                                                 {
168                                                         irc::string n2 = a->target.c_str();
169                                                         if (n1 == n2)
170                                                         {
171                                                                 // already on watch list
172                                                                 exists = true;
173                                                         }
174                                                 }
175                                         }
176                                         if (!exists)
177                                         {
178                                                 watchentry* w = new watchentry();
179                                                 w->watcher = user;
180                                                 w->target = nick;
181                                                 watches.push_back(w);
182                                                 log(DEBUG,"*** Added %s to watchlist of %s",nick,user->nick);
183                                         }
184                                         userrec* a = ServerInstance->FindNick(nick);
185                                         if (a)
186                                         {
187                                                 user->WriteServ("604 %s %s %s %s %lu :is online",user->nick,a->nick,a->ident,a->dhost,a->age);
188                                         }
189                                         else
190                                         {
191                                                 user->WriteServ("605 %s %s * * 0 :is offline",user->nick,nick);
192                                         }
193                                 }
194                         }
195                 }
196                 return;
197         }
198 };
199
200 class Modulewatch : public Module
201 {
202         cmd_watch* mycommand;
203  public:
204
205         Modulewatch(Server* Me)
206                 : Module::Module(Me)
207         {
208                 Srv = Me;
209                 mycommand = new cmd_watch();
210                 Srv->AddCommand(mycommand);
211         }
212
213         void Implements(char* List)
214         {
215                 List[I_OnUserQuit] = List[I_OnGlobalConnect] = List[I_OnUserPostNick] = List[I_On005Numeric] = 1;
216         }
217
218         virtual void OnUserQuit(userrec* user, const std::string &reason)
219         {
220                 log(DEBUG,"*** WATCH: On global quit: user %s",user->nick);
221                 irc::string n2 = user->nick;
222                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
223                 {
224                         watchentry* a = (watchentry*)(*q);
225                         irc::string n1 = a->target.c_str();
226                         if (n1 == n2)
227                         {
228                                 log(DEBUG,"*** WATCH: On global quit: user %s is in notify of %s",user->nick,a->watcher->nick);
229                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,user->nick,user->ident,user->dhost,time(NULL));
230                         }
231                 }
232                 bool done = false;
233                 while (!done)
234                 {
235                         done = true;
236                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
237                         {
238                                 watchentry* a = (watchentry*)(*q);
239                                 if (a->watcher == user)
240                                 {
241                                         done = false;
242                                         watches.erase(q);
243                                         delete a;
244                                         break;
245                                 }
246                         }
247                 }
248         }
249
250         virtual void OnGlobalConnect(userrec* user)
251         {
252                 irc::string n2 = user->nick;
253                 log(DEBUG,"*** WATCH: On global connect: user %s",user->nick);
254                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
255                 {
256                         watchentry* a = (watchentry*)(*q);
257                         irc::string n1 = a->target.c_str();
258                         if (n1 == n2)
259                         {
260                                 log(DEBUG,"*** WATCH: On global connect: user %s is in notify of %s",user->nick,a->watcher->nick);
261                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
262                         }
263                 }
264         }
265
266         virtual void OnUserPostNick(userrec* user, const std::string &oldnick)
267         {
268                 irc::string n2 = oldnick.c_str();
269                 irc::string n3 = user->nick;
270                 log(DEBUG,"*** WATCH: On global nickchange: old nick: %s new nick: %s",oldnick.c_str(),user->nick);
271                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
272                 {
273                         watchentry* a = (watchentry*)(*q);
274                         irc::string n1 = a->target.c_str();
275                         // changed from a nick on the watchlist to one that isnt
276                         if (n1 == n2)
277                         {
278                                 log(DEBUG,"*** WATCH: On global nickchange: old nick %s was on notify list of %s",oldnick.c_str(),a->watcher->nick);
279                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,oldnick.c_str(),user->ident,user->dhost,time(NULL));
280                         }
281                         else if (n1 == n3)
282                         {
283                                 // changed from a nick not on notify to one that is
284                                 log(DEBUG,"*** WATCH: On global nickchange: new nick %s is on notify list of %s",user->nick,a->watcher->nick);
285                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
286                         }
287                 }
288         }       
289
290         virtual void On005Numeric(std::string &output)
291         {
292                 // we don't really have a limit...
293                 output = output + " WATCH=999";
294         }
295         
296         virtual ~Modulewatch()
297         {
298         }
299         
300         virtual Version GetVersion()
301         {
302                 return Version(1,0,0,1,VF_VENDOR);
303         }
304 };
305
306
307 class ModulewatchFactory : public ModuleFactory
308 {
309  public:
310         ModulewatchFactory()
311         {
312         }
313         
314         ~ModulewatchFactory()
315         {
316         }
317         
318         virtual Module * CreateModule(Server* Me)
319         {
320                 return new Modulewatch(Me);
321         }
322         
323 };
324
325
326 extern "C" void * init_module( void )
327 {
328         return new ModulewatchFactory;
329 }
330