]>
jfr.im git - irc/quakenet/newserv.git/blob - request/request.c
1 /* shroud's service request */
4 #include "../localuser/localuser.h"
5 #include "../localuser/localuserchannel.h"
6 #include "../core/schedule.h"
7 #include "../lib/irc_string.h"
8 #include "../lib/splitline.h"
9 #include "../control/control.h"
11 #include "request_block.h"
13 #include "sqrequest.h"
17 CommandTree
*rqcommands
;
19 void rq_registeruser(void);
20 void rq_handler(nick
*target
, int type
, void **args
);
22 int rqcmd_showcommands(void *user
, int cargc
, char **cargv
);
23 int rqcmd_request(void *user
, int cargc
, char **cargv
);
24 int rqcmd_requestspamscan(void *user
, int cargc
, char **cargv
);
25 int rqcmd_addblock(void *user
, int cargc
, char **cargv
);
26 int rqcmd_delblock(void *user
, int cargc
, char **cargv
);
27 int rqcmd_listblocks(void *user
, int cargc
, char **cargv
);
28 int rqcmd_stats(void *user
, int cargc
, char **cargv
);
29 int rqcmd_legacyrequest(void *user
, int cargc
, char **cargv
);
31 int rqcmd_adduser(void *user
, int cargc
, char **cargv
);
32 int rqcmd_deluser(void *user
, int cargc
, char **cargv
);
33 int rqcmd_changelev(void *user
, int cargc
, char **cargv
);
34 int rqcmd_userlist(void *user
, int cargc
, char **cargv
);
36 #define min(a,b) ((a > b) ? b : a)
45 rqcommands
= newcommandtree();
47 addcommandtotree(rqcommands
, "showcommands", RQU_ANY
, 1, &rqcmd_showcommands
);
48 addcommandtotree(rqcommands
, "requestbot", RQU_ANY
, 1, &rqcmd_request
);
49 addcommandtotree(rqcommands
, "requestspamscan", RQU_ANY
, 1, &rqcmd_requestspamscan
);
50 addcommandtotree(rqcommands
, "addblock", RQU_ACCOUNT
, 3, &rqcmd_addblock
);
51 addcommandtotree(rqcommands
, "delblock", RQU_ACCOUNT
, 1, &rqcmd_delblock
);
52 addcommandtotree(rqcommands
, "listblocks", RQU_ACCOUNT
, 1, &rqcmd_listblocks
);
53 addcommandtotree(rqcommands
, "stats", RQU_ACCOUNT
, 1, &rqcmd_stats
);
55 addcommandtotree(rqcommands
, "adduser", RQU_OPER
, 2, &rqcmd_adduser
);
56 addcommandtotree(rqcommands
, "deluser", RQU_OPER
, 1, &rqcmd_deluser
);
57 addcommandtotree(rqcommands
, "changelev", RQU_OPER
, 2, &rqcmd_changelev
);
58 addcommandtotree(rqcommands
, "userlist", RQU_OPER
, 1, &rqcmd_userlist
);
60 /* old legacy stuff */
61 addcommandtotree(rqcommands
, "requestq", RQU_ANY
, 1, &rqcmd_legacyrequest
);
67 scheduleoneshot(time(NULL
) + 1, (ScheduleCallback
)&rq_registeruser
, NULL
);
71 deregisterlocaluser(rqnick
, NULL
);
73 deletecommandfromtree(rqcommands
, "showcommands", &rqcmd_showcommands
);
74 deletecommandfromtree(rqcommands
, "requestbot", &rqcmd_request
);
75 deletecommandfromtree(rqcommands
, "requestspamscan", &rqcmd_requestspamscan
);
76 deletecommandfromtree(rqcommands
, "addblock", &rqcmd_addblock
);
77 deletecommandfromtree(rqcommands
, "delblock", &rqcmd_delblock
);
78 deletecommandfromtree(rqcommands
, "listblocks", &rqcmd_listblocks
);
79 deletecommandfromtree(rqcommands
, "stats", &rqcmd_stats
);
81 deletecommandfromtree(rqcommands
, "adduser", &rqcmd_adduser
);
82 deletecommandfromtree(rqcommands
, "deluser", &rqcmd_deluser
);
83 deletecommandfromtree(rqcommands
, "changelev", &rqcmd_changelev
);
84 deletecommandfromtree(rqcommands
, "userlist", &rqcmd_userlist
);
87 /* old legacy stuff */
88 deletecommandfromtree(rqcommands
, "requestq", &rqcmd_legacyrequest
);
90 destroycommandtree(rqcommands
);
96 deleteallschedules((ScheduleCallback
)&rq_registeruser
);
99 void rq_registeruser(void) {
102 rqnick
= registerlocaluser(RQ_REQUEST_NICK
, RQ_REQUEST_USER
, RQ_REQUEST_HOST
,
103 RQ_REQUEST_REAL
, RQ_REQUEST_AUTH
,
104 UMODE_ACCOUNT
| UMODE_SERVICE
| UMODE_OPER
,
107 cp
= findchannel(RQ_TLZ
);
110 localcreatechannel(rqnick
, RQ_TLZ
);
112 localjoinchannel(rqnick
, cp
);
115 char *rq_longtoduration(unsigned long interval
) {
116 static char buf
[100];
118 strncpy(buf
, longtoduration(interval
, 0), sizeof(buf
));
120 /* chop off last character if it's a space */
121 if (buf
[strlen(buf
)] == ' ')
122 buf
[strlen(buf
)] = '\0';
127 void rq_handler(nick
*target
, int type
, void **params
) {
139 cargc
= splitline(line
, cargv
, 30, 0);
144 cmd
= findcommandintree(rqcommands
, cargv
[0], 1);
147 sendnoticetouser(rqnick
, user
, "Unknown command.");
152 if ((cmd
->level
& RQU_OPER
) && !IsOper(user
)) {
153 sendnoticetouser(rqnick
, user
, "Sorry, this command is not "
154 "available to you.");
159 if ((cmd
->level
& RQU_ACCOUNT
) && (!IsAccount(user
) || ru_getlevel(user
) == 0) && !IsOper(user
)) {
160 sendnoticetouser(rqnick
, user
, "Sorry, this command is not "
161 "available to you.");
166 if (cargc
- 1 > cmd
->maxparams
)
167 rejoinline(cargv
[cmd
->maxparams
], cargc
- cmd
->maxparams
);
169 /* handle the command */
170 cmd
->handler((void*)user
, min(cargc
- 1, cmd
->maxparams
), &(cargv
[1]));
174 scheduleoneshot(time(NULL
) + 5, (ScheduleCallback
)&rq_registeruser
, NULL
);
178 qr_handlenotice(params
[0], params
[1]);
184 int rqcmd_showcommands(void *user
, int cargc
, char **cargv
) {
186 Command
* cmdlist
[50];
188 n
= getcommandlist(rqcommands
, cmdlist
, 50);
190 sendnoticetouser(rqnick
, (nick
*)user
, "Available commands:");
191 sendnoticetouser(rqnick
, (nick
*)user
, "-------------------");
193 for (i
= 0; i
< n
; i
++) {
194 if (((cmdlist
[i
]->level
& RQU_OPER
) == 0 || IsOper((nick
*)user
)) &&
195 (((cmdlist
[i
]->level
& RQU_ACCOUNT
) == 0 || (IsOper((nick
*)user
) || (IsAccount((nick
*)user
)) && ru_getlevel((nick
*)user
) > 0))))
196 sendnoticetouser(rqnick
, (nick
*)user
, "%s", cmdlist
[i
]->command
->content
);
199 sendnoticetouser(rqnick
, (nick
*)user
, "End of SHOWCOMMANDS");
204 int rq_genericrequestcheck(nick
*np
, char *channelname
, channel
**cp
, nick
**lnick
, nick
**qnick
) {
205 unsigned long *userhand
;
208 if (!IsAccount(np
)) {
209 sendnoticetouser(rqnick
, np
, "Error: You must be authed.");
214 *cp
= findchannel(channelname
);
217 sendnoticetouser(rqnick
, np
, "Error: Channel %s does not exist.",
223 *lnick
= getnickbynick(RQ_LNICK
);
225 if (*lnick
== NULL
|| findserver(RQ_LSERVER
) < 0) {
226 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
227 "Try again later.", RQ_LNICK
);
232 *qnick
= getnickbynick(RQ_QNICK
);
234 if (*qnick
== NULL
|| findserver(RQ_QSERVER
) < 0) {
235 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
236 "Try again later.", RQ_QNICK
);
241 userhand
= getnumerichandlefromchanhash((*cp
)->users
, np
->numeric
);
243 if (userhand
== NULL
) {
244 sendnoticetouser(rqnick
, np
, "Error: You're not on that channel.");
249 if ((*userhand
& CUMODE_OP
) == 0) {
250 sendnoticetouser(rqnick
, np
, "Error: You must be op'd on the channel to "
251 "request a service.");
256 block
= rq_findblock(channelname
);
259 sendnoticetouser(rqnick
, np
, "Error: You are not allowed to request a "
260 "service to this channel.");
261 sendnoticetouser(rqnick
, np
, "Reason: %s", block
->reason
->content
);
268 block
= rq_findblock(np
->authname
);
270 /* only tell the user if the block is going to expire in the next 48 hours
271 so we can have our fun with longterm blocks.
272 the request subsystems should deal with longterm blocks on their own */
273 if (block
!= NULL
&& block
->expires
< getnettime() + 3600 * 24 * 2) {
274 sendnoticetouser(rqnick
, np
, "Error: You are not allowed to request a "
275 "service. Keep waiting for at least %s before you try again.",
276 rq_longtoduration(block
->expires
- getnettime()));
278 sendnoticetouser(rqnick
, np
, "Reason: %s", block
->reason
->content
);
280 /* give them another 5 minutes to think about it */
281 block
->expires
+= 300;
292 int rqcmd_request(void *user
, int cargc
, char **cargv
) {
293 nick
*np
= (nick
*)user
;
295 unsigned long *lhand
, *qhand
;
300 sendnoticetouser(rqnick
, np
, "Syntax: requestbot <#channel>");
307 if (rq_genericrequestcheck(np
, cargv
[0], &cp
, &lnick
, &qnick
) == RQ_ERROR
) {
313 lhand
= getnumerichandlefromchanhash(cp
->users
, lnick
->numeric
);
315 qhand
= getnumerichandlefromchanhash(cp
->users
, qnick
->numeric
);
318 sendnoticetouser(rqnick
, np
, "Error: %s is already on that channel.", RQ_QNICK
);
327 if (lhand
== NULL
&& qhand
== NULL
) {
328 /* try 'instant' Q request */
329 retval
= qr_instantrequestq(np
, cp
);
332 if (retval
== RQ_ERROR
) {
336 retval
= lr_requestl(rqnick
, np
, cp
, lnick
);
338 logcp
= findchannel(RQ_LOGCHANNEL
);
341 sendmessagetochannel(rqnick
, logcp
, "request (%s) for %s from %s: Request was %s.", RQ_LNICK
, cp
->index
->name
->content
, np
->nick
, (retval
== RQ_OK
) ? "accepted" : "denied");
346 retval
= qr_requestq(rqnick
, np
, cp
, lnick
, qnick
);
350 if (retval
== RQ_ERROR
)
352 else if (retval
== RQ_OK
)
358 int rqcmd_requestspamscan(void *user
, int cargc
, char **cargv
) {
359 nick
*np
= (nick
*)user
;
361 nick
*lnick
, *qnick
, *snick
;
362 unsigned long *lhand
, *qhand
, *shand
;
366 sendnoticetouser(rqnick
, np
, "Syntax: requestspamscan <#channel>");
373 if (rq_genericrequestcheck(np
, cargv
[0], &cp
, &lnick
, &qnick
) == RQ_ERROR
) {
379 snick
= getnickbynick(RQ_SNICK
);
381 if (snick
== NULL
|| findserver(RQ_SSERVER
) < 0) {
382 sendnoticetouser(rqnick
, np
, "Error: %s does not seem to be online. "
383 "Try again later.", RQ_SNICK
);
390 /* does the user already have S on that channel? */
391 shand
= getnumerichandlefromchanhash(cp
->users
, snick
->numeric
);
394 sendnoticetouser(rqnick
, np
, "Error: %s is already on that channel.", RQ_SNICK
);
401 /* we need either L or Q */
402 lhand
= getnumerichandlefromchanhash(cp
->users
, lnick
->numeric
);
403 qhand
= getnumerichandlefromchanhash(cp
->users
, qnick
->numeric
);
405 if (lhand
|| qhand
) {
406 /* great, now try to request */
407 retval
= qr_requests(rqnick
, np
, cp
, lnick
, qnick
);
411 else if (retval
== RQ_ERROR
)
416 /* channel apparently doesn't have L or Q */
418 sendnoticetouser(rqnick
, np
, "Error: You need %s or %s in order to be "
419 "able to request %s.", RQ_LNICK
, RQ_QNICK
, RQ_SNICK
);
427 int rqcmd_addblock(void *user
, int cargc
, char **cargv
) {
428 nick
*np
= (nick
*)user
;
432 int level
= ru_getlevel(np
);
435 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
441 sendnoticetouser(rqnick
, np
, "Syntax: addblock <mask> <duration> <reason>");
446 block
= rq_findblock(cargv
[0]);
449 sendnoticetouser(rqnick
, np
, "That mask is already blocked by %s "
450 "(reason: %s).", block
->creator
->content
, block
->reason
->content
);
456 account
= np
->authname
;
460 expires
= getnettime() + durationtolong(cargv
[1]);
462 if (expires
> getnettime() + RQU_HELPER_MAXEXPIRE
&& level
< 30) {
463 sendnoticetouser(rqnick
, np
, "Maximum expiry time is %s.", rq_longtoduration(RQU_HELPER_MAXEXPIRE
));
468 rq_addblock(cargv
[0], cargv
[2], account
, 0, expires
);
470 sendnoticetouser(rqnick
, np
, "Blocked channels/accounts matching '%s' from "
471 "requesting a service.", cargv
[0]);
476 int rqcmd_delblock(void *user
, int cargc
, char **cargv
) {
477 nick
*np
= (nick
*)user
;
481 level
= ru_getlevel(np
);
484 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
490 sendnoticetouser(rqnick
, np
, "Syntax: delblock <mask>");
495 block
= rq_findblock(cargv
[0]);
497 if (block
!= NULL
&& level
< 50) {
498 if (ircd_strcmp(block
->creator
->content
, np
->authname
) != 0) {
499 sendnoticetouser(rqnick
, np
, "This block was created by someone else. You cannot remove it.");
505 result
= rq_removeblock(cargv
[0]);
508 sendnoticetouser(rqnick
, np
, "Block for '%s' was removed.", cargv
[0]);
512 sendnoticetouser(rqnick
, np
, "There is no such block.");
518 int rqcmd_listblocks(void *user
, int cargc
, char **cargv
) {
519 nick
*np
= (nick
*)user
;
523 level
= ru_getlevel(np
);
526 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
531 sendnoticetouser(rqnick
, np
, "Mask By Expires"
534 for (i
= 0; i
< rqblocks
.cursi
; i
++) {
535 block
= ((rq_block
*)rqblocks
.content
)[i
];
537 if (block
.expires
!= 0 && block
.expires
< getnettime())
538 continue; /* ignore blocks which have already expired,
539 rq_findblock will deal with them later on */
541 if (cargc
< 1 || match2strings(block
.pattern
->content
, cargv
[0]))
542 sendnoticetouser(rqnick
, np
, "%-11s %-9s %-25s %s",
543 block
.pattern
->content
, block
.creator
->content
,
544 rq_longtoduration(block
.expires
- getnettime()),
545 block
.reason
->content
);
548 sendnoticetouser(rqnick
, np
, "--- End of blocklist");
553 int rqcmd_stats(void *user
, int cargc
, char **cargv
) {
554 nick
*np
= (nick
*)user
;
555 int level
= ru_getlevel(np
);
558 sendnoticetouser(rqnick
, np
, "You do not have access to this command.");
563 sendnoticetouser(rqnick
, np
, "Total requests: %d", rq_count
);
564 sendnoticetouser(rqnick
, np
, "Successful requests: %d", rq_success
);
565 sendnoticetouser(rqnick
, np
, "Failed requests: %d", rq_failed
);
566 sendnoticetouser(rqnick
, np
, "- Blocked: %d", rq_blocked
);
568 lr_requeststats(rqnick
, np
);
569 qr_requeststats(rqnick
, np
);
574 int rqcmd_legacyrequest(void *user
, int cargc
, char **cargv
) {
575 nick
*np
= (nick
*)user
;
577 sendnoticetouser(rqnick
, np
, "This command is no longer valid. Please use "
578 "/msg %s REQUESTBOT #channel instead.", RQ_REQUEST_NICK
);
583 int rqcmd_adduser(void *user
, int cargc
, char **cargv
) {
584 nick
*np
= (nick
*)user
;
588 sendnoticetouser(rqnick
, np
, "Syntax: adduser <account> <level>");
593 level
= atoi(cargv
[1]);
596 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
601 result
= ru_create(cargv
[0], level
);
604 sendnoticetouser(rqnick
, np
, "User '%s' was added with level '%d'.", cargv
[0], level
);
608 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
614 int rqcmd_deluser(void *user
, int cargc
, char **cargv
) {
615 nick
*np
= (nick
*)user
;
619 sendnoticetouser(rqnick
, np
, "Syntax: deluser <account>");
624 level
= ru_getlevel_str(cargv
[0]);
627 sendnoticetouser(rqnick
, np
, "There is no such user.");
632 ru_destroy(cargv
[0]);
634 sendnoticetouser(rqnick
, np
, "Done.");
639 int rqcmd_changelev(void *user
, int cargc
, char **cargv
) {
640 nick
*np
= (nick
*)user
;
644 sendnoticetouser(rqnick
, np
, "Syntax: changelev <account> <level>");
649 level
= atoi(cargv
[1]);
652 sendnoticetouser(rqnick
, np
, "Level must be a positive integer.");
657 if (ru_getlevel_str(cargv
[0]) <= 0) {
658 sendnoticetouser(rqnick
, np
, "Unknown user.");
663 result
= ru_setlevel(cargv
[0], level
);
666 sendnoticetouser(rqnick
, np
, "Done.");
670 sendnoticetouser(rqnick
, np
, "Something strange happened. Contact shroud.");
676 int rqcmd_userlist(void *user
, int cargc
, char **cargv
) {
677 nick
*np
= (nick
*)user
;
678 r_user_t
*userp
= r_userlist
;
680 sendnoticetouser(rqnick
, np
, "User Level");
683 sendnoticetouser(rqnick
, np
, "%s %d", userp
->name
, userp
->level
);
687 sendnoticetouser(rqnick
, np
, "--- End of USERS.");