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