]>
jfr.im git - irc/quakenet/newserv.git/blob - qabot/qabot_chancommands.c
5 #include "../nick/nick.h"
6 #include "../localuser/localuserchannel.h"
7 #include "../core/hooks.h"
8 #include "../core/schedule.h"
9 #include "../lib/array.h"
10 #include "../lib/base64.h"
11 #include "../lib/irc_string.h"
12 #include "../lib/splitline.h"
16 int qabot_dochananswer ( void * np
, int cargc
, char ** cargv
) {
17 nick
* sender
= ( nick
*) np
;
18 qab_bot
* bot
= qabot_getcurrentbot ();
24 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !answer <id> <answer>" );
28 id
= strtol ( cargv
[ 0 ], NULL
, 10 );
31 if (( id
< 1 ) || ( id
> bot
-> lastquestionID
)) {
32 sendnoticetouser ( bot
-> np
, sender
, "Invalid question ID %d ." , id
);
36 for ( q
= bot
-> questions
[ id
% QUESTIONHASHSIZE
]; q
; q
= q
-> next
)
41 sendnoticetouser ( bot
-> np
, sender
, "Can't find question %d ." , id
);
45 switch ( q
-> flags
& QAQ_QSTATE
) {
47 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been answered." , id
);
51 sendnoticetouser ( bot
-> np
, sender
, "Question %d has been marked as off-topic." , id
);
55 sendnoticetouser ( bot
-> np
, sender
, "Question %d has been marked as spam." , id
);
62 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_ANSWERED
;
63 q
-> answer
= strdup ( ch
);
67 if (! bot
-> nextspam
&& ! bot
-> micnumeric
) {
68 sendmessagetochannel ( bot
-> np
, bot
-> public_chan
-> channel
, " %s asked: %s " , q
-> nick
, q
-> question
);
69 sendmessagetochannel ( bot
-> np
, bot
-> public_chan
-> channel
, " %s answers: %s " , sender
-> nick
, ch
);
74 a
= ( qab_answer
*) malloc ( sizeof ( qab_answer
));
76 strncpy ( a
-> nick
, sender
-> nick
, NICKLEN
);
77 a
-> nick
[ NICKLEN
] = '\0' ;
78 a
-> next
= bot
-> answers
;
81 sendnoticetouser ( bot
-> np
, sender
, "Can't send your answer right now. Answer was stored and will be sent later on." );
85 sendnoticetouser ( bot
-> np
, sender
, "Answer to question %d has been sent and stored." , id
);
90 int qabot_dochanblock ( void * np
, int cargc
, char ** cargv
) {
91 nick
* sender
= ( nick
*) np
;
92 qab_bot
* bot
= qabot_getcurrentbot ();
96 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !block [-q|-t] <account|mask>" );
101 if (! ircd_strncmp ( cargv
[ 0 ], "-q" , 2 )) {
103 char * target
= cargv
[ 1 ];
105 if (* target
== '#' ) {
108 if ( strchr ( target
, '*' ) || strchr ( target
, '?' )) {
109 sendnoticetouser ( bot
-> np
, sender
, "Wildcard account blocks are not supported." );
116 if (!( tnick
= getnickbynick ( target
))) {
117 sendnoticetouser ( bot
-> np
, sender
, "Couldn't find user %s ." , target
);
121 if (! IsAccount ( tnick
)) {
122 sendnoticetouser ( bot
-> np
, sender
, " %s is not authed." , tnick
-> nick
);
126 target
= tnick
-> authname
;
129 b
= ( qab_block
*) malloc ( sizeof ( qab_block
));
130 b
-> type
= QABBLOCK_ACCOUNT
;
131 b
-> created
= time ( 0 );
132 strncpy ( b
-> creator
, IsAccount ( sender
) ? sender
-> authname
: "UNKNOWN" , ACCOUNTLEN
);
133 b
-> creator
[ ACCOUNTLEN
] = '\0' ;
134 b
-> blockstr
= strdup ( target
);
136 b
-> next
= bot
-> blocks
;
138 bot
-> blocks
-> prev
= b
;
142 sendnoticetouser ( bot
-> np
, sender
, "Now blocking all messages from users with accountname %s ." , target
);
144 if ( bot
-> flags
& QAB_BLOCKMARK
) {
146 int i
, spamqcount
= 0 ;
149 for ( i
= 0 ; i
< QUESTIONHASHSIZE
; i
++) {
150 for ( q
= bot
-> questions
[ i
]; q
; q
= q
-> next
) {
151 if (( q
-> flags
& QAQ_QSTATE
) != QAQ_NEW
)
154 if (!( qnick
= getnickbynumeric ( q
-> numeric
)))
157 if (! IsAccount ( qnick
))
160 if ( ircd_strcmp ( qnick
-> authname
, b
-> blockstr
))
163 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_SPAM
;
168 sendnoticetouser ( bot
-> np
, sender
, "Block caused %d message %s to be marked as spam." , spamqcount
, ( spamqcount
== 1 ) ? "" : "s" );
171 else if (! ircd_strncmp ( cargv
[ 0 ], "-t" , 2 )) {
173 char * mask
= cargv
[ 1 ];
175 b
= ( qab_block
*) malloc ( sizeof ( qab_block
));
176 b
-> type
= QABBLOCK_TEXT
;
177 b
-> created
= time ( 0 );
178 strncpy ( b
-> creator
, sender
-> authname
, ACCOUNTLEN
);
179 b
-> creator
[ ACCOUNTLEN
] = '\0' ;
180 b
-> blockstr
= strdup ( mask
);
182 b
-> next
= bot
-> blocks
;
184 bot
-> blocks
-> prev
= b
;
188 sendnoticetouser ( bot
-> np
, sender
, "Now blocking all questions which match %s ." , mask
);
190 if ( bot
-> flags
& QAB_BLOCKMARK
) {
192 int i
, spamqcount
= 0 ;
194 for ( i
= 0 ; i
< QUESTIONHASHSIZE
; i
++) {
195 for ( q
= bot
-> questions
[ i
]; q
; q
= q
-> next
) {
196 if (( q
-> flags
& QAQ_QSTATE
) != QAQ_NEW
)
199 if ( match ( b
-> blockstr
, q
-> question
))
202 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_SPAM
;
207 sendnoticetouser ( bot
-> np
, sender
, "Block caused %d message %s to be marked as spam." , spamqcount
, ( spamqcount
== 1 ) ? "" : "s" );
211 sendnoticetouser ( bot
-> np
, sender
, "Invalid flag." );
217 char * mask
= cargv
[ 0 ];
219 if (! strchr ( mask
, '@' ) || ! strchr ( mask
, '!' )) {
220 sendnoticetouser ( bot
-> np
, sender
, " %s is not a valid hostmask." , mask
);
224 b
= ( qab_block
*) malloc ( sizeof ( qab_block
));
225 b
-> type
= QABBLOCK_HOST
;
226 b
-> created
= time ( 0 );
227 strncpy ( b
-> creator
, sender
-> authname
, ACCOUNTLEN
);
228 b
-> creator
[ ACCOUNTLEN
] = '\0' ;
229 b
-> blockstr
= strdup ( mask
);
231 b
-> next
= bot
-> blocks
;
233 bot
-> blocks
-> prev
= b
;
237 sendnoticetouser ( bot
-> np
, sender
, "Now blocking all messages from users with a hostmask matching %s ." , mask
);
239 if ( bot
-> flags
& QAB_BLOCKMARK
) {
241 int i
, spamqcount
= 0 ;
243 char hostbuf
[ NICKLEN
+ USERLEN
+ HOSTLEN
+ 3 ];
245 for ( i
= 0 ; i
< QUESTIONHASHSIZE
; i
++) {
246 for ( q
= bot
-> questions
[ i
]; q
; q
= q
-> next
) {
247 if (( q
-> flags
& QAQ_QSTATE
) != QAQ_NEW
)
250 if (!( qnick
= getnickbynumeric ( q
-> numeric
)))
253 sprintf ( hostbuf
, " %s ! %s @ %s " , qnick
-> nick
, qnick
-> ident
, qnick
-> host
-> name
-> content
);
255 if ( match ( b
-> blockstr
, hostbuf
))
258 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_SPAM
;
263 sendnoticetouser ( bot
-> np
, sender
, "Block caused %d message %s to be marked as spam." , spamqcount
, ( spamqcount
== 1 ) ? "" : "s" );
270 int qabot_dochanclear ( void * np
, int cargc
, char ** cargv
) {
271 qab_bot
* bot
= qabot_getcurrentbot ();
272 channel
* cp
= qabot_getcurrentchannel ();
276 for ( s
= bot
-> nextspam
; s
; s
= ns
) {
282 bot
-> nextspam
= bot
-> lastspam
= 0 ;
284 sendmessagetochannel ( bot
-> np
, cp
, "Cleared message buffer." );
285 if ( bot
-> micnumeric
) {
287 sendmessagetochannel ( bot
-> np
, cp
, "Mic deactivated." );
289 if ( bot
-> recnumeric
) {
291 sendmessagetochannel ( bot
-> np
, cp
, "Recorder deactivated." );
294 fclose ( bot
-> recfile
);
298 fclose ( bot
-> playfile
);
299 bot
-> playfile
= NULL
;
305 int qabot_dochanclosechan ( void * np
, int cargc
, char ** cargv
) {
306 nick
* sender
= ( nick
*) np
;
307 qab_bot
* bot
= qabot_getcurrentbot ();
310 localsetmodeinit (& changes
, bot
-> public_chan
-> channel
, bot
-> np
);
311 localdosetmode_simple (& changes
, CHANMODE_INVITEONLY
, 0 );
312 localsetmodeflush (& changes
, 1 );
313 sendnoticetouser ( bot
-> np
, sender
, "Public channel has been closed." );
318 int qabot_dochanconfig ( void * np
, int cargc
, char ** cargv
) {
319 nick
* sender
= ( nick
*) np
;
320 qab_bot
* bot
= qabot_getcurrentbot ();
325 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !config <option> [<value>]" );
326 sendnoticetouser ( bot
-> np
, sender
, "Displays or sets configuration option. Valid options are:" );
327 sendnoticetouser ( bot
-> np
, sender
, "blockcontrol - Block questions containing control chars." );
328 sendnoticetouser ( bot
-> np
, sender
, "blockcolour - Block questions containing colour." );
329 sendnoticetouser ( bot
-> np
, sender
, "blockmark - Mark questions affected by blocks as spam." );
330 sendnoticetouser ( bot
-> np
, sender
, "authedonly - Accept questions from authed users only." );
331 sendnoticetouser ( bot
-> np
, sender
, "linebreak - Separate questions with line breaks." );
332 sendnoticetouser ( bot
-> np
, sender
, "flooddetect - Attempt to detect floodclone spam." );
333 sendnoticetouser ( bot
-> np
, sender
, "floodblock - Automatically block floodclone spam." );
334 sendnoticetouser ( bot
-> np
, sender
, "spamint - Text spam interval." );
335 sendnoticetouser ( bot
-> np
, sender
, "nickblockint - Time to wait before sending another question." );
336 sendnoticetouser ( bot
-> np
, sender
, "queuedqint - Queued answer spam interval." );
337 sendnoticetouser ( bot
-> np
, sender
, "mictimeout - Idle time before mic is automatically disabled." );
347 if (! ircd_strcmp ( opt
, "blockcontrol" )) {
349 if (! ircd_strcmp ( value
, "on" )) {
350 bot
-> flags
|= QAB_CONTROLCHAR
;
351 sendnoticetouser ( bot
-> np
, sender
, "Questions containing control characters will now be blocked." );
353 else if (! ircd_strcmp ( value
, "off" )) {
354 bot
-> flags
&= (~ QAB_CONTROLCHAR
);
355 sendnoticetouser ( bot
-> np
, sender
, "Questions containing control characters will no longer be blocked." );
358 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
361 sendnoticetouser ( bot
-> np
, sender
, "Control characters are currently %s blocked." , ( bot
-> flags
& QAB_CONTROLCHAR
) ? "being" : "not being" );
363 else if (! ircd_strcmp ( opt
, "blockcolour" )) {
365 if (! ircd_strcmp ( value
, "on" )) {
366 bot
-> flags
|= QAB_COLOUR
;
367 sendnoticetouser ( bot
-> np
, sender
, "Questions containing colour will now be blocked." );
369 else if (! ircd_strcmp ( value
, "off" )) {
370 bot
-> flags
&= (~ QAB_COLOUR
);
371 sendnoticetouser ( bot
-> np
, sender
, "Questions containing colour will no longer be blocked." );
374 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
377 sendnoticetouser ( bot
-> np
, sender
, "Colours are currently %s blocked." , ( bot
-> flags
& QAB_COLOUR
) ? "being" : "not being" );
379 else if (! ircd_strcmp ( opt
, "blockmark" )) {
381 if (! ircd_strcmp ( value
, "on" )) {
382 bot
-> flags
|= QAB_BLOCKMARK
;
383 sendnoticetouser ( bot
-> np
, sender
, "New blocks will automatically mark affected questions as spam." );
385 else if (! ircd_strcmp ( value
, "off" )) {
386 bot
-> flags
&= (~ QAB_BLOCKMARK
);
387 sendnoticetouser ( bot
-> np
, sender
, "New blocks will no longer automatically mark affected questions as spam." );
390 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
393 sendnoticetouser ( bot
-> np
, sender
, "Blocks are currently %s marking affected questions as spam." , ( bot
-> flags
& QAB_BLOCKMARK
) ? "" : "not " );
395 else if (! ircd_strcmp ( opt
, "authedonly" )) {
397 if (! ircd_strcmp ( value
, "on" )) {
398 bot
-> flags
|= QAB_AUTHEDONLY
;
399 sendnoticetouser ( bot
-> np
, sender
, "Questions from unauthed users will now be blocked." );
401 else if (! ircd_strcmp ( value
, "off" )) {
402 bot
-> flags
&= (~ QAB_AUTHEDONLY
);
403 sendnoticetouser ( bot
-> np
, sender
, "Questions from unauthed users will no longer be blocked." );
406 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
409 sendnoticetouser ( bot
-> np
, sender
, "Unauthed users may currently %s send questions." , ( bot
-> flags
& QAB_AUTHEDONLY
) ? "NOT " : "" );
411 else if (! ircd_strcmp ( opt
, "linebreak" )) {
413 if (! ircd_strcmp ( value
, "on" )) {
414 bot
-> flags
|= QAB_LINEBREAK
;
415 sendnoticetouser ( bot
-> np
, sender
, "Line breaks are now enabled." );
417 else if (! ircd_strcmp ( value
, "off" )) {
418 bot
-> flags
&= (~ QAB_LINEBREAK
);
419 sendnoticetouser ( bot
-> np
, sender
, "Line breaks are now disabled." );
422 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
425 sendnoticetouser ( bot
-> np
, sender
, "Line breaks are currently %s ." , ( bot
-> flags
& QAB_LINEBREAK
) ? "enabled" : "disabled" );
427 else if (! ircd_strcmp ( opt
, "flooddetect" )) {
429 if (! ircd_strcmp ( value
, "on" )) {
430 bot
-> flags
|= QAB_FLOODDETECT
;
431 sendnoticetouser ( bot
-> np
, sender
, "Flood detection is now enabled." );
433 else if (! ircd_strcmp ( value
, "off" )) {
434 bot
-> flags
&= (~ QAB_FLOODDETECT
);
435 sendnoticetouser ( bot
-> np
, sender
, "Flood detection is now disabled." );
438 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
441 sendnoticetouser ( bot
-> np
, sender
, "Flood detection is currently %s ." , ( bot
-> flags
& QAB_FLOODDETECT
) ? "enabled" : "disabled" );
443 else if (! ircd_strcmp ( opt
, "floodblock" )) {
445 if (! ircd_strcmp ( value
, "on" )) {
446 bot
-> flags
|= QAB_FLOODSTOP
;
447 sendnoticetouser ( bot
-> np
, sender
, "Flood blocking is now enabled." );
449 else if (! ircd_strcmp ( value
, "off" )) {
450 bot
-> flags
&= (~ QAB_FLOODSTOP
);
451 sendnoticetouser ( bot
-> np
, sender
, "Flood blocking is now disabled." );
454 sendnoticetouser ( bot
-> np
, sender
, "Invalid option. Valid options are 'on' or 'off'." );
457 sendnoticetouser ( bot
-> np
, sender
, "Flood blocking is currently %s ." , ( bot
-> flags
& QAB_FLOODSTOP
) ? "enabled" : "disabled" );
459 else if (! ircd_strcmp ( opt
, "mictimeout" )) {
461 int v
= ( int ) strtol ( value
, NULL
, 10 );
463 if (( v
< 0 ) || ( v
> 300 )) {
464 sendnoticetouser ( bot
-> np
, sender
, "Value must be between 0 (off) and 300." );
468 bot
-> mic_timeout
= v
;
469 sendnoticetouser ( bot
-> np
, sender
, "Value set." );
472 if ( bot
-> mic_timeout
)
473 sendnoticetouser ( bot
-> np
, sender
, "Mic timeout is currently %d second %s ." , bot
-> mic_timeout
, ( bot
-> mic_timeout
== 1 ) ? "" : "s" );
475 sendnoticetouser ( bot
-> np
, sender
, "Mic timeout is currently disabled." );
478 else if (! ircd_strcmp ( opt
, "spamint" )) {
480 int v
= ( int ) strtol ( value
, NULL
, 10 );
482 if (( v
< 1 ) || ( v
> 30 )) {
483 sendnoticetouser ( bot
-> np
, sender
, "Value must be between 1 and 30." );
487 bot
-> spam_interval
= v
;
488 sendnoticetouser ( bot
-> np
, sender
, "Value set." );
491 sendnoticetouser ( bot
-> np
, sender
, "Spam interval is currently %d second %s ." , bot
-> spam_interval
, ( bot
-> spam_interval
== 1 ) ? "" : "s" );
493 else if (! ircd_strcmp ( opt
, "nickblockint" )) {
495 int v
= ( int ) strtol ( value
, NULL
, 10 );
497 if (( v
< 1 ) || ( v
> 300 )) {
498 sendnoticetouser ( bot
-> np
, sender
, "Value must be between 1 and 300." );
503 sendnoticetouser ( bot
-> np
, sender
, "Value set." );
506 sendnoticetouser ( bot
-> np
, sender
, "Nick block interval is currently %d second %s ." , bot
-> ask_wait
, ( bot
-> ask_wait
== 1 ) ? "" : "s" );
508 else if (! ircd_strcmp ( opt
, "queuedqint" )) {
510 int v
= ( int ) strtol ( value
, NULL
, 10 );
512 if (( v
< 1 ) || ( v
> 20 )) {
513 sendnoticetouser ( bot
-> np
, sender
, "Value must be between 1 and 20." );
517 bot
-> queued_question_interval
= v
;
518 sendnoticetouser ( bot
-> np
, sender
, "Value set." );
521 sendnoticetouser ( bot
-> np
, sender
, "Queued question interval is currently %d second %s ." , bot
-> queued_question_interval
, ( bot
-> queued_question_interval
== 1 ) ? "" : "s" );
524 sendnoticetouser ( bot
-> np
, sender
, "Invalid configuration option." );
529 int qabot_dochanhelp ( void * np
, int cargc
, char ** cargv
) {
530 nick
* sender
= ( nick
*) np
;
531 qab_bot
* bot
= qabot_getcurrentbot ();
540 if (! ircd_strcmp ( ch
, "record" )) {
541 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !record [filename]" );
542 sendnoticetouser ( bot
-> np
, sender
, "Turn the recorder on or off. When turned on, anything said is recorded." );
543 sendnoticetouser ( bot
-> np
, sender
, "File name is required when starting the recorder." );
545 else if (! ircd_strcmp ( ch
, "play" )) {
546 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !play <filename>" );
547 sendnoticetouser ( bot
-> np
, sender
, "Begin playback from the file specified." );
549 else if (! ircd_strcmp ( ch
, "continue" )) {
550 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !continue" );
551 sendnoticetouser ( bot
-> np
, sender
, "Continue playback from a file." );
553 else if (! ircd_strcmp ( ch
, "stop" )) {
554 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !stop" );
555 sendnoticetouser ( bot
-> np
, sender
, "Stop playback of a file before it reaches the end." );
557 else if (! ircd_strcmp ( ch
, "list" )) {
558 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !list" );
559 sendnoticetouser ( bot
-> np
, sender
, "Lists recording files." );
561 else if (! ircd_strcmp ( ch
, "delete" )) {
562 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !delete <filename>" );
563 sendnoticetouser ( bot
-> np
, sender
, "Deletes a recording file." );
565 else if (! ircd_strcmp ( ch
, "mic" )) {
566 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !mic" );
567 sendnoticetouser ( bot
-> np
, sender
, "Turn the microphone on or off. When turned on, anything said by the microphone holder is relayed to %s ." , bot
-> public_chan
-> name
-> content
);
569 else if (! ircd_strcmp ( ch
, "clear" )) {
570 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !clear" );
571 sendnoticetouser ( bot
-> np
, sender
, "Clear currently queued text to relay, and turn off the microphone." );
573 else if (! ircd_strcmp ( ch
, "ping" )) {
574 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !ping" );
575 sendnoticetouser ( bot
-> np
, sender
, "Pings the bot." );
577 else if (! ircd_strcmp ( ch
, "config" )) {
578 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !config <option|help> [<value>]" );
579 sendnoticetouser ( bot
-> np
, sender
, "Display or set bot configuration options." );
581 else if (! ircd_strcmp ( ch
, "answer" )) {
582 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !answer <id> <answer>" );
583 sendnoticetouser ( bot
-> np
, sender
, "Answer a question." );
585 else if (! ircd_strcmp ( ch
, "block" )) {
586 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !block [<-q|-t>] <mask>" );
587 sendnoticetouser ( bot
-> np
, sender
, "Add a block, where:" );
588 sendnoticetouser ( bot
-> np
, sender
, "-q: blocks a Q account." );
589 sendnoticetouser ( bot
-> np
, sender
, "-t: blocks question text." );
590 sendnoticetouser ( bot
-> np
, sender
, "No flag results in a hostmask block." );
592 else if (! ircd_strcmp ( ch
, "listblocks" )) {
593 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !listblocks" );
594 sendnoticetouser ( bot
-> np
, sender
, "View the currently added blocks." );
596 else if (! ircd_strcmp ( ch
, "spam" )) {
597 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !spam <id>" );
598 sendnoticetouser ( bot
-> np
, sender
, "Mark a question as spam. This stops it being answered." );
600 else if (! ircd_strcmp ( ch
, "offtopic" )) {
601 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !offtopic <id>" );
602 sendnoticetouser ( bot
-> np
, sender
, "Mark a question as off-topic. This stops it being answered." );
604 else if (! ircd_strcmp ( ch
, "unblock" )) {
605 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !unblock [<-q|-t>] <mask>" );
606 sendnoticetouser ( bot
-> np
, sender
, "Removes a block. See \" !help block \" for a description of the flags." );
608 else if (! ircd_strcmp ( ch
, "reset" )) {
609 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !reset <all|questions|blocks|stats>" );
610 sendnoticetouser ( bot
-> np
, sender
, "Reset the questions, blocks or both; or the stats." );
612 else if (! ircd_strcmp ( ch
, "closechan" )) {
613 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !closechan" );
614 sendnoticetouser ( bot
-> np
, sender
, "Closes the public channel." );
616 else if (! ircd_strcmp ( ch
, "openchan" )) {
617 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !openchan" );
618 sendnoticetouser ( bot
-> np
, sender
, "Opens the public channel." );
620 else if (! ircd_strcmp ( ch
, "status" )) {
621 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !status" );
622 sendnoticetouser ( bot
-> np
, sender
, "Displays some status information and statistics." );
624 else if (! ircd_strcmp ( ch
, "help" )) {
625 sendnoticetouser ( bot
-> np
, sender
, "Syntax !help [<command>]" );
626 sendnoticetouser ( bot
-> np
, sender
, "List available commands or view help for a particular command." );
629 sendnoticetouser ( bot
-> np
, sender
, "No help available for ' %s '." , ch
);
633 sendnoticetouser ( bot
-> np
, sender
, "The following channel commands are recognised:" );
634 sendnoticetouser ( bot
-> np
, sender
, "!answer - Answer a question." );
635 sendnoticetouser ( bot
-> np
, sender
, "!block - Block a hostmask, account or string." );
636 sendnoticetouser ( bot
-> np
, sender
, "!clear - Clear currently queued text to spam." );
637 sendnoticetouser ( bot
-> np
, sender
, "!closechan - Close the public channel." );
638 sendnoticetouser ( bot
-> np
, sender
, "!config - Display or set bot configuration options." );
639 sendnoticetouser ( bot
-> np
, sender
, "!help - List commands or view the help for a command" );
640 sendnoticetouser ( bot
-> np
, sender
, "!listblocks - List currently added blocks." );
641 sendnoticetouser ( bot
-> np
, sender
, "!mic - Turn the microphone on or off." );
642 sendnoticetouser ( bot
-> np
, sender
, "!offtopic - Mark a question or questions as off-topic." );
643 sendnoticetouser ( bot
-> np
, sender
, "!openchan - Open the public channel." );
644 sendnoticetouser ( bot
-> np
, sender
, "!ping - Ping the bot." );
645 sendnoticetouser ( bot
-> np
, sender
, "!reset - Clear all blocks, questions or both." );
646 sendnoticetouser ( bot
-> np
, sender
, "!spam - Mark a question or questions as spam." );
647 sendnoticetouser ( bot
-> np
, sender
, "!status - Display some status statistics." );
648 sendnoticetouser ( bot
-> np
, sender
, "!unblock - Remove a block." );
649 sendnoticetouser ( bot
-> np
, sender
, "!record - Turn the recorder on or off." );
650 sendnoticetouser ( bot
-> np
, sender
, "!play - Start playback of a recording." );
651 sendnoticetouser ( bot
-> np
, sender
, "!continue - Continue playback of a recording." );
652 sendnoticetouser ( bot
-> np
, sender
, "!stop - Stop playback of a recording." );
653 sendnoticetouser ( bot
-> np
, sender
, "!list - Lists recordings." );
654 sendnoticetouser ( bot
-> np
, sender
, "!delete - Deletes a previous recording." );
655 sendnoticetouser ( bot
-> np
, sender
, "End of list." );
661 int qabot_dochanlistblocks ( void * np
, int cargc
, char ** cargv
) {
662 nick
* sender
= ( nick
*) np
;
663 qab_bot
* bot
= qabot_getcurrentbot ();
666 if (!( b
= bot
-> blocks
)) {
667 sendnoticetouser ( bot
-> np
, sender
, "There are no blocks currently added." );
671 sendnoticetouser ( bot
-> np
, sender
, "Type: Hostmask/Account/Textmask:" );
673 for (; b
; b
= b
-> next
) {
674 if ( b
-> type
== QABBLOCK_ACCOUNT
)
675 sendnoticetouser ( bot
-> np
, sender
, "A %s " , b
-> blockstr
);
676 else if ( b
-> type
== QABBLOCK_HOST
)
677 sendnoticetouser ( bot
-> np
, sender
, "H %s " , b
-> blockstr
);
679 sendnoticetouser ( bot
-> np
, sender
, "T %s " , b
-> blockstr
);
682 sendnoticetouser ( bot
-> np
, sender
, "End of list." );
687 int qabot_dochanmic ( void * np
, int cargc
, char ** cargv
) {
688 nick
* sender
= ( nick
*) np
;
689 qab_bot
* bot
= qabot_getcurrentbot ();
690 channel
* cp
= qabot_getcurrentchannel ();
692 if ( bot
-> micnumeric
) {
693 if ( bot
-> micnumeric
== sender
-> numeric
) {
695 sendmessagetochannel ( bot
-> np
, cp
, "Mic deactivated." );
697 qabot_spamstored (( void *) bot
);
700 bot
-> lastmic
= time ( NULL
);
701 bot
-> micnumeric
= sender
-> numeric
;
702 sendmessagetochannel ( bot
-> np
, cp
, " %s now has the mic. Anything said by %s will be relayed in %s ." ,
703 sender
-> nick
, sender
-> nick
, bot
-> public_chan
-> name
-> content
);
704 deleteschedule ( 0 , qabot_spamstored
, ( void *) bot
);
708 bot
-> lastmic
= time ( NULL
);
709 bot
-> micnumeric
= sender
-> numeric
;
710 sendmessagetochannel ( bot
-> np
, cp
, "Mic activated. Anything said by %s will be relayed in %s ." ,
711 sender
-> nick
, bot
-> public_chan
-> name
-> content
);
712 deleteschedule ( 0 , qabot_spamstored
, ( void *) bot
);
718 int qabot_dochanrecord ( void * np
, int cargc
, char ** cargv
) {
720 unsigned int i
, filenamelen
;
721 nick
* sender
= ( nick
*) np
;
722 qab_bot
* bot
= qabot_getcurrentbot ();
723 channel
* cp
= qabot_getcurrentchannel ();
725 if ( bot
-> recnumeric
) {
726 if ( bot
-> recnumeric
== sender
-> numeric
) {
728 fclose ( bot
-> recfile
);
730 sendmessagetochannel ( bot
-> np
, cp
, "Recorder deactivated." );
732 sendmessagetochannel ( bot
-> np
, cp
, "Someone else is recording at the moment." );
738 sendmessagetochannel ( bot
-> np
, cp
, "You cannot record whilst a playback is in progress." );
743 sendmessagetochannel ( bot
-> np
, cp
, "You did not specify a file name." );
747 filenamelen
= strlen ( cargv
[ 0 ]);
749 if ( filenamelen
> 50 ) {
750 sendmessagetochannel ( bot
-> np
, cp
, "File name too long." );
754 for ( i
= 0 ; i
< filenamelen
; i
++) {
755 if ( cargv
[ 0 ][ i
] < '0' || ( cargv
[ 0 ][ i
] > '9' && cargv
[ 0 ][ i
] < 'A' ) || ( cargv
[ 0 ][ i
] > 'Z' && cargv
[ 0 ][ i
] < 'a' ) || cargv
[ 0 ][ i
] > 'z' ) {
756 sendmessagetochannel ( bot
-> np
, cp
, "Invalid characters in file name." );
761 snprintf ( buf
, 150 , "./qabotrecords/ %s _ %s " , bot
-> nick
, cargv
[ 0 ]);
762 bot
-> recfile
= fopen ( buf
, "w" );
764 if (!( bot
-> recfile
)) {
765 sendmessagetochannel ( bot
-> np
, cp
, "Could not open record file." );
769 bot
-> recnumeric
= sender
-> numeric
;
771 sendmessagetochannel ( bot
-> np
, cp
, "Recorder activated. Anything said by %s will be recorded." ,
777 int qabot_dochanplay ( void * np
, int cargc
, char ** cargv
) {
779 unsigned int i
, filenamelen
;
780 qab_bot
* bot
= qabot_getcurrentbot ();
781 channel
* cp
= qabot_getcurrentchannel ();
784 sendmessagetochannel ( bot
-> np
, cp
, "A playback is already in progress, use !stop to abort current playback." );
789 sendmessagetochannel ( bot
-> np
, cp
, "You cannot playback whilst recording is in progress." );
794 sendmessagetochannel ( bot
-> np
, cp
, "You did not specify a file name." );
798 filenamelen
= strlen ( cargv
[ 0 ]);
800 if ( filenamelen
> 50 ) {
801 sendmessagetochannel ( bot
-> np
, cp
, "File name too long." );
805 for ( i
= 0 ; i
< filenamelen
; i
++) {
806 if ( cargv
[ 0 ][ i
] < '0' || ( cargv
[ 0 ][ i
] > '9' && cargv
[ 0 ][ i
] < 'A' ) || ( cargv
[ 0 ][ i
] > 'Z' && cargv
[ 0 ][ i
] < 'a' ) || cargv
[ 0 ][ i
] > 'z' ) {
807 sendmessagetochannel ( bot
-> np
, cp
, "Invalid characters in file name." );
812 snprintf ( buf
, 150 , "./qabotrecords/ %s _ %s " , bot
-> nick
, cargv
[ 0 ]);
813 bot
-> playfile
= fopen ( buf
, "r" );
815 if (!( bot
-> playfile
)) {
816 sendmessagetochannel ( bot
-> np
, cp
, "Could not open playback file." );
820 sendmessagetochannel ( bot
-> np
, cp
, "Starting playback..." );
825 int qabot_dochancontinue ( void * np
, int cargc
, char ** cargv
) {
826 qab_bot
* bot
= qabot_getcurrentbot ();
827 channel
* cp
= qabot_getcurrentchannel ();
829 if (!( bot
-> playfile
)) {
830 sendmessagetochannel ( bot
-> np
, cp
, "No playback in progress." );
834 sendmessagetochannel ( bot
-> np
, cp
, "Continuing playback..." );
839 int qabot_dochanstop ( void * np
, int cargc
, char ** cargv
) {
840 qab_bot
* bot
= qabot_getcurrentbot ();
841 channel
* cp
= qabot_getcurrentchannel ();
843 if (!( bot
-> playfile
)) {
844 sendmessagetochannel ( bot
-> np
, cp
, "No playback in progress." );
848 fclose ( bot
-> playfile
);
849 bot
-> playfile
= NULL
;
850 sendmessagetochannel ( bot
-> np
, cp
, "Stopped playback." );
854 int qabot_dochanlist ( void * np
, int cargc
, char ** cargv
) {
856 struct dirent
* direntry
;
857 nick
* sender
= ( nick
*) np
;
858 qab_bot
* bot
= qabot_getcurrentbot ();
860 recordlist
= opendir ( "./qabotrecords" );
863 sendnoticetouser ( bot
-> np
, sender
, "Unable to retreive directory list." );
867 sendnoticetouser ( bot
-> np
, sender
, "Recording list:" );
869 for ( direntry
= readdir ( recordlist
); direntry
; direntry
= readdir ( recordlist
)) {
870 if ( direntry
-> d_name
[ 0 ] == '.' )
873 sendnoticetouser ( bot
-> np
, sender
, " %s " , direntry
-> d_name
);
876 sendnoticetouser ( bot
-> np
, sender
, "End of list." );
877 closedir ( recordlist
);
882 int qabot_dochandelete ( void * np
, int cargc
, char ** cargv
) {
884 unsigned int i
, filenamelen
;
885 qab_bot
* bot
= qabot_getcurrentbot ();
886 channel
* cp
= qabot_getcurrentchannel ();
889 sendmessagetochannel ( bot
-> np
, cp
, "You cannot delete recordings whilst playback is in progress." );
894 sendmessagetochannel ( bot
-> np
, cp
, "You cannot delete recordings whilst recording is in progress." );
899 sendmessagetochannel ( bot
-> np
, cp
, "You did not specify a file name." );
903 filenamelen
= strlen ( cargv
[ 0 ]);
905 if ( filenamelen
> 50 ) {
906 sendmessagetochannel ( bot
-> np
, cp
, "File name too long." );
910 for ( i
= 0 ; i
< filenamelen
; i
++) {
911 if ( cargv
[ 0 ][ i
] < '0' || ( cargv
[ 0 ][ i
] > '9' && cargv
[ 0 ][ i
] < 'A' ) || ( cargv
[ 0 ][ i
] > 'Z' && cargv
[ 0 ][ i
] < 'a' ) || cargv
[ 0 ][ i
] > 'z' ) {
912 sendmessagetochannel ( bot
-> np
, cp
, "Invalid characters in file name." );
917 snprintf ( buf
, 150 , "./qabotrecords/ %s _ %s " , bot
-> nick
, cargv
[ 0 ]);
920 sendmessagetochannel ( bot
-> np
, cp
, "Recording deleted." );
922 sendmessagetochannel ( bot
-> np
, cp
, "Unable to delete recording." );
928 int qabot_dochanmoo ( void * np
, int cargc
, char ** cargv
) {
929 qab_bot
* bot
= qabot_getcurrentbot ();
931 int i
, moocount
= 5 + ( rand () % 40 );
932 channel
* cp
= qabot_getcurrentchannel ();
935 for ( i
= 1 ; i
< moocount
; i
++)
936 moostr
[ i
] = (( rand () % 100 ) > 50 ) ? 'o' : '0' ;
939 sendmessagetochannel ( bot
-> np
, cp
, " %s " , moostr
);
944 int qabot_dochanofftopic ( void * np
, int cargc
, char ** cargv
) {
945 nick
* sender
= ( nick
*) np
;
946 qab_bot
* bot
= qabot_getcurrentbot ();
952 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !spam <id> [<id> ... <id>]" );
956 for ( i
= 0 ; i
< cargc
; i
++) {
957 id
= strtol ( cargv
[ i
], NULL
, 10 );
959 if (( id
< 1 ) || ( id
> bot
-> lastquestionID
)) {
960 sendnoticetouser ( bot
-> np
, sender
, "Invalid question ID %d ." , id
);
964 for ( q
= bot
-> questions
[ id
% QUESTIONHASHSIZE
]; q
; q
= q
-> next
)
969 sendnoticetouser ( bot
-> np
, sender
, "Can't find question %d ." , id
);
973 switch ( q
-> flags
& QAQ_QSTATE
) {
975 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been answered." , id
);
979 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been marked as off-topic." , id
);
983 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been marked as spam." , id
);
990 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_OFFTOPIC
;
991 sendnoticetouser ( bot
-> np
, sender
, "Question %d has been marked as off-topic." , id
);
997 int qabot_dochanopenchan ( void * np
, int cargc
, char ** cargv
) {
998 nick
* sender
= ( nick
*) np
;
999 qab_bot
* bot
= qabot_getcurrentbot ();
1000 modechanges changes
;
1002 localsetmodeinit (& changes
, bot
-> public_chan
-> channel
, bot
-> np
);
1003 localdosetmode_simple (& changes
, CHANMODE_MODERATE
| CHANMODE_DELJOINS
, CHANMODE_INVITEONLY
);
1004 localsetmodeflush (& changes
, 1 );
1005 sendnoticetouser ( bot
-> np
, sender
, "Public channel has been opened." );
1010 int qabot_dochanping ( void * np
, int cargc
, char ** cargv
) {
1011 qab_bot
* bot
= qabot_getcurrentbot ();
1012 channel
* cp
= qabot_getcurrentchannel ();
1014 sendmessagetochannel ( bot
-> np
, cp
, "pong!" );
1019 int qabot_dochanreset ( void * np
, int cargc
, char ** cargv
) {
1020 nick
* sender
= ( nick
*) np
;
1021 qab_bot
* bot
= qabot_getcurrentbot ();
1025 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !reset <blocks|questions|stats|all>" );
1029 if (! ircd_strcmp ( cargv
[ 0 ], "blocks" ))
1031 else if (! ircd_strcmp ( cargv
[ 0 ], "questions" ))
1033 else if (! ircd_strcmp ( cargv
[ 0 ], "stats" ))
1035 else if (! ircd_strcmp ( cargv
[ 0 ], "all" ))
1038 sendnoticetouser ( bot
-> np
, sender
, "Unknown parameter: %s ." , cargv
[ 0 ]);
1045 while ( bot
-> blocks
) {
1047 bot
-> blocks
= bot
-> blocks
-> next
;
1053 bot
-> block_count
= 0 ;
1055 sendnoticetouser ( bot
-> np
, sender
, "Reset (blocks): Done." );
1062 for ( i
= 0 ; i
< QUESTIONHASHSIZE
; i
++) {
1063 while ( bot
-> questions
[ i
]) {
1064 q
= bot
-> questions
[ i
];
1065 bot
-> questions
[ i
] = bot
-> questions
[ i
]-> next
;
1074 bot
-> lastquestionID
= 0 ;
1077 sendnoticetouser ( bot
-> np
, sender
, "Reset (questions): Done." );
1083 sendnoticetouser ( bot
-> np
, sender
, "Reset (stats): Done." );
1089 int qabot_dochanspam ( void * np
, int cargc
, char ** cargv
) {
1090 nick
* sender
= ( nick
*) np
;
1091 qab_bot
* bot
= qabot_getcurrentbot ();
1097 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !spam <id> [<id> ... <id>]" );
1101 for ( i
= 0 ; i
< cargc
; i
++) {
1102 id
= strtol ( cargv
[ i
], NULL
, 10 );
1104 if (( id
< 1 ) || ( id
> bot
-> lastquestionID
)) {
1105 sendnoticetouser ( bot
-> np
, sender
, "Invalid question ID %d ." , id
);
1109 for ( q
= bot
-> questions
[ id
% QUESTIONHASHSIZE
]; q
; q
= q
-> next
)
1114 sendnoticetouser ( bot
-> np
, sender
, "Can't find question %d ." , id
);
1118 switch ( q
-> flags
& QAQ_QSTATE
) {
1120 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been answered." , id
);
1124 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been marked as off-topic." , id
);
1128 sendnoticetouser ( bot
-> np
, sender
, "Question %d has already been marked as spam." , id
);
1135 q
-> flags
= (( q
-> flags
) & ~ QAQ_QSTATE
) | QAQ_SPAM
;
1136 sendnoticetouser ( bot
-> np
, sender
, "Question %d has been marked as spam." , id
);
1142 int qabot_dochanstatus ( void * np
, int cargc
, char ** cargv
) {
1143 nick
* sender
= ( nick
*) np
;
1144 qab_bot
* bot
= qabot_getcurrentbot ();
1146 sendnoticetouser ( bot
-> np
, sender
, "Lines spammed: %d " , bot
-> spammed
);
1147 sendnoticetouser ( bot
-> np
, sender
, "Questions asked: %d " , bot
-> lastquestionID
);
1148 sendnoticetouser ( bot
-> np
, sender
, "Questions answered: %d " , bot
-> answered
);
1149 sendnoticetouser ( bot
-> np
, sender
, "Blocks: %d " , bot
-> block_count
);
1150 /*sendnoticetouser(bot->np, sender, "Question interval: %d seconds", bot->question_interval);*/
1151 sendnoticetouser ( bot
-> np
, sender
, "Spam interval: %d seconds" , bot
-> spam_interval
);
1152 sendnoticetouser ( bot
-> np
, sender
, "Nick block interval: %d seconds" , bot
-> ask_wait
);
1153 sendnoticetouser ( bot
-> np
, sender
, "Queued question interval: %d seconds" , bot
-> queued_question_interval
);
1154 sendnoticetouser ( bot
-> np
, sender
, "Block control chars: %s " , ( bot
-> flags
& QAB_CONTROLCHAR
) ? "Yes" : "No" );
1155 sendnoticetouser ( bot
-> np
, sender
, "Block colour: %s " , ( bot
-> flags
& QAB_COLOUR
) ? "Yes" : "No" );
1156 sendnoticetouser ( bot
-> np
, sender
, "Authed users only: %s " , ( bot
-> flags
& QAB_AUTHEDONLY
) ? "Yes" : "No" );
1157 sendnoticetouser ( bot
-> np
, sender
, "Line break: %s " , ( bot
-> flags
& QAB_LINEBREAK
) ? "Yes" : "No" );
1158 sendnoticetouser ( bot
-> np
, sender
, "Question flood detection: %s " , ( bot
-> flags
& QAB_FLOODDETECT
) ? "Yes" : "No" );
1159 sendnoticetouser ( bot
-> np
, sender
, "Question flood blocking: %s " , ( bot
-> flags
& QAB_FLOODSTOP
) ? "Yes" : "No" );
1160 sendnoticetouser ( bot
-> np
, sender
, "Blocks mark as spam: %s " , ( bot
-> flags
& QAB_BLOCKMARK
) ? "Yes" : "No" );
1161 if ( bot
-> micnumeric
) {
1162 nick
* mnick
= getnickbynumeric ( bot
-> micnumeric
);
1164 sendnoticetouser ( bot
-> np
, np
, "Mic: Enabled ( %s )" , mnick
? mnick
-> nick
: "UNKNOWN" );
1167 sendnoticetouser ( bot
-> np
, np
, "Mic: Disabled" );
1168 sendnoticetouser ( bot
-> np
, sender
, "Mic timeout: %d " , bot
-> mic_timeout
);
1169 /*sendnoticetouser(bot->np, sender, "");*/
1174 int qabot_dochanunblock ( void * np
, int cargc
, char ** cargv
) {
1175 nick
* sender
= ( nick
*) np
;
1176 qab_bot
* bot
= qabot_getcurrentbot ();
1182 sendnoticetouser ( bot
-> np
, sender
, "Syntax: !unblock [-q|-t] <account|mask>" );
1187 if (! ircd_strncmp ( cargv
[ 0 ], "-q" , 2 )) {
1188 type
= QABBLOCK_ACCOUNT
;
1194 else if (! ircd_strncmp ( cargv
[ 0 ], "-t" , 2 )) {
1195 type
= QABBLOCK_TEXT
;
1199 sendnoticetouser ( bot
-> np
, sender
, "Invalid flag." );
1204 type
= QABBLOCK_HOST
;
1208 for ( b
= bot
-> blocks
; b
; b
= b
-> next
) {
1209 if ( b
-> type
!= type
)
1212 if (! ircd_strcmp ( b
-> blockstr
, ch
)) {
1214 b
-> next
-> prev
= b
-> prev
;
1216 b
-> prev
-> next
= b
-> next
;
1218 bot
-> blocks
= b
-> next
;
1225 sendnoticetouser ( bot
-> np
, sender
, "Block removed." );
1230 sendnoticetouser ( bot
-> np
, sender
, "No such block." );