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