]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_watch.cpp
e60196c009e7e9e0fc6bd5cd975df396f2d22791
[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 "hashcomp.h"
26 #include "inspircd.h"
27
28 /* $ModDesc: Provides support for the /watch command */
29
30 /** A watchlist entry
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 /** Handle /WATCH
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         CmdResult 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 CMD_FAILURE;
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 CMD_FAILURE;
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                 /* So that spanningtree doesnt pass the WATCH commands to the network! */
207                 return CMD_FAILURE;
208         }
209 };
210
211 class Modulewatch : public Module
212 {
213         cmd_watch* mycommand;
214  public:
215
216         Modulewatch(InspIRCd* Me)
217                 : Module::Module(Me)
218         {
219                 
220                 mycommand = new cmd_watch(ServerInstance);
221                 ServerInstance->AddCommand(mycommand);
222         }
223
224         void Implements(char* List)
225         {
226                 List[I_OnUserQuit] = List[I_OnPostConnect] = List[I_OnUserPostNick] = List[I_On005Numeric] = 1;
227         }
228
229         virtual void OnUserQuit(userrec* user, const std::string &reason)
230         {
231                 ServerInstance->Log(DEBUG,"*** WATCH: On global quit: user %s",user->nick);
232                 irc::string n2 = user->nick;
233                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
234                 {
235                         watchentry* a = (watchentry*)(*q);
236                         irc::string n1 = a->target.c_str();
237                         if (n1 == n2)
238                         {
239                                 ServerInstance->Log(DEBUG,"*** WATCH: On global quit: user %s is in notify of %s",user->nick,a->watcher->nick);
240                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,user->nick,user->ident,user->dhost,time(NULL));
241                         }
242                 }
243                 bool done = false;
244                 while (!done)
245                 {
246                         done = true;
247                         for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
248                         {
249                                 watchentry* a = (watchentry*)(*q);
250                                 if (a->watcher == user)
251                                 {
252                                         done = false;
253                                         watches.erase(q);
254                                         delete a;
255                                         break;
256                                 }
257                         }
258                 }
259         }
260
261         virtual void OnPostConnect(userrec* user)
262         {
263                 irc::string n2 = user->nick;
264                 ServerInstance->Log(DEBUG,"*** WATCH: On global connect: user %s",user->nick);
265                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
266                 {
267                         watchentry* a = (watchentry*)(*q);
268                         irc::string n1 = a->target.c_str();
269                         if (n1 == n2)
270                         {
271                                 ServerInstance->Log(DEBUG,"*** WATCH: On global connect: user %s is in notify of %s",user->nick,a->watcher->nick);
272                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
273                         }
274                 }
275         }
276
277         virtual void OnUserPostNick(userrec* user, const std::string &oldnick)
278         {
279                 irc::string n2 = oldnick.c_str();
280                 irc::string n3 = user->nick;
281                 ServerInstance->Log(DEBUG,"*** WATCH: On global nickchange: old nick: %s new nick: %s",oldnick.c_str(),user->nick);
282                 for (watchlist::iterator q = watches.begin(); q != watches.end(); q++)
283                 {
284                         watchentry* a = (watchentry*)(*q);
285                         irc::string n1 = a->target.c_str();
286                         // changed from a nick on the watchlist to one that isnt
287                         if (n1 == n2)
288                         {
289                                 ServerInstance->Log(DEBUG,"*** WATCH: On global nickchange: old nick %s was on notify list of %s",oldnick.c_str(),a->watcher->nick);
290                                 a->watcher->WriteServ("601 %s %s %s %s %lu :went offline",a->watcher->nick,oldnick.c_str(),user->ident,user->dhost,time(NULL));
291                         }
292                         else if (n1 == n3)
293                         {
294                                 // changed from a nick not on notify to one that is
295                                 ServerInstance->Log(DEBUG,"*** WATCH: On global nickchange: new nick %s is on notify list of %s",user->nick,a->watcher->nick);
296                                 a->watcher->WriteServ("600 %s %s %s %s %lu :arrived online",a->watcher->nick,user->nick,user->ident,user->dhost,user->age);
297                         }
298                 }
299         }       
300
301         virtual void On005Numeric(std::string &output)
302         {
303                 // we don't really have a limit...
304                 output = output + " WATCH=999";
305         }
306         
307         virtual ~Modulewatch()
308         {
309         }
310         
311         virtual Version GetVersion()
312         {
313                 return Version(1,1,0,1,VF_VENDOR,API_VERSION);
314         }
315 };
316
317
318 class ModulewatchFactory : public ModuleFactory
319 {
320  public:
321         ModulewatchFactory()
322         {
323         }
324         
325         ~ModulewatchFactory()
326         {
327         }
328         
329         virtual Module * CreateModule(InspIRCd* Me)
330         {
331                 return new Modulewatch(Me);
332         }
333         
334 };
335
336
337 extern "C" void * init_module( void )
338 {
339         return new ModulewatchFactory;
340 }
341