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