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