]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hcommands.c
Merged revisions 310,312-314,322-323,328-329 via svnmerge from
[irc/quakenet/newserv.git] / helpmod2 / hcommands.c
1 #include <string.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <assert.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7
8 #include "../nick/nick.h"
9 #include "../channel/channel.h"
10 #include "../lib/irc_string.h"
11
12 #include "hcommands.h"
13 #include "hcommand.h"
14
15 #include "helpmod.h"
16 #include "klingon.h"
17 #include "helpmod_alias.h"
18
19 #include "haccount.h"
20 #include "hqueue.h"
21 #include "hterm.h"
22
23 #include "hgen.h"
24 #include "hban.h"
25 #include "hchanban.h"
26
27 #include "hticket.h"
28 #include "hconf.h"
29
30 /* following are macros for use ONLY IN HERE
31 they may not look pretty, but work surprisingly well */
32
33 #define SKIP_WORD \
34 {\
35 if (*ostr == '"' && strchr(ostr+1, '"'))\
36 ostr = strchr(ostr+1, '"');\
37 while (!isspace(*ostr) && *ostr)\
38 ostr++;\
39 while (isspace(*ostr) && *ostr)\
40 ostr++;\
41 argc--;\
42 argv++;\
43 }
44
45 #define DEFINE_HCHANNEL \
46 {\
47 if (argc == 0)\
48 hchan = hchannel_get_by_channel(returntype);\
49 else if (*argv[0] == '#')\
50 {\
51 hchan = hchannel_get_by_name(argv[0]);\
52 SKIP_WORD;\
53 }\
54 else\
55 hchan = hchannel_get_by_channel(returntype);\
56 }
57
58 #define HCHANNEL_VERIFY_AUTHORITY(c, u)\
59 {\
60 if ((c) != NULL && !hchannel_authority((c), (u)))\
61 {\
62 helpmod_reply(u, returntype, "Sorry, channel %s is oper only", hchannel_get_name((c)));\
63 return;\
64 }\
65 }
66
67 enum
68 {
69 H_CMD_OP,
70 H_CMD_DEOP,
71 H_CMD_VOICE,
72 H_CMD_DEVOICE
73 };
74
75 enum
76 {
77 H_TERM_FIND,
78 H_TERM_MINUS,
79 H_TERM_PLUS
80 };
81
82 static void helpmod_cmd_addchan (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
83 {
84 if (argc == 0)
85 {
86 helpmod_reply(sender, returntype, "Cannot add channel: Channel not defined");
87 return;
88 }
89
90 if (*argv[0] != '#')
91 {
92 helpmod_reply(sender, returntype, "Can not add channel: Channel name must start with '#'");
93 return;
94 }
95
96 if (hchannel_get_by_name(argv[0]) != NULL)
97 {
98 helpmod_reply(sender, returntype, "Can not add channel: Channel %s already active", argv[0]);
99 return;
100 }
101
102 if (hchannel_add(argv[0]) != NULL)
103 {
104 helpmod_reply(sender, returntype, "Channel %s added succesfully", argv[0]);
105 return;
106 }
107 }
108
109 static void helpmod_cmd_delchan (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
110 {
111 hchannel *hchan;
112 char buffer[256];
113 DEFINE_HCHANNEL;
114
115 if (hchan == NULL)
116 {
117 helpmod_reply(sender, returntype, "Can not delete channel: Channel not defined or not found");
118 return;
119 }
120 strcpy(buffer, hchan->real_channel->index->name->content);
121 if (argc == 0 || strcmp(argv[0], "YesImSure"))
122 {
123 helpmod_reply(sender, returntype, "Can not delete channel: Sanity check. Please add a parameter \"YesImSure\" to confirm channel deletion");
124 return;
125 }
126 hchannel_del(hchan);
127
128 helpmod_reply(sender, returntype, "Channel %s deleted succesfully", buffer);
129 }
130
131 static void helpmod_cmd_whoami (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
132 {
133 helpmod_reply(sender, returntype, "You are %s", huser_get_nick(sender));
134 helpmod_reply(sender, returntype, "Your userlevel is %s", hlevel_name(huser_get_level(sender)));
135 if (sender->account == NULL)
136 helpmod_reply(sender, returntype, "You do not have an account with me");
137 else
138 helpmod_reply(sender, returntype, "Your accounts name is %s", sender->account->name->content);
139 if (huser_get_level(sender) < H_TRIAL)
140 {
141 if (sender->lc[0] || sender->lc[1] || sender->lc[2] || sender->lc[3] || sender->lc[4])
142 helpmod_reply(sender, returntype, "You violated the following rules: Excessive use of capital letters: %d, repeating: %d, improper use of language: %d, flooding: %d and spamming: %d", sender->lc[0], sender->lc[1], sender->lc[2], sender->lc[3], sender->lc[4]);
143 else
144 helpmod_reply(sender, returntype, "You have not violated any rules");
145 }
146
147 {
148 int pos;
149 huser_channel *huserchan = sender->hchannels;
150 for (;huserchan;huserchan = huserchan->next)
151 if ((pos = hqueue_get_position(huserchan->hchan, sender)) > -1)
152 helpmod_reply(sender, returntype, "You have queue position #%d on channel %s", pos, hchannel_get_name(huserchan->hchan));
153 }
154
155 if (IsAccount(sender->real_user))
156 {
157 hchannel *hchan;
158 hticket *htick;
159 for (hchan = hchannels;hchan;hchan = hchan->next)
160 if (hchan->flags & H_REQUIRE_TICKET)
161 {
162 htick = hticket_get(huser_get_auth(sender), hchan);
163 if (htick != NULL)
164 helpmod_reply(sender, returntype, "You have an invite ticket for channel %s that expires in %s", hchannel_get_name(hchan), helpmod_strtime(time(NULL) - htick->time_expiration));
165 }
166 }
167 }
168
169 static void helpmod_cmd_whois (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
170 {
171 huser *husr;
172 int i;
173
174 if (argc == 0)
175 {
176 helpmod_reply(sender, returntype, "Cannot get user information: User not specified");
177 return;
178 }
179 if (argc > H_CMD_MAX_ARGS)
180 argc = H_CMD_MAX_ARGS;
181
182 for (i=0;i<argc;i++)
183 {
184 husr = huser_get(getnickbynick(argv[i]));
185 if (husr == NULL)
186 {
187 if (getnickbynick(argv[i]) == NULL)
188 helpmod_reply(sender, returntype, "Cannot get user information: User %s does not exist in the network", argv[i]);
189 else
190 helpmod_reply(sender, returntype, "Cannot get user information: User %s exists but is not known to me", argv[i]);
191 continue;
192 }
193 helpmod_reply(sender, returntype, "User %s has userlevel %s", huser_get_nick(husr), hlevel_name(huser_get_level(husr)));
194 if (husr->account == NULL)
195 helpmod_reply(sender, returntype, "User %s does not have an account with me", huser_get_nick(husr));
196 else
197 helpmod_reply(sender, returntype, "User %s has account named %s", huser_get_nick(husr),husr->account->name->content);
198 if (huser_get_level(husr) < H_TRIAL)
199 {
200 if (husr->lc[0] || husr->lc[1] || husr->lc[2] || husr->lc[3] || husr->lc[4])
201 helpmod_reply(sender, returntype, "User %s has lamercontrol entries: Excessive use of capital letters: %d, repeating: %d, improper use of language: %d, flooding: %d and spamming: %d", huser_get_nick(husr), husr->lc[0], husr->lc[1], husr->lc[2], husr->lc[3], husr->lc[4]);
202 else
203 helpmod_reply(sender, returntype, "User %s has no lamercontrol entries", huser_get_nick(husr));
204 }
205 {
206 int pos;
207 huser_channel *huserchan = husr->hchannels;
208 for (;huserchan;huserchan = huserchan->next)
209 {
210 if ((pos = hqueue_get_position(huserchan->hchan, husr)) > -1)
211 helpmod_reply(sender, returntype, "User %s has queue queue position #%d on channel %s", huser_get_nick(husr), pos, hchannel_get_name(huserchan->hchan));
212 if (on_desk(husr, huserchan))
213 helpmod_reply(sender, returntype, "User %s is receiving support on channel %s", huser_get_nick(husr), hchannel_get_name(huserchan->hchan));
214 }
215 }
216 if (IsAccount(husr->real_user))
217 {
218 hchannel *hchan;
219 hticket *htick;
220 for (hchan = hchannels;hchan;hchan = hchan->next)
221 if (hchan->flags & H_REQUIRE_TICKET)
222 {
223 htick = hticket_get(huser_get_auth(husr), hchan);
224 if (htick != NULL)
225 helpmod_reply(sender, returntype, "User %s has an invite ticket for channel %s that expires in %s", huser_get_nick(husr), hchannel_get_name(hchan), helpmod_strtime(time(NULL) - htick->time_expiration));
226 }
227 }
228 }
229 }
230 /*
231 void helpmod_cmd_megod (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
232 {
233 if (sender->account == NULL)
234 sender->account = haccount_add(huser_get_nick(sender), H_ADMIN);
235
236 sender->account->level = H_ADMIN;
237 }
238 */
239
240 static void helpmod_cmd_seen (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
241 {
242 huser *target_huser;
243 haccount *target_haccount;
244 int i;
245
246 if (argc == 0)
247 {
248 helpmod_reply(sender, returntype, "No targets specified for seen");
249 return;
250 }
251 for (i=0;i < argc;i++)
252 {
253 if (*argv[i] == '#')
254 { /* account */
255 if (!ci_strcmp(argv[i] + 1, HELPMOD_AUTH))
256 { /* A nice special case */
257 helpmod_reply(sender, returntype, "I'm right here");
258 continue;
259 }
260 target_haccount = haccount_get_by_name(argv[i]);
261 if (target_haccount == NULL)
262 {
263 helpmod_reply(sender, returntype, "Account %s not found", argv[i] + 1);
264 continue;
265 }
266
267 helpmod_reply(sender, returntype, "Account %s's last recorded activity was %s ago", target_haccount->name->content, helpmod_strtime(time(NULL) - target_haccount->last_activity));
268 }
269 else
270 {
271 if (getnickbynick(argv[i]) == helpmodnick)
272 { /* A nice special case */
273 helpmod_reply(sender, returntype, "I'm right here");
274 continue;
275 }
276 target_huser = huser_get(getnickbynick(argv[i]));
277 if (target_huser == NULL)
278 {
279 helpmod_reply(sender, returntype, "User %s not found", argv[i]);
280 continue;
281 }
282 helpmod_reply(sender, returntype, "User %s's last recorded activity was %s ago", huser_get_nick(target_huser), helpmod_strtime(time(NULL) - target_huser->last_activity));
283 }
284 }
285 }
286
287 static void helpmod_cmd_change_userlevel(huser *sender, hlevel target_level, channel* returntype, char* ostr, int argc, char *argv[])
288 {
289 huser *target_huser;
290 haccount *target_haccount;
291 int i;
292
293 if (argc == 0)
294 {
295 helpmod_reply(sender, returntype, "Incorrect syntax: Nick or account required");
296 return ;
297 }
298
299 if (argc > H_CMD_MAX_ARGS)
300 argc = H_CMD_MAX_ARGS;
301
302 for (i = 0;i < argc;i++)
303 {
304 if (*argv[i] == '#') /* account */
305 {
306 target_haccount = haccount_get_by_name(argv[i]);
307 if (target_haccount == NULL)
308 {
309 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' not found", argv[i]);
310 continue;
311 }
312 if (target_haccount->level > huser_get_level(sender))
313 {
314 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' has a userlevel higher than yours", argv[i]);
315 continue;
316 }
317
318 if (target_haccount->level == target_level)
319 {
320 helpmod_reply(sender, returntype, "Cannot change userlevel: Account '%s' already has userlevel %s", argv[i], hlevel_name(target_level));
321 continue;
322 }
323
324 target_haccount->level = target_level;
325
326 helpmod_reply(sender, returntype, "Userlevel changed: Account '%s' now has userlevel %s", argv[i], hlevel_name(target_level));
327
328 }
329 else
330 {
331 target_huser = huser_get(getnickbynick(argv[i]));
332 if (target_huser == NULL)
333 {
334 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' not found", argv[i]);
335 continue;
336 }
337 if (huser_get_level(target_huser) > huser_get_level(sender))
338 {
339 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' has a userlevel higher than yours", argv[i]);
340 continue;
341 }
342 if (huser_get_level(target_huser) == H_STAFF && huser_get_level(sender) == H_STAFF)
343 {
344 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' has the same userlevel as you have", argv[i]);
345 continue;
346 }
347
348 if (huser_get_level(target_huser) == target_level)
349 {
350 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' already has userlevel %s", argv[i], hlevel_name(target_level));
351 continue;
352 }
353 if (target_huser == sender)
354 {
355 helpmod_reply(sender, returntype, "Cannot change userlevel: Sanity check, you're changing your own userlevel, use #account instead of nick if you really wish to do this");
356 continue;
357 }
358
359 if (target_level == H_LAMER)
360 {
361 const char *banmask = hban_ban_string(target_huser->real_user, HBAN_HOST);
362 hban_add(banmask, "Improper user", time(NULL) + HCMD_OUT_DEFAULT, 1);
363 if (!IsAccount(target_huser->real_user))
364 {
365 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' is not authed. Banning user instead.", argv[i]);
366 continue;
367 }
368 }
369
370 if (!IsAccount(target_huser->real_user))
371 {
372 helpmod_reply(sender, returntype, "Cannot change userlevel: User '%s' is not authed", argv[i]);
373 continue;
374 }
375
376 if (target_huser->account == NULL)
377 {
378 if (haccount_get_by_name(huser_get_auth(target_huser)) != NULL)
379 {
380 helpmod_reply(sender, returntype, "Cannot change userlevel: Unable to create an account. Account %s already exists", huser_get_auth(target_huser));
381 continue;
382 }
383 else
384 target_huser->account = haccount_add(huser_get_auth(target_huser), target_level);
385 }
386
387 target_huser->account->level = target_level;
388
389 helpmod_reply(sender, returntype, "Userlevel changed: User '%s' now has userlevel %s", argv[i], hlevel_name(target_level));
390
391 if (target_level != H_LAMER)
392 helpmod_reply(target_huser, NULL, "Your userlevel has been changed, your current userlevel is %s", hlevel_name(target_level));
393 }
394 }
395 }
396
397 /* pseudo commands for the above */
398 static void helpmod_cmd_improper (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_LAMER, returntype, ostr, argc, argv); }
399 static void helpmod_cmd_peon (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_PEON, returntype, ostr, argc, argv); }
400 static void helpmod_cmd_trial (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_TRIAL, returntype, ostr, argc, argv); }
401 static void helpmod_cmd_staff (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_STAFF, returntype, ostr, argc, argv); }
402 static void helpmod_cmd_oper (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_OPER, returntype, ostr, argc, argv); }
403 static void helpmod_cmd_admin (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_change_userlevel(sender, H_ADMIN, returntype, ostr, argc, argv); }
404
405 static void helpmod_cmd_deluser (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
406 {
407 int i;
408 huser *target_huser;
409 haccount *target_haccount;
410
411 if (argc == 0)
412 {
413 helpmod_reply(sender, returntype, "Usage: deluser [nick|#account]");
414 return;
415 }
416
417 if (argc > H_CMD_MAX_ARGS)
418 argc = H_CMD_MAX_ARGS;
419
420 for (i = 0;i < argc;i++)
421 {
422 if (*argv[i] != '#')
423 {
424 target_huser = huser_get(getnickbynick(argv[i]));
425 if (target_huser == NULL)
426 {
427 helpmod_reply(sender, returntype, "Cannot delete the account: User %s does not exist", argv[i]);
428 continue;
429 }
430 if (target_huser->account == NULL)
431 {
432 helpmod_reply(sender, returntype, "Cannot delete the account: User %s does not have an account", argv[i]);
433 continue;
434 }
435 target_haccount = target_huser->account;
436 }
437 else
438 target_haccount = haccount_get_by_name(argv[i]);
439
440 if (target_haccount == NULL)
441 {
442 helpmod_reply(sender, returntype, "Cannot delete the account: Account %s does not exist", argv[i]);
443 continue;
444 }
445 if (target_haccount->level > huser_get_level(sender))
446 {
447 helpmod_reply(sender, returntype, "Cannot delete the account: Account %s has higher userlevel than you", target_haccount->name->content);
448 continue;
449 }
450 helpmod_reply(sender, returntype, "Account %s deleted", target_haccount->name->content);
451 haccount_del(target_haccount);
452 }
453 }
454
455 static void helpmod_cmd_listuser (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
456 {
457 char *pattern;
458 haccount *hack = haccounts;
459 int count = 0, lvl = -1;
460 time_t timer;
461
462 if (argc > 0 && sscanf(argv[0], "%d", &lvl) && lvl >= H_LAMER && lvl <= H_ADMIN)
463 {
464 SKIP_WORD;
465 }
466 else
467 lvl = -1;
468
469 if (argc == 0)
470 pattern = "*";
471 else
472 pattern = argv[0];
473
474 if (lvl >= 0)
475 helpmod_reply(sender, returntype, "%s accounts matching pattern %s: (account name, userlevel, expires in)", hlevel_name(lvl), pattern);
476 else
477 helpmod_reply(sender, returntype, "Accounts matching pattern %s: (account name, userlevel, expires in)", pattern);
478 for (;hack;hack = hack->next)
479 {
480 if (strregexp(hack->name->content, pattern))
481 {
482 if (lvl >= 0 && hack->level != lvl)
483 continue;
484 timer = hack->last_activity + HELPMOD_ACCOUNT_EXPIRATION[hack->level];
485 helpmod_reply(sender, returntype, "%-16s %-32s %s", hack->name->content, hlevel_name(hack->level), asctime(localtime(&timer)));
486 count++;
487 }
488 }
489 if (lvl >= 0)
490 helpmod_reply(sender, returntype, "%s accounts matching pattern %d", hlevel_name(lvl), count);
491 else
492 helpmod_reply(sender, returntype, "Accounts matching pattern %d", count);
493 }
494
495 static void helpmod_cmd_censor (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
496 {
497 hchannel *hchan;
498 hcensor *hcens;
499 int i = 0;
500
501 DEFINE_HCHANNEL;
502
503 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
504
505 if (hchan == NULL)
506 {
507 helpmod_reply(sender, returntype, "Cannot handle the censor: Channel not specified or found");
508 return;
509 }
510
511 if (argc < 2 || !ci_strcmp(argv[0], "list")) /* view */
512 {
513 if (hchan->censor == NULL)
514 helpmod_reply(sender, returntype, "Nothing is censored on channel %s", hchan->real_channel->index->name->content);
515 else
516 {
517 helpmod_reply(sender, returntype, "Censored patterns for channel %s (%s):", hchan->real_channel->index->name->content, (hchan->flags & H_CENSOR)?"active":"inactive");
518 for (hcens = hchan->censor;hcens;hcens = hcens->next)
519 helpmod_reply(sender, returntype, "#%-4d %-8s %s%s%s", i++, hcensor_get_typename(hcens->type), hcens->pattern->content, hcens->reason?" :: ":"", hcens->reason?hcens->reason->content:"");
520 }
521 }
522 else
523 {
524 if (!ci_strcmp(argv[0], "add"))
525 {
526 char *pattern;
527 char *reason;
528 int type = HCENSOR_KICK;
529
530 SKIP_WORD;
531
532 /* not very elegant but will have to do */
533 if (argc > 1)
534 {
535 if (!ci_strcmp(argv[0], "warn"))
536 {
537 type = HCENSOR_WARN;
538 if (argc <= 2)
539 {
540 helpmod_reply(sender, returntype, "Cannot add censor entry: Entries of type warn require a reason");
541 return;
542 }
543 SKIP_WORD;
544 }
545 else if (!ci_strcmp(argv[0], "kick"))
546 {
547 type = HCENSOR_KICK;
548 SKIP_WORD;
549 }
550 else if (!ci_strcmp(argv[0], "chanban"))
551 {
552 type = HCENSOR_CHANBAN;
553 SKIP_WORD;
554 }
555 else if (!ci_strcmp(argv[0], "ban"))
556 {
557 type = HCENSOR_BAN;
558 SKIP_WORD;
559 }
560 }
561
562 pattern = argv[0];
563
564 if (strlen(pattern) == 0)
565 {
566 helpmod_reply(sender, returntype, "Cannot add censor entry: Pattern must be non-empty");
567 return;
568 }
569
570 SKIP_WORD;
571 if (argc && strlen(ostr) > 0)
572 reason = ostr;
573 else
574 reason = NULL;
575
576 if (hcensor_get_by_pattern(hchan->censor, pattern))
577 {
578 helpmod_reply(sender, returntype, "Cannot add censor entry: Pattern '%s' is already censored", pattern);
579 return;
580 }
581
582 if (hcensor_add(&hchan->censor, pattern, reason, type))
583 helpmod_reply(sender, returntype, "Pattern '%s' (%s) with type %s, censored succesfully", pattern, reason?reason:"no reason specified", hcensor_get_typename(type));
584 else
585 helpmod_reply(sender, returntype, "Cannot add censor entry: Pattern '%s' is already censored", pattern);
586
587 }
588 else if (!ci_strcmp(argv[0], "del"))
589 {
590 SKIP_WORD;
591 if (*argv[0] == '#')
592 {
593 int tmp;
594 if (!sscanf(argv[0], "#%d", &tmp))
595 {
596 helpmod_reply(sender, returntype, "Cannot delete censor entry: Bad index, integer expected");
597 return;
598 }
599 hcens = hcensor_get_by_index(hchan->censor, tmp);
600 }
601 else
602 hcens = hcensor_get_by_pattern(hchan->censor, argv[0]);
603
604 if (hcens == NULL)
605 helpmod_reply(sender, returntype, "Cannot delete censor entry: Entry not found");
606 else
607 {
608 hcensor_del(&hchan->censor, hcens);
609 helpmod_reply(sender, returntype, "Censor entry deleted succesfully");
610 }
611 }
612 else
613 helpmod_reply(sender, returntype, "Unknown censor command %s", argv[0]);
614 }
615 }
616
617 static void helpmod_cmd_chanconf (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
618 {
619 hchannel *hchan;
620 int old_flags=0;
621
622 DEFINE_HCHANNEL;
623
624 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
625
626 if (hchan == NULL)
627 {
628 helpmod_reply(sender, returntype, "Cannot change or view channel configuration: Channel not specified or found");
629 return;
630 }
631
632 if (argc == 0) /* view, spammy but with pretty formatting */
633 {
634 int i;
635 helpmod_reply(sender, returntype, "Channel configuration for %s:", hchan->real_channel->index->name->content);
636
637 for (i=0;i<=HCHANNEL_CONF_COUNT;i++)
638 helpmod_reply(sender, returntype, "(%02d) %-32s : %s", i, hchannel_get_sname(i), hchannel_get_state(hchan, 1 << i));
639 }
640 else /* change */
641 {
642 int i, tmp, type;
643 old_flags = hchan->flags;
644
645 if (argc > H_CMD_MAX_ARGS)
646 argc = H_CMD_MAX_ARGS;
647
648 for (i=0;i<argc;i++)
649 {
650 if (*argv[i] == '+')
651 {
652 type = 1;
653 argv[i]++;
654 }
655 else if (*argv[i] == '-')
656 {
657 type = -1;
658 argv[i]++;
659 }
660 else
661 type = 0;
662
663 if (!sscanf(argv[i], "%d", &tmp) || (tmp < 0) || (tmp > HCHANNEL_CONF_COUNT))
664 {
665 helpmod_reply(sender, returntype, "Cannot change channel configuration: Expected integer between [0, %d]", HCHANNEL_CONF_COUNT);
666 continue;
667 }
668
669 switch (type)
670 {
671 case -1: /* unset */
672 hchan->flags &= ~(1 << tmp);
673 helpmod_reply(sender, returntype, "Channel configuration for %s changed: %s set to %s",hchannel_get_name(hchan), hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
674 break;
675 case 0: /* view */
676 helpmod_reply(sender, returntype, "(%02d) %-32s : %s", tmp, hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
677 break;
678 case 1: /* set */
679 hchan->flags |= (1 << tmp);
680 helpmod_reply(sender, returntype, "Channel configuration for %s changed: %s set to %s", hchannel_get_name(hchan), hchannel_get_sname(tmp), hchannel_get_state(hchan, 1 << tmp));
681 break;
682 }
683 }
684 hchannel_conf_change(hchan, old_flags);
685 }
686 }
687
688 static void helpmod_cmd_acconf (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
689 {
690 haccount *hacc = sender->account;
691
692 if (hacc == NULL)
693 {
694 helpmod_reply(sender, returntype, "Account configuration impossible: You do not have an account");
695 return;
696 }
697
698 if (argc == 0) /* view, spammy but with pretty formatting */
699 {
700 int i;
701 helpmod_reply(sender, returntype, "Account configuration for %s:", hacc->name->content);
702
703 for (i=0;i<=HACCOUNT_CONF_COUNT;i++)
704 helpmod_reply(sender, returntype, "(%02d) %-35s : %s", i, haccount_get_sname(i), haccount_get_state(hacc, 1 << i));
705 }
706 else /* change */
707 {
708 int i, tmp, type;
709
710 if (argc > H_CMD_MAX_ARGS)
711 argc = H_CMD_MAX_ARGS;
712
713 for (i=0;i<argc;i++)
714 {
715 if (*argv[i] == '+')
716 {
717 type = 1;
718 argv[i]++;
719 }
720 else if (*argv[i] == '-')
721 {
722 type = -1;
723 argv[i]++;
724 }
725 else
726 type = 0;
727
728 if (!sscanf(argv[i], "%d", &tmp) || (tmp < 0) || (tmp > HACCOUNT_CONF_COUNT))
729 {
730 helpmod_reply(sender, returntype, "Cannot change account configuration: Expected integer between [0, %d]", HACCOUNT_CONF_COUNT);
731 continue;
732 }
733
734 switch (type)
735 {
736 case -1: /* unset */
737 hacc->flags &= ~(1 << tmp);
738 helpmod_reply(sender, returntype, "Account configuration for %s changed: %s set to %s",hacc->name->content, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
739 break;
740 case 0: /* view */
741 helpmod_reply(sender, returntype, "(%02d) %-35s : %s", tmp, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
742 break;
743 case 1: /* set */
744 hacc->flags |= (1 << tmp);
745 helpmod_reply(sender, returntype, "Account configuration for %s changed: %s set to %s", hacc->name->content, haccount_get_sname(tmp), haccount_get_state(hacc, 1 << tmp));
746 break;
747 }
748 }
749 }
750 }
751
752 static void helpmod_cmd_welcome (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
753 {
754 hchannel *hchan;
755
756 DEFINE_HCHANNEL;
757
758 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
759
760 if (hchan == NULL)
761 {
762 helpmod_reply(sender, returntype, "Cannot change or view the welcome message: Channel not specified or found");
763 return;
764 }
765
766 if (argc == 0) /* view */
767 {
768 helpmod_reply(sender, returntype, "Welcome message for channel %s (%s): %s", hchan->real_channel->index->name->content, hchannel_get_state(hchan, H_WELCOME), hchan->welcome);
769 }
770 else
771 {
772 strcpy(hchan->welcome, ostr);
773 helpmod_reply(sender, returntype, "Welcome message for channel %s (%s) is now: %s", hchan->real_channel->index->name->content, hchannel_get_state(hchan, H_WELCOME), hchan->welcome);
774 }
775 }
776
777 static void helpmod_cmd_aliases (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
778 {
779 char buf[512];
780 int i = 0;
781 void helpmod_list_aliases(alias_tree node)
782 {
783 if (i > 256)
784 {
785 helpmod_reply(sender, returntype, "%s", buf);
786 i = 0;
787 }
788 if (!node)
789 return;
790 sprintf(buf+i,"%.200s ",node->name->content);
791 i+=(1+strlen(node->name->content));
792 helpmod_list_aliases(node->left);
793 helpmod_list_aliases(node->right);
794 }
795 helpmod_list_aliases(aliases);
796 if (i)
797 helpmod_reply(sender, returntype, "%s", buf);
798 }
799
800 static void helpmod_cmd_showcommands (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
801 {
802 int level = H_PEON, previous_level = H_PEON;
803 hcommand *tmp;
804
805 if (!(argc && (sscanf(argv[0], "%d", &level)) && (level >= 0) && (level <= huser_get_level(sender))))
806 level = huser_get_level(sender);
807
808 helpmod_reply(sender, returntype, "HelpMod %s commands for userlevel %s:", HELPMOD_VERSION, hlevel_name(level));
809
810 hcommand_list(H_NONE);
811
812 while ((tmp = hcommand_list(level)) != NULL)
813 {
814 if (tmp->level > previous_level)
815 {
816 helpmod_reply(sender, returntype, "--- Additional commands for userlevel %s ---", hlevel_name(tmp->level));
817 previous_level = tmp->level;
818 }
819 helpmod_reply(sender, returntype, "%-16s %s", tmp->name->content, tmp->help->content);
820 }
821
822 return;
823 }
824
825 static void helpmod_cmd_lamercontrol (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
826 {
827 hchannel *hchan;
828 hlc_profile *ptr;
829
830 DEFINE_HCHANNEL;
831
832 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
833
834 if (hchan == NULL) /* list profiles */
835 {
836 helpmod_reply(sender, returntype, "Following lamercontrol profiles are available:");
837 for (ptr = hlc_profiles;ptr;ptr = ptr->next)
838 helpmod_reply(sender, returntype, "%s", ptr->name->content);
839 return;
840 }
841 if (argc == 0)
842 {
843 if (hchan->lc_profile == NULL)
844 helpmod_reply(sender, returntype, "Channel %s has no lamercontrol profile set", hchannel_get_name(hchan));
845 else
846 helpmod_reply(sender, returntype, "Channel %s is using lamercontrol profile %s (%s)", hchannel_get_name(hchan), hchan->lc_profile->name->content, hchannel_get_state(hchan, H_LAMER_CONTROL));
847 return;
848 }
849 if (!ci_strcmp(argv[0], "list"))
850 {
851 helpmod_reply(sender, returntype, "Following lamercontrol profiles are available:");
852 for (ptr = hlc_profiles;ptr;ptr = ptr->next)
853 helpmod_reply(sender, returntype, "%s", ptr->name->content);
854 return;
855 }
856 ptr = hlc_get(argv[0]);
857 if (ptr == NULL)
858 {
859 helpmod_reply(sender, returntype, "Cannot set the lamercontrol profile: Profile %s does not exist:", argv[0]);
860 return;
861 }
862 else
863 {
864 hchan->lc_profile = ptr;
865 helpmod_reply(sender, returntype, "Lamercontrol profile %s set to channel %s succesfully",ptr->name->content,hchannel_get_name(hchan));
866 }
867
868 }
869
870 static void helpmod_cmd_term_find_general (huser *sender, channel* returntype, int type, char* ostr, int argc, char *argv[])
871 {
872 hterm *htrm;
873 hterm *source;
874 hchannel *hchan;
875 huser *targets[6];
876 int i,ntargets = 0;
877
878 DEFINE_HCHANNEL;
879
880 if (hchan == NULL)
881 source = hterms;
882 else
883 source = hchan->channel_hterms;
884
885 if (argc == 0)
886 {
887 if (type == H_TERM_PLUS)
888 hqueue_advance(hchan, sender, 1);
889 else
890 helpmod_reply(sender, returntype, "Cannot find term: Term not specified");
891 return;
892 }
893 htrm = hterm_get_and_find(source, argv[0]);
894 if (htrm == NULL)
895 {
896 helpmod_reply(sender, returntype, "No term found matching '%s'", argv[0]);
897 return;
898 }
899 if (returntype != NULL && huser_get_level(sender) > H_PEON)
900 {
901 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
902
903 if (argc > 1)
904 {
905 SKIP_WORD;
906 if (argc > H_CMD_MAX_ARGS)
907 argc = H_CMD_MAX_ARGS;
908 for (i=0;i<argc;i++)
909 {
910 targets[ntargets] = huser_get(getnickbynick(argv[i]));
911 if (targets[ntargets] == NULL)
912 {
913 helpmod_reply(sender, returntype, "Error using ?: User %s not found", argv[i]);
914 continue;
915 }
916 else
917 ntargets++;
918 }
919 }
920
921 if (ntargets == 0)
922 helpmod_message_channel_long(hchannel_get_by_channel(returntype), "(%s): %s", htrm->name->content, htrm->description->content);
923 else
924 {
925 char buffer[256] = "";
926 for (i=0;i<ntargets;i++)
927 {
928 if (i != 0)
929 strcat(buffer, " ");
930 strcat(buffer, huser_get_nick(targets[i]));
931 }
932
933 helpmod_message_channel_long(hchannel_get_by_channel(returntype), "%s: (%s) %s", buffer, htrm->name->content, htrm->description->content);
934 if (type != H_TERM_FIND)
935 {
936 if (hchan->flags & H_QUEUE)
937 {
938 for (i=0;i<ntargets;i++)
939 {
940 huser_channel *huserchan = huser_on_channel(targets[i], hchan);
941 huserchan->flags |= HQUEUE_DONE;
942 if (huserchan->flags & HCUMODE_VOICE)
943 helpmod_channick_modes(targets[i], hchan, MC_DEVOICE, HLAZY);
944 }
945 if (type == H_TERM_PLUS)
946 hqueue_advance(hchan, sender, ntargets);
947 }
948 }
949 }
950 }
951 else
952 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
953 }
954
955 static void helpmod_cmd_term_find (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
956 {
957 helpmod_cmd_term_find_general(sender, returntype, H_TERM_FIND, ostr, argc, argv);
958 }
959
960 static void helpmod_cmd_term_find_minus (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
961 {
962 helpmod_cmd_term_find_general(sender, returntype, H_TERM_MINUS, ostr, argc, argv);
963 }
964
965 static void helpmod_cmd_term_find_plus (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
966 {
967 helpmod_cmd_term_find_general(sender, returntype, H_TERM_PLUS, ostr, argc, argv);
968 }
969
970 static void helpmod_cmd_klingon (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
971 {
972 hchannel *hchan;
973 huser *target = NULL;
974 int rand_val;
975
976 DEFINE_HCHANNEL;
977
978 if (hchan == NULL)
979 {
980 rand_val = rand() % KLINGON_NTARGETED;
981 helpmod_reply(sender, NULL, "%s: %s", huser_get_nick(sender), klingon_targeted[rand_val]);
982 return;
983 }
984
985 if (argc)
986 target = huser_get(getnickbynick(argv[0]));
987
988 if (target)
989 {
990 rand_val = rand() % KLINGON_NTARGETED;
991 helpmod_message_channel(hchan, "%s: %s", huser_get_nick(target), klingon_targeted[rand_val]);
992 }
993 else
994 {
995 rand_val = rand() % KLINGON_NGENERAL;
996 helpmod_message_channel(hchan, "%s", klingon_general[rand_val]);
997 }
998 }
999
1000 void helpmod_cmd_term (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1001 {
1002 hterm *htrm;
1003 hterm **source;
1004 hchannel *hchan;
1005
1006 DEFINE_HCHANNEL;
1007
1008 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1009
1010 if (hchan == NULL)
1011 source = &hterms;
1012 else
1013 source = &hchan->channel_hterms;
1014
1015 if (argc == 0)
1016 {
1017 helpmod_reply(sender, returntype, "Cannot handle terms: Operation not specified");
1018 return;
1019 }
1020 if (!ci_strcmp(argv[0], "list"))
1021 {
1022 char buffer[512];
1023 int count = 0;
1024 char *pattern = "*";
1025
1026 buffer[0] = '\0';
1027 htrm = *source;
1028
1029 if (argc >= 2)
1030 pattern = argv[1];
1031 else
1032 pattern = "*";
1033
1034 helpmod_reply(sender, returntype, "Terms matching pattern '%s'", pattern);
1035 for (;htrm;htrm = htrm->next)
1036 {
1037 if (strlen(buffer) >= 250)
1038 {
1039 helpmod_reply(sender, returntype, "%s", buffer);
1040 buffer[0] = '\0';
1041 }
1042 if (strregexp(htrm->description->content, pattern) || strregexp(htrm->name->content, pattern))
1043 {
1044 sprintf(buffer+strlen(buffer) /* :) */, "%s(%d) ", htrm->name->content, strlen(htrm->description->content));
1045 count++;
1046 }
1047 }
1048 if (buffer[0])
1049 helpmod_reply(sender, returntype, "%s", buffer);
1050 helpmod_reply(sender, returntype, "%d term%s match%s pattern '%s'", count, (count == 1)?"":"s", (count == 1)?"es":"", pattern);
1051 }
1052 else if (!ci_strcmp(argv[0], "listfull"))
1053 {
1054 htrm = *source;
1055 helpmod_reply(sender, returntype, "Following terms have been entered:");
1056 for (;htrm;htrm = htrm->next)
1057 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1058 }
1059 else if (!ci_strcmp(argv[0], "get"))
1060 {
1061 if (argc < 2)
1062 {
1063 helpmod_reply(sender, returntype, "Cannot get term: Term not specified");
1064 return;
1065 }
1066 htrm = hterm_get(*source, argv[1]);
1067 if (htrm == NULL)
1068 helpmod_reply(sender, returntype, "Cannot get term: Term %s not found", argv[1]);
1069 else
1070 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1071 }
1072 else if (!ci_strcmp(argv[0], "add"))
1073 {
1074 if (argc < 2)
1075 helpmod_reply(sender, returntype, "Cannot add term: Term name not specified");
1076 else if (argc < 3)
1077 helpmod_reply(sender, returntype, "Cannot add term: Term description not specified");
1078 else if ((htrm = hterm_get(*source, argv[1])) != NULL)
1079 helpmod_reply(sender, returntype, "Cannot add term: Term %s is already added", argv[1]);
1080 else
1081 {
1082 char *name = argv[1], *description;
1083 SKIP_WORD; SKIP_WORD;
1084 description = ostr;
1085 htrm = hterm_add(source, name, description);
1086 helpmod_reply(sender, returntype, "Term %s added succesfully", name);
1087 }
1088 }
1089 else if (!ci_strcmp(argv[0], "del"))
1090 {
1091 int i;
1092 if (argc < 2)
1093 {
1094 helpmod_reply(sender, returntype, "Cannot delete term: Term name not specified");
1095 return;
1096 }
1097 if (argc > H_CMD_MAX_ARGS)
1098 argc = H_CMD_MAX_ARGS;
1099 for (i=1;i<argc;i++)
1100 {
1101 htrm = hterm_get(*source, argv[i]);
1102 if (htrm == NULL)
1103 {
1104 helpmod_reply(sender, returntype, "Cannot delete term: Term %s not found", argv[i]);
1105 continue;
1106 }
1107 hterm_del(source != NULL?source:&hterms, htrm);
1108 helpmod_reply(sender, returntype, "Term %s deleted succesfully", argv[i]);
1109 }
1110 }
1111 else if (!ci_strcmp(argv[0], "find"))
1112 {
1113 if (argc < 2)
1114 {
1115 helpmod_reply(sender, returntype, "Cannot find term: Term name not specified");
1116 return;
1117 }
1118 htrm = hterm_get_and_find(*source, argv[1]);
1119
1120 if (htrm == NULL)
1121 {
1122 helpmod_reply(sender, returntype, "No term found matching '%s'", argv[1]);
1123 return;
1124 }
1125 if (returntype != NULL && huser_get_level(sender) > H_PEON)
1126 helpmod_message_channel(hchannel_get_by_channel(returntype), "(%s): %s", htrm->name->content, htrm->description->content);
1127 else
1128 helpmod_reply(sender, returntype, "(%s): %s", htrm->name->content, htrm->description->content);
1129 }
1130 else
1131 {
1132 helpmod_reply(sender, returntype, "Cannot handle terms: Operation not specified");
1133 }
1134 }
1135
1136 static void helpmod_cmd_queue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1137 {
1138 hchannel *hchan;
1139 int operation;
1140
1141 DEFINE_HCHANNEL;
1142
1143 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1144
1145 if (argc == 0)
1146 {
1147 helpmod_reply(sender, returntype, "Cannot handle queue: Operation not specified");
1148 return;
1149 }
1150
1151 if (!ci_strcmp(argv[0], "done"))
1152 operation = HQ_DONE;
1153 else if (!ci_strcmp(argv[0], "next"))
1154 operation = HQ_NEXT;
1155 else if (!ci_strcmp(argv[0], "on"))
1156 operation = HQ_ON;
1157 else if (!ci_strcmp(argv[0], "off"))
1158 operation = HQ_OFF;
1159 else if (!ci_strcmp(argv[0], "maintain"))
1160 operation = HQ_MAINTAIN;
1161 else if (!ci_strcmp(argv[0], "list"))
1162 operation = HQ_LIST;
1163 else if (!ci_strcmp(argv[0], "summary"))
1164 operation = HQ_SUMMARY;
1165 else if (!ci_strcmp(argv[0], "reset"))
1166 operation = HQ_RESET;
1167 else
1168 operation = HQ_NONE;
1169
1170 SKIP_WORD;
1171
1172 helpmod_queue_handler(sender, returntype, hchan, operation, ostr, argc, argv);
1173 }
1174
1175 static void helpmod_cmd_done (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1176 {
1177 hchannel *hchan;
1178 DEFINE_HCHANNEL;
1179 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1180 helpmod_queue_handler(sender, returntype, hchan, HQ_DONE, ostr, argc, argv);
1181 }
1182
1183 static void helpmod_cmd_next (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1184 {
1185 hchannel *hchan;
1186 DEFINE_HCHANNEL;
1187 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1188 helpmod_queue_handler(sender, returntype, hchan, HQ_NEXT, ostr, argc, argv);
1189 }
1190
1191 static void helpmod_cmd_enqueue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1192 {
1193 hchannel *hchan;
1194 DEFINE_HCHANNEL;
1195 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1196 helpmod_queue_handler(sender, returntype, hchan, HQ_ON, ostr, argc, argv);
1197 }
1198
1199 static void helpmod_cmd_dequeue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1200 {
1201 hchannel *hchan;
1202 DEFINE_HCHANNEL;
1203 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1204 helpmod_queue_handler(sender, returntype, hchan, HQ_OFF, ostr, argc, argv);
1205 }
1206
1207 static void helpmod_cmd_autoqueue (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1208 {
1209 hchannel *hchan;
1210 DEFINE_HCHANNEL;
1211 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1212 helpmod_queue_handler(sender, returntype, hchan, HQ_MAINTAIN, ostr, argc, argv);
1213 }
1214
1215 static void helpmod_cmd_dnmo (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1216 {
1217 int i;
1218 if (argc == 0)
1219 {
1220 helpmod_reply(sender, returntype, "Cannot correct the luser: User not defined");
1221 return;
1222 }
1223 if (argc > H_CMD_MAX_ARGS)
1224 argc = H_CMD_MAX_ARGS;
1225 for (i=0;i<argc;i++)
1226 {
1227 huser *husr = huser_get(getnickbynick(argv[i]));
1228 if (husr == NULL)
1229 {
1230 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s not found", argv[i]);
1231 continue;
1232 }
1233 if (huser_get_level(husr) > H_PEON)
1234 {
1235 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s is not a peon", argv[i]);
1236 continue;
1237 }
1238 /*
1239 if (!hchannels_on_queue(husr) && !hchannels_on_desk(husr))
1240 {
1241 helpmod_reply(sender, returntype, "Cannot correct the luser: User %s is not in any queue", argv[i]);
1242 continue;
1243 }
1244 */
1245 hchannels_dnmo(husr);
1246
1247 helpmod_reply(husr, NULL, "You contacted a channel operator without permission. This is a violation of the channel rules. As a result you have been set to the last queue position");
1248 helpmod_reply(sender, returntype, "User %s has been informed of his mistake", argv[i]);
1249 }
1250 { /* fix the autoqueue for the channel(s) */
1251 hchannel *hchan;
1252 for (hchan = hchannels;hchan;hchan = hchan->next)
1253 hqueue_handle_queue(hchan, sender);
1254 }
1255 }
1256
1257 static void helpmod_cmd_ban (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1258 {
1259 if (argc == 0 || !ci_strcmp(argv[0], "list"))
1260 {
1261 hban *ptr = hbans;
1262 char *pattern;
1263 int count = 0;
1264
1265 if (argc <= 1)
1266 pattern = "*";
1267 else
1268 pattern = argv[1];
1269
1270 helpmod_reply(sender, returntype, "Global bans matching pattern %s", pattern);
1271
1272 for (;ptr;ptr = ptr->next)
1273 if (strregexp(bantostring(ptr->real_ban), pattern))
1274 {
1275 helpmod_reply(sender, returntype, "%-64s %-20s %s", bantostring(ptr->real_ban), helpmod_strtime(ptr->expiration - time(NULL)), ptr->reason?ptr->reason->content:"");
1276 count++;
1277 }
1278
1279 helpmod_reply(sender, returntype, "%d Global bans match pattern %s", count, pattern);
1280 }
1281 else if (!ci_strcmp(argv[0], "add"))
1282 {
1283 int duration = 4 * HDEF_h;
1284 char *reason = "Banned";
1285 char *target = argv[1];
1286
1287 if (argc == 1)
1288 {
1289 helpmod_reply(sender, returntype, "Cannot add global ban: Target hostmask not defined");
1290 return;
1291 }
1292 if (argc >= 3)
1293 {
1294 if ((duration = helpmod_read_strtime(argv[2])) < 0)
1295 {
1296 helpmod_reply(sender, returntype, "Cannot add global ban: Invalid time %s", argv[2]);
1297 return;
1298 }
1299 }
1300 if (argc >= 4)
1301 {
1302 SKIP_WORD;
1303 SKIP_WORD;
1304 SKIP_WORD;
1305
1306 reason = ostr;
1307 }
1308 hban_add(target, reason, time(NULL) + duration, 0);
1309 helpmod_reply(sender, returntype, "Added ban for %s (%s), expires in %s", target, reason, helpmod_strtime(duration));
1310 }
1311 else if (!ci_strcmp(argv[0], "del"))
1312 {
1313 int i;
1314 if (argc == 1)
1315 {
1316 helpmod_reply(sender, returntype, "Cannot remove global ban: Target hostmask not defined");
1317 return;
1318 }
1319 if (argc > H_CMD_MAX_ARGS)
1320 argc = H_CMD_MAX_ARGS;
1321 for (i=1;i<argc;i++)
1322 {
1323 hban *ptr = hban_get(argv[i]);
1324 if (ptr == NULL)
1325 {
1326 helpmod_reply(sender, returntype, "Cannot remove global ban: Hostmask %s is not banned", argv[i]);
1327 continue;
1328 }
1329 helpmod_reply(sender, returntype, "Global ban for hostmask %s removed", argv[i]);
1330 hban_del(ptr,0);
1331 }
1332 }
1333 else
1334 {
1335 helpmod_reply(sender, returntype, "Cannot handle global bans: Unknown operation %s", argv[0]);
1336 return;
1337 }
1338 }
1339
1340 static void helpmod_cmd_chanban (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1341 {
1342 hchannel *hchan;
1343 int i;
1344
1345 DEFINE_HCHANNEL;
1346
1347 if (hchan == NULL)
1348 {
1349 helpmod_reply(sender, returntype, "Cannot handle channel bans: Channel not defined or not found");
1350 return;
1351 }
1352
1353 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1354 /*
1355 if (argc == 0)
1356 {
1357 helpmod_reply(sender, returntype, "Cannot handle channel bans: Operation not defined");
1358 return;
1359 }
1360 */
1361 if (argc == 0 || !ci_strcmp(argv[0], "list"))
1362 {
1363 char *pattern, *cban;
1364 chanban *ptr = hchan->real_channel->bans;
1365 int count = 0;
1366
1367 if (argc <= 1)
1368 pattern = "*";
1369 else
1370 pattern = argv[1];
1371
1372 helpmod_reply(sender, returntype, "Bans matching pattern %s for channel %s", pattern, hchannel_get_name(hchan));
1373 for (;ptr;ptr = ptr->next)
1374 if (strregexp((cban = bantostring(ptr)), pattern))
1375 {
1376 count++;
1377 if (hchanban_get(hchan,cban) != NULL)
1378 helpmod_reply(sender, returntype, "%s Expires in %s", bantostring(ptr), helpmod_strtime(hchanban_get(hchan, cban)->expiration - time(NULL)));
1379 else
1380 helpmod_reply(sender, returntype, "%s", bantostring(ptr));
1381 }
1382 helpmod_reply(sender, returntype, "%d bans match pattern %s on channel %s", count, pattern, hchannel_get_name(hchan));
1383 }
1384 else if (!ci_strcmp(argv[0], "add"))
1385 {
1386 if (argc == 1)
1387 {
1388 helpmod_reply(sender, returntype, "Cannot add channel bans: Pattern not defined");
1389 return;
1390 }
1391 if (argc > H_CMD_MAX_ARGS)
1392 argc = H_CMD_MAX_ARGS;
1393 for (i=1;i<argc;i++)
1394 {
1395 /* POSSIBLE BUG ? */
1396 helpmod_setban(hchan, argv[i], H_ETERNITY, MCB_ADD, HLAZY);
1397 helpmod_reply(sender, returntype, "Added ban %s to channel %s", argv[i], hchannel_get_name(hchan));
1398 }
1399 }
1400 else if (!ci_strcmp(argv[0], "del"))
1401 {
1402 if (argc == 1)
1403 {
1404 helpmod_reply(sender, returntype, "Cannot remove channel bans: Pattern not defined");
1405 return;
1406 }
1407 if (argc > H_CMD_MAX_ARGS)
1408 argc = H_CMD_MAX_ARGS;
1409 for (i=1;i<argc;i++)
1410 {
1411 chanban *ptr = hchan->real_channel->bans;
1412 for (;ptr;ptr = ptr->next)
1413 if (strregexp(bantostring(ptr), argv[i]))
1414 {
1415 helpmod_setban(hchan, argv[i], 0, MCB_DEL, HLAZY);
1416 helpmod_reply(sender, returntype, "Channel ban %s removed from channel %s", argv[i], hchannel_get_name(hchan));
1417 break;
1418 }
1419 if (ptr == NULL)
1420 helpmod_reply(sender, returntype, "Cannot remove channel ban: Pattern %s not banned on channel %s", argv[i], hchannel_get_name(hchan));
1421 }
1422 }
1423 else
1424 {
1425 helpmod_reply(sender, returntype, "Cannot handle channel bans: Unknown operation %s", argv[0]);
1426 return;
1427 }
1428 }
1429
1430 static void helpmod_cmd_idlekick (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1431 {
1432 hchannel *hchan;
1433 int tmp;
1434
1435 DEFINE_HCHANNEL;
1436
1437 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1438
1439 if (hchan == NULL)
1440 {
1441 helpmod_reply(sender, returntype, "Cannot handle the idlekick: Channel not defined or not found");
1442 return;
1443 }
1444 if (argc == 0) /* view */
1445 {
1446 helpmod_reply(sender, returntype, "Idlekick for channel %s is set to %s", hchannel_get_name(hchan), helpmod_strtime(hchan->max_idle));
1447 return;
1448 }
1449 else if ((tmp = helpmod_read_strtime(argv[0])) < 0 || tmp < HDEF_m || tmp > HDEF_w)
1450 {
1451 helpmod_reply(sender, returntype, "Cannot set the idlekick: Invalid time given '%s'", argv[0]);
1452 return;
1453 }
1454 else /* set it ! */
1455 {
1456 hchan->max_idle = tmp;
1457 helpmod_reply(sender, returntype, "Idlekick for channel %s set to %s succesfully", hchannel_get_name(hchan), helpmod_strtime(hchan->max_idle));
1458 }
1459 }
1460
1461 static void helpmod_cmd_topic (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1462 {
1463 hchannel *hchan;
1464 DEFINE_HCHANNEL;
1465
1466 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1467
1468 if (hchan == NULL)
1469 {
1470 helpmod_reply(sender, returntype, "Cannot handle the topic: Channel not defined or not found");
1471 return;
1472 }
1473 if (!(hchan -> flags & H_HANDLE_TOPIC))
1474 helpmod_reply(sender, returntype, "Note: I'm not set to handle the topic on channel %s", hchannel_get_name(hchan));
1475
1476 if (argc == 0) /* check the topic */
1477 {
1478 helpmod_reply(sender, returntype, "Topic of channel %s is currently: %s", hchannel_get_name(hchan), htopic_construct(hchan->topic));
1479 return;
1480 }
1481 if (!ci_strcmp(argv[0], "erase"))
1482 {
1483 htopic_del_all(&hchan->topic);
1484 hchannel_set_topic(hchan);
1485 helpmod_reply(sender, returntype, "Topic of channel %s erased", hchannel_get_name(hchan));
1486 }
1487 else if (!ci_strcmp(argv[0], "refresh"))
1488 {
1489 hchannel_set_topic(hchan);
1490 helpmod_reply(sender, returntype, "Topic of channel %s refreshed", hchannel_get_name(hchan));
1491 }
1492 else if (!ci_strcmp(argv[0], "add"))
1493 {
1494 int pos;
1495 SKIP_WORD;
1496 if (argc == 0)
1497 {
1498 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1499 return;
1500 }
1501 if (sscanf(argv[0], "%d", &pos) && pos >= 0)
1502 {
1503 SKIP_WORD;
1504 }
1505 else
1506 pos = 0;
1507 if (argc == 0) /* lame repeat :( */
1508 {
1509 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1510 return;
1511 }
1512 if (htopic_len(hchan->topic) + strlen(ostr) + 3 > TOPICLEN)
1513 {
1514 helpmod_reply(sender, returntype, "Cannot add to the topic of channel %s: Maximum topic length exceeded", hchannel_get_name(hchan));
1515 return;
1516 }
1517
1518 htopic_add(&hchan->topic, ostr, pos);
1519 hchannel_set_topic(hchan);
1520 helpmod_reply(sender, returntype, "Added '%s' to the topic of channel %s", ostr, hchannel_get_name(hchan));
1521 }
1522 else if (!ci_strcmp(argv[0], "del"))
1523 {
1524 int pos;
1525 if (argc == 1)
1526 {
1527 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1528 return;
1529 }
1530 SKIP_WORD;
1531 if (!sscanf(argv[0], "%d", &pos) || pos < 0)
1532 {
1533 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Expected positive integer", hchannel_get_name(hchan));
1534 return;
1535 }
1536 if (htopic_count(hchan->topic) < pos)
1537 {
1538 helpmod_reply(sender, returntype, "Cannot delete from the topic of channel %s: No such topic element %d", hchannel_get_name(hchan), pos);
1539 return;
1540 }
1541 htopic_del(&hchan->topic, htopic_get(hchan->topic, pos));
1542 hchannel_set_topic(hchan);
1543 }
1544 else if (!ci_strcmp(argv[0], "set"))
1545 {
1546 if (argc == 1)
1547 {
1548 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Additional arguments required", hchannel_get_name(hchan));
1549 return;
1550 }
1551 SKIP_WORD;
1552 htopic_del_all(&hchan->topic);
1553 htopic_add(&hchan->topic, ostr, 0);
1554 hchannel_set_topic(hchan);
1555 }
1556 else
1557 helpmod_reply(sender, returntype, "Cannot handle the topic of channel %s: Unknown operation %s", hchannel_get_name(hchan), argv[0]);
1558 }
1559
1560 static void helpmod_cmd_out (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1561 {
1562 huser *husr;
1563 int i;
1564 char *reason = "Banned";
1565 huser *targets[H_CMD_MAX_ARGS];
1566 int ntargets = 0;
1567
1568 if (argc == 0)
1569 {
1570 helpmod_reply(sender, returntype, "Cannot get rid of the user: User not specified");
1571 return;
1572 }
1573
1574 if (argc > H_CMD_MAX_ARGS)
1575 argc = H_CMD_MAX_ARGS;
1576 for (i=0;i<argc;i++)
1577 {
1578 if (argv[i][0] == ':')
1579 {
1580 if (i == 0)
1581 {
1582 helpmod_reply(sender, returntype, "Cannot get rid of users: No users specified");
1583 return;
1584 }
1585 while (i--)
1586 {
1587 SKIP_WORD;
1588 }
1589 reason = ostr + 1;
1590
1591 if (!strncmp(reason, "?? ", 3))
1592 { /* obtain reason from hterms */
1593 hchannel *hchan = NULL;
1594 hterm *new_reason;
1595 if (returntype != NULL)
1596 { /* if hchan is NULL here then everything is broken already */
1597 hchan = hchannel_get_by_channel(returntype);
1598 new_reason = hterm_get_and_find(hchan->channel_hterms, reason + 3);
1599 }
1600 else
1601 new_reason = hterm_get_and_find(hterms, reason + 3);
1602
1603 if (new_reason != NULL)
1604 reason = new_reason->description->content;
1605 }
1606 break;
1607 }
1608
1609 husr = huser_get(getnickbynick(argv[i]));
1610 if (husr == NULL)
1611 {
1612 helpmod_reply(sender, returntype, "Cannot get rid of the user: User %s not found", argv[i]);
1613 continue;
1614 }
1615 if (huser_get_level(husr) > H_PEON)
1616 {
1617 helpmod_reply(sender, returntype, "Cannot get rid of the user: User %s is not a peon", huser_get_nick(husr));
1618 continue;
1619 }
1620 targets[ntargets++] = husr;
1621 }
1622
1623 for (i=0;i<ntargets;i++)
1624 {
1625 const char *banmask = hban_ban_string(targets[i]->real_user, HBAN_HOST);
1626
1627 hban_add(banmask, reason, time(NULL) + HCMD_OUT_DEFAULT, HLAZY);
1628
1629 helpmod_reply(sender, returntype, "User %s is now gone", huser_get_nick(targets[i]));
1630 }
1631 hcommit_modes();
1632 }
1633
1634 static void helpmod_cmd_everyoneout (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1635 {
1636 hchannel *hchan;
1637 hchannel_user **hchanuser;
1638 char *reason = "clearing channel";
1639 int autoqueue_tmp = -1;
1640
1641 DEFINE_HCHANNEL;
1642
1643 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1644
1645 if (hchan == NULL)
1646 {
1647 helpmod_reply(sender, returntype, "Cannot clear channel: Channel not defined or not found");
1648 return;
1649 }
1650
1651 if (argc)
1652 reason = ostr;
1653
1654 hchan->flags |= H_MAINTAIN_I;
1655 hchannel_mode_check(hchan);
1656
1657 hchanuser = &hchan->channel_users;
1658
1659 if ((hchan->flags & H_QUEUE) && (hchan->flags & H_QUEUE_MAINTAIN))
1660 {
1661 autoqueue_tmp = hchan->autoqueue;
1662 hchan->autoqueue = 0;
1663 }
1664
1665 while (*hchanuser)
1666 {
1667 if (huser_get_level((*hchanuser)->husr) < H_TRIAL)
1668 helpmod_kick(hchan, (*hchanuser)->husr, reason);
1669 else
1670 hchanuser = &(*hchanuser)->next;
1671 }
1672
1673 if (autoqueue_tmp > 0)
1674 hchan->autoqueue = autoqueue_tmp;
1675
1676 helpmod_reply(sender, returntype, "Channel %s has been cleared of normal users", hchannel_get_name(hchan));
1677 }
1678
1679 static void helpmod_cmd_kick (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1680 {
1681 hchannel *hchan;
1682 int i;
1683 huser *husr, *targets[H_CMD_MAX_ARGS];
1684 int ntargets = 0;
1685 char *reason = "out";
1686 DEFINE_HCHANNEL;
1687
1688 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1689
1690 if (hchan == NULL)
1691 {
1692 helpmod_reply(sender, returntype, "Cannot kick the user: Channel not defined or not found");
1693 return;
1694 }
1695
1696 if (argc == 0)
1697 {
1698 helpmod_reply(sender, returntype, "Cannot kick users: No users specified");
1699 return;
1700 }
1701
1702 if (argc > H_CMD_MAX_ARGS)
1703 argc = H_CMD_MAX_ARGS;
1704 for (i=0;i<argc;i++)
1705 {
1706 if (*argv[i] == ':')
1707 {
1708 if (i == 0)
1709 {
1710 helpmod_reply(sender, returntype, "Cannot kick the user: No users defined");
1711 return;
1712 }
1713 while (i--)
1714 {
1715 SKIP_WORD;
1716 }
1717 reason = ostr+1;
1718 break;
1719 }
1720 husr = huser_get(getnickbynick(argv[i]));
1721 if (husr == NULL)
1722 {
1723 helpmod_reply(sender, returntype, "Cannot kick the user: User %s not found", argv[i]);
1724 continue;
1725 }
1726 if (huser_on_channel(husr, hchan) == NULL)
1727 {
1728 helpmod_reply(sender, returntype, "Cannot kick the user: User %s is not on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
1729 continue;
1730 }
1731 if (huser_get_level(husr) > H_PEON)
1732 {
1733 helpmod_reply(sender, returntype, "Cannot kick the user: User %s is not a peon", huser_get_nick(husr));
1734 continue;
1735 }
1736 targets[ntargets++] = husr;
1737 }
1738
1739 for (i=0;i<ntargets;i++)
1740 helpmod_kick(hchan, targets[i], reason);
1741 }
1742
1743 static void helpmod_cmd_stats (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1744 {
1745 hchannel *hchan;
1746 haccount *target = sender->account;
1747 hstat_account *ptr;
1748 hstat_account_entry *stat_entry;
1749 int days = 1, weeks = 0;
1750 int type = HSTAT_ACCOUNT_SHORT;
1751
1752 time_t timer = time(NULL);
1753 struct tm *tstruct = localtime(&timer);
1754
1755 int i = 0;
1756
1757 DEFINE_HCHANNEL;
1758
1759 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1760
1761 if (hchan == NULL)
1762 {
1763 helpmod_reply(sender, returntype, "Cannot show user statistics: Channel not defined or not found");
1764 return;
1765 }
1766
1767 if (argc > 0 && huser_get_level(sender) == H_ADMIN)
1768 { /* not very elegant */
1769 if (argv[0][0] == '#') /* account */
1770 {
1771 target = haccount_get_by_name(argv[0]+1);
1772 if (target == NULL)
1773 {
1774 helpmod_reply(sender, returntype, "Cannot show user statistics: Account %s not found", argv[0]);
1775 return;
1776 }
1777 SKIP_WORD;
1778 }
1779 }
1780
1781 if (target == NULL)
1782 {
1783 helpmod_reply(sender, returntype, "Cannot show user statistics: You do not have an account");
1784 return;
1785 }
1786
1787 if (argc > 0)
1788 {
1789 if (!ci_strcmp(argv[0], "short") || !ci_strcmp(argv[0], "s"))
1790 {
1791 type = HSTAT_ACCOUNT_SHORT;
1792 SKIP_WORD;
1793 }
1794 else if (!ci_strcmp(argv[0], "long") || !ci_strcmp(argv[0], "l"))
1795 {
1796 type = HSTAT_ACCOUNT_LONG;
1797 SKIP_WORD;
1798 }
1799 }
1800
1801 if (argc > 0)
1802 if (sscanf(argv[0], "%d", &days))
1803 {
1804 if (days < 0 || days > 7)
1805 {
1806 helpmod_reply(sender, returntype, "Cannot show user statistics: Expected integer between [0, 7]");
1807 return;
1808 }
1809 else
1810 {
1811 SKIP_WORD;
1812 }
1813 }
1814
1815 if (argc > 0)
1816 if (sscanf(argv[0], "%d", &weeks))
1817 {
1818 if (weeks < 0 || weeks > 10)
1819 {
1820 helpmod_reply(sender, returntype, "Cannot show user statistics: Expected integer between [0, 10]");
1821 return;
1822 }
1823 else
1824 {
1825 SKIP_WORD;
1826 }
1827 }
1828
1829 for (ptr = target->stats;ptr;ptr = ptr->next)
1830 if (ptr->hchan == hchan)
1831 break;
1832
1833 if (ptr == NULL)
1834 {
1835 helpmod_reply(sender, returntype, "Cannot show user statistics: User %s has no statistics for channel %s", target->name->content, hchannel_get_name(hchan));
1836 return;
1837 }
1838
1839 if (!days && !weeks)
1840 return;
1841
1842 helpmod_reply(sender, returntype, "Statistics for user %s on channel %s", target->name->content, hchannel_get_name(hchan));
1843
1844 if (days)
1845 {
1846 helpmod_reply(sender, returntype, "Last %d day%s", days, (days==1)?"":"s");
1847 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1848 for (i=0;i<days;i++)
1849 {
1850 stat_entry = &ptr->week[(tstruct->tm_wday - i + 7) % 7];
1851 helpmod_reply(sender, returntype, "%s", hstat_account_print(stat_entry, type));
1852 }
1853 }
1854
1855 if (weeks)
1856 {
1857 helpmod_reply(sender, returntype, "Last %d week%s", weeks, (weeks==1)?"":"s");
1858 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1859 for (i=0;i<weeks;i++)
1860 {
1861 stat_entry = &ptr->longterm[(hstat_week() - i + 10) % 10];
1862 helpmod_reply(sender, returntype, "%s", hstat_account_print(stat_entry, type));
1863 }
1864 }
1865 }
1866
1867 static void helpmod_cmd_chanstats (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1868 {
1869 hchannel *hchan;
1870 hstat_channel *channel_stats;
1871 hstat_channel_entry *stat_entry;
1872
1873 time_t timer = time(NULL);
1874 struct tm *tstruct = localtime(&timer);
1875
1876 int days=1;
1877 int type = HSTAT_CHANNEL_SHORT;
1878 int weeks=0;
1879
1880 int i = 7;
1881
1882 DEFINE_HCHANNEL;
1883
1884 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
1885
1886 if (hchan == NULL)
1887 {
1888 helpmod_reply(sender, returntype, "Cannot show channel statistics: Channel not defined or not found");
1889 return;
1890 }
1891
1892 if (argc > 0)
1893 {
1894 if (!ci_strcmp(argv[0], "short") || !ci_strcmp(argv[0], "s"))
1895 {
1896 type = HSTAT_CHANNEL_SHORT;
1897 SKIP_WORD;
1898 }
1899 else if (!ci_strcmp(argv[0], "long") || !ci_strcmp(argv[0], "l"))
1900 {
1901 type = HSTAT_CHANNEL_LONG;
1902 SKIP_WORD;
1903 }
1904 }
1905
1906 if (argc > 0)
1907 if (sscanf(argv[0], "%d", &days))
1908 {
1909 if (days < 0 || days > 7)
1910 {
1911 helpmod_reply(sender, returntype, "Cannot show channel statistics: Expected integer between [0, 7]");
1912 return;
1913 }
1914 else
1915 {
1916 SKIP_WORD;
1917 }
1918 }
1919
1920 if (argc > 0)
1921 if (sscanf(argv[0], "%d", &weeks))
1922 {
1923 if (weeks < 0 || weeks > 10)
1924 {
1925 helpmod_reply(sender, returntype, "Cannot show channel statistics: Expected integer between [0, 10]");
1926 return;
1927 }
1928 else
1929 {
1930 SKIP_WORD;
1931 }
1932 }
1933
1934 channel_stats = hchan->stats;
1935
1936 if (!days && !weeks)
1937 return;
1938
1939 helpmod_reply(sender, returntype, "Statistics for channel %s", hchannel_get_name(hchan));
1940
1941 if (days)
1942 {
1943 helpmod_reply(sender, returntype, "Last %d day%s", days, (days==1)?"":"s");
1944 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1945 for (i=0;i<days;i++) /* latest week */
1946 {
1947 stat_entry = &hchan->stats->week[(tstruct->tm_wday - i + 7) % 7];
1948 helpmod_reply(sender, returntype, "%s", hstat_channel_print(stat_entry, type));
1949 }
1950 }
1951
1952 if (weeks)
1953 {
1954 helpmod_reply(sender, returntype, "Last %d week%s", weeks, (weeks==1)?"":"s");
1955 helpmod_reply(sender, returntype, "%s", hstat_header(type));
1956 for (i=0;i<weeks;i++) /* latest weeks */
1957 {
1958 stat_entry = &hchan->stats->longterm[(hstat_week() - i + 10) % 10];
1959 helpmod_reply(sender, returntype, "%s", hstat_channel_print(stat_entry, type));
1960 }
1961 }
1962 }
1963
1964 static void helpmod_cmd_activestaff (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
1965 {
1966 hchannel *hchan;
1967 hstat_accounts_array arr;
1968 hlevel lvl = H_OPER;
1969 int listtype = 0;
1970 int i;
1971
1972 DEFINE_HCHANNEL;
1973
1974 if (hchan == NULL)
1975 {
1976 helpmod_reply(sender, returntype, "Cannot list active staff: Channel not specified or not found");
1977 return;
1978 }
1979
1980 if (argc == 1)
1981 {
1982 if (!ci_strcmp(argv[0], "opers") || !ci_strcmp(argv[0], "o"))
1983 {
1984 lvl = H_OPER;
1985 SKIP_WORD;
1986 }
1987 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
1988 {
1989 lvl = H_STAFF;
1990 SKIP_WORD;
1991 }
1992 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
1993 {
1994 lvl = H_ANY;
1995 SKIP_WORD;
1996 }
1997 }
1998
1999 if (argc == 1)
2000 {
2001 if (!ci_strcmp(argv[0], "active") || !ci_strcmp(argv[0], "a"))
2002 {
2003 listtype = 0;
2004 SKIP_WORD;
2005 }
2006 else if (!ci_strcmp(argv[0], "inactive") || !ci_strcmp(argv[0], "i"))
2007 {
2008 listtype = 1;
2009 SKIP_WORD;
2010 }
2011 }
2012
2013 arr = create_hstat_account_array(hchan, lvl);
2014
2015 helpmod_reply(sender, returntype, "%s %ss for channel %s", listtype?"Inactive":"Active", hlevel_name(lvl), hchannel_get_name(hchan));
2016 switch (listtype)
2017 {
2018 case 0:
2019 for (i=0;i < arr.arrlen && arr.array[i].prime_time_spent > H_ACTIVE_LIMIT;i++)
2020 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s", i+1,((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
2021 break;
2022 case 1:
2023 for (i=arr.arrlen-1;i >= 0 && arr.array[i].prime_time_spent < H_ACTIVE_LIMIT;i--)
2024 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s", (arr.arrlen - i),((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
2025 break;
2026 }
2027
2028 free(arr.array);
2029 }
2030
2031 static void helpmod_cmd_top10 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2032 {
2033 hchannel *hchan;
2034 hstat_accounts_array arr;
2035 hlevel lvl = H_OPER;
2036 int i, top_n = 10;
2037
2038 DEFINE_HCHANNEL;
2039
2040 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2041
2042 if (hchan == NULL)
2043 {
2044 helpmod_reply(sender, returntype, "Cannot list channel Top10: Channel not specified or not found");
2045 return;
2046 }
2047
2048 if (argc >= 1)
2049 {
2050 if (!ci_strcmp(argv[0], "opers") || !ci_strcmp(argv[0], "o"))
2051 lvl = H_OPER;
2052 else if (!ci_strcmp(argv[0], "staff") || !ci_strcmp(argv[0], "s"))
2053 lvl = H_STAFF;
2054 else if (!ci_strcmp(argv[0], "all") || !ci_strcmp(argv[0], "a"))
2055 lvl = H_ANY;
2056 }
2057 if (argc == 2)
2058 {
2059 int tmp;
2060 if (sscanf(argv[1], "%d", &tmp) && (tmp >= 10) && (tmp <= 50))
2061 top_n = tmp;
2062 }
2063
2064 arr = create_hstat_account_array(hchan, lvl);
2065
2066 helpmod_reply(sender, returntype, "Top%d most active %ss of channel %s", top_n, hlevel_name(lvl), hchannel_get_name(hchan));
2067 for (i=0;i < arr.arrlen && i < top_n;i++)
2068 helpmod_reply(sender, returntype, "#%-2d %-20s %-20s %-20s",i+1,((haccount*)(arr.array[i].owner))->name->content, helpmod_strtime(arr.array[i].prime_time_spent), helpmod_strtime(arr.array[i].time_spent));
2069
2070 free(arr.array);
2071 }
2072
2073 static void helpmod_cmd_report (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2074 {
2075 hchannel *hchan, *target;
2076 DEFINE_HCHANNEL;
2077
2078 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2079
2080 if (hchan != NULL && (argc == 2))
2081 {
2082 hchan = hchannel_get_by_name(argv[0]);
2083 SKIP_WORD;
2084 }
2085
2086 if (hchan == NULL)
2087 {
2088 helpmod_reply(sender, returntype, "Cannot view or set channel reporting: Channel not defined or not found");
2089 return;
2090 }
2091 if (argc != 1)
2092 {
2093 if (hchan->report_to == NULL || !hchannel_is_valid(hchan->report_to))
2094 helpmod_reply(sender, returntype, "Channel %s is not reported anywhere (%s)", hchannel_get_name(hchan), hchannel_get_state(hchan, H_REPORT));
2095 else
2096 helpmod_reply(sender, returntype, "Channel %s is reported to channel %s (%s)", hchannel_get_name(hchan), hchannel_get_name(hchan->report_to), hchannel_get_state(hchan, H_REPORT));
2097 return;
2098 }
2099 if ((target = hchannel_get_by_name(argv[0])) == NULL)
2100 {
2101 helpmod_reply(sender, returntype, "Cannot set channel reporting: Channel %s not found", argv[0]);
2102 return;
2103 }
2104 hchan->report_to = target;
2105 helpmod_reply(sender, returntype, "Channel %s is now reported to channel %s (%s)", hchannel_get_name(hchan), hchannel_get_name(hchan->report_to), hchannel_get_state(hchan, H_REPORT));
2106 }
2107
2108 static void helpmod_cmd_mode(huser *sender, channel* returntype, int change, char* ostr, int argc, char *argv[])
2109 {
2110 hchannel *hchan;
2111 huser_channel *huserchan;
2112 huser *husr;
2113 int i;
2114
2115 DEFINE_HCHANNEL;
2116
2117 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2118
2119 if (hchan == NULL)
2120 {
2121 helpmod_reply(sender, returntype, "Cannot change mode: Channel not specified or not found");
2122 return;
2123 }
2124
2125 if (argc==0) /* for a simple opme */
2126 {
2127 argc = 1;
2128 argv[0] = (char*)huser_get_nick(sender);
2129 }
2130
2131 if (argc > H_CMD_MAX_ARGS)
2132 argc = H_CMD_MAX_ARGS;
2133
2134 for (i=0;i<argc;i++)
2135 {
2136 husr = huser_get(getnickbynick(argv[i]));
2137 if (husr == NULL)
2138 {
2139 helpmod_reply(sender, returntype, "Cannot change mode: User %s not found", argv[i], hchannel_get_name(hchan));
2140 continue;
2141 }
2142 huserchan = huser_on_channel(husr, hchan);
2143 if (huserchan == NULL)
2144 {
2145 helpmod_reply(sender, returntype, "Cannot change mode: User %s it not on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2146 continue;
2147 }
2148
2149 switch (change)
2150 {
2151 case H_CMD_OP:
2152 {
2153 int j;
2154 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2155 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2156 break;
2157 if ((huserchan->flags & HCUMODE_OP) && !(hchan->real_channel->users->content[j] & CUMODE_OP))
2158 {
2159 huserchan->flags &= ~HCUMODE_OP;
2160 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (+o when should be -o)");
2161 }
2162 if (huserchan->flags & HCUMODE_OP)
2163 {
2164 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2165 continue;
2166 }
2167 if (huser_get_level(husr) < H_STAFF)
2168 {
2169 helpmod_reply(sender, returntype, "Cannot change mode: User %s is not allowed to have +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2170 continue;
2171 }
2172 helpmod_channick_modes(husr, hchan, MC_OP, HLAZY);
2173 }
2174 break;
2175 case H_CMD_DEOP:
2176 {
2177 int j;
2178 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2179 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2180 break;
2181 if (!(huserchan->flags & HCUMODE_OP) && (hchan->real_channel->users->content[j] & CUMODE_OP))
2182 {
2183 huserchan->flags |= HCUMODE_OP;
2184 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (-o when should be +o)");
2185 }
2186 if (!(huserchan->flags & HCUMODE_OP))
2187 {
2188 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already -o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2189 continue;
2190 }
2191 if (huser_get_level(husr) > huser_get_level(sender))
2192 {
2193 helpmod_reply(sender, returntype, "Cannot change mode: User %s is meant to have +o on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2194 continue;
2195 }
2196 helpmod_channick_modes(husr, hchan, MC_DEOP, HLAZY);
2197 }
2198 break;
2199 case H_CMD_VOICE:
2200 {
2201 int j;
2202 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2203 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2204 break;
2205 if ((huserchan->flags & HCUMODE_VOICE) && !(hchan->real_channel->users->content[j] & CUMODE_VOICE))
2206 {
2207 huserchan->flags &= ~HCUMODE_VOICE;
2208 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (+v when should be -v)");
2209 }
2210 if (huserchan->flags & HCUMODE_VOICE)
2211 {
2212 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already +v on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2213 continue;
2214 }
2215 helpmod_channick_modes(husr, hchan, MC_VOICE, HLAZY);
2216 }
2217 break;
2218 case H_CMD_DEVOICE:
2219 {
2220 int j;
2221 for (j=0;j < hchan->real_channel->users->hashsize;j++)
2222 if (getnickbynumeric(hchan->real_channel->users->content[j]) == husr->real_user)
2223 break;
2224 if (!(huserchan->flags & HCUMODE_VOICE) && (hchan->real_channel->users->content[j] & CUMODE_VOICE))
2225 {
2226 huserchan->flags |= HCUMODE_VOICE;
2227 Error("helpmod", ERR_ERROR, "userchannelmode inconsistency (-v when should be +v)");
2228 }
2229 if (!(huserchan->flags & HCUMODE_VOICE))
2230 {
2231 helpmod_reply(sender, returntype, "Cannot change mode: User %s is already -v on channel %s", huser_get_nick(husr), hchannel_get_name(hchan));
2232 continue;
2233 }
2234 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
2235 }
2236 break;
2237 }
2238 }
2239 }
2240
2241 static void helpmod_cmd_op (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_OP, ostr, argc, argv); }
2242 static void helpmod_cmd_deop (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_DEOP, ostr, argc, argv); }
2243 static void helpmod_cmd_voice (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_VOICE, ostr, argc, argv); }
2244 static void helpmod_cmd_devoice (huser *sender, channel* returntype, char* ostr, int argc, char *argv[]) { helpmod_cmd_mode(sender, returntype, H_CMD_DEVOICE, ostr, argc, argv); }
2245
2246 static void helpmod_cmd_invite (huser *sender, channel *returntype, char* arg, int argc, char *argv[])
2247 {
2248 hchannel *hchan;
2249 int i;
2250
2251 if (argc == 0)
2252 {
2253 helpmod_reply(sender, returntype, "Cannot invite: Channel not defined or not found");
2254 return;
2255 }
2256
2257 if (huser_get_level(sender) == H_PEON)
2258 {
2259 hticket *htick;
2260 hchan = hchannel_get_by_name(argv[0]);
2261 if (hchan == NULL)
2262 {
2263 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[0]);
2264 return;
2265 }
2266 /* if tickets don't work, it's better that the user doesn't know that the channel really exists */
2267 if (!(hchan->flags & H_REQUIRE_TICKET))
2268 {
2269 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[0]);
2270 return;
2271 }
2272 htick = hticket_get(huser_get_auth(sender), hchan);
2273
2274 if (htick == NULL)
2275 {
2276 helpmod_reply(sender, returntype, "Cannot invite: You do not have an invite ticket for channel %s", argv[0]);
2277 return;
2278 }
2279
2280 if (nickbanned(sender->real_user, hchan->real_channel))
2281 {
2282 helpmod_reply(sender, returntype, "Cannot invite: You are banned from channel %s", argv[0]);
2283 return;
2284 }
2285
2286 helpmod_invite(hchan, sender);
2287 helpmod_reply(sender, returntype, "Invited you to channel %s", hchannel_get_name(hchan));
2288 return;
2289 }
2290
2291 if (argc > H_CMD_MAX_ARGS)
2292 argc = H_CMD_MAX_ARGS;
2293
2294 for (i = 0;i < argc; i++)
2295 {
2296 hchan = hchannel_get_by_name(argv[i]);
2297 if (hchan == NULL)
2298 {
2299 helpmod_reply(sender, returntype, "Cannot invite: Unknown channel %s", argv[i]);
2300 continue;
2301 }
2302 if (!(hchannel_authority(hchan, sender) || hticket_get(huser_get_auth(sender), hchan)))
2303 {
2304 helpmod_reply(sender, returntype, "Sorry, channel %s is oper only", hchannel_get_name(hchan));
2305 continue;
2306 }
2307 if (huser_on_channel(sender, hchan) != NULL)
2308 {
2309 helpmod_reply(sender, returntype, "Cannot invite: You are already on channel %s", hchannel_get_name(hchan));
2310 continue;
2311 }
2312 helpmod_invite(hchan, sender);
2313 helpmod_reply(sender, returntype, "Invited you to channel %s", hchannel_get_name(hchan));
2314 }
2315 }
2316
2317 static void helpmod_cmd_ticket (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2318 {
2319 int expiration = HTICKET_EXPIRATION_TIME;
2320 hchannel *hchan;
2321 huser *husr;
2322 hticket *htick;
2323
2324 if (argc < 1)
2325 {
2326 helpmod_reply(sender, returntype, "Cannot issue a ticket: Channel not specified");
2327 return;
2328 }
2329
2330 hchan = hchannel_get_by_name(argv[0]);
2331 if (hchan == NULL)
2332 {
2333 helpmod_reply(sender, returntype, "Cannot issue a ticket: Unknown channel %s", argv[0]);
2334 return;
2335 }
2336 if (!(hchan->flags & H_REQUIRE_TICKET))
2337 {
2338 helpmod_reply(sender, returntype, "Cannot issue a ticket: Tickets are not enabled for channel %s", argv[0]);
2339 return;
2340 }
2341 if (argc < 2)
2342 {
2343 helpmod_reply(sender, returntype, "Cannot issue a ticket: Target user not specified");
2344 return;
2345 }
2346
2347 husr = huser_get(getnickbynick(argv[1]));
2348 if (husr == NULL)
2349 {
2350 helpmod_reply(sender, returntype, "Cannot issue a ticket: Unknown user %s", argv[1]);
2351 return;
2352 }
2353 if (!IsAccount(husr->real_user))
2354 {
2355 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s is not authed", argv[1]);
2356 return;
2357 }
2358 if (huser_get_level(husr) < H_PEON)
2359 {
2360 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s is considered improper and not worthy of a ticket", argv[1]);
2361 return;
2362 }
2363 if (huser_get_level(husr) > H_PEON)
2364 {
2365 helpmod_reply(sender, returntype, "Cannot issue a ticket: User %s does not require a ticket", argv[1]);
2366 return;
2367 }
2368 if (argc >= 3)
2369 {
2370 int tmp;
2371 tmp = helpmod_read_strtime(argv[2]);
2372 if (tmp > HDEF_m && tmp < 2 * HDEF_M)
2373 expiration = tmp;
2374 }
2375
2376 htick = hticket_get(huser_get_auth(husr), hchan);
2377
2378 if (htick != NULL)
2379 htick->time_expiration = time(NULL) + expiration;
2380 else
2381 hticket_add(huser_get_auth(husr), time(NULL) + expiration, hchan);
2382
2383 helpmod_reply(sender, returntype, "Issued an invite ticket to user %s for channel %s expiring in %s", huser_get_nick(husr), hchannel_get_name(hchan), helpmod_strtime(expiration));
2384 helpmod_reply(husr, NULL, "You have been issued an invite ticket for channel %s. This ticket is valid for a period of %s. You can use my invite command to get to the channel now. Type /msg %s invite %s",hchannel_get_name(hchan), helpmod_strtime(HTICKET_EXPIRATION_TIME), helpmodnick->nick, hchannel_get_name(hchan));
2385 if (hchan->flags & H_TICKET_MESSAGE && hchan->ticket_message != NULL)
2386 helpmod_reply(husr, NULL, "Ticket information for %s: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2387
2388 }
2389 static void helpmod_cmd_resolve (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2390 {
2391 int i;
2392 hchannel *hchan;
2393 hticket *htick;
2394 huser *husr;
2395
2396 DEFINE_HCHANNEL;
2397
2398 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2399
2400 if (argc > H_CMD_MAX_ARGS)
2401 argc = H_CMD_MAX_ARGS;
2402
2403 if (hchan == NULL)
2404 {
2405 helpmod_reply(sender, returntype, "Cannot resolve a ticket: The channel is not specified");
2406 return;
2407 }
2408
2409 for (i = 0;i< argc;i++)
2410 {
2411 if (argv[i][0] == '#')
2412 {
2413 htick = hticket_get(&argv[i][1], hchan);
2414 if (htick == NULL)
2415 {
2416 helpmod_reply(sender, returntype, "Cannot resolve a ticket: Authname %s does not have a ticket for channel %s", &argv[i][1], hchannel_get_name(hchan));
2417 continue;
2418 }
2419 hticket_del(htick, hchan);
2420 helpmod_reply(sender, returntype, "Resolved authname %s's ticket for channel %s", &argv[i][1], hchannel_get_name(hchan));
2421 }
2422 else
2423 {
2424 husr = huser_get(getnickbynick(argv[i]));
2425 if (husr == NULL)
2426 {
2427 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s not found", argv[i]);
2428 continue;
2429 }
2430 if (!IsAccount(husr->real_user))
2431 {
2432 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s is not authed", argv[i]);
2433 continue;
2434 }
2435 htick = hticket_get(huser_get_auth(husr),hchan);
2436 if (htick == NULL)
2437 {
2438 helpmod_reply(sender, returntype, "Cannot resolve a ticket: User %s does not have a ticket for channel %s", argv[i], hchannel_get_name(hchan));
2439 continue;
2440 }
2441 hticket_del(htick, hchan);
2442 helpmod_reply(sender, returntype, "Resolved user %s's ticket for channel %s", argv[i], hchannel_get_name(hchan));
2443 }
2444 }
2445 }
2446
2447 static void helpmod_cmd_tickets (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2448 {
2449 hchannel *hchan;
2450 hticket *htick;
2451 int i;
2452
2453 DEFINE_HCHANNEL;
2454
2455 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2456
2457 if (hchan == NULL)
2458 {
2459 helpmod_reply(sender, returntype, "Cannot list tickets: Channel not defined or not found");
2460 return;
2461 }
2462
2463 if (!(hchan->flags & H_REQUIRE_TICKET))
2464 {
2465 helpmod_reply(sender, returntype, "Cannot list tickets: Channel %s does not use the ticket system", hchannel_get_name(hchan));
2466 return;
2467 }
2468
2469 htick = hchan->htickets;
2470
2471 if (htick == NULL)
2472 {
2473 helpmod_reply(sender, returntype, "Channel %s has no valid tickets", hchannel_get_name(hchan));
2474 return;
2475 }
2476
2477 helpmod_reply(sender, returntype, "Valid tickets for channel %s", hchannel_get_name(hchan));
2478
2479 for (i = 0;htick;htick = htick->next, i++)
2480 helpmod_reply(sender, returntype, "%4d %16s %48s", i, htick->authname, helpmod_strtime(time(NULL) - htick->time_expiration));
2481
2482 helpmod_reply(sender, returntype, "Done listing tickets. Channel %s had %d valid ticket%s", hchannel_get_name(hchan), i, (i==1)?"":"s");
2483 }
2484
2485 static void helpmod_cmd_showticket (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2486 {
2487 hchannel *hchan;
2488 huser *husr;
2489 hticket *htick;
2490 int i;
2491
2492 DEFINE_HCHANNEL;
2493 /*
2494 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2495 */
2496 if (argc > H_CMD_MAX_ARGS)
2497 argc = H_CMD_MAX_ARGS;
2498
2499 if (hchan == NULL)
2500 {
2501 helpmod_reply(sender, returntype, "Cannot show the ticket: Channel not defined or not found");
2502 return;
2503 }
2504 for (i = 0;i < argc;i++)
2505 {
2506 husr = huser_get(getnickbynick(argv[i]));
2507 if (husr == NULL)
2508 {
2509 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s not found", argv[i]);
2510 continue;
2511 }
2512 if (!IsAccount(husr->real_user))
2513 {
2514 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s is not authed", argv[i]);
2515 continue;
2516 }
2517 htick = hticket_get(huser_get_auth(husr), hchan);
2518 if (htick == NULL)
2519 {
2520 helpmod_reply(sender, returntype, "Cannot show the ticket: User %s does not have a valid ticket for channel %s", argv[i], hchannel_get_name(hchan));
2521 continue;
2522 }
2523 helpmod_reply(sender, returntype, "User %s has a ticket for channel %s expiring in %s", argv[i], hchannel_get_name(hchan), helpmod_strtime(htick->time_expiration - time(NULL)));
2524 }
2525 }
2526
2527 static int helpmod_cmd_termstats_sort(const void *left, const void *right)
2528 {
2529 return (*((hterm**)right))->usage - (*((hterm**)left))->usage;
2530 }
2531
2532 static void helpmod_cmd_termstats(huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2533 {
2534 hterm **arr, *origin;
2535 hchannel *hchan;
2536 int i, count;
2537
2538 DEFINE_HCHANNEL;
2539
2540 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2541
2542 if (hchan == NULL)
2543 origin = hterms;
2544 else
2545 origin = hchan->channel_hterms;
2546
2547 count = hterm_count(origin);
2548
2549 if (count == 0)
2550 {
2551 helpmod_reply(sender, returntype, "Cannot list term usage statistics: No terms available");
2552 return;
2553 }
2554
2555 arr = malloc(sizeof(hterm*) * count);
2556 assert(arr != NULL);
2557
2558 for (i=0;i < count;i++,origin = origin->next)
2559 arr[i] = origin;
2560
2561 qsort(arr, count, sizeof(hterm*), helpmod_cmd_termstats_sort);
2562
2563 if (hchan == NULL)
2564 helpmod_reply(sender, returntype, "10 Most used global terms");
2565 else
2566 helpmod_reply(sender, returntype, "10 Most used terms for channel %s", hchannel_get_name(hchan));
2567
2568 for (i=0;i < 10 && i < count;i++)
2569 helpmod_reply(sender, returntype, "#%02d %32s :%d",i+1, arr[i]->name->content,arr[i]->usage);
2570
2571 free(arr);
2572 }
2573
2574 static int helpmod_cmd_checkchannel_nicksort(const void *left, const void *right)
2575 {
2576 return ci_strcmp(getnickbynumeric(*((unsigned long*)left))->nick, getnickbynumeric(*((unsigned long*)right))->nick);
2577 }
2578
2579 static int helpmod_cmd_checkchannel_statussort(const void *left, const void *right)
2580 {
2581 int level1 = 0, level2 = 0;
2582
2583 if (*((unsigned long*)left) & CUMODE_VOICE)
2584 level1 = 1;
2585 if (*((unsigned long*)left) & CUMODE_OP)
2586 level1 = 2;
2587
2588 if (*((unsigned long*)right) & CUMODE_VOICE)
2589 level2 = 1;
2590 if (*((unsigned long*)right) & CUMODE_OP)
2591 level2 = 2;
2592
2593 return level2 - level1;
2594 }
2595
2596 static void helpmod_cmd_checkchannel(huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2597 {
2598 channel *chan;
2599 nick *nck;
2600 int i, j, nick_count = 0, authed_count = 0, o_limit = 0, v_limit = 0, summary_only = 0;
2601 unsigned long *numeric_array;
2602
2603 if (argc == 0)
2604 {
2605 helpmod_reply(sender, returntype, "Cannot check channel: Channel not defined");
2606 return;
2607 }
2608
2609 chan = findchannel(argv[0]);
2610 if (chan == NULL)
2611 {
2612 helpmod_reply(sender, returntype, "Cannot check channel: Channel %s not found", argv[0]);
2613 return;
2614 }
2615 if (argc > 1 && !ci_strcmp(argv[1], "summary"))
2616 summary_only = 1;
2617
2618 /* first pass - verify validity and count nicks */
2619 for (i=0;i < chan->users->hashsize;i++)
2620 {
2621 nck = getnickbynumeric(chan->users->content[i]);
2622 if (!nck) /* it's a hash, not an array */
2623 continue;
2624
2625 nick_count++;
2626
2627 if (IsAccount(nck))
2628 authed_count++;
2629
2630 if (IsOper(nck) && strlen(nck->nick) > 1)
2631 {
2632 helpmod_reply(sender, returntype, "Cannot check channel: Permission denied. Channel %s has an oper on it", argv[0]);
2633 return;
2634 }
2635 }
2636
2637 numeric_array = (unsigned long*)malloc(nick_count * sizeof(unsigned long));
2638
2639 /* second pass - construct array */
2640 for (i=0,j=0;i < chan->users->hashsize;i++)
2641 {
2642 if (getnickbynumeric(chan->users->content[i]) == NULL) /* it's a hash, not an array */
2643 continue;
2644
2645 numeric_array[j++] = chan->users->content[i];
2646 }
2647
2648 qsort(numeric_array, nick_count, sizeof(unsigned long), helpmod_cmd_checkchannel_statussort);
2649
2650 /* third pass - find status boundaries */
2651 {
2652 for (;o_limit < nick_count && numeric_array[o_limit] & CUMODE_OP; o_limit++);
2653 v_limit = o_limit;
2654 for(v_limit = o_limit; (v_limit < nick_count) && numeric_array[v_limit] & CUMODE_VOICE; v_limit++);
2655 }
2656
2657 helpmod_reply(sender, returntype, "Information on channel %s", argv[0]);
2658 helpmod_reply(sender, returntype, "Channel created %s ago", helpmod_strtime(time(NULL) - chan->timestamp));
2659 if (!IsKey(chan) && !IsInviteOnly(chan))
2660 helpmod_reply(sender, returntype, "Channel topic: %s", chan->topic?chan->topic->content:"Not set");
2661 helpmod_reply(sender, returntype, "Channel modes: %s", printflags(chan->flags, cmodeflags));
2662
2663
2664 /* sort the sub arrays */
2665
2666 if (o_limit > 0)
2667 qsort(numeric_array, o_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2668 if (v_limit - o_limit > 0)
2669 qsort(numeric_array + o_limit, v_limit - o_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2670 if (nick_count - v_limit > 0)
2671 qsort(numeric_array + v_limit, nick_count - v_limit, sizeof(unsigned long), helpmod_cmd_checkchannel_nicksort);
2672
2673 /* fourth pass - print results */
2674 if (!summary_only)
2675 for (i=0;i < nick_count;i++)
2676 {
2677 char buf[256], status;
2678
2679 if (numeric_array[i] & CUMODE_OP)
2680 status = '@';
2681 else if (numeric_array[i] & CUMODE_VOICE)
2682 status = '+';
2683 else
2684 status = ' ';
2685
2686 visiblehostmask(getnickbynumeric(numeric_array[i]), buf);
2687 if (IsAccount(getnickbynumeric(numeric_array[i])))
2688 helpmod_reply(sender, returntype, "%c%s (%s)", status, buf, getnickbynumeric(numeric_array[i])->authname);
2689 else
2690 helpmod_reply(sender, returntype, "%c%s", status, buf);
2691 }
2692
2693 helpmod_reply(sender, returntype, "Users: %d Clones: %d Opped: %d Voiced: %d Authed: %3.0f%%", nick_count, nick_count - countuniquehosts(chan), o_limit, v_limit - o_limit, ((float)authed_count / (float)nick_count) * 100.0);
2694
2695 free(numeric_array);
2696 }
2697
2698 static void helpmod_cmd_statsdump (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2699 {
2700 haccount *hacc = haccounts;
2701 hstat_account *ptr;
2702 int i;
2703
2704 helpmod_reply(sender, returntype, "Account statistics");
2705 for (;hacc;hacc = hacc->next)
2706 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2707 {
2708 helpmod_reply(sender, returntype, "Account %s channel %s short-term", hacc->name->content, hchannel_get_name(ptr->hchan));
2709 for (i = 0;i < 7;i++)
2710 helpmod_reply(sender, returntype, "%d %d %d %d", ptr->week[i].time_spent, ptr->week[i].prime_time_spent, ptr->week[i].lines, ptr->week[i].words);
2711 helpmod_reply(sender, returntype, "Account %s channel %s long-term", hacc->name->content, hchannel_get_name(ptr->hchan));
2712 for (i = 0;i < 10;i++)
2713 helpmod_reply(sender, returntype, "%d %d %d %d", ptr->longterm[i].time_spent, ptr->longterm[i].prime_time_spent, ptr->longterm[i].lines, ptr->longterm[i].words);
2714 }
2715 }
2716
2717 static void helpmod_cmd_statsrepair (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2718 {
2719 haccount *hacc = haccounts;
2720 hstat_account *ptr;
2721 int i;
2722
2723 helpmod_reply(sender, returntype, "Repairing account statistics");
2724 for (;hacc;hacc = hacc->next)
2725 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2726 {
2727 for (i = 0;i < 7;i++)
2728 {
2729 if (ptr->week[i].time_spent > HDEF_d)
2730 {
2731 ptr->week[i].time_spent = 0;
2732 helpmod_reply(sender, returntype, "repaired short term TimeSpent %s @ %s : Greater than one day",hacc->name->content, hchannel_get_name(ptr->hchan));
2733 }
2734 if (ptr->week[i].time_spent < 0)
2735 {
2736 ptr->week[i].time_spent = 0;
2737 helpmod_reply(sender, returntype, "repaired short term TimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2738 }
2739
2740 if (ptr->week[i].prime_time_spent > HDEF_d)
2741 {
2742 ptr->week[i].prime_time_spent = 0;
2743 helpmod_reply(sender, returntype, "repaired short term PrimeTimeSpent %s @ %s : Greater than one day",hacc->name->content, hchannel_get_name(ptr->hchan));
2744 }
2745 if (ptr->week[i].prime_time_spent < 0)
2746 {
2747 ptr->week[i].prime_time_spent = 0;
2748 helpmod_reply(sender, returntype, "repaired short term PrimeTimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2749 }
2750
2751 if (ptr->week[i].lines > 10000)
2752 {
2753 ptr->week[i].lines = 0;
2754 helpmod_reply(sender, returntype, "repaired short term Lines %s @ %s : Greater than 10000",hacc->name->content, hchannel_get_name(ptr->hchan));
2755 }
2756 if (ptr->week[i].lines < 0)
2757 {
2758 ptr->week[i].lines = 0;
2759 helpmod_reply(sender, returntype, "repaired short term Lines %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2760 }
2761
2762 if (ptr->week[i].words > 50000)
2763 {
2764 ptr->week[i].words = 0;
2765 helpmod_reply(sender, returntype, "repaired short term Words %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2766 }
2767 if (ptr->week[i].words < 0)
2768 {
2769 ptr->week[i].words = 0;
2770 helpmod_reply(sender, returntype, "repaired short term Words %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2771 }
2772 }
2773 for (i = 0;i < 10;i++)
2774 {
2775 if (ptr->longterm[i].time_spent > HDEF_w)
2776 {
2777 ptr->longterm[i].time_spent = 0;
2778 helpmod_reply(sender, returntype, "repaired long term TimeSpent %s @ %s : Greater than one week",hacc->name->content, hchannel_get_name(ptr->hchan));
2779 }
2780 if (ptr->longterm[i].time_spent < 0)
2781 {
2782 ptr->longterm[i].time_spent = 0;
2783 helpmod_reply(sender, returntype, "repaired long term TimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2784 }
2785
2786 if (ptr->longterm[i].prime_time_spent > HDEF_w)
2787 {
2788 ptr->longterm[i].prime_time_spent = 0;
2789 helpmod_reply(sender, returntype, "repaired long term PrimeTimeSpent %s @ %s : Greater than one week",hacc->name->content, hchannel_get_name(ptr->hchan));
2790 }
2791 if (ptr->longterm[i].prime_time_spent < 0)
2792 {
2793 ptr->longterm[i].prime_time_spent = 0;
2794 helpmod_reply(sender, returntype, "repaired long term PrimeTimeSpent %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2795 }
2796
2797 if (ptr->longterm[i].lines > 50000)
2798 {
2799 ptr->longterm[i].lines = 0;
2800 helpmod_reply(sender, returntype, "repaired long term Lines %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2801 }
2802 if (ptr->longterm[i].lines < 0)
2803 {
2804 ptr->longterm[i].lines = 0;
2805 helpmod_reply(sender, returntype, "repaired long term Lines %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2806 }
2807
2808 if (ptr->longterm[i].words > 50000)
2809 {
2810 ptr->longterm[i].words = 0;
2811 helpmod_reply(sender, returntype, "repaired long term Words %s @ %s : Greater than 50000",hacc->name->content, hchannel_get_name(ptr->hchan));
2812 }
2813 if (ptr->longterm[i].words < 0)
2814 {
2815 ptr->longterm[i].words = 0;
2816 helpmod_reply(sender, returntype, "repaired long term Words %s @ %s : Less than zero",hacc->name->content, hchannel_get_name(ptr->hchan));
2817 }
2818 }
2819 }
2820 helpmod_reply(sender, returntype, "Account statistics repaired");
2821
2822 }
2823
2824 static void helpmod_cmd_statsreset (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2825 {
2826 haccount *hacc = haccounts;
2827 hstat_account *ptr;
2828 hchannel *hchan;
2829 int i, short_del, long_del;
2830
2831 if (argc < 2)
2832 {
2833 helpmod_reply(sender, returntype, "Insufficient parameters");
2834 return;
2835 }
2836
2837 if (sscanf(argv[0], "%d", &short_del) == 0)
2838 {
2839 helpmod_reply(sender, returntype, "Invalid parameter");
2840 return;
2841 }
2842 if (sscanf(argv[1], "%d", &long_del) == 0)
2843 {
2844 helpmod_reply(sender, returntype, "Invalid parameter");
2845 return;
2846 }
2847
2848 for (;hacc;hacc = hacc->next)
2849 for (ptr = hacc->stats;ptr;ptr = ptr->next)
2850 {
2851 for (i = 1;i < short_del + 1;i++)
2852 HSTAT_ACCOUNT_ZERO(ptr->week[(hstat_day() + i) % 7]);
2853 for (i = 1;i < long_del + 1;i++)
2854 HSTAT_ACCOUNT_ZERO(ptr->longterm[(hstat_week() + i) % 10]);
2855 }
2856
2857 for (hchan = hchannels;hchan;hchan = hchan->next)
2858 {
2859 for (i = 1;i < short_del + 1;i++)
2860 HSTAT_CHANNEL_ZERO(hchan->stats->week[(hstat_day() + i) % 7]);
2861 for (i = 1;i < long_del + 1;i++)
2862 HSTAT_CHANNEL_ZERO(hchan->stats->longterm[(hstat_week() + i) % 10]);
2863
2864 }
2865
2866 helpmod_reply(sender, returntype, "Statistics reset complete");
2867 }
2868
2869 static void helpmod_cmd_message (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2870 {
2871 hchannel *hchan;
2872
2873 if (argc < 2)
2874 {
2875 helpmod_reply(sender, returntype, "Cannot send a message: Insufficient arguments");
2876 return;
2877 }
2878 hchan = hchannel_get_by_name(argv[0]);
2879 if (hchan == NULL)
2880 {
2881 helpmod_reply(sender, returntype, "Cannot send a message: Invalid channel %s", argv[0]);
2882 return;
2883 }
2884 SKIP_WORD;
2885 helpmod_message_channel(hchan, "(%s) %s", huser_get_nick(sender), ostr);
2886 helpmod_reply(sender, returntype, "Message sent to %s", hchannel_get_name(hchan));
2887 }
2888
2889 static void helpmod_cmd_version (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2890 {
2891 helpmod_reply(sender, returntype, "HelpMod version " HELPMOD_VERSION " by strutsi (strutsi@quakenet.org)");
2892 }
2893
2894 static void helpmod_cmd_ticketmsg (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2895 {
2896 hchannel *hchan;
2897
2898 DEFINE_HCHANNEL;
2899
2900 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
2901
2902 if (hchan == NULL)
2903 {
2904 helpmod_reply(sender, returntype, "Can not view or set ticket message: No channel is specified.");
2905 return;
2906 }
2907
2908 if (argc == 0)
2909 { /* view */
2910 if (hchan->ticket_message == NULL)
2911 helpmod_reply(sender, returntype, "No ticket message is set for channel %s", hchannel_get_name(hchan));
2912 else
2913 helpmod_reply(sender, returntype, "Ticket message for channel %s is: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2914 return;
2915 }
2916
2917 /* set */
2918 if (hchan->ticket_message != NULL)
2919 freesstring(hchan->ticket_message);
2920
2921 hchan->ticket_message = getsstring(ostr, strlen(ostr));
2922 helpmod_reply(sender, returntype, "Ticket message for channel %s set to: %s", hchannel_get_name(hchan), hchan->ticket_message->content);
2923 }
2924
2925 static void helpmod_cmd_lcedit (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
2926 {
2927 hlc_profile *profile;
2928
2929 if (argc == 0)
2930 {
2931 helpmod_reply(sender, returntype, "Can not handle lamer control profiles: Operation not defined");
2932 return;
2933 }
2934
2935 if (!ci_strcmp(argv[0], "list"))
2936 {
2937 if (hlc_profiles == NULL)
2938 {
2939 helpmod_reply(sender, returntype, "Can not list lamer control profiles: No profiles");
2940 return;
2941 }
2942 helpmod_reply(sender, returntype, "Following lamer control profiles are currently available:");
2943 for (profile = hlc_profiles;profile != NULL;profile = profile->next)
2944 helpmod_reply(sender, returntype, "%s", profile->name->content);
2945 }
2946 else if (!ci_strcmp(argv[0], "add"))
2947 {
2948 if (argc < 2)
2949 {
2950 helpmod_reply(sender, returntype, "Can not add a lamer control profile: Profile name not defined");
2951 return;
2952 }
2953
2954 profile = hlc_get(argv[1]);
2955
2956 if (profile != NULL)
2957 {
2958 helpmod_reply(sender, returntype, "Can not add a lamer control profile: Profile named %s already exists", argv[1]);
2959 return;
2960 }
2961 profile = hlc_add(argv[1]);
2962
2963 { /* set the default values */
2964 profile->caps_max_percentage = 40;
2965 profile->caps_min_count = 20;
2966
2967 profile->repeats_max_count = 3;
2968 profile->repeats_min_length = 7;
2969
2970 profile->symbol_repeat_max_count = 6;
2971 profile->character_repeat_max_count = 7;
2972 profile->symbol_max_count = 9;
2973
2974 profile->tolerance_flood = 5;
2975
2976 profile->tolerance_spam = 0.008;
2977 profile->constant_spam = 10;
2978
2979 profile->tolerance_warn = 1;
2980 profile->tolerance_kick = 3;
2981 profile->tolerance_remove = 5;
2982 }
2983
2984 helpmod_reply(sender, returntype, "Lamer control profile %s added", argv[1]);
2985 }
2986 else if (!ci_strcmp(argv[0], "del"))
2987 {
2988 hchannel *hchan;
2989 if (argc < 2)
2990 {
2991 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile name not defined");
2992 return;
2993 }
2994
2995 profile = hlc_get(argv[1]);
2996
2997 if (profile == NULL)
2998 {
2999 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile named %s does not exist", argv[1]);
3000 return;
3001 }
3002 for (hchan = hchannels;hchan != NULL;hchan = hchan->next)
3003 if (hchan->lc_profile == profile)
3004 {
3005 helpmod_reply(sender, returntype, "Can not delete a lamer control profile: Profile %s is in use", argv[1]);
3006 return;
3007 }
3008 hlc_del(profile);
3009 helpmod_reply(sender, returntype, "Lamer control profile %s deleted", argv[1]);
3010 }
3011 else if (!ci_strcmp(argv[0], "view"))
3012 {
3013 if (argc < 2)
3014 {
3015 helpmod_reply(sender, returntype, "Can not view a lamer control profile: Profile name not defined");
3016 return;
3017 }
3018
3019 profile = hlc_get(argv[1]);
3020
3021 if (profile == NULL)
3022 {
3023 helpmod_reply(sender, returntype, "Can not view a lamer control profile: Profile named %s not found", argv[1]);
3024 return;
3025 }
3026
3027 helpmod_reply(sender, returntype, "Lamer control profile %s:", profile->name->content);
3028 helpmod_reply(sender, returntype, "Maximum caps percentage: %d", profile->caps_max_percentage);
3029 helpmod_reply(sender, returntype, "Caps minimum count: %d", profile->caps_min_count);
3030 helpmod_reply(sender, returntype, "Repeat tolerance: %d", profile->repeats_max_count);
3031 helpmod_reply(sender, returntype, "Repeat minimum length: %d", profile->repeats_min_length);
3032 helpmod_reply(sender, returntype, "Symbol repeat tolerance: %d", profile->symbol_repeat_max_count);
3033 helpmod_reply(sender, returntype, "Character repeat tolerance: %d", profile->character_repeat_max_count);
3034 helpmod_reply(sender, returntype, "Continuous symbol tolerance: %d", profile->symbol_max_count);
3035 helpmod_reply(sender, returntype, "Flood tolerance: %d", profile->tolerance_flood);
3036 helpmod_reply(sender, returntype, "Spam tolerance: %d", profile->tolerance_spam);
3037 helpmod_reply(sender, returntype, "Spam multiplier: %f", profile->constant_spam);
3038 helpmod_reply(sender, returntype, "Warning limit: %d", profile->tolerance_warn);
3039 helpmod_reply(sender, returntype, "Kick limit: %d", profile->tolerance_kick);
3040 helpmod_reply(sender, returntype, "Ban limit: %d", profile->tolerance_remove);
3041 }
3042 else if (!ci_strcmp(argv[0], "edit"))
3043 {
3044 int int_val = -1;
3045 double dbl_val = -1;
3046
3047 if (argc != 4)
3048 {
3049 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Syntax error");
3050 return;
3051 }
3052
3053 profile = hlc_get(argv[1]);
3054
3055 if (profile == NULL)
3056 {
3057 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Profile %s not found", argv[1]);
3058 return;
3059 }
3060
3061 sscanf(argv[3], "%d", &int_val);
3062 sscanf(argv[3], "%lf", &dbl_val);
3063
3064 if (dbl_val < 0)
3065 { /* All int values are also valid double values */
3066 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: Invalid argument");
3067 return;
3068 }
3069
3070 if (!ci_strcmp(argv[2], "caps_percentage"))
3071 profile->caps_max_percentage = int_val;
3072 else if (!ci_strcmp(argv[2], "caps_count"))
3073 profile->caps_min_count = int_val;
3074 else if (!ci_strcmp(argv[2], "repeat_tolerance"))
3075 profile->repeats_max_count = int_val;
3076 else if (!ci_strcmp(argv[2], "repeat_length"))
3077 profile->repeats_min_length = int_val;
3078 else if (!ci_strcmp(argv[2], "symbol_repeat"))
3079 profile->symbol_repeat_max_count = int_val;
3080 else if (!ci_strcmp(argv[2], "character_repeat"))
3081 profile->character_repeat_max_count = int_val;
3082 else if (!ci_strcmp(argv[2], "continuous_symbol"))
3083 profile->symbol_max_count = int_val;
3084 else if (!ci_strcmp(argv[2], "flood_tolerance"))
3085 profile->tolerance_flood = int_val;
3086 else if (!ci_strcmp(argv[2], "spam_tolerance"))
3087 profile->tolerance_spam = int_val;
3088 else if (!ci_strcmp(argv[2], "spam_multiplier"))
3089 profile->constant_spam = dbl_val;
3090 else if (!ci_strcmp(argv[2], "warn_limit"))
3091 profile->tolerance_warn = int_val;
3092 else if (!ci_strcmp(argv[2], "kick_limit"))
3093 profile->tolerance_kick = int_val;
3094 else if (!ci_strcmp(argv[2], "ban_limit"))
3095 profile->tolerance_remove = int_val;
3096 else
3097 {
3098 helpmod_reply(sender, returntype, "Can not edit a lamer control profile: No component named %s", argv[2]);
3099 return;
3100 }
3101 helpmod_reply(sender, returntype, "Lamer control profile component value changed succesfully.");
3102 }
3103 }
3104
3105 static void helpmod_cmd_ged (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3106 {
3107 helpmod_editor *editor;
3108
3109 if (sender->editor == NULL)
3110 { /* Start a new editor */
3111 if (argc == 0)
3112 {
3113 helpmod_reply(sender, returntype, "Can not use ged: Filename not specified");
3114 return;
3115 }
3116 editor = hed_open(sender, argv[0]);
3117 if (editor == NULL)
3118 {
3119 helpmod_reply(sender, returntype, "Can not use ged: Invalid filename %s", argv[0]);
3120 return;
3121 }
3122 if (editor->user != sender)
3123 {
3124 helpmod_reply(sender, returntype, "Can not use ged: File %s is currently being edited by %s", editor->filename, huser_get_nick(editor->user));
3125 return;
3126 }
3127 editor->user = sender;
3128 sender->editor = editor;
3129
3130 helpmod_reply(sender, returntype, "Ged: %d", hed_byte_count(editor));
3131 }
3132 else
3133 {
3134 hed_command(sender, returntype, ostr, argc, argv);
3135 }
3136 }
3137
3138 static void helpmod_cmd_text (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3139 {
3140 hchannel *hchan;
3141 DEFINE_HCHANNEL;
3142 FILE *in;
3143
3144 if (argc == 0 || !ci_strcmp(argv[0], "list"))
3145 {
3146 DIR *dir;
3147 struct dirent *dent;
3148 char buffer[384], **lines, *start;
3149 int nwritten, bufpos = 0, nlines = 0,i;
3150
3151 dir = opendir(HELPMOD_TEXT_DIR);
3152 assert(dir != NULL);
3153
3154 /* First pass, count */
3155 for (dent = readdir(dir);dent != NULL;dent = readdir(dir))
3156 {
3157 /* Skip stuff like . and .. */
3158 if (!strncmp(dent->d_name, ".", 1))
3159 continue;
3160 nlines++;
3161 }
3162
3163 if (nlines == 0)
3164 {
3165 helpmod_reply(sender, returntype, "No texts are available.");
3166 return;
3167 }
3168
3169 helpmod_reply(sender, returntype, "Following texts are available:");
3170
3171 {
3172 lines = (char **)malloc(sizeof(char*) * nlines);
3173 *lines = (char *)malloc(sizeof(char) * (HED_FILENAME_LENGTH+1) * nlines);
3174 /* We need the start to free this array */
3175 start = *lines;
3176 for(i=0;i < nlines;i++)
3177 lines[i] = &lines[0][(HED_FILENAME_LENGTH+1) * i];
3178 }
3179
3180 /* Second pass, create array */
3181 rewinddir(dir);
3182 for (dent = readdir(dir), i = 0;dent != NULL && i < nlines;dent = readdir(dir))
3183 {
3184 /* Skip stuff like . and .. */
3185 if (!strncmp(dent->d_name, ".", 1))
3186 continue;
3187 strncpy(lines[i], dent->d_name, 64);
3188 i++;
3189 }
3190 /* Sort */
3191 qsort(*lines, nlines, sizeof(char)*(HED_FILENAME_LENGTH+1), (int (*)(const void*, const void*))&strcmp);
3192
3193 for (i = 0;i < nlines;i++)
3194 {
3195 if (bufpos)
3196 {
3197 buffer[bufpos] = ' ';
3198 bufpos++;
3199 }
3200 sprintf(buffer + bufpos, "%s%n", lines[i], &nwritten);
3201 bufpos+=nwritten;
3202
3203 if (bufpos > (384 - (HED_FILENAME_LENGTH+1)))
3204 {
3205 helpmod_reply(sender, returntype, buffer);
3206 bufpos = 0;
3207 }
3208 }
3209
3210 if (bufpos)
3211 helpmod_reply(sender, returntype, buffer);
3212
3213 free(start);
3214 free(lines);
3215
3216 return;
3217 }
3218 else if (!ci_strcmp(argv[0], "show"))
3219 {
3220 char fname_buffer[128], buffer[512];
3221 if (argc < 2)
3222 {
3223 helpmod_reply(sender, returntype, "Can not show text: Text not specified");
3224 return;
3225 }
3226 if (!hed_is_valid_filename(argv[1]))
3227 {
3228 helpmod_reply(sender, returntype, "Can not show text: Invalid filename");
3229 return;
3230 }
3231 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3232 in = fopen(fname_buffer, "rwt");
3233 if (in == NULL)
3234 {
3235 helpmod_reply(sender, returntype, "Can not show text: Text %s not found", argv[1]);
3236 return;
3237 }
3238 while (!feof(in))
3239 {
3240 if (!fgets(buffer, 512, in))
3241 break;
3242 if (returntype != NULL && huser_get_level(sender) > H_PEON)
3243 helpmod_message_channel(hchannel_get_by_channel(returntype), "%s: %s", argv[1], buffer);
3244 else
3245 helpmod_reply(sender, returntype, "%s", buffer);
3246 }
3247 fclose (in);
3248 return;
3249 }
3250
3251 if (huser_get_level(sender) < H_STAFF)
3252 {
3253 helpmod_reply(sender, returntype, "Can not handle text: Insufficient user level");
3254 return;
3255 }
3256
3257 if (!ci_strcmp(argv[0], "add"))
3258 {
3259 char fname_buffer[128];
3260 if (argc < 2)
3261 {
3262 helpmod_reply(sender, returntype, "Can not add text: Text not specified");
3263 return;
3264 }
3265 if (!hed_is_valid_filename(argv[1]))
3266 {
3267 helpmod_reply(sender, returntype, "Can not add text: Invalid filename");
3268 return;
3269 }
3270 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3271 if ((in = fopen(fname_buffer, "rt")) != NULL)
3272 {
3273 helpmod_reply(sender, returntype, "Can not add text: Text %s already exists", argv[1]);
3274 return;
3275 }
3276 else
3277 {
3278 if ((in = fopen(fname_buffer, "wt")) == NULL)
3279 {
3280 helpmod_reply(sender, returntype, "Can not add text: Unexpected error, please contact strutsi");
3281 return;
3282 }
3283 fclose(in);
3284 }
3285 helpmod_reply(sender, returntype, "Text %s added succesfully", argv[1]);
3286 }
3287 else if (!ci_strcmp(argv[0], "del"))
3288 {
3289 char fname_buffer[128];
3290 if (argc < 2)
3291 {
3292 helpmod_reply(sender, returntype, "Can not delete text: Text not specified");
3293 return;
3294 }
3295 if (!hed_is_valid_filename(argv[1]))
3296 {
3297 helpmod_reply(sender, returntype, "Can not delete text: Invalid filename");
3298 return;
3299 }
3300 sprintf(fname_buffer, HELPMOD_TEXT_DIR"/%s" ,argv[1]);
3301
3302 if (!remove(fname_buffer))
3303 helpmod_reply(sender, returntype, "Text %s removed", argv[1]);
3304 else
3305 helpmod_reply(sender, returntype, "Can not delete text: Text %s does not exist or can not be deleted", argv[1]);
3306 }
3307 else
3308 {
3309 helpmod_reply(sender, returntype, "Can not handle text: Unknown operation %s", argv[0]);
3310 return;
3311 }
3312 }
3313
3314 static void helpmod_cmd_rating (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3315 {
3316 hchannel *hchan;
3317 hstat_account_entry sum = {0,0,0,0};
3318 hstat_account *ptr;
3319 int i;
3320
3321 DEFINE_HCHANNEL;
3322
3323 HCHANNEL_VERIFY_AUTHORITY(hchan, sender);
3324
3325 if (hchan == NULL)
3326 {
3327 helpmod_reply(sender, returntype, "Can not show rating: Unknown channel");
3328 return;
3329 }
3330 if (sender->account == NULL)
3331 {
3332 helpmod_reply(sender, returntype, "Can not show rating: You do not have an account");
3333 return;
3334 }
3335 for (ptr = sender->account->stats;ptr != NULL;ptr = ptr->next)
3336 if (ptr->hchan == hchan)
3337 {
3338 if (hstat_day() == 0)
3339 { /* Sunday screws the indexing */
3340 for (i = 0;i < 7;i++)
3341 HSTAT_ACCOUNT_SUM(sum, sum, ptr->week[i]);
3342 }
3343 else
3344 { /* Normal case */
3345 for (i = 1;i <= hstat_day();i++)
3346 HSTAT_ACCOUNT_SUM(sum, sum, ptr->week[i]);
3347 }
3348
3349 helpmod_reply(sender, returntype, "Your rating for channel %s for this week is: %s", hchannel_get_name(hchan), helpmod_strtime(sum.time_spent));
3350 return;
3351 }
3352 helpmod_reply(sender, returntype, "Can not show rating: You do not have any statistics for channel %s", hchannel_get_name(hchan));
3353 }
3354
3355 static void helpmod_cmd_writedb (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3356 {
3357 rename(HELPMOD_DEFAULT_DB, HELPMOD_DEFAULT_DB".old");
3358 helpmod_config_write(HELPMOD_DEFAULT_DB);
3359
3360 helpmod_reply(sender, returntype, "Database written");
3361 }
3362
3363 static void helpmod_cmd_evilhack1 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3364 {
3365 int tmp;
3366
3367 if (argc == 0)
3368 helpmod_reply(sender, returntype, "hstat_cycle: %d", hstat_cycle);
3369 else
3370 {
3371 if (!sscanf(argv[0], "%d", &tmp) || tmp < 0)
3372 {
3373 helpmod_reply(sender, returntype, "Invalid argument");
3374 return;
3375 }
3376 hstat_cycle = tmp;
3377 helpmod_reply(sender, returntype, "hstat_cycle is now: %d", hstat_cycle);
3378 }
3379 }
3380
3381 static void helpmod_cmd_evilhack2 (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3382 {
3383 haccount *hacc = haccounts;
3384 hchannel *hchan;
3385 hstat_account *ptr;
3386 hstat_account_entry tmp_account;
3387 hstat_channel_entry tmp_channel;
3388 int first, second;
3389
3390 if (argc != 2)
3391 {
3392 helpmod_reply(sender, returntype, "Syntax error: evilhack2 <first> <second>");
3393 return;
3394 }
3395
3396 if (!sscanf(argv[0],"%d", &first) || first < 0 || first > 9)
3397 {
3398 helpmod_reply(sender, returntype, "Syntax error: Invalid first");
3399 return;
3400 }
3401
3402 if (!sscanf(argv[1],"%d", &second) || second < 0 || second > 9)
3403 {
3404 helpmod_reply(sender, returntype, "Syntax error: Invalid second");
3405 return;
3406 }
3407
3408 for (;hacc;hacc = hacc->next)
3409 for (ptr = hacc->stats;ptr;ptr = ptr->next)
3410 {
3411 tmp_account = ptr->longterm[first];
3412 ptr->longterm[first] = ptr->longterm[second];
3413 ptr->longterm[second] = tmp_account;
3414 }
3415
3416 for (hchan = hchannels;hchan;hchan = hchan->next)
3417 {
3418 tmp_channel = hchan->stats->longterm[first];
3419 hchan->stats->longterm[first] = hchan->stats->longterm[second];
3420 hchan->stats->longterm[second] = tmp_channel;
3421 }
3422
3423 helpmod_reply(sender, returntype, "Evilhack2 done: Swapped %d and %d", first, second);
3424 }
3425
3426 /* old H stuff */
3427 void helpmod_cmd_load (huser *sender, channel *returntype, char* arg, int argc, char *argv[])
3428 {
3429 FILE *tmp_file;
3430 char buf[128] = "helpmod/default";
3431
3432 if (!arg)
3433 helpmod_reply(sender, returntype, "Warning: No config specified, using default");
3434 else
3435 {
3436 if (strlen(arg) >= 100)
3437 return;
3438 else
3439 sprintf(buf, "helpmod/%s", arg);
3440 }
3441
3442 if (!(tmp_file = fopen(buf, "rt")))
3443 {
3444 helpmod_reply(sender, returntype, "File %s not found", buf);
3445 return;
3446 }
3447 else
3448 fclose(tmp_file);
3449
3450 helpmod_clear_aliases(&aliases);
3451 helpmod_clear_all_entries();
3452 helpmod_init_entry(&helpmod_base);
3453 huser_reset_states();
3454 helpmod_load_entries(buf);
3455 strcpy(helpmod_db, buf);
3456 helpmod_reply(sender, returntype, "New config loaded and system reset");
3457 }
3458
3459 void helpmod_cmd_status (huser *sender, channel* returntype, char* ostr, int argc, char *argv[])
3460 {
3461 helpmod_reply(sender, returntype, "HelpMod version %s (built %s, up %s)", HELPMOD_VERSION, __DATE__, helpmod_strtime(time(NULL) - helpmod_startup_time));
3462 helpmod_reply(sender, returntype, "Channels %d", hchannel_count());
3463 helpmod_reply(sender, returntype, "Accounts %d", haccount_count(H_ANY));
3464 helpmod_reply(sender, returntype, "Users %d", huser_count());
3465 helpmod_reply(sender, returntype, "Help entries %d", helpmod_entry_count(helpmod_base));
3466 helpmod_reply(sender, returntype, "Bans %d", hban_count());
3467 helpmod_reply(sender, returntype, "Help provided %d", helpmod_usage);
3468 helpmod_reply(sender, returntype, "Tickets %d", hticket_count());
3469 }
3470
3471 /* not really a command, but help wants this one */
3472 void helpmod_send_help(huser* target)
3473 {
3474 int i;
3475 helpmod_usage++;
3476 for (i=0;i<target->state->text_lines;i++)
3477 helpmod_reply(target, NULL, "%s", target->state->text[i]->content);
3478 for (i=0;i<target->state->option_count;i++)
3479 helpmod_reply(target, NULL, "%d) %s", i+1, target->state->options[i]->description->content);
3480 if (!target->state->option_count)
3481 {
3482 helpmod_reply(target, NULL, "This concludes the help for this topic, if you want to, you can restart the service with the 'help' command, or return to the previous entry by selecting 0");
3483 }
3484 }
3485
3486 void helpmod_cmd_command(huser* sender, channel* returntype, char* arg, int argc, char *argv[])
3487 {
3488 hcommand *hcom;
3489 char buffer[512], *ptr = argv[0];
3490 FILE *in;
3491
3492 if (argc == 0)
3493 {
3494 helpmod_reply(sender, returntype, "Usage: command [name of the command] for a list see 'showcommands'");
3495 return;
3496 }
3497
3498 hcom = hcommand_get(argv[0], huser_get_level(sender));
3499
3500 if (hcom == NULL)
3501 {
3502 helpmod_reply(sender, returntype, "Unknown command '%s'", argv[0]);
3503 return;
3504 }
3505
3506 /* tolower */
3507 while (*(ptr++))
3508 *ptr = tolower(*ptr);
3509
3510 /* ?,?+.?- is handled like this because windows is shit */
3511 if (!ci_strcmp(argv[0], "?"))
3512 sprintf(buffer, "./helpmod2/commands/questionmark");
3513 else if (!ci_strcmp(argv[0], "?+"))
3514 sprintf(buffer, "./helpmod2/commands/questionmarkplus");
3515 else if (!ci_strcmp(argv[0], "?-"))
3516 sprintf(buffer, "./helpmod2/commands/questionmarkminus");
3517 else
3518 sprintf(buffer, "./helpmod2/commands/%s", argv[0]);
3519
3520 if ((in = fopen(buffer, "rt")) == NULL)
3521 {
3522 helpmod_reply(sender, returntype, "No help available for command '%s' (Ask strutsi to write it)", argv[0]);
3523 return;
3524 }
3525
3526 while (!feof(in))
3527 {
3528 fgets(buffer, 512, in);
3529 if (feof(in))
3530 break;
3531 helpmod_reply(sender, returntype, "%s", buffer);
3532 }
3533
3534 fclose(in);
3535 }
3536
3537 void helpmod_cmd_help (huser* sender, channel* returntype, char* arg, int argc, char *argv[])
3538 {
3539 int hlp_target;
3540
3541 if (helpmod_base == NULL || !helpmod_base->option_count)
3542 {
3543 helpmod_reply(sender, returntype, "The help service is not available at this time, please try again later");
3544 return;
3545 }
3546
3547 if (!argc)
3548 {
3549 sender->state = helpmod_base;
3550 helpmod_send_help(sender);
3551 return;
3552 }
3553 else
3554 if (!sscanf(arg, "%d", &hlp_target))
3555 {
3556 helpmod_entry tmp;
3557
3558 tmp = helpmod_get_alias(arg);
3559 if (!tmp)
3560 helpmod_reply(sender, returntype, "Invalid value. Either use 'help' to restart or give an integer as a valid selection");
3561 else
3562 {
3563 sender->state = tmp;
3564 helpmod_send_help(sender);
3565 }
3566 return;
3567 }
3568
3569 hlp_target--;
3570 if (!helpmod_valid_selection(sender->state, hlp_target))
3571 {
3572 if (!sender->state->option_count)
3573 helpmod_reply(sender, returntype, "There are no more options to choose from, you can restart the service by giving the 'help' command or select 0 to return to the previous entry");
3574 else if (!sender->state->parent)
3575 helpmod_reply(sender, returntype, "Bad selection, please enter your selection as an integer from %d to %d", 1, sender->state->option_count);
3576 else
3577 helpmod_reply(sender, returntype, "Bad selection, please enter your selection as an integer from %d to %d, selecting 0 will take you to the previous entry", 1, sender->state->option_count);
3578 return;
3579 }
3580
3581 sender->state = helpmod_make_selection(sender->state, hlp_target);
3582 helpmod_send_help(sender);
3583
3584 return;
3585 }
3586 /* adds all of the abowe to the system */
3587 void hcommands_add(void)
3588 {
3589 hcommand_add("help", H_PEON, helpmod_cmd_help,"Offers the H1 type help");
3590 hcommand_add("status",H_OPER, helpmod_cmd_status,"Gives service status");
3591 hcommand_add("load", H_OPER, helpmod_cmd_load,"Loads a new help database");
3592 hcommand_add("aliases",H_STAFF, helpmod_cmd_aliases,"Lists all aliases currently in use");
3593 hcommand_add("showcommands", H_LAMER, helpmod_cmd_showcommands,"Lists all commands available to you");
3594
3595 hcommand_add("improper", H_STAFF, helpmod_cmd_improper, "Sets the userlevel of the target to banned (lvl 0). Long term ban.");
3596 hcommand_add("peon", H_STAFF, helpmod_cmd_peon, "Sets the userlevel of the target to peon (lvl 1)");
3597 hcommand_add("trial", H_OPER, helpmod_cmd_trial, "Sets the userlevel of the target to trial staff (lvl 2)");
3598 hcommand_add("staff", H_OPER, helpmod_cmd_staff, "Sets the userlevel of the target to staff (lvl 3)");
3599 hcommand_add("oper", H_OPER, helpmod_cmd_oper, "Sets the userlevel of the target to oper (lvl 4)");
3600 hcommand_add("admin", H_ADMIN, helpmod_cmd_admin, "Sets the userlevel of the target to admin (lvl 5)");
3601 hcommand_add("deluser", H_OPER, helpmod_cmd_deluser, "Removes an account from " HELPMOD_NICK);
3602 hcommand_add("listuser", H_STAFF, helpmod_cmd_listuser, "Lists user accounts of " HELPMOD_NICK);
3603
3604 hcommand_add("chanconf", H_STAFF, helpmod_cmd_chanconf, "Channel configuration");
3605 hcommand_add("acconf", H_TRIAL, helpmod_cmd_acconf, "Personalise " HELPMOD_NICK " behaviour");
3606 hcommand_add("welcome", H_STAFF, helpmod_cmd_welcome, "Views or changes the channel welcome message");
3607 hcommand_add("censor", H_STAFF, helpmod_cmd_censor, "Handles the censored patterns for a channel");
3608
3609 hcommand_add("queue", H_TRIAL, helpmod_cmd_queue, "Handles the channel queue");
3610 hcommand_add("next", H_TRIAL, helpmod_cmd_next, "Same as queue next");
3611 hcommand_add("done", H_TRIAL, helpmod_cmd_done, "Same as queue done");
3612 hcommand_add("enqueue", H_TRIAL, helpmod_cmd_enqueue, "Same as queue on or chanconf +3");
3613 hcommand_add("dequeue", H_TRIAL, helpmod_cmd_dequeue, "Same as queue off or chanconf -3");
3614 hcommand_add("autoqueue", H_TRIAL, helpmod_cmd_autoqueue, "Same as queue maintain");
3615
3616 hcommand_add("?", H_PEON, helpmod_cmd_term_find, "Same as term find with multiple targets");
3617 hcommand_add("?+", H_TRIAL, helpmod_cmd_term_find_plus, "Multitarget term find which advances the queue");
3618 hcommand_add("?-", H_TRIAL, helpmod_cmd_term_find_minus, "Multitarget term find which removes users from queue");
3619 hcommand_add("term", H_STAFF, helpmod_cmd_term, "Term handling");
3620
3621 hcommand_add("klingon", H_OPER, helpmod_cmd_klingon, "Phrases in klingon, both targeted and general");
3622 hcommand_add("out", H_STAFF, helpmod_cmd_out, "Sets the userlevel of the target to banned (lvl 0) for a short while");
3623 hcommand_add("kick", H_TRIAL, helpmod_cmd_kick, "Kicks user(s) from a channel");
3624 hcommand_add("ban", H_STAFF, helpmod_cmd_ban, "Handles global bans");
3625 hcommand_add("chanban", H_TRIAL, helpmod_cmd_chanban, "Handles channel bans");
3626 hcommand_add("dnmo", H_STAFF, helpmod_cmd_dnmo, "DoNotMessageOpers informs the luser of his mistake and sets him to the bottom of the queue");
3627 hcommand_add("lamercontrol", H_OPER, helpmod_cmd_lamercontrol, "Views or changes the channel lamercontrol profile");
3628 hcommand_add("topic", H_STAFF, helpmod_cmd_topic, "Handles the topic of a channel");
3629 hcommand_add("idlekick", H_OPER, helpmod_cmd_idlekick, "Views or sets the idle kick time");
3630 hcommand_add("everyoneout", H_STAFF, helpmod_cmd_everyoneout, "Removes all normal users from a channel and enforces +i");
3631
3632 hcommand_add("stats", H_STAFF, helpmod_cmd_stats, "Shows staff activity statistics");
3633 hcommand_add("chanstats", H_STAFF, helpmod_cmd_chanstats, "Shows channel activity statistics");
3634 hcommand_add("activestaff", H_ADMIN, helpmod_cmd_activestaff, "Shows active staff members for a channel");
3635 hcommand_add("top10", H_STAFF, helpmod_cmd_top10, "Shows the top 10 most active staff");
3636 hcommand_add("report", H_OPER, helpmod_cmd_report, "Sets the channel where to report this channels statistics every 5 minutes");
3637
3638 hcommand_add("whoami", H_LAMER, helpmod_cmd_whoami, "Tells who you are to " HELPMOD_NICK);
3639 hcommand_add("whois", H_STAFF, helpmod_cmd_whois, "Tells you who someone is");
3640 hcommand_add("command", H_LAMER, helpmod_cmd_command, "Gives detailed information on a command");
3641 hcommand_add("addchan", H_ADMIN, helpmod_cmd_addchan, "Joins " HELPMOD_NICK " to a new channel");
3642 hcommand_add("delchan", H_ADMIN, helpmod_cmd_delchan, "Removes " HELPMOD_NICK " permanently from a channel");
3643
3644 hcommand_add("seen", H_STAFF, helpmod_cmd_seen, "Tells when a specific user/account has had activity");
3645 hcommand_add("op", H_STAFF, helpmod_cmd_op, "Sets mode +o on channels");
3646 hcommand_add("deop", H_STAFF, helpmod_cmd_deop, "Sets mode -o on channels");
3647 hcommand_add("voice", H_TRIAL, helpmod_cmd_voice, "Sets mode +v on channels");
3648 hcommand_add("devoice", H_TRIAL, helpmod_cmd_devoice, "Sets mode -v on channels");
3649
3650 hcommand_add("invite", H_PEON, helpmod_cmd_invite, "Invites you to a channel");
3651 hcommand_add("ticket", H_TRIAL, helpmod_cmd_ticket, "Gives a ticket to be used with invite");
3652 hcommand_add("resolve", H_STAFF, helpmod_cmd_resolve, "Resolves (deletes) a ticket");
3653 hcommand_add("tickets", H_STAFF, helpmod_cmd_tickets, "Lists all valid tickets for a channel");
3654 hcommand_add("showticket", H_STAFF, helpmod_cmd_showticket, "Shows the ticket for the user");
3655
3656 hcommand_add("termstats", H_OPER, helpmod_cmd_termstats, "Lists usage statistics for terms");
3657 hcommand_add("checkchannel", H_STAFF, helpmod_cmd_checkchannel, "Shows channel information for any channel");
3658 hcommand_add("message", H_TRIAL, helpmod_cmd_message, "Sends a message to a channel");
3659 hcommand_add("version", H_PEON, helpmod_cmd_version, "G version information");
3660 hcommand_add("ticketmsg", H_STAFF, helpmod_cmd_ticketmsg, "Handle the ticket message for a channel");
3661
3662 hcommand_add("lcedit", H_ADMIN, helpmod_cmd_lcedit, "Lamer control profile manager");
3663 hcommand_add("ged", H_STAFF, helpmod_cmd_ged, "Ged IRC text editor");
3664 hcommand_add("text", H_PEON, helpmod_cmd_text, "Lists or shows text files");
3665 hcommand_add("evilhack1", H_ADMIN, helpmod_cmd_evilhack1, "An evil hack, don't use");
3666 hcommand_add("evilhack2", H_ADMIN, helpmod_cmd_evilhack2, "Another evil hack, don't use");
3667
3668 hcommand_add("statsdump", H_ADMIN, helpmod_cmd_statsdump, "Statistics dump command");
3669 hcommand_add("statsrepair", H_ADMIN, helpmod_cmd_statsrepair, "Statistics repair command");
3670 hcommand_add("statsreset", H_ADMIN, helpmod_cmd_statsreset, "Statistics reset command");
3671 hcommand_add("rating", H_TRIAL, helpmod_cmd_rating, "Simple rating for the current week");
3672 hcommand_add("writedb", H_OPER, helpmod_cmd_writedb, "Writes the " HELPMOD_NICK " database to disk");
3673
3674 /*hcommand_add("megod", H_PEON, helpmod_cmd_megod, "Gives you userlevel 4, if you see this in the final version, please kill strutsi");*/
3675 /*hcommand_add("test", H_PEON, helpmod_cmd_test, "Gives you userlevel 4, if you see this in the final version, please kill strutsi");*/
3676 }
3677
3678 void helpmod_command(huser *sender, channel* returntype, char *args)
3679 {
3680 int argc = 0, useless_var;
3681 char args_copy[512];
3682 char *parsed_args[H_CMD_MAX_ARGS + 3], *ptr = args_copy;
3683
3684 /* only accept commands from valid sources */
3685 if (huser_get_level(sender) > H_ADMIN)
3686 return;
3687
3688 if (returntype && !strncmp(args, helpmodnick->nick, strlen(helpmodnick->nick)))
3689 {
3690 if (!args[1])
3691 return;
3692 else
3693 args+=strlen(helpmodnick->nick)+1;
3694 }
3695
3696 if (*args == '-' || *args == '?')
3697 args++;
3698
3699 strcpy(args_copy, args);
3700 /* FIX stringituki */
3701 while (argc < 10)
3702 {
3703 while (isspace(*ptr) && *ptr)
3704 ptr++;
3705
3706 if (*ptr == '\0')
3707 break;
3708
3709 if (*ptr == '"' && strchr(ptr+1, '"'))
3710 { /* string support */
3711 parsed_args[argc++] = ptr+1;
3712 ptr = strchr(ptr+1, '"');
3713
3714 *(ptr++) = '\0';
3715
3716 while (!isspace(*ptr) && *ptr)
3717 ptr++;
3718
3719 if (*ptr == '\0')
3720 break;
3721 }
3722 else
3723 {
3724 parsed_args[argc++] = ptr;
3725
3726 while (!isspace(*ptr) && *ptr)
3727 ptr++;
3728
3729 if (*ptr == '\0')
3730 break;
3731
3732 *(ptr++) = '\0';
3733 }
3734 }
3735
3736 if (!argc)
3737 return;
3738
3739 /* old H compatibility */
3740 if (sscanf(parsed_args[0], "%d", &useless_var) && returntype == NULL)
3741 {
3742 helpmod_cmd_help(sender, NULL, parsed_args[0], 1, NULL);
3743 return;
3744 }
3745
3746 {
3747 char *ostr = args, **argv = (char**)&parsed_args;
3748 hcommand *hcom = hcommand_get(parsed_args[0], huser_get_level(sender));
3749
3750 if (hcom == NULL)
3751 {
3752 if ((returntype == NULL) ||
3753 (sender->account != NULL && !(sender->account->flags & H_NO_CMD_ERROR)))
3754 helpmod_reply(sender, returntype, "Unknown command '%s', please see showcommands for a list of all commands available to you", parsed_args[0]);
3755 }
3756 else
3757 {
3758 SKIP_WORD;
3759 hcom->function(sender, returntype, ostr, argc, argv);
3760 }
3761 }
3762 }
3763
3764 #undef SKIP_WORD
3765 #undef DEFINE_HCHANNEL
3766 #undef HCHANNEL_VERIFY_AUTHORITY