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