]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/helpmod.c
r657@blue (orig r496): slug | 2006-05-16 00:09:51 +0100
[irc/quakenet/newserv.git] / helpmod2 / helpmod.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5
6 #include "../localuser/localuser.h"
7 #include "../localuser/localuserchannel.h"
8 #include "../control/control.h"
9 #include "../channel/channel.h"
10 #include "../nick/nick.h"
11 #include "../core/config.h"
12 #include "../core/schedule.h"
13 #include "../core/hooks.h"
14
15 #include "helpmod_entries.h"
16 #include "helpmod_alias.h"
17
18 #include "helpmod.h"
19 #include "hcommand.h"
20 #include "hcommands.h"
21 #include "hterm.h"
22 #include "hchanban.h"
23 #include "hcensor.h"
24 #include "hchannel.h"
25 #include "hlamer.h"
26 #include "hban.h"
27 #include "hconf.h"
28 #include "hhooks.h"
29 #include "hstat.h"
30 #include "hgen.h"
31 #include "hdef.h"
32 #include "hticket.h"
33 #include "hed.h"
34
35 int HELPMOD_ACCOUNT_EXPIRATION[] =
36 {
37 14 * HDEF_d, /* H_LAMER */
38 7 * HDEF_d, /* H_PEON */
39 1 * HDEF_M, /* H_FRIEND */
40 2 * HDEF_M, /* H_TRIAL */
41 6 * HDEF_M, /* H_STAFF */
42 1 * HDEF_y, /* H_OPER */
43 2 * HDEF_y /* H_ADMIN */
44 };
45
46 /* new H stuff */
47 hcommand *hcommands;
48 hchannel *hchannels;
49 haccount *haccounts;
50 hterm *hterms;
51 hlc_profile *hlc_profiles;
52 hban *hbans;
53 huser *husers;
54 hchanban *hchanbans;
55 helpmod_editor *helpmod_editors;
56
57 modechanges hmodechanges;
58 time_t helpmod_startup_time;
59
60 helpmod_entry helpmod_base;
61 alias_tree aliases;
62 nick *helpmodnick;
63 char helpmod_db[128] = "helpmod/default";
64 long helpmod_usage;
65
66 int hstat_cycle;
67 time_t hstat_last_cycle;
68
69 enum
70 {
71 H_REPLY_PRIVMSG,
72 H_REPLY_NOTICE
73 };
74
75 void hcommit_modes(void)
76 {
77 if (hmodechanges.cp == NULL)
78 return;
79 if (hchannel_get_by_channel(hmodechanges.cp)->flags & H_PASSIVE)
80 {
81 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
82 return;
83 }
84 localsetmodeflush(&hmodechanges, 1);
85 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
86 }
87
88 void helpmod_reply(huser *target, channel* returntype, const char *message, ... )
89 {
90 char buf[512];
91 va_list va;
92 int reply_type;
93
94 if (helpmodnick==NULL) {
95 return;
96 }
97
98 va_start(va,message);
99 vsnprintf(buf,512,message,va);
100 va_end(va);
101
102 if (buf[0] == '\0' || buf[0] == '\n')
103 return;
104
105 if (returntype) /* channel */
106 reply_type = H_REPLY_NOTICE;
107 else /* private */
108 reply_type = H_REPLY_PRIVMSG;
109
110 if (target->account != NULL)
111 {
112 if (target->account->flags & H_ALL_PRIVMSG)
113 reply_type = H_REPLY_PRIVMSG;
114 if (target->account->flags & H_ALL_NOTICE)
115 reply_type = H_REPLY_NOTICE;
116 }
117
118 if (reply_type == H_REPLY_PRIVMSG)
119 sendmessagetouser(helpmodnick,target->real_user, "%s", buf);
120 else
121 sendnoticetouser(helpmodnick,target->real_user, "%s", buf);
122 }
123
124 void helpmod_message_channel(hchannel *hchan, const char *message, ...)
125 {
126 char buf[512];
127 va_list va;
128
129 if (helpmodnick==NULL || hchan == NULL) {
130 return;
131 }
132
133 va_start(va,message);
134 vsnprintf(buf,512,message,va);
135 va_end(va);
136
137 if (hchan->flags & H_PASSIVE)
138 return;
139
140 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", buf);
141 }
142
143 void helpmod_message_channel_long(hchannel *hchan, const char *message, ...)
144 {
145 char buf[2048], *bp = buf;
146 va_list va;
147 int i;
148
149 if (helpmodnick==NULL || hchan == NULL) {
150 return;
151 }
152
153 va_start(va,message);
154 vsnprintf(buf,2048,message,va);
155 va_end(va);
156
157 if (hchan->flags & H_PASSIVE)
158 return;
159
160 while (strlen(bp) > 450)
161 {
162 for (i=0;i<50;i++)
163 if (isspace(bp[390 + i]))
164 {
165 bp[390 + i] = '\0';
166 break;
167 }
168 if (i == 50)
169 bp[390 + i] = '\0';
170 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
171 bp+=(390+i+1);
172 }
173 if (*bp)
174 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
175 }
176
177 void helpmod_kick(hchannel *hchan, huser *target, const char *reason, ...)
178 {
179 char buf[512];
180 va_list va;
181
182 if (hchan->flags & H_PASSIVE)
183 return;
184
185 va_start(va,reason);
186 vsnprintf(buf,512,reason,va);
187 va_end(va);
188
189 localkickuser(helpmodnick, hchan->real_channel, target->real_user, buf);
190 }
191
192 void helpmod_invite(hchannel *hchan, huser *husr)
193 {
194 if (hchan->flags & H_PASSIVE)
195 return;
196
197 localinvite(helpmodnick, hchan->real_channel, husr->real_user);
198 }
199
200 static void hmode_set_channel(hchannel *hchan)
201 {
202 if (hmodechanges.cp && hmodechanges.cp != hchan->real_channel)
203 hcommit_modes();
204 hmodechanges.cp = hchan->real_channel;
205 }
206
207 void helpmod_channick_modes(huser *target, hchannel *hchan, short mode, int now)
208 {
209 void *args[] = { hchan->real_channel, helpmodnick, target->real_user};
210 hmode_set_channel(hchan);
211 localdosetmode_nick(&hmodechanges, target->real_user, mode);
212
213 if (huser_on_channel(target, hchan) == NULL)
214 {
215 Error("helpmod", ERR_WARNING, "Channick mode for user %s not on channel %s", huser_get_nick(target), hchannel_get_name(hchan));
216 return;
217 }
218
219 if (hchan->flags & H_PASSIVE)
220 return;
221
222 switch (mode)
223 {
224 case MC_OP:
225 triggerhook(HOOK_CHANNEL_OPPED, args);
226 break;
227 case MC_DEOP:
228 triggerhook(HOOK_CHANNEL_DEOPPED, args);
229 break;
230 case MC_VOICE:
231 triggerhook(HOOK_CHANNEL_VOICED, args);
232 break;
233 case MC_DEVOICE:
234 triggerhook(HOOK_CHANNEL_DEVOICED, args);
235 break;
236 }
237
238 if (now)
239 hcommit_modes();
240 }
241
242 void helpmod_setban(hchannel *hchan, const char *banstr, time_t expiration, int type, int now)
243 {
244 hmode_set_channel(hchan);
245
246 if (hchan->flags & H_PASSIVE)
247 return;
248
249 localdosetmode_ban(&hmodechanges, banstr, type);
250
251 if ((type == MCB_ADD) && (expiration > time(NULL)))
252 scheduleoneshot(expiration, (ScheduleCallback)&hchanban_schedule_entry, hchanban_add(hchan, banstr, expiration));
253
254 if (now)
255 hcommit_modes();
256 }
257
258 void helpmod_simple_modes(hchannel *hchan, int add, int remove, int now)
259 {
260 hmode_set_channel(hchan);
261
262 if (hchan->flags & H_PASSIVE)
263 return;
264
265 localdosetmode_simple(&hmodechanges, add, remove);
266
267 if (now)
268 hcommit_modes();
269 }
270
271 void helpmod_set_topic(hchannel *hchan, const char* topic)
272 {
273 if (hchan->flags & H_PASSIVE)
274 return;
275
276 localsettopic(helpmodnick, hchan->real_channel, (char*)topic);
277 }
278
279 void helpmod_privmsg(void **args)
280 {
281 void *sender = args[0];
282 void *message = args[1];
283
284 nick *sender_nick;
285 huser *sender_huser;
286
287 sender_nick = getnickbynick((char*)sender);
288
289 if ((sender_huser = huser_get(sender_nick)) == NULL)
290 sender_huser = huser_add(sender_nick);
291
292 huser_activity(sender_huser, NULL);
293
294 helpmod_command(sender_huser, NULL, (char*)message);
295 }
296
297 void helpmod_chan_privmsg(void **args)
298 {
299 void *sender = args[0];
300 channel *chan = (channel*)args[1];
301 void *message = args[2];
302
303 nick *sender_nick;
304 huser *sender_huser;
305 hcensor *tmp;
306 hchannel *hchan = hchannel_get_by_channel(chan);
307
308 sender_nick = getnickbynick((char*)sender);
309
310 if ((hchan == NULL || hchan->flags & H_PASSIVE))
311 return;
312
313 if ((sender_huser = huser_get(sender_nick)) == NULL)
314 sender_huser = huser_add(sender_nick);
315
316 if (hchan->flags & H_DO_STATS)
317 {
318 if (sender_huser->account != NULL)
319 hstat_calculate_account(hchan, sender_huser, message);
320 hstat_calculate_channel(hchan, sender_huser, message);
321 }
322 huser_activity(sender_huser, hchan);
323
324 if (huser_get_level(sender_huser) < H_TRIAL) /* staff and staff trials are not subject to any control */
325 {
326 if ((hchan->flags & H_CENSOR) && (tmp = hcensor_check(hchan->censor, (char*)message)))
327 { /* censor match */
328 if (hcensor_match(hchan, sender_huser, tmp))
329 return;
330 }
331 if ((hchan->flags & H_LAMER_CONTROL) && (hlc_check(hchan, sender_huser, (char*)message)))
332 return;
333 if ((hchan->flags & H_DISALLOW_LAME_TEXT) && helpmod_is_lame_line(message))
334 {
335 helpmod_kick(hchan, sender_huser, "Please only use normal text on %s", hchannel_get_name(hchan));
336 return;
337 }
338 if ((hchan->flags & H_HIGHLIGHT_PREVENTION) && hchannel_highlight_detection(hchan, (char*)message))
339 {
340 helpmod_kick(hchan, sender_huser, "Please do not abuse the highlight feature of IRC clients");
341 return;
342 }
343 }
344
345 if (hcommand_is_command((char*)message) && (hchan->flags & H_CHANNEL_COMMANDS))
346 helpmod_command(sender_huser, chan, (char*)message);
347 }
348
349 void helpmod_kicked(void **args)
350 {
351 /* just rejoin the channel, if an oper wants H gone he can use delchan */
352 channel *cp = findchannel(args[1]);
353 if (!cp)
354 localcreatechannel(helpmodnick, args[1]);
355 else
356 {
357 localjoinchannel(helpmodnick, cp);
358 localgetops(helpmodnick, cp);
359 }
360 }
361
362 void helpmodmessagehandler(nick *sender, int messagetype, void **args)
363 {
364 switch (messagetype)
365 {
366 case LU_PRIVMSG:
367 helpmod_privmsg(args);
368 break;
369 case LU_CHANMSG:
370 helpmod_chan_privmsg(args);
371 break;
372 case LU_KICKED:
373 helpmod_kicked(args);
374 break;
375 }
376
377 hcommit_modes();
378 }
379
380 void helpconnect(void) {
381 /* register H */
382 helpmodnick=registerlocaluser(HELPMOD_NICK,
383 "help",
384 "quakenet.org",
385 "NewServ HelpMod 2, /msg "HELPMOD_NICK" help",
386 HELPMOD_AUTH,
387 UMODE_OPER|UMODE_ACCOUNT|UMODE_SERVICE,&helpmodmessagehandler);
388 /* register hooks */
389 helpmod_registerhooks();
390
391 /* continue with the database */
392 if (helpmod_config_read(HELPMOD_DEFAULT_DB))
393 {
394 Error("helpmod", ERR_WARNING, "Error reading the default database '%s'", HELPMOD_DEFAULT_DB);
395 if (helpmod_config_read(HELPMOD_FALLBACK_DB))
396 Error("helpmod", ERR_ERROR, "Error reading the fallback database '%s'", HELPMOD_FALLBACK_DB);
397 }
398 if (!haccounts)
399 Error("helpmod", ERR_ERROR, "Read 0 accounts from database (something is broken)");
400
401 /* old H */
402 helpmod_init_entry(&helpmod_base);
403 helpmod_load_entries(HELPMOD_HELP_DEFAULT_DB);
404 }
405
406 void _init()
407 {
408 helpmod_usage = 0;
409 helpmod_base = NULL;
410 aliases = NULL;
411
412 hcommands = NULL;
413 hchannels = NULL;
414 hlc_profiles = NULL;
415 husers = NULL;
416 haccounts = NULL;
417 hbans = NULL;
418 hterms = NULL;
419 hchanbans = NULL;
420
421 helpmod_startup_time = time(NULL);
422 /* add the supported commands, needs to be done like this since 3 arrays would just become a mess */
423 /* first the legacy old-H commands */
424
425 hcommands_add();
426
427 srand(time(NULL));
428
429 /* init hmodechanges */
430 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
431
432 schedulerecurring(time(NULL)+1,0,HDEF_h,(ScheduleCallback)&huser_clear_inactives,NULL);
433 schedulerecurring(time(NULL)+1,0,HDEF_d,(ScheduleCallback)&haccount_clear_inactives,NULL);
434 schedulerecurring(time(NULL)+1,0,HDEF_m,(ScheduleCallback)&hban_remove_expired,NULL);
435 schedulerecurring(time(NULL)+1,0,30 * HDEF_s, (ScheduleCallback)&hchannel_remove_inactive_users, NULL);
436 schedulerecurring(time(NULL)+1,0,60 * HDEF_m,(ScheduleCallback)&hchannel_report, NULL);
437 schedulerecurring(time(NULL) + HDEF_h, 0, 6 * HDEF_h, (ScheduleCallback)&helpmod_config_scheduled_events, NULL);
438 schedulerecurring(time(NULL)+1,0,10 * HDEF_m, (ScheduleCallback)&hticket_remove_expired, NULL);
439 schedulerecurring(hstat_get_schedule_time() - 5 * HDEF_m, 0, HDEF_d, (ScheduleCallback)&hstat_scheduler, NULL);
440
441 helpconnect();
442 }
443
444 void _fini()
445 {
446 helpmod_deregisterhooks();
447 /* write the database so that we don't lose anything
448 existance of atleast one account is required (sanity check)
449 */
450 if (haccounts)
451 helpmod_config_write(HELPMOD_DEFAULT_DB);
452
453 /* delete schedule stuff */
454 deleteallschedules((ScheduleCallback)&helpconnect);
455 deleteallschedules((ScheduleCallback)&huser_clear_inactives);
456 deleteallschedules((ScheduleCallback)&haccount_clear_inactives);
457 deleteallschedules((ScheduleCallback)&hban_remove_expired);
458 deleteallschedules((ScheduleCallback)&hchannel_remove_inactive_users);
459 deleteallschedules((ScheduleCallback)&hchannel_report);
460 deleteallschedules((ScheduleCallback)&helpmod_config_scheduled_events);
461 deleteallschedules((ScheduleCallback)&hstat_scheduler);
462 deleteallschedules((ScheduleCallback)&hchannel_deactivate_join_flood);
463 deleteallschedules((ScheduleCallback)&hchanban_schedule_entry);
464 deleteallschedules((ScheduleCallback)&hticket_remove_expired);
465
466 hcommand_del_all();
467 hchannel_del_all();
468 huser_del_all();
469 hlc_del_all();
470 hban_del_all();
471 hterm_del_all(NULL);
472 hchanban_del_all();
473 helpmod_clear_aliases(&aliases);
474 helpmod_clear_all_entries();
475
476 deregisterlocaluser(helpmodnick, "Module unloaded");
477 }