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