]> jfr.im git - irc/quakenet/newserv.git/blob - request/request.c
14cdcb4918793209b3ecf44ee50f941ee68822d6
[irc/quakenet/newserv.git] / request / request.c
1 /* shroud's service request */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include "../localuser/localuser.h"
6 #include "../localuser/localuserchannel.h"
7 #include "../core/schedule.h"
8 #include "../lib/irc_string.h"
9 #include "../lib/splitline.h"
10 #include "../lib/version.h"
11 #include "../control/control.h"
12 #include "../splitlist/splitlist.h"
13 #include "request.h"
14 #include "request_block.h"
15 #include "lrequest.h"
16 #include "sqrequest.h"
17 #include "user.h"
18
19 MODULE_VERSION("");
20
21 nick *rqnick;
22 CommandTree *rqcommands;
23
24 void rq_registeruser(void);
25 void rq_handler(nick *target, int type, void **args);
26
27 int rqcmd_showcommands(void *user, int cargc, char **cargv);
28 int rqcmd_request(void *user, int cargc, char **cargv);
29 int rqcmd_requestspamscan(void *user, int cargc, char **cargv);
30 int rqcmd_addblock(void *user, int cargc, char **cargv);
31 int rqcmd_delblock(void *user, int cargc, char **cargv);
32 int rqcmd_listblocks(void *user, int cargc, char **cargv);
33 int rqcmd_stats(void *user, int cargc, char **cargv);
34 int rqcmd_requestop(void *user, int cargc, char **cargv);
35
36 int rqcmd_adduser(void *user, int cargc, char **cargv);
37 int rqcmd_deluser(void *user, int cargc, char **cargv);
38 int rqcmd_changelev(void *user, int cargc, char **cargv);
39 int rqcmd_userlist(void *user, int cargc, char **cargv);
40
41 #define min(a,b) ((a > b) ? b : a)
42
43 /* stats counters */
44 int rq_count = 0;
45 int rq_failed = 0;
46 int rq_success = 0;
47 int rq_blocked = 0;
48
49 /* log fd */
50 FILE *rq_logfd;
51
52 static int extloaded = 0;
53
54 void _init(void) {
55 if(!rq_initblocks())
56 return;
57
58 extloaded = 1;
59
60 rqcommands = newcommandtree();
61
62 addcommandtotree(rqcommands, "showcommands", RQU_ANY, 1, &rqcmd_showcommands);
63 addcommandtotree(rqcommands, "requestbot", RQU_ANY, 1, &rqcmd_request);
64 addcommandtotree(rqcommands, "requestspamscan", RQU_ANY, 1, &rqcmd_requestspamscan);
65 addcommandtotree(rqcommands, "requestop", RQU_ANY, 2, &rqcmd_requestop);
66
67 addcommandtotree(rqcommands, "addblock", RQU_ACCOUNT, 3, &rqcmd_addblock);
68 addcommandtotree(rqcommands, "delblock", RQU_ACCOUNT, 1, &rqcmd_delblock);
69 addcommandtotree(rqcommands, "listblocks", RQU_ACCOUNT, 1, &rqcmd_listblocks);
70 addcommandtotree(rqcommands, "stats", RQU_ACCOUNT, 1, &rqcmd_stats);
71
72 addcommandtotree(rqcommands, "adduser", RQU_OPER, 2, &rqcmd_adduser);
73 addcommandtotree(rqcommands, "deluser", RQU_OPER, 1, &rqcmd_deluser);
74 addcommandtotree(rqcommands, "changelev", RQU_OPER, 2, &rqcmd_changelev);
75 addcommandtotree(rqcommands, "userlist", RQU_OPER, 1, &rqcmd_userlist);
76
77 qr_initrequest();
78 ru_load();
79
80 rq_logfd = fopen(RQ_LOGFILE, "a");
81
82 scheduleoneshot(time(NULL) + 1, (ScheduleCallback)&rq_registeruser, NULL);
83 }
84
85 void _fini(void) {
86 if(!extloaded)
87 return;
88
89 deregisterlocaluser(rqnick, NULL);
90
91 deletecommandfromtree(rqcommands, "showcommands", &rqcmd_showcommands);
92 deletecommandfromtree(rqcommands, "requestbot", &rqcmd_request);
93 deletecommandfromtree(rqcommands, "requestspamscan", &rqcmd_requestspamscan);
94 deletecommandfromtree(rqcommands, "requestop", &rqcmd_requestop);
95
96 deletecommandfromtree(rqcommands, "addblock", &rqcmd_addblock);
97 deletecommandfromtree(rqcommands, "delblock", &rqcmd_delblock);
98 deletecommandfromtree(rqcommands, "listblocks", &rqcmd_listblocks);
99 deletecommandfromtree(rqcommands, "stats", &rqcmd_stats);
100
101 deletecommandfromtree(rqcommands, "adduser", &rqcmd_adduser);
102 deletecommandfromtree(rqcommands, "deluser", &rqcmd_deluser);
103 deletecommandfromtree(rqcommands, "changelev", &rqcmd_changelev);
104 deletecommandfromtree(rqcommands, "userlist", &rqcmd_userlist);
105
106 destroycommandtree(rqcommands);
107
108 rq_finiblocks();
109 qr_finirequest();
110 ru_persist();
111
112 if (rq_logfd != NULL)
113 fclose(rq_logfd);
114
115 deleteallschedules((ScheduleCallback)&rq_registeruser);
116 }
117
118 void rq_registeruser(void) {
119 channel *cp;
120
121 rqnick = registerlocaluser(RQ_REQUEST_NICK, RQ_REQUEST_USER, RQ_REQUEST_HOST,
122 RQ_REQUEST_REAL, RQ_REQUEST_AUTH,
123 UMODE_ACCOUNT | UMODE_SERVICE | UMODE_OPER,
124 rq_handler);
125
126 cp = findchannel(RQ_TLZ);
127
128 if (cp == NULL)
129 localcreatechannel(rqnick, RQ_TLZ);
130 else
131 localjoinchannel(rqnick, cp);
132 }
133
134 char *rq_longtoduration(unsigned long interval) {
135 static char buf[100];
136
137 strncpy(buf, longtoduration(interval, 0), sizeof(buf));
138
139 /* chop off last character if it's a space */
140 if (buf[strlen(buf)] == ' ')
141 buf[strlen(buf)] = '\0';
142
143 return buf;
144 }
145
146 void rq_handler(nick *target, int type, void **params) {
147 Command* cmd;
148 nick* user;
149 char* line;
150 int cargc;
151 char* cargv[30];
152
153 switch (type) {
154 case LU_PRIVMSG:
155 case LU_SECUREMSG:
156 user = params[0];
157 line = params[1];
158 cargc = splitline(line, cargv, 30, 0);
159
160 if (cargc == 0)
161 return;
162
163 cmd = findcommandintree(rqcommands, cargv[0], 1);
164
165 if (cmd == NULL) {
166 sendnoticetouser(rqnick, user, "Unknown command.");
167
168 return;
169 }
170
171 if ((cmd->level & RQU_OPER) && !IsOper(user)) {
172 sendnoticetouser(rqnick, user, "Sorry, this command is not "
173 "available to you.");
174
175 return;
176 }
177
178 if ((cmd->level & RQU_ACCOUNT) && (!IsAccount(user) || ru_getlevel(user) == 0) && !IsOper(user)) {
179 sendnoticetouser(rqnick, user, "Sorry, this command is not "
180 "available to you.");
181
182 return;
183 }
184
185 if (cargc - 1 > cmd->maxparams)
186 rejoinline(cargv[cmd->maxparams], cargc - cmd->maxparams);
187
188 /* handle the command */
189 cmd->handler((void*)user, min(cargc - 1, cmd->maxparams), &(cargv[1]));
190
191 break;
192 case LU_KILLED:
193 scheduleoneshot(time(NULL) + 5, (ScheduleCallback)&rq_registeruser, NULL);
194
195 break;
196 case LU_PRIVNOTICE:
197 qr_handle_notice(params[0], params[1]);
198
199 break;
200 }
201 }
202
203 int rqcmd_showcommands(void *user, int cargc, char **cargv) {
204 nick* np = (nick*)user;
205 int n, i;
206 Command* cmdlist[50];
207
208 n = getcommandlist(rqcommands, cmdlist, 50);
209
210 sendnoticetouser(rqnick, np, "Available commands:");
211 sendnoticetouser(rqnick, np, "-------------------");
212
213 for (i = 0; i < n; i++) {
214 if ((cmdlist[i]->level & RQU_OPER) && !IsOper(np))
215 continue;
216
217 if ((cmdlist[i]->level & RQU_ACCOUNT) && !(IsOper(np) || (IsAccount(np) && ru_getlevel(np) > 0)))
218 continue;
219
220 sendnoticetouser(rqnick, np, "%s", cmdlist[i]->command->content);
221 }
222
223 sendnoticetouser(rqnick, np, "End of SHOWCOMMANDS");
224
225 return 0;
226 }
227
228 int rq_genericrequestcheck(nick *np, char *channelname, channel **cp, nick **lnick, nick **qnick) {
229 unsigned long *userhand;
230 rq_block *block;
231
232 if (!IsAccount(np)) {
233 sendnoticetouser(rqnick, np, "Error: You must be authed.");
234
235 return RQ_ERROR;
236 }
237
238 *cp = findchannel(channelname);
239
240 if (*cp == NULL) {
241 sendnoticetouser(rqnick, np, "Error: Channel %s does not exist.",
242 channelname);
243
244 return RQ_ERROR;
245 }
246
247 *lnick = getnickbynick(RQ_LNICK);
248
249 if (*lnick == NULL || findserver(RQ_LSERVER) < 0) {
250 sendnoticetouser(rqnick, np, "Error: %s does not seem to be online. "
251 "Try again later.", RQ_LNICK);
252
253 return RQ_ERROR;
254 }
255
256 *qnick = getnickbynick(RQ_QNICK);
257
258 if (*qnick == NULL || findserver(RQ_QSERVER) < 0) {
259 sendnoticetouser(rqnick, np, "Error: %s does not seem to be online. "
260 "Try again later.", RQ_QNICK);
261
262 return RQ_ERROR;
263 }
264
265 userhand = getnumerichandlefromchanhash((*cp)->users, np->numeric);
266
267 if (userhand == NULL) {
268 sendnoticetouser(rqnick, np, "Error: You're not on that channel.");
269
270 return RQ_ERROR;
271 }
272
273 if ((*userhand & CUMODE_OP) == 0) {
274 sendnoticetouser(rqnick, np, "Error: You must be op'd on the channel to "
275 "request a service.");
276
277 return RQ_ERROR;
278 }
279
280 block = rq_findblock(channelname);
281
282 if (block != NULL) {
283 /* only say when block expires if <7 days */
284 if ( block->expires < getnettime() + 3600 * 24 * 7) {
285 sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
286 "service to this channel. Keep waiting for at least %s before you try again.",
287 rq_longtoduration(block->expires - getnettime()));
288 /* give them another 5 minutes to think about it */
289 block->expires += 300;
290 rq_saveblocks();
291 } else {
292 sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
293 "service to this channel.");
294 }
295 sendnoticetouser(rqnick, np, "Reason: %s", block->reason->content);
296
297 rq_blocked++;
298
299 return RQ_ERROR;
300 }
301
302 block = rq_findblock(np->authname);
303
304 /* only tell the user if the block is going to expire in the next 48 hours
305 so we can have our fun with longterm blocks.
306 the request subsystems should deal with longterm blocks on their own */
307 if (block != NULL && block->expires < getnettime() + 3600 * 24 * 2) {
308 sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
309 "service. Keep waiting for at least %s before you try again.",
310 rq_longtoduration(block->expires - getnettime()));
311
312 sendnoticetouser(rqnick, np, "Reason: %s", block->reason->content);
313
314 /* give them another 5 minutes to think about it */
315 block->expires += 300;
316 rq_saveblocks();
317
318 rq_blocked++;
319
320 return RQ_ERROR;
321 }
322
323 return RQ_OK;
324 }
325
326 int rqcmd_request(void *user, int cargc, char **cargv) {
327 nick *np = (nick*)user;
328 nick *lnick, *qnick;
329 unsigned long *lhand, *qhand;
330 channel *cp;
331 int retval;
332 time_t now_ts;
333 char now[50];
334
335 if (cargc < 1) {
336 sendnoticetouser(rqnick, np, "Syntax: requestbot <#channel>");
337
338 return RQ_ERROR;
339 }
340
341 rq_count++;
342
343 if (rq_genericrequestcheck(np, cargv[0], &cp, &lnick, &qnick) == RQ_ERROR) {
344 rq_failed++;
345
346 return RQ_ERROR;
347 }
348
349 lhand = getnumerichandlefromchanhash(cp->users, lnick->numeric);
350
351 qhand = getnumerichandlefromchanhash(cp->users, qnick->numeric);
352
353 if (qhand != NULL) {
354 sendnoticetouser(rqnick, np, "Error: %s is already on that channel.", RQ_QNICK);
355
356 rq_failed++;
357
358 return RQ_ERROR;
359 }
360
361 retval = RQ_ERROR;
362
363 if (lhand == NULL && qhand == NULL) {
364 /* try 'instant' Q request */
365 retval = qr_instantrequestq(np, cp);
366 }
367
368 if (retval == RQ_ERROR) {
369 if (lhand == NULL) {
370 /* user 'wants' L */
371
372 retval = lr_requestl(rqnick, np, cp, lnick);
373
374 if (rq_logfd != NULL) {
375 now[0] = '\0';
376 now_ts = time(NULL);
377 strftime(now, sizeof(now), "%c", localtime(&now_ts));
378
379 fprintf(rq_logfd, "%s: request (%s) for %s from %s: Request was %s.\n", now, RQ_LNICK, cp->index->name->content, np->nick, (retval == RQ_OK) ? "accepted" : "denied");
380 fflush(rq_logfd);
381 }
382 } else {
383 /* user 'wants' Q */
384
385 retval = qr_requestq(rqnick, np, cp, lnick, qnick);
386 }
387 }
388
389 if (retval == RQ_ERROR)
390 rq_failed++;
391 else if (retval == RQ_OK)
392 rq_success++;
393
394 return retval;
395 }
396
397 int rqcmd_requestspamscan(void *user, int cargc, char **cargv) {
398 nick *np = (nick*)user;
399 channel *cp;
400 nick *lnick, *qnick, *snick;
401 unsigned long *lhand, *qhand, *shand;
402 int retval;
403
404 if (cargc < 1) {
405 sendnoticetouser(rqnick, np, "Syntax: requestspamscan <#channel>");
406
407 return RQ_ERROR;
408 }
409
410 rq_count++;
411
412 if (rq_genericrequestcheck(np, cargv[0], &cp, &lnick, &qnick) == RQ_ERROR) {
413 rq_failed++;
414
415 return RQ_ERROR;
416 }
417
418 snick = getnickbynick(RQ_SNICK);
419
420 if (snick == NULL || findserver(RQ_SSERVER) < 0) {
421 sendnoticetouser(rqnick, np, "Error: %s does not seem to be online. "
422 "Try again later.", RQ_SNICK);
423
424 rq_failed++;
425
426 return RQ_ERROR;
427 }
428
429 /* does the user already have S on that channel? */
430 shand = getnumerichandlefromchanhash(cp->users, snick->numeric);
431
432 if (shand != NULL) {
433 sendnoticetouser(rqnick, np, "Error: %s is already on that channel.", RQ_SNICK);
434
435 rq_failed++;
436
437 return RQ_ERROR;
438 }
439
440 /* we need either L or Q */
441 lhand = getnumerichandlefromchanhash(cp->users, lnick->numeric);
442 qhand = getnumerichandlefromchanhash(cp->users, qnick->numeric);
443
444 if (lhand || qhand) {
445 /* great, now try to request */
446 retval = qr_requests(rqnick, np, cp, lnick, qnick);
447
448 if (retval == RQ_OK)
449 rq_success++;
450 else if (retval == RQ_ERROR)
451 rq_failed++;
452
453 return retval;
454 } else {
455 /* channel apparently doesn't have L or Q */
456
457 sendnoticetouser(rqnick, np, "Error: You need %s or %s in order to be "
458 "able to request %s.", RQ_LNICK, RQ_QNICK, RQ_SNICK);
459
460 rq_failed++;
461
462 return RQ_ERROR;
463 }
464 }
465
466 int rqcmd_requestop(void *source, int cargc, char **cargv) {
467 nick *np2, *np = (nick *)source;
468 nick *user = np;
469 channel *cp;
470 int ret, a, count;
471 unsigned long *hand;
472 modechanges changes;
473
474 if (cargc < 1) {
475 sendnoticetouser(rqnick, np, "Syntax: requestop <#channel> [nick]");
476
477 return CMD_ERROR;
478 }
479
480 cp = findchannel(cargv[0]);
481
482 if (cp == NULL) {
483 sendnoticetouser(rqnick, np, "Error: No such channel.");
484
485 return CMD_ERROR;
486 }
487
488 if (cargc > 1) {
489 user = getnickbynick(cargv[1]);
490
491 if (!user) {
492 sendnoticetouser(rqnick, np, "Error: No such user.");
493
494 return CMD_ERROR;
495 }
496 }
497
498 if (getnettime() - np->timestamp < 300) {
499 sendnoticetouser(rqnick, np, "Error: You connected %s ago. To"
500 " request ops you must have been on the network for"
501 " at least 5 minutes.",
502 rq_longtoduration(getnettime() - np->timestamp));
503
504 return CMD_ERROR;
505 }
506
507 if (getnettime() - user->timestamp < 300) {
508 sendnoticetouser(rqnick, np, "Error: The nick you requested op for"
509 " connected %s ago. To request op, it must have"
510 "been on the network for at least 5 minutes.",
511 rq_longtoduration(getnettime() - user->timestamp));
512
513 return CMD_ERROR;
514 }
515
516 hand = getnumerichandlefromchanhash(cp->users, user->numeric);
517
518 if (!hand) {
519 sendnoticetouser(rqnick, np, "Error: User %s is not on channel %s.", user->nick, cargv[0]);
520
521 return CMD_ERROR;
522 }
523
524
525 count = 0;
526
527 localsetmodeinit(&changes, cp, rqnick);
528
529 /* reop any services first */
530 for(a=0;a<cp->users->hashsize;a++) {
531 if(cp->users->content[a] != nouser) {
532 np2 = getnickbynumeric(cp->users->content[a]);
533
534 if (IsService(np2) && (np2->nick[1] == '\0') && !(cp->users->content[a] & CUMODE_OP)) {
535 localdosetmode_nick(&changes, np2, MC_OP);
536 count++;
537 }
538 }
539 }
540
541 localsetmodeflush(&changes, 1);
542
543 if (count > 0) {
544 if (count == 1)
545 sendnoticetouser(rqnick, np, "1 service was reopped.");
546 else
547 sendnoticetouser(rqnick, np, "%d services were reopped.", count);
548
549 return CMD_ERROR;
550 }
551
552 for (a=0;a<cp->users->hashsize;a++) {
553 if ((cp->users->content[a] != nouser) && (cp->users->content[a] & CUMODE_OP)) {
554 sendnoticetouser(rqnick, np, "There are ops on channel %s. This command can only be"
555 " used if there are no ops.", cargv[0]);
556
557 return CMD_ERROR;
558 }
559 }
560
561 if (sp_countsplitservers() > 0) {
562 sendnoticetouser(rqnick, np, "One or more servers are currently split. Wait until the"
563 " netsplit is over and try again.");
564
565 return CMD_ERROR;
566 }
567
568 if (cf_wouldreop(user, cp)) {
569 localsetmodeinit(&changes, cp, rqnick);
570 localdosetmode_nick(&changes, user, MC_OP);
571 localsetmodeflush(&changes, 1);
572
573 sendnoticetouser(rqnick, np, "Chanfix opped you on the specified channel.");
574 } else {
575 ret = cf_fixchannel(cp);
576
577 if (ret == CFX_NOUSERSAVAILABLE)
578 sendnoticetouser(rqnick, np, "Chanfix knows regular ops for that channel. They will"
579 " be opped when they return.");
580 else
581 sendnoticetouser(rqnick, np, "Chanfix has opped known ops for that channel.");
582 }
583
584 return CMD_OK;
585
586 }
587
588 int rqcmd_addblock(void *user, int cargc, char **cargv) {
589 nick *np = (nick*)user;
590 rq_block *block;
591 time_t expires;
592 char *account;
593 int level = ru_getlevel(np);
594
595 if (level < 20) {
596 sendnoticetouser(rqnick, np, "You do not have access to this command.");
597
598 return RQ_ERROR;
599 }
600
601 if (cargc < 3) {
602 sendnoticetouser(rqnick, np, "Syntax: addblock <mask> <duration> <reason>");
603
604 return RQ_ERROR;
605 }
606
607 block = rq_findblock(cargv[0]);
608
609 if (block != NULL) {
610 sendnoticetouser(rqnick, np, "That mask is already blocked by %s "
611 "(reason: %s).", block->creator->content, block->reason->content);
612
613 return RQ_ERROR;
614 }
615
616 if (IsAccount(np))
617 account = np->authname;
618 else
619 account = "unknown";
620
621 expires = getnettime() + durationtolong(cargv[1]);
622
623 if (expires > getnettime() + RQU_HELPER_MAXEXPIRE && level < 30) {
624 sendnoticetouser(rqnick, np, "Maximum expiry time is %s.", rq_longtoduration(RQU_HELPER_MAXEXPIRE));
625
626 return RQ_ERROR;
627 }
628
629 rq_addblock(cargv[0], cargv[2], account, 0, expires);
630
631 sendnoticetouser(rqnick, np, "Blocked channels/accounts matching '%s' from "
632 "requesting a service.", cargv[0]);
633
634 return RQ_OK;
635 }
636
637 int rqcmd_delblock(void *user, int cargc, char **cargv) {
638 nick *np = (nick*)user;
639 int result, level;
640 rq_block *block;
641
642 level = ru_getlevel(np);
643
644 if (level < 20) {
645 sendnoticetouser(rqnick, np, "You do not have access to this command.");
646
647 return RQ_ERROR;
648 }
649
650 if (cargc < 1) {
651 sendnoticetouser(rqnick, np, "Syntax: delblock <mask>");
652
653 return RQ_ERROR;
654 }
655
656 block = rq_findblock(cargv[0]);
657
658 if (block != NULL && level < 50) {
659 if (ircd_strcmp(block->creator->content, np->authname) != 0) {
660 sendnoticetouser(rqnick, np, "This block was created by someone else. You cannot remove it.");
661
662 return RQ_ERROR;
663 }
664 }
665
666 result = rq_removeblock(cargv[0]);
667
668 if (result > 0) {
669 sendnoticetouser(rqnick, np, "Block for '%s' was removed.", cargv[0]);
670
671 return RQ_OK;
672 } else {
673 sendnoticetouser(rqnick, np, "There is no such block.");
674
675 return RQ_OK;
676 }
677 }
678
679 int rqcmd_listblocks(void *user, int cargc, char **cargv) {
680 nick *np = (nick*)user;
681 rq_block block;
682 int i, level;
683
684 level = ru_getlevel(np);
685
686 if (level < 10) {
687 sendnoticetouser(rqnick, np, "You do not have access to this command.");
688
689 return RQ_ERROR;
690 }
691
692 sendnoticetouser(rqnick, np, "Mask By Expires"
693 " Reason");
694
695 for (i = 0; i < rqblocks.cursi; i++) {
696 block = ((rq_block*)rqblocks.content)[i];
697
698 if (block.expires != 0 && block.expires < getnettime())
699 continue; /* ignore blocks which have already expired,
700 rq_findblock will deal with them later on */
701
702 if (cargc < 1 || match2strings(block.pattern->content, cargv[0]))
703 sendnoticetouser(rqnick, np, "%-11s %-9s %-25s %s",
704 block.pattern->content, block.creator->content,
705 rq_longtoduration(block.expires - getnettime()),
706 block.reason->content);
707 }
708
709 sendnoticetouser(rqnick, np, "--- End of blocklist");
710
711 return RQ_OK;
712 }
713
714 int rqcmd_stats(void *user, int cargc, char **cargv) {
715 nick *np = (nick*)user;
716 int level = ru_getlevel(np);
717
718 if (level < 10) {
719 sendnoticetouser(rqnick, np, "You do not have access to this command.");
720
721 return RQ_ERROR;
722 }
723
724 sendnoticetouser(rqnick, np, "Total requests: %d", rq_count);
725 sendnoticetouser(rqnick, np, "Successful requests: %d", rq_success);
726 sendnoticetouser(rqnick, np, "Failed requests: %d", rq_failed);
727 sendnoticetouser(rqnick, np, "- Blocked: %d", rq_blocked);
728
729 lr_requeststats(rqnick, np);
730 qr_requeststats(rqnick, np);
731
732 return RQ_OK;
733 }
734
735 int rqcmd_adduser(void *user, int cargc, char **cargv) {
736 nick *np = (nick*)user;
737 int result, level;
738
739 if (cargc < 2) {
740 sendnoticetouser(rqnick, np, "Syntax: adduser <account> <level>");
741
742 return RQ_ERROR;
743 }
744
745 level = atoi(cargv[1]);
746
747 if (level <= 0) {
748 sendnoticetouser(rqnick, np, "Level must be a positive integer.");
749
750 return RQ_ERROR;
751 }
752
753 result = ru_create(cargv[0], level);
754
755 if (result) {
756 sendnoticetouser(rqnick, np, "User '%s' was added with level '%d'.", cargv[0], level);
757
758 return RQ_OK;
759 } else {
760 sendnoticetouser(rqnick, np, "Something strange happened. Contact shroud.");
761
762 return RQ_ERROR;
763 }
764 }
765
766 int rqcmd_deluser(void *user, int cargc, char **cargv) {
767 nick *np = (nick*)user;
768 int level;
769
770 if (cargc < 1) {
771 sendnoticetouser(rqnick, np, "Syntax: deluser <account>");
772
773 return RQ_ERROR;
774 }
775
776 level = ru_getlevel_str(cargv[0]);
777
778 if (level <= 0) {
779 sendnoticetouser(rqnick, np, "There is no such user.");
780
781 return RQ_ERROR;
782 }
783
784 ru_destroy(cargv[0]);
785
786 sendnoticetouser(rqnick, np, "Done.");
787
788 return RQ_OK;
789 }
790
791 int rqcmd_changelev(void *user, int cargc, char **cargv) {
792 nick *np = (nick*)user;
793 int result, level;
794
795 if (cargc < 2) {
796 sendnoticetouser(rqnick, np, "Syntax: changelev <account> <level>");
797
798 return RQ_ERROR;
799 }
800
801 level = atoi(cargv[1]);
802
803 if (level <= 0) {
804 sendnoticetouser(rqnick, np, "Level must be a positive integer.");
805
806 return RQ_ERROR;
807 }
808
809 if (ru_getlevel_str(cargv[0]) <= 0) {
810 sendnoticetouser(rqnick, np, "Unknown user.");
811
812 return RQ_ERROR;
813 }
814
815 result = ru_setlevel(cargv[0], level);
816
817 if (result != 0) {
818 sendnoticetouser(rqnick, np, "Done.");
819
820 return RQ_OK;
821 } else {
822 sendnoticetouser(rqnick, np, "Something strange happened. Contact shroud.");
823
824 return RQ_ERROR;
825 }
826 }
827
828 int rqcmd_userlist(void *user, int cargc, char **cargv) {
829 nick *np = (nick*)user;
830 r_user_t *userp = r_userlist;
831
832 sendnoticetouser(rqnick, np, "User Level");
833
834 while (userp) {
835 sendnoticetouser(rqnick, np, "%s %d", userp->name, userp->level);
836 userp = userp->next;
837 }
838
839 sendnoticetouser(rqnick, np, "--- End of USERS.");
840
841 return RQ_OK;
842 }
843