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