]> jfr.im git - irc/quakenet/newserv.git/blob - nickwatch/nickwatch.c
nickwatch: Implement hook for nick changes.
[irc/quakenet/newserv.git] / nickwatch / nickwatch.c
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include "../core/schedule.h"
5 #include "../control/control.h"
6 #include "../newsearch/newsearch.h"
7 #include "../newsearch/parser.h"
8
9 typedef struct nickwatch {
10 int id;
11
12 char term[512];
13 parsertree *tree;
14
15 struct nickwatch *next;
16 } nickwatch;
17
18 typedef struct nickwatchevent {
19 char description[128];
20 long numeric;
21 } nickwatchevent;
22
23 static nickwatch *nickwatches;
24 static int nextnickwatch = 1;
25
26 static void nw_dummyreply(nick *np, char *format, ...) { }
27
28 static void nw_dummywall(int level, char *format, ...) { }
29
30 static int nw_currentid;
31 static nickwatchevent *nw_currentevent;
32
33 static void nw_printnick(searchCtx *ctx, nick *sender, nick *np) {
34 char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
35
36 controlwall(NO_OPER, NL_HITS, "nickwatch(#%d, %s): %s [%s] (%s) (%s)", nw_currentid, nw_currentevent->description, visiblehostmask(np,hostbuf),
37 IPtostr(np->ipaddress), printflags(np->umodes, umodeflags), np->realname->name->content);
38 }
39
40 static nickwatchevent *nwe_new(nick *np, const char *format, ...) {
41 nickwatchevent *nwe;
42 va_list va;
43
44 nwe = malloc(sizeof(nickwatchevent));
45 nwe->numeric = np->numeric;
46
47 va_start(va, format);
48 vsnprintf(nwe->description, sizeof(nwe->description), format, va);
49 va_end(va);
50
51 return nwe;
52 }
53
54 static void nwe_free(nickwatchevent *nwe) {
55 free(nwe);
56 }
57
58 static void nw_sched_processevent(void *arg) {
59 nickwatchevent *nwe = arg;
60 nick *np;
61 nickwatch *nw;
62
63 np = getnickbynumeric(nwe->numeric);
64
65 if (!np) {
66 nwe_free(nwe);
67 return;
68 }
69 nw_currentevent = nwe;
70
71 for (nw = nickwatches; nw; nw = nw->next) {
72 nw_currentid = nw->id;
73 ast_nicksearch(nw->tree->root, &nw_dummyreply, mynick, &nw_dummywall, &nw_printnick, NULL, NULL, 10, np);
74 }
75
76 nwe_free(nwe);
77 }
78
79 static void nw_hook_newnick(int hooknum, void *arg) {
80 nick *np = arg;
81 nickwatchevent *nwe = nwe_new(np, "new user");
82 scheduleoneshot(0, nw_sched_processevent, nwe);
83 }
84
85 static void nw_hook_rename(int hooknum, void *arg) {
86 void **args = arg;
87 nick *np = args[0];
88 char *oldnick = args[1];
89 nickwatchevent *nwe = nwe_new(np, "renamed from %s", oldnick);
90 scheduleoneshot(0, nw_sched_processevent, nwe);
91 }
92
93 static void nw_hook_joinchannel(int hooknum, void *arg) {
94 void **args = arg;
95 channel *cp = args[0];
96 nick *np = args[1];
97 nickwatchevent *nwe = nwe_new(np, "join channel %s", cp->index->name->content);
98 scheduleoneshot(0, nw_sched_processevent, nwe);
99 }
100
101 static int nw_cmd_nickwatch(void *source, int cargc, char **cargv) {
102 nick *sender = source;
103 nickwatch *nw;
104 parsertree *tree;
105
106 if (cargc < 1)
107 return CMD_USAGE;
108
109 tree = parse_string(reg_nicksearch, cargv[0]);
110 if (!tree) {
111 displaystrerror(controlreply, sender, cargv[0]);
112 return CMD_ERROR;
113 }
114
115 nw = malloc(sizeof(nickwatch));
116 nw->id = nextnickwatch++;
117 strncpy(nw->term, cargv[0], sizeof(nw->term));
118 nw->tree = parse_string(reg_nicksearch, cargv[0]);
119 nw->next = nickwatches;
120 nickwatches = nw;
121
122 controlreply(sender, "Done.");
123
124 return CMD_OK;
125 }
126
127 static int nw_cmd_nickunwatch(void *source, int cargc, char **cargv) {
128 nick *sender = source;
129 nickwatch **pnext, *nw;
130 int id;
131
132 if (cargc < 1)
133 return CMD_USAGE;
134
135 id = atoi(cargv[0]);
136
137 for (pnext = &nickwatches; *pnext; pnext = &((*pnext)->next)) {
138 nw = *pnext;
139
140 if (nw->id == id) {
141 parse_free(nw->tree);
142 *pnext = nw->next;
143 free(nw);
144
145 controlreply(sender, "Done.");
146 return CMD_OK;
147 }
148 }
149
150 controlreply(sender, "Nickwatch #%d not found.", id);
151
152 return CMD_ERROR;
153 }
154
155 static int nw_cmd_nickwatches(void *source, int cargc, char **cargv) {
156 nick *sender = source;
157 nickwatch *nw;
158
159 controlreply(sender, "ID Term");
160
161 for (nw = nickwatches; nw; nw = nw->next)
162 controlreply(sender, "%-5d %s", nw->id, nw->term);
163
164 controlreply(sender, "--- End of nickwatches.");
165
166 return CMD_OK;
167 }
168
169 void _init(void) {
170 registercontrolhelpcmd("nickwatch", NO_OPER, 1, &nw_cmd_nickwatch, "Usage: nickwatch <nicksearch term>\nAdds a nickwatch entry.");
171 registercontrolhelpcmd("nickunwatch", NO_OPER, 1, &nw_cmd_nickunwatch, "Usage: nickunwatch <#id>\nRemoves a nickwatch entry.");
172 registercontrolhelpcmd("nickwatches", NO_OPER, 0, &nw_cmd_nickwatches, "Usage: nickwatches\nLists nickwatches.");
173
174 registerhook(HOOK_NICK_NEWNICK, &nw_hook_newnick);
175 registerhook(HOOK_NICK_RENAME, &nw_hook_rename);
176 registerhook(HOOK_CHANNEL_CREATE, &nw_hook_joinchannel);
177 registerhook(HOOK_CHANNEL_JOIN, &nw_hook_joinchannel);
178 }
179
180 void _fini(void) {
181 nickwatch *nw, *next;
182
183 deregistercontrolcmd("nickwatch", &nw_cmd_nickwatch);
184 deregistercontrolcmd("nickunwatch", &nw_cmd_nickunwatch);
185 deregistercontrolcmd("nickwatches", &nw_cmd_nickwatches);
186
187 deregisterhook(HOOK_NICK_NEWNICK, &nw_hook_newnick);
188 deregisterhook(HOOK_NICK_RENAME, &nw_hook_rename);
189 deregisterhook(HOOK_CHANNEL_CREATE, &nw_hook_joinchannel);
190 deregisterhook(HOOK_CHANNEL_JOIN, &nw_hook_joinchannel);
191
192 for (nw = nickwatches; nw; nw = next) {
193 next = nw->next;
194
195 parse_free(nw->tree);
196 free(nw);
197 }
198 }