]>
jfr.im git - irc/quakenet/newserv.git/blob - nickwatch/nickwatch.c
4 #include "../core/schedule.h"
5 #include "../control/control.h"
6 #include "../newsearch/newsearch.h"
7 #include "../newsearch/parser.h"
9 typedef struct nickwatch
{
17 struct nickwatch
*next
;
20 typedef struct nickwatchevent
{
21 char description
[128];
22 struct nickwatchevent
*next
;
25 static nickwatch
*nickwatches
;
26 static int nextnickwatch
= 1;
27 static int nickwatchext
;
29 static void nw_dummyreply(nick
*np
, char *format
, ...) { }
30 static void nw_dummywall(int level
, char *format
, ...) { }
32 static nickwatch
*nw_currentwatch
;
33 static array nw_pendingnicks
;
35 static void nw_printnick(searchCtx
*ctx
, nick
*sender
, nick
*np
) {
36 char hostbuf
[HOSTLEN
+NICKLEN
+USERLEN
+4], modebuf
[34];
38 nickwatchevent
*nwe
= np
->exts
[nickwatchext
];
41 nw_currentwatch
->hits
++;
46 for (nwe
= np
->exts
[nickwatchext
]; nwe
; nwe
= nwe
->next
) {
48 len
+= snprintf(events
+ len
, sizeof(events
) - len
, ", ");
50 len
+= snprintf(events
+ len
, sizeof(events
) - len
, "%s", nwe
->description
);
53 strncpy(modebuf
, printflags(np
->umodes
, umodeflags
), sizeof(modebuf
));
55 controlwall(NO_OPER
, NL_HITS
, "nickwatch(#%d, %s): %s [%s] (%s) (%s)", nw_currentwatch
->id
, events
, visiblehostmask(np
,hostbuf
),
56 IPtostr(np
->ipaddress
), modebuf
, np
->realname
->name
->content
);
59 static void nwe_enqueue(nick
*np
, const char *format
, ...) {
64 nwe
= malloc(sizeof(nickwatchevent
));
67 vsnprintf(nwe
->description
, sizeof(nwe
->description
), format
, va
);
70 nwe
->next
= np
->exts
[nickwatchext
];
71 np
->exts
[nickwatchext
] = nwe
;
73 slot
= array_getfreeslot(&nw_pendingnicks
);
74 ((nick
**)nw_pendingnicks
.content
)[slot
] = np
;
77 static void nwe_clear(nick
*np
) {
78 nickwatchevent
*nwe
, *next
;
80 for (nwe
= np
->exts
[nickwatchext
]; nwe
; nwe
= next
) {
85 np
->exts
[nickwatchext
] = NULL
;
88 static void nw_sched_processevents(void *arg
) {
95 array_init(&nicks
, sizeof(nick
*));
96 marker
= nextnickmarker();
98 for (i
= 0; i
< nw_pendingnicks
.cursi
; i
++) {
99 np
= ((nick
**)nw_pendingnicks
.content
)[i
];
104 if (np
->marker
!= marker
) {
106 slot
= array_getfreeslot(&nicks
);
107 ((nick
**)nicks
.content
)[slot
] = np
;
111 array_free(&nw_pendingnicks
);
112 array_init(&nw_pendingnicks
, sizeof(nick
*));
114 for (nw
= nickwatches
; nw
; nw
= nw
->next
) {
115 nw_currentwatch
= nw
;
116 ast_nicksearch(nw
->tree
->root
, &nw_dummyreply
, mynick
, &nw_dummywall
, &nw_printnick
, NULL
, NULL
, 10, &nicks
);
119 for (i
= 0; i
< nicks
.cursi
; i
++) {
120 np
= ((nick
**)nicks
.content
)[i
];
127 static void nw_hook_newnick(int hooknum
, void *arg
) {
129 nwe_enqueue(np
, "new user");
132 static void nw_hook_account(int hooknum
, void *arg
) {
134 nwe_enqueue(np
, "logged in with account %s", np
->authname
);
137 static void nw_hook_lostnick(int hooknum
, void *arg
) {
143 for (i
= 0; i
< nw_pendingnicks
.cursi
; i
++)
144 if (((nick
**)nw_pendingnicks
.content
)[i
] == np
)
145 ((nick
**)nw_pendingnicks
.content
)[i
] = NULL
;
148 static void nw_hook_rename(int hooknum
, void *arg
) {
151 char *oldnick
= args
[1];
152 nwe_enqueue(np
, "renamed from %s", oldnick
);
155 static void nw_hook_umodechange(int hooknum
, void *arg
) {
158 flag_t oldmodes
= (uintptr_t)args
[1];
160 strncpy(buf
, printflags(np
->umodes
, umodeflags
), sizeof(buf
));
161 nwe_enqueue(np
, "umodes %s -> %s", printflags(oldmodes
, umodeflags
), buf
);
164 static void nw_hook_message(int hooknum
, void *arg
) {
167 int isnotice
= (uintptr_t)args
[2];
168 nwe_enqueue(np
, isnotice
? "notice" : "message");
171 static void nw_hook_joinchannel(int hooknum
, void *arg
) {
173 channel
*cp
= args
[0];
175 nwe_enqueue(np
, "join channel %s", cp
->index
->name
->content
);
178 static int nw_cmd_nickwatch(void *source
, int cargc
, char **cargv
) {
179 nick
*sender
= source
;
186 tree
= parse_string(reg_nicksearch
, cargv
[0]);
188 displaystrerror(controlreply
, sender
, cargv
[0]);
192 nw
= malloc(sizeof(nickwatch
));
193 nw
->id
= nextnickwatch
++;
194 snprintf(nw
->createdby
, sizeof(nw
->createdby
), "#%s", sender
->authname
);
196 strncpy(nw
->term
, cargv
[0], sizeof(nw
->term
));
197 nw
->tree
= parse_string(reg_nicksearch
, cargv
[0]);
198 nw
->next
= nickwatches
;
201 controlreply(sender
, "Done.");
206 static int nw_cmd_nickunwatch(void *source
, int cargc
, char **cargv
) {
207 nick
*sender
= source
;
208 nickwatch
**pnext
, *nw
;
216 for (pnext
= &nickwatches
; *pnext
; pnext
= &((*pnext
)->next
)) {
220 parse_free(nw
->tree
);
224 controlreply(sender
, "Done.");
229 controlreply(sender
, "Nickwatch #%d not found.", id
);
234 static int nw_cmd_nickwatches(void *source
, int cargc
, char **cargv
) {
235 nick
*sender
= source
;
238 controlreply(sender
, "ID Created By Hits Term");
240 for (nw
= nickwatches
; nw
; nw
= nw
->next
)
241 controlreply(sender
, "%-5d %-15s %-7d %s", nw
->id
, nw
->createdby
, nw
->hits
, nw
->term
);
243 controlreply(sender
, "--- End of nickwatches.");
249 nickwatchext
= registernickext("nickwatch");
251 array_init(&nw_pendingnicks
, sizeof(nick
*));
253 registercontrolhelpcmd("nickwatch", NO_OPER
, 1, &nw_cmd_nickwatch
, "Usage: nickwatch <nicksearch term>\nAdds a nickwatch entry.");
254 registercontrolhelpcmd("nickunwatch", NO_OPER
, 1, &nw_cmd_nickunwatch
, "Usage: nickunwatch <#id>\nRemoves a nickwatch entry.");
255 registercontrolhelpcmd("nickwatches", NO_OPER
, 0, &nw_cmd_nickwatches
, "Usage: nickwatches\nLists nickwatches.");
257 registerhook(HOOK_NICK_NEWNICK
, &nw_hook_newnick
);
258 registerhook(HOOK_NICK_ACCOUNT
, &nw_hook_account
);
259 registerhook(HOOK_NICK_LOSTNICK
, &nw_hook_lostnick
);
260 registerhook(HOOK_NICK_RENAME
, &nw_hook_rename
);
261 registerhook(HOOK_NICK_MODECHANGE
, &nw_hook_umodechange
);
262 registerhook(HOOK_NICK_MESSAGE
, &nw_hook_message
);
263 registerhook(HOOK_CHANNEL_CREATE
, &nw_hook_joinchannel
);
264 registerhook(HOOK_CHANNEL_JOIN
, &nw_hook_joinchannel
);
266 schedulerecurring(time(NULL
) + 5, 0, 1, &nw_sched_processevents
, NULL
);
270 nickwatch
*nw
, *next
;
272 deregistercontrolcmd("nickwatch", &nw_cmd_nickwatch
);
273 deregistercontrolcmd("nickunwatch", &nw_cmd_nickunwatch
);
274 deregistercontrolcmd("nickwatches", &nw_cmd_nickwatches
);
276 deregisterhook(HOOK_NICK_NEWNICK
, &nw_hook_newnick
);
277 deregisterhook(HOOK_NICK_ACCOUNT
, &nw_hook_account
);
278 deregisterhook(HOOK_NICK_LOSTNICK
, &nw_hook_lostnick
);
279 deregisterhook(HOOK_NICK_RENAME
, &nw_hook_rename
);
280 deregisterhook(HOOK_NICK_MODECHANGE
, &nw_hook_umodechange
);
281 deregisterhook(HOOK_NICK_MESSAGE
, &nw_hook_message
);
282 deregisterhook(HOOK_CHANNEL_CREATE
, &nw_hook_joinchannel
);
283 deregisterhook(HOOK_CHANNEL_JOIN
, &nw_hook_joinchannel
);
285 deleteallschedules(&nw_sched_processevents
);
287 /* Process all pending events */
288 nw_sched_processevents(NULL
);
290 array_free(&nw_pendingnicks
);
292 releasenickext(nickwatchext
);
294 for (nw
= nickwatches
; nw
; nw
= next
) {
297 parse_free(nw
->tree
);