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