]> jfr.im git - irc/quakenet/newserv.git/blame - helpmod2/helpmod.c
r657@blue (orig r496): slug | 2006-05-16 00:09:51 +0100
[irc/quakenet/newserv.git] / helpmod2 / helpmod.c
CommitLineData
c86edd1d
Q
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"
9af95c3d 33#include "hed.h"
c86edd1d
Q
34
35int HELPMOD_ACCOUNT_EXPIRATION[] =
36{
37 14 * HDEF_d, /* H_LAMER */
e908ecfa 38 7 * HDEF_d, /* H_PEON */
052247fa 39 1 * HDEF_M, /* H_FRIEND */
e908ecfa 40 2 * HDEF_M, /* H_TRIAL */
41 6 * HDEF_M, /* H_STAFF */
42 1 * HDEF_y, /* H_OPER */
43 2 * HDEF_y /* H_ADMIN */
c86edd1d
Q
44};
45
46/* new H stuff */
47hcommand *hcommands;
48hchannel *hchannels;
49haccount *haccounts;
50hterm *hterms;
51hlc_profile *hlc_profiles;
52hban *hbans;
53huser *husers;
54hchanban *hchanbans;
9af95c3d 55helpmod_editor *helpmod_editors;
c86edd1d
Q
56
57modechanges hmodechanges;
58time_t helpmod_startup_time;
59
60helpmod_entry helpmod_base;
61alias_tree aliases;
62nick *helpmodnick;
63char helpmod_db[128] = "helpmod/default";
64long helpmod_usage;
65
66int hstat_cycle;
67time_t hstat_last_cycle;
68
69enum
70{
71 H_REPLY_PRIVMSG,
72 H_REPLY_NOTICE
73};
74
75void 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
88void 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
9af95c3d 102 if (buf[0] == '\0' || buf[0] == '\n')
103 return;
104
c86edd1d
Q
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
124void 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
e908ecfa 137 if (hchan->flags & H_PASSIVE)
138 return;
139
b808acb7 140 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", buf);
c86edd1d
Q
141}
142
143void 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
e908ecfa 157 if (hchan->flags & H_PASSIVE)
158 return;
159
c86edd1d
Q
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';
b808acb7 170 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
c86edd1d
Q
171 bp+=(390+i+1);
172 }
173 if (*bp)
b808acb7 174 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
c86edd1d
Q
175}
176
177void 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
192void helpmod_invite(hchannel *hchan, huser *husr)
193{
e908ecfa 194 if (hchan->flags & H_PASSIVE)
195 return;
196
c86edd1d
Q
197 localinvite(helpmodnick, hchan->real_channel, husr->real_user);
198}
199
200static 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
207void 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 {
3a839281 215 Error("helpmod", ERR_WARNING, "Channick mode for user %s not on channel %s", huser_get_nick(target), hchannel_get_name(hchan));
c86edd1d
Q
216 return;
217 }
218
e908ecfa 219 if (hchan->flags & H_PASSIVE)
220 return;
221
c86edd1d
Q
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
242void helpmod_setban(hchannel *hchan, const char *banstr, time_t expiration, int type, int now)
243{
244 hmode_set_channel(hchan);
e908ecfa 245
246 if (hchan->flags & H_PASSIVE)
247 return;
248
c86edd1d
Q
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
258void helpmod_simple_modes(hchannel *hchan, int add, int remove, int now)
259{
260 hmode_set_channel(hchan);
261
e908ecfa 262 if (hchan->flags & H_PASSIVE)
263 return;
264
c86edd1d
Q
265 localdosetmode_simple(&hmodechanges, add, remove);
266
267 if (now)
268 hcommit_modes();
269}
270
271void helpmod_set_topic(hchannel *hchan, const char* topic)
272{
e908ecfa 273 if (hchan->flags & H_PASSIVE)
274 return;
275
c86edd1d
Q
276 localsettopic(helpmodnick, hchan->real_channel, (char*)topic);
277}
278
279void 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
297void 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)
3a839281 317 {
318 if (sender_huser->account != NULL)
319 hstat_calculate_account(hchan, sender_huser, message);
320 hstat_calculate_channel(hchan, sender_huser, message);
321 }
c86edd1d
Q
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 */
643deb1b 328 if (hcensor_match(hchan, sender_huser, tmp))
329 return;
c86edd1d
Q
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 {
3a839281 335 helpmod_kick(hchan, sender_huser, "Please only use normal text on %s", hchannel_get_name(hchan));
c86edd1d 336 return;
135d6084 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 }
c86edd1d
Q
343 }
344
345 if (hcommand_is_command((char*)message) && (hchan->flags & H_CHANNEL_COMMANDS))
346 helpmod_command(sender_huser, chan, (char*)message);
347}
348
349void 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
362void 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
380void helpconnect(void) {
381 /* register H */
382 helpmodnick=registerlocaluser(HELPMOD_NICK,
383 "help",
384 "quakenet.org",
b808acb7 385 "NewServ HelpMod 2, /msg "HELPMOD_NICK" help",
c86edd1d
Q
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
406void _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);
e908ecfa 436 schedulerecurring(time(NULL)+1,0,60 * HDEF_m,(ScheduleCallback)&hchannel_report, NULL);
c86edd1d
Q
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
444void _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}