-
-.PHONY: all
-all: qabot.so
-
-qabot.so: qabot.o qabot_bot.o qabot_chancommands.o qabot_commands.o qabot_dbase.o qabot_help.o qabot_texts.o
- ld -shared -Bdynamic -o $@ $^
+\r
+.PHONY: all\r
+all: qabot.so\r
+\r
+qabot.so: qabot.o qabot_bot.o qabot_chancommands.o qabot_commands.o qabot_dbase.o qabot_help.o\r
+ ld -shared -Bdynamic -o $@ $^\r
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-time_t qab_startime;
-int qabot_nickext;
-int qabot_spam_nickext;
-int qabot_chanext;
-nick* qabot_nick = 0;
-CommandTree* qabot_commands;
-CommandTree* qabot_chancommands;
-qab_bot* qab_bots = 0;
-unsigned long qab_lastq_crc = 0;
-int qab_lastq_count = 0;
-qab_bot* qabot_currentbot = 0;
-channel* qabot_currentchan = 0;
-
-void _init() {
- qab_startime = time(0);
-
- registerhook(HOOK_NICK_LOSTNICK, qabot_lostnick);
- registerhook(HOOK_CHANNEL_PART, qabot_channel_part);
-
- qabot_commands = newcommandtree();
- addcommandtotree(qabot_commands, "showcommands", 0, 0, qabot_doshowcommands);
- addcommandtotree(qabot_commands, "help", QAUFLAG_STAFF, 1, qabot_dohelp);
- addcommandtotree(qabot_commands, "hello", 0, 0, qabot_dohello);
- addcommandtotree(qabot_commands, "save", QAUFLAG_ADMIN, 0, qabot_dosave);
- addcommandtotree(qabot_commands, "listbots", QAUFLAG_STAFF, 0, qabot_dolistbots);
- addcommandtotree(qabot_commands, "listusers", QAUFLAG_STAFF, 0, qabot_dolistusers);
- addcommandtotree(qabot_commands, "showbot", QAUFLAG_STAFF, 1, qabot_doshowbot);
- addcommandtotree(qabot_commands, "addbot", QAUFLAG_STAFF, 6, qabot_doaddbot);
- addcommandtotree(qabot_commands, "delbot", QAUFLAG_STAFF, 1, qabot_dodelbot);
- addcommandtotree(qabot_commands, "adduser", QAUFLAG_ADMIN, 2, qabot_doadduser);
- addcommandtotree(qabot_commands, "changelev", QAUFLAG_ADMIN, 2, qabot_dochangelev);
- addcommandtotree(qabot_commands, "deluser", QAUFLAG_ADMIN, 1, qabot_dodeluser);
- addcommandtotree(qabot_commands, "whois", QAUFLAG_STAFF, 1, qabot_dowhois);
- addcommandtotree(qabot_commands, "status", QAUFLAG_DEVELOPER, 0, qabot_dostatus);
-
- qabot_chancommands = newcommandtree();
- addcommandtotree(qabot_chancommands, "answer", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochananswer);
- addcommandtotree(qabot_chancommands, "block", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanblock);
- addcommandtotree(qabot_chancommands, "clear", QAC_STAFFCHAN, 0, qabot_dochanclear);
- addcommandtotree(qabot_chancommands, "closechan", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanclosechan);
- addcommandtotree(qabot_chancommands, "config", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanconfig);
- addcommandtotree(qabot_chancommands, "help", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 1, qabot_dochanhelp);
- addcommandtotree(qabot_chancommands, "listblocks", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanlistblocks);
- addcommandtotree(qabot_chancommands, "mic", QAC_STAFFCHAN, 0, qabot_dochanmic);
- addcommandtotree(qabot_chancommands, "moo", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanmoo);
- addcommandtotree(qabot_chancommands, "offtopic", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 30, qabot_dochanofftopic);
- addcommandtotree(qabot_chancommands, "openchan", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanopenchan);
- addcommandtotree(qabot_chancommands, "ping", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanping);
- addcommandtotree(qabot_chancommands, "reset", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 1, qabot_dochanreset);
- addcommandtotree(qabot_chancommands, "spam", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 30, qabot_dochanspam);
- addcommandtotree(qabot_chancommands, "status", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanstatus);
- addcommandtotree(qabot_chancommands, "unblock", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanunblock);
- addcommandtotree(qabot_chancommands, "listtexts", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanlisttexts);
- addcommandtotree(qabot_chancommands, "showsection", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanshowsection);
- addcommandtotree(qabot_chancommands, "addtext", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanaddtext);
- addcommandtotree(qabot_chancommands, "deltext", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 1, qabot_dochandeltext);
- addcommandtotree(qabot_chancommands, "addsection", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanaddsection);
- addcommandtotree(qabot_chancommands, "delsection", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochandelsection);
- addcommandtotree(qabot_chancommands, "record", QAC_STAFFCHAN, 2, qabot_dochanrecord);
-
- if ((qabot_nickext = registernickext("QABOT")) == -1) {
- return;
- }
-
- if ((qabot_spam_nickext = registernickext("QABOT_SPAM")) == -1) {
- return;
- }
-
- qabot_loaddb();
-
- scheduleoneshot(time(NULL) + 1, &qabot_createfakeuser, NULL);
- scheduleoneshot(time(NULL) + QABOT_SAVEWAIT, &qabot_savetimer, NULL);
-}
-
-void _fini() {
- deregisterhook(HOOK_NICK_LOSTNICK, qabot_lostnick);
- deregisterhook(HOOK_CHANNEL_PART, qabot_channel_part);
-
- deleteschedule(0, qabot_savetimer, NULL);
-
- qabot_savedb();
-
- while (qab_bots)
- qabot_delbot(qab_bots);
-
- if (qabot_nickext != -1)
- releasenickext(qabot_nickext);
-
- if (qabot_spam_nickext != -1)
- releasenickext(qabot_spam_nickext);
-
- if (qabot_nick) {
- deregisterlocaluser(qabot_nick, "Module unloaded.");
- qabot_nick = NULL;
- }
-
- while (qabot_users)
- qabot_squelchuser(qabot_users);
-
- deletecommandfromtree(qabot_commands, "showcommands", qabot_doshowcommands);
- deletecommandfromtree(qabot_commands, "help", qabot_dohelp);
- deletecommandfromtree(qabot_commands, "hello", qabot_dohello);
- deletecommandfromtree(qabot_commands, "save", qabot_dosave);
- deletecommandfromtree(qabot_commands, "listbots", qabot_dolistbots);
- deletecommandfromtree(qabot_commands, "listusers", qabot_dolistusers);
- deletecommandfromtree(qabot_commands, "showbot", qabot_doshowbot);
- deletecommandfromtree(qabot_commands, "addbot", qabot_doaddbot);
- deletecommandfromtree(qabot_commands, "delbot", qabot_dodelbot);
- deletecommandfromtree(qabot_commands, "adduser", qabot_doadduser);
- deletecommandfromtree(qabot_commands, "changelev", qabot_dochangelev);
- deletecommandfromtree(qabot_commands, "deluser", qabot_dodeluser);
- deletecommandfromtree(qabot_commands, "whois", qabot_dowhois);
- deletecommandfromtree(qabot_commands, "status", qabot_dostatus);
- destroycommandtree(qabot_commands);
-
- deletecommandfromtree(qabot_chancommands, "answer", qabot_dochananswer);
- deletecommandfromtree(qabot_chancommands, "block", qabot_dochanblock);
- deletecommandfromtree(qabot_chancommands, "clear", qabot_dochanclear);
- deletecommandfromtree(qabot_chancommands, "closechan", qabot_dochanclosechan);
- deletecommandfromtree(qabot_chancommands, "config", qabot_dochanconfig);
- deletecommandfromtree(qabot_chancommands, "help", qabot_dochanhelp);
- deletecommandfromtree(qabot_chancommands, "listblocks", qabot_dochanlistblocks);
- deletecommandfromtree(qabot_chancommands, "mic", qabot_dochanmic);
- deletecommandfromtree(qabot_chancommands, "moo", qabot_dochanmoo);
- deletecommandfromtree(qabot_chancommands, "offtopic", qabot_dochanofftopic);
- deletecommandfromtree(qabot_chancommands, "openchan", qabot_dochanopenchan);
- deletecommandfromtree(qabot_chancommands, "ping", qabot_dochanping);
- deletecommandfromtree(qabot_chancommands, "reset", qabot_dochanreset);
- deletecommandfromtree(qabot_chancommands, "spam", qabot_dochanspam);
- deletecommandfromtree(qabot_chancommands, "status", qabot_dochanstatus);
- deletecommandfromtree(qabot_chancommands, "unblock", qabot_dochanunblock);
- deletecommandfromtree(qabot_chancommands, "listtexts", qabot_dochanlisttexts);
- deletecommandfromtree(qabot_chancommands, "showsection", qabot_dochanshowsection);
- deletecommandfromtree(qabot_chancommands, "addtext", qabot_dochanaddtext);
- deletecommandfromtree(qabot_chancommands, "deltext", qabot_dochandeltext);
- deletecommandfromtree(qabot_chancommands, "addsection", qabot_dochanaddsection);
- deletecommandfromtree(qabot_chancommands, "delsection", qabot_dochandelsection);
- deletecommandfromtree(qabot_chancommands, "record", qabot_dochanrecord);
- destroycommandtree(qabot_chancommands);
-}
-
-void qabot_lostnick(int hooknum, void* arg) {
- nick* np = (nick*)arg;
- qab_bot* b;
-
- if (!qab_bots)
- return;
-
- if (!IsAccount(np))
- return;
-
- for (b = qab_bots; b; b = b->next) {
- if (b->micnumeric == np->numeric) {
- b->micnumeric = 0;
- sendmessagetochannel(b->np, b->staff_chan->channel, "%s deactivated.",
- bot->recording_section ? "Recorder" : "Mic");
- if (!b->lastspam && !b->recording_section)
- qabot_spamstored((void*)b);
- b->recording_section = 0;
- }
- }
-}
-
-void qabot_channel_part(int hooknum, void* arg) {
- channel* cp = (channel*)((void**)arg)[0];
- nick* np = (nick*)((void**)arg)[1];
- qab_bot* b;
-
- if (!qab_bots)
- return;
-
- if (!IsAccount(np))
- return;
-
- for (b = qab_bots; b; b = b->next) {
- if ((b->micnumeric == np->numeric) && (b->staff_chan->channel == cp)) {
- b->micnumeric = 0;
- sendmessagetochannel(b->np, b->staff_chan->channel, "%s deactivated.",
- b->recording_section ? "Recorder" : "Mic");
- if (!b->lastspam && !b->recording_section)
- qabot_spamstored((void*)b);
- b->recording_section = 0;
- }
- }
-}
-
-void qabot_createfakeuser(void* arg) {
- channel* cp;
-
- if ((qabot_nick = registerlocaluser(QABOT_NICK, QABOT_USER, QABOT_HOST,
- QABOT_NAME, QABOT_ACCT, QABOT_UMDE, &qabot_handler))) {
- if ((cp = findchannel(QABOT_HOMECHAN))) {
- localjoinchannel(qabot_nick, cp);
- localgetops(qabot_nick, cp);
- }
- else
- localcreatechannel(qabot_nick, QABOT_HOMECHAN);
- }
-}
-
-void qabot_handler(nick* me, int type, void** args) {
- nick* sender;
- Command* cmd;
- channel* cp;
- char* cargv[50];
- int cargc;
- qab_user* u;
-
- switch (type) {
- case LU_PRIVMSG:
- case LU_SECUREMSG:
- sender = (nick*)args[0];
-
- if (!strncmp("\001VERSION", args[1], 8)) {
- sendnoticetouser(qabot_nick, sender, "\001VERSION %s\001", QABOT_NAME);
- return;
- }
-
- cargc = splitline((char*)args[1], cargv, 50, 0);
- cmd = findcommandintree(qabot_commands, cargv[0], 1);
- if (!cmd) {
- sendnoticetouser(qabot_nick, sender, "Unknown command.");
- return;
- }
-
- if (!IsAccount(sender)) {
- sendnoticetouser(qabot_nick, sender, "You must be authed to use this command.");
- return;
- }
-
- u = qabot_getuser(sender->authname);
- if (cmd->level) {
- if (!u) {
- sendnoticetouser(qabot_nick, sender, "You need an account to use this command.");
- return;
- }
-
- if ((cmd->level & QAUFLAG_STAFF) && !QAIsStaff(u)) {
- sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");
- return;
- }
-
- if ((cmd->level & QAUFLAG_ADMIN) && !QAIsAdmin(u)) {
- sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");
- return;
- }
-
- if ((cmd->level & QAUFLAG_DEVELOPER) && !QAIsDeveloper(u)) {
- sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");
- return;
- }
- }
-
- if (cmd->maxparams < (cargc-1)) {
- rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));
- cargc=(cmd->maxparams) + 1;
- }
-
- (cmd->handler)((void*)sender, cargc - 1, &(cargv[1]));
-
- break;
-
- case LU_KILLED:
- qabot_nick = NULL;
- scheduleoneshot(time(NULL) + 1, &qabot_createfakeuser, NULL);
- break;
-
- case LU_KICKED:
- cp = (channel*)args[1];
- if (cp) {
- localjoinchannel(qabot_nick, cp);
- localgetops(qabot_nick, cp);
- }
- break;
- }
-}
-
-void qabot_child_handler(nick* me, int type, void** args) {
- nick* sender;
- channel* cp;
- qab_bot* bot = me->exts[qabot_nickext];
- char* text;
- Command* cmd;
- char* cargv[50];
- int cargc;
-
- if (!bot) {
- return;
- }
-
- switch (type) {
- case LU_CHANMSG:
- sender = (nick*)args[0];
- cp = (channel*)args[1];
- text = (char*)args[2];
-
- if (*text == '!') {
- cargc = splitline((char*)(++text), cargv, 50, 0);
- cmd = findcommandintree(qabot_chancommands, cargv[0], 1);
- if (!cmd) {
- sendnoticetouser(me, sender, "Unknown command.");
- return;
- }
-
- if ((cp->index == bot->staff_chan) && !(cmd->level & QAC_STAFFCHAN)) {
- sendnoticetouser(me, sender, "This command cannot be used in the staff channel.");
- return;
- }
-
- if ((cp->index == bot->question_chan) && !(cmd->level & QAC_QUESTIONCHAN)) {
- sendnoticetouser(me, sender, "This command cannot be used in the question channel.");
- return;
- }
-
- if (cmd->maxparams < (cargc-1)) {
- rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));
- cargc=(cmd->maxparams) + 1;
- }
-
- qabot_currentbot = bot;
- qabot_currentchan = cp;
-
- (cmd->handler)((void*)sender, cargc - 1, &(cargv[1]));
- }
- else if ((*text != '!') && (bot->micnumeric == sender->numeric) && (cp->index == bot->staff_chan)) {
- bot->lastmic = time(NULL);
- if (bot->lastspam) {
- qab_spam* s;
-
- s = (qab_spam*)malloc(sizeof(qab_spam));
- s->message = strdup(text);
- s->next = 0;
- bot->lastspam->next = s;
- bot->lastspam = s;
- }
- else {
- if ((bot->spamtime + bot->spam_interval) < time(0)) {
- sendmessagetochannel(me, bot->public_chan->channel, "%s", text);
- bot->spammed++;
- bot->spamtime = time(0);
- }
- else {
- qab_spam* s;
-
- s = (qab_spam*)malloc(sizeof(qab_spam));
- s->message = strdup(text);
- s->next = 0;
- bot->nextspam = bot->lastspam = s;
- scheduleoneshot(bot->spamtime + bot->spam_interval, qabot_spam, (void*)bot);
- }
- }
- }
- break;
-
- case LU_PRIVMSG:
- case LU_SECUREMSG:
- sender = (nick*)args[0];
- text = (char*)args[1];
- time_t lastmsg;
-
- lastmsg = (time_t)sender->exts[qabot_spam_nickext];
-
- if ((lastmsg + bot->ask_wait) > time(0)) {
- sendnoticetouser(me, sender, "You have already sent a question recently, please wait at least %d seconds between asking questions.", bot->ask_wait);
- return;
- }
- else {
- char hostbuf[NICKLEN + USERLEN + HOSTLEN + 3];
- qab_block* b;
- qab_question* q;
- unsigned long crc;
- int len;
-
- sendnoticetouser(me, sender, "Your question has been relayed to the %s staff.", bot->public_chan->name->content);
-
- if (!getnumerichandlefromchanhash(bot->public_chan->channel->users, sender->numeric))
- return;
-
- if (*text == '<')
- text++;
-
- len = strlen(text);
- if ((len > 0) && (text[len - 1] == '>')) {
- text[len - 1] = '\0';
- len--;
- }
-
- if ((len < 5) || !strchr(text, ' ') || (*text == 1))
- return;
-
- if ((bot->flags & QAB_AUTHEDONLY) && !IsAccount(sender))
- return;
-
- if (bot->flags & QAB_CONTROLCHAR) {
- char* ch;
-
- for (ch = text; *ch; ch++)
- if ((*ch == 2) || (*ch == 3) || (*ch == 22) || (*ch == 27) || (*ch == 31))
- return;
- }
- else if (bot->flags & QAB_COLOUR) {
- char* ch;
-
- for (ch = text; *ch; ch++)
- if (*ch == 3)
- return;
- }
-
- if (bot->flags & QAB_FLOODDETECT) {
- crc = crc32i(text);
- if (crc == qab_lastq_crc) {
- qab_lastq_count++;
- if (qab_lastq_count >= 3) {
- if ((qab_lastq_count == 3) || ((qab_lastq_count % 10) == 0))
- sendmessagetochannel(me, bot->question_chan->channel, "WARNING: Possible question flood detected%s", (bot->flags & QAB_FLOODSTOP) ? " - AUTO IGNORED." : ".");
- if (bot->flags & QAB_FLOODSTOP)
- return;
- }
- }
- else {
- qab_lastq_crc = crc;
- qab_lastq_count = 1;
- }
- }
-
- sprintf(hostbuf,"%s!%s@%s", sender->nick, sender->ident, sender->host->name->content);
-
- for (b = bot->blocks; b; b = b->next) {
- switch (b->type) {
- case QABBLOCK_ACCOUNT:
- if (IsAccount(sender) && !ircd_strncmp(sender->authname, b->blockstr, ACCOUNTLEN))
- return;
- break;
-
- case QABBLOCK_HOST:
- if (!match(b->blockstr, hostbuf))
- return;
- break;
-
- case QABBLOCK_TEXT:
- if (!match(b->blockstr, text))
- return;
- break;
- }
- }
-
- sender->exts[qabot_spam_nickext] = (void*)time(0);
-
- q = (qab_question*)malloc(sizeof(qab_question));
- q->id = ++bot->lastquestionID;
- q->question = strdup(text);
- q->flags = QAQ_NEW;
- strncpy(q->nick, sender->nick, NICKLEN);
- q->nick[NICKLEN] = '\0';
- q->numeric = sender->numeric;
- q->crc = (bot->flags & QAB_FLOODDETECT) ? crc : 0;
- q->answer = 0;
- q->next = bot->questions[q->id % QUESTIONHASHSIZE];
-
- bot->questions[q->id % QUESTIONHASHSIZE] = q;
-
- sendmessagetochannel(me, bot->question_chan->channel, "ID: %3d <%s> %s", q->id, visiblehostmask(sender, hostbuf), text);
-
- if ((bot->flags & QAB_LINEBREAK) && ((bot->lastquestionID % 10) == 0))
- sendmessagetochannel(me, bot->question_chan->channel, "-----------------------------------");
- }
- break;
-
- case LU_KILLED:
- bot->np = NULL;
- scheduleoneshot(time(NULL) + 1, &qabot_createbotfakeuser, (void*)bot);
- break;
-
- case LU_KICKED:
- cp = (channel*)args[1];
- if (cp) {
- localjoinchannel(bot->np, cp);
- localgetops(bot->np, cp);
- }
- break;
-
- default:
- break;
- }
-}
-
-char* qabot_getvictim(nick* np, char* target) {
- if (*target != '#') {
- nick* victim;
-
- if (!(victim = getnickbynick(target))) {
- sendnoticetouser(qabot_nick, np, "No such nickname.");
- return 0;
- }
-
- if (!IsAccount(victim)) {
- sendnoticetouser(qabot_nick, np, "%s is not authed.", victim->nick);
- return 0;
- }
-
- return victim->authname;
- }
-
- return target + 1;
-}
-
-const char* qabot_uflagtostr(flag_t flags) {
- static char buf[20];
- int i = 0;
-
- buf[i++] = '+';
-
- if (flags & QAUFLAG_ADMIN) { buf[i++] = 'a'; }
- if (flags & QAUFLAG_DEVELOPER) { buf[i++] = 'd'; }
- if (flags & QAUFLAG_STAFF) { buf[i++] = 's'; }
-
- buf[i] = '\0';
-
- return buf;
-}
-
-const char* qabot_formattime(time_t tme) {
- static char buf[50];
- struct tm* tmp;
-
- tmp = gmtime(&tme);
- strftime(buf, 15, "%d/%m/%y %H:%M", tmp);
-
- return buf;
-}
-
-qab_bot* qabot_getcurrentbot() {
- return qabot_currentbot;
-}
-
-channel* qabot_getcurrentchannel() {
- return qabot_currentchan;
-}
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+time_t qab_startime;\r
+int qabot_nickext;\r
+int qabot_spam_nickext;\r
+int qabot_chanext;\r
+nick* qabot_nick = 0;\r
+CommandTree* qabot_commands;\r
+CommandTree* qabot_chancommands;\r
+qab_bot* qab_bots = 0;\r
+unsigned long qab_lastq_crc = 0;\r
+int qab_lastq_count = 0;\r
+qab_bot* qabot_currentbot = 0;\r
+channel* qabot_currentchan = 0;\r
+\r
+void _init() {\r
+ qab_startime = time(0);\r
+ \r
+ registerhook(HOOK_NICK_LOSTNICK, qabot_lostnick);\r
+ registerhook(HOOK_CHANNEL_PART, qabot_channel_part);\r
+ \r
+ qabot_commands = newcommandtree();\r
+ addcommandtotree(qabot_commands, "showcommands", 0, 0, qabot_doshowcommands);\r
+ addcommandtotree(qabot_commands, "help", QAUFLAG_STAFF, 1, qabot_dohelp);\r
+ addcommandtotree(qabot_commands, "hello", 0, 0, qabot_dohello);\r
+ addcommandtotree(qabot_commands, "save", QAUFLAG_ADMIN, 0, qabot_dosave);\r
+ addcommandtotree(qabot_commands, "listbots", QAUFLAG_STAFF, 0, qabot_dolistbots);\r
+ addcommandtotree(qabot_commands, "listusers", QAUFLAG_STAFF, 0, qabot_dolistusers);\r
+ addcommandtotree(qabot_commands, "showbot", QAUFLAG_STAFF, 1, qabot_doshowbot);\r
+ addcommandtotree(qabot_commands, "addbot", QAUFLAG_STAFF, 6, qabot_doaddbot);\r
+ addcommandtotree(qabot_commands, "delbot", QAUFLAG_STAFF, 1, qabot_dodelbot);\r
+ addcommandtotree(qabot_commands, "adduser", QAUFLAG_ADMIN, 2, qabot_doadduser);\r
+ addcommandtotree(qabot_commands, "changelev", QAUFLAG_ADMIN, 2, qabot_dochangelev);\r
+ addcommandtotree(qabot_commands, "deluser", QAUFLAG_ADMIN, 1, qabot_dodeluser);\r
+ addcommandtotree(qabot_commands, "whois", QAUFLAG_STAFF, 1, qabot_dowhois);\r
+ addcommandtotree(qabot_commands, "status", QAUFLAG_DEVELOPER, 0, qabot_dostatus);\r
+ \r
+ qabot_chancommands = newcommandtree();\r
+ addcommandtotree(qabot_chancommands, "answer", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochananswer);\r
+ addcommandtotree(qabot_chancommands, "block", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanblock);\r
+ addcommandtotree(qabot_chancommands, "clear", QAC_STAFFCHAN, 0, qabot_dochanclear);\r
+ addcommandtotree(qabot_chancommands, "closechan", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanclosechan);\r
+ addcommandtotree(qabot_chancommands, "config", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanconfig);\r
+ addcommandtotree(qabot_chancommands, "help", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 1, qabot_dochanhelp);\r
+ addcommandtotree(qabot_chancommands, "listblocks", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanlistblocks);\r
+ addcommandtotree(qabot_chancommands, "mic", QAC_STAFFCHAN, 0, qabot_dochanmic);\r
+ addcommandtotree(qabot_chancommands, "moo", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanmoo);\r
+ addcommandtotree(qabot_chancommands, "offtopic", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 30, qabot_dochanofftopic);\r
+ addcommandtotree(qabot_chancommands, "openchan", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanopenchan);\r
+ addcommandtotree(qabot_chancommands, "ping", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanping);\r
+ addcommandtotree(qabot_chancommands, "reset", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 1, qabot_dochanreset);\r
+ addcommandtotree(qabot_chancommands, "spam", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 30, qabot_dochanspam);\r
+ addcommandtotree(qabot_chancommands, "status", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 0, qabot_dochanstatus);\r
+ addcommandtotree(qabot_chancommands, "unblock", QAC_QUESTIONCHAN|QAC_STAFFCHAN, 2, qabot_dochanunblock);\r
+\r
+ if ((qabot_nickext = registernickext("QABOT")) == -1) {\r
+ return;\r
+ }\r
+ \r
+ if ((qabot_spam_nickext = registernickext("QABOT_SPAM")) == -1) {\r
+ return;\r
+ }\r
+ \r
+ qabot_loaddb();\r
+\r
+ scheduleoneshot(time(NULL) + 1, &qabot_createfakeuser, NULL);\r
+ scheduleoneshot(time(NULL) + QABOT_SAVEWAIT, &qabot_savetimer, NULL);\r
+}\r
+\r
+void _fini() {\r
+ deregisterhook(HOOK_NICK_LOSTNICK, qabot_lostnick);\r
+ deregisterhook(HOOK_CHANNEL_PART, qabot_channel_part);\r
+ \r
+ deleteschedule(0, qabot_savetimer, NULL);\r
+ \r
+ qabot_savedb();\r
+ \r
+ while (qab_bots)\r
+ qabot_delbot(qab_bots);\r
+\r
+ if (qabot_nickext != -1)\r
+ releasenickext(qabot_nickext);\r
+ \r
+ if (qabot_spam_nickext != -1)\r
+ releasenickext(qabot_spam_nickext);\r
+\r
+ if (qabot_nick) {\r
+ deregisterlocaluser(qabot_nick, "Module unloaded.");\r
+ qabot_nick = NULL;\r
+ }\r
+\r
+ while (qabot_users)\r
+ qabot_squelchuser(qabot_users);\r
+ \r
+ deletecommandfromtree(qabot_commands, "showcommands", qabot_doshowcommands);\r
+ deletecommandfromtree(qabot_commands, "help", qabot_dohelp);\r
+ deletecommandfromtree(qabot_commands, "hello", qabot_dohello);\r
+ deletecommandfromtree(qabot_commands, "save", qabot_dosave);\r
+ deletecommandfromtree(qabot_commands, "listbots", qabot_dolistbots);\r
+ deletecommandfromtree(qabot_commands, "listusers", qabot_dolistusers);\r
+ deletecommandfromtree(qabot_commands, "showbot", qabot_doshowbot);\r
+ deletecommandfromtree(qabot_commands, "addbot", qabot_doaddbot);\r
+ deletecommandfromtree(qabot_commands, "delbot", qabot_dodelbot);\r
+ deletecommandfromtree(qabot_commands, "adduser", qabot_doadduser);\r
+ deletecommandfromtree(qabot_commands, "changelev", qabot_dochangelev);\r
+ deletecommandfromtree(qabot_commands, "deluser", qabot_dodeluser);\r
+ deletecommandfromtree(qabot_commands, "whois", qabot_dowhois);\r
+ deletecommandfromtree(qabot_commands, "status", qabot_dostatus);\r
+ destroycommandtree(qabot_commands);\r
+ \r
+ deletecommandfromtree(qabot_chancommands, "answer", qabot_dochananswer);\r
+ deletecommandfromtree(qabot_chancommands, "block", qabot_dochanblock);\r
+ deletecommandfromtree(qabot_chancommands, "clear", qabot_dochanclear);\r
+ deletecommandfromtree(qabot_chancommands, "closechan", qabot_dochanclosechan);\r
+ deletecommandfromtree(qabot_chancommands, "config", qabot_dochanconfig);\r
+ deletecommandfromtree(qabot_chancommands, "help", qabot_dochanhelp);\r
+ deletecommandfromtree(qabot_chancommands, "listblocks", qabot_dochanlistblocks);\r
+ deletecommandfromtree(qabot_chancommands, "mic", qabot_dochanmic);\r
+ deletecommandfromtree(qabot_chancommands, "moo", qabot_dochanmoo);\r
+ deletecommandfromtree(qabot_chancommands, "offtopic", qabot_dochanofftopic);\r
+ deletecommandfromtree(qabot_chancommands, "openchan", qabot_dochanopenchan);\r
+ deletecommandfromtree(qabot_chancommands, "ping", qabot_dochanping);\r
+ deletecommandfromtree(qabot_chancommands, "reset", qabot_dochanreset);\r
+ deletecommandfromtree(qabot_chancommands, "spam", qabot_dochanspam);\r
+ deletecommandfromtree(qabot_chancommands, "status", qabot_dochanstatus);\r
+ deletecommandfromtree(qabot_chancommands, "unblock", qabot_dochanunblock);\r
+ destroycommandtree(qabot_chancommands);\r
+}\r
+\r
+void qabot_lostnick(int hooknum, void* arg) {\r
+ nick* np = (nick*)arg;\r
+ qab_bot* b;\r
+ \r
+ if (!qab_bots)\r
+ return;\r
+ \r
+ if (!IsAccount(np))\r
+ return;\r
+ \r
+ for (b = qab_bots; b; b = b->next) {\r
+ if (b->micnumeric == np->numeric) {\r
+ b->micnumeric = 0;\r
+ sendmessagetochannel(b->np, b->staff_chan->channel, "Mic deactivated.");\r
+ if (!b->lastspam)\r
+ qabot_spamstored((void*)b);\r
+ }\r
+ }\r
+}\r
+\r
+void qabot_channel_part(int hooknum, void* arg) {\r
+ channel* cp = (channel*)((void**)arg)[0];\r
+ nick* np = (nick*)((void**)arg)[1];\r
+ qab_bot* b;\r
+ \r
+ if (!qab_bots)\r
+ return;\r
+ \r
+ if (!IsAccount(np))\r
+ return;\r
+ \r
+ for (b = qab_bots; b; b = b->next) {\r
+ if ((b->micnumeric == np->numeric) && (b->staff_chan->channel == cp)) {\r
+ b->micnumeric = 0;\r
+ sendmessagetochannel(b->np, b->staff_chan->channel, "Mic deactivated.");\r
+ if (!b->lastspam)\r
+ qabot_spamstored((void*)b);\r
+ }\r
+ }\r
+}\r
+\r
+void qabot_createfakeuser(void* arg) {\r
+ channel* cp;\r
+ \r
+ if ((qabot_nick = registerlocaluser(QABOT_NICK, QABOT_USER, QABOT_HOST,\r
+ QABOT_NAME, QABOT_ACCT, QABOT_UMDE, &qabot_handler))) {\r
+ if ((cp = findchannel(QABOT_HOMECHAN))) {\r
+ localjoinchannel(qabot_nick, cp);\r
+ localgetops(qabot_nick, cp);\r
+ }\r
+ else\r
+ localcreatechannel(qabot_nick, QABOT_HOMECHAN);\r
+ }\r
+}\r
+\r
+void qabot_handler(nick* me, int type, void** args) {\r
+ nick* sender;\r
+ Command* cmd;\r
+ channel* cp;\r
+ char* cargv[50];\r
+ int cargc;\r
+ qab_user* u;\r
+\r
+ switch (type) {\r
+ case LU_PRIVMSG:\r
+ case LU_SECUREMSG:\r
+ sender = (nick*)args[0];\r
+\r
+ if (!strncmp("\001VERSION", args[1], 8)) {\r
+ sendnoticetouser(qabot_nick, sender, "\001VERSION %s\001", QABOT_NAME);\r
+ return;\r
+ }\r
+\r
+ cargc = splitline((char*)args[1], cargv, 50, 0);\r
+ cmd = findcommandintree(qabot_commands, cargv[0], 1);\r
+ if (!cmd) {\r
+ sendnoticetouser(qabot_nick, sender, "Unknown command.");\r
+ return;\r
+ }\r
+\r
+ if (!IsAccount(sender)) {\r
+ sendnoticetouser(qabot_nick, sender, "You must be authed to use this command.");\r
+ return;\r
+ }\r
+\r
+ u = qabot_getuser(sender->authname);\r
+ if (cmd->level) {\r
+ if (!u) {\r
+ sendnoticetouser(qabot_nick, sender, "You need an account to use this command.");\r
+ return;\r
+ }\r
+\r
+ if ((cmd->level & QAUFLAG_STAFF) && !QAIsStaff(u)) {\r
+ sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");\r
+ return;\r
+ }\r
+\r
+ if ((cmd->level & QAUFLAG_ADMIN) && !QAIsAdmin(u)) {\r
+ sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");\r
+ return;\r
+ }\r
+ \r
+ if ((cmd->level & QAUFLAG_DEVELOPER) && !QAIsDeveloper(u)) {\r
+ sendnoticetouser(qabot_nick, sender, "You do not have access to this command.");\r
+ return;\r
+ }\r
+ }\r
+ \r
+ if (cmd->maxparams < (cargc-1)) {\r
+ rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));\r
+ cargc=(cmd->maxparams) + 1;\r
+ }\r
+ \r
+ (cmd->handler)((void*)sender, cargc - 1, &(cargv[1]));\r
+\r
+ break;\r
+\r
+ case LU_KILLED:\r
+ qabot_nick = NULL;\r
+ scheduleoneshot(time(NULL) + 1, &qabot_createfakeuser, NULL);\r
+ break;\r
+\r
+ case LU_KICKED:\r
+ cp = (channel*)args[1];\r
+ if (cp) {\r
+ localjoinchannel(qabot_nick, cp);\r
+ localgetops(qabot_nick, cp);\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+void qabot_child_handler(nick* me, int type, void** args) {\r
+ nick* sender;\r
+ channel* cp;\r
+ qab_bot* bot = me->exts[qabot_nickext];\r
+ char* text;\r
+ Command* cmd;\r
+ char* cargv[50];\r
+ int cargc;\r
+ \r
+ if (!bot) {\r
+ return;\r
+ }\r
+ \r
+ switch (type) {\r
+ case LU_CHANMSG:\r
+ sender = (nick*)args[0];\r
+ cp = (channel*)args[1];\r
+ text = (char*)args[2];\r
+ \r
+ if (*text == '!') {\r
+ cargc = splitline((char*)(++text), cargv, 50, 0);\r
+ cmd = findcommandintree(qabot_chancommands, cargv[0], 1);\r
+ if (!cmd) {\r
+ sendnoticetouser(me, sender, "Unknown command.");\r
+ return;\r
+ }\r
+ \r
+ if ((cp->index == bot->staff_chan) && !(cmd->level & QAC_STAFFCHAN)) {\r
+ sendnoticetouser(me, sender, "This command cannot be used in the staff channel.");\r
+ return;\r
+ }\r
+ \r
+ if ((cp->index == bot->question_chan) && !(cmd->level & QAC_QUESTIONCHAN)) {\r
+ sendnoticetouser(me, sender, "This command cannot be used in the question channel.");\r
+ return;\r
+ }\r
+ \r
+ if (cmd->maxparams < (cargc-1)) {\r
+ rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));\r
+ cargc=(cmd->maxparams) + 1;\r
+ }\r
+ \r
+ qabot_currentbot = bot;\r
+ qabot_currentchan = cp;\r
+ \r
+ (cmd->handler)((void*)sender, cargc - 1, &(cargv[1]));\r
+ }\r
+ else if ((*text != '!') && (bot->micnumeric == sender->numeric) && (cp->index == bot->staff_chan)) {\r
+ bot->lastmic = time(NULL);\r
+ if (bot->lastspam) {\r
+ qab_spam* s;\r
+ \r
+ s = (qab_spam*)malloc(sizeof(qab_spam));\r
+ s->message = strdup(text);\r
+ s->next = 0;\r
+ bot->lastspam->next = s;\r
+ bot->lastspam = s;\r
+ }\r
+ else {\r
+ if ((bot->spamtime + bot->spam_interval) < time(0)) {\r
+ sendmessagetochannel(me, bot->public_chan->channel, "%s", text);\r
+ bot->spammed++;\r
+ bot->spamtime = time(0);\r
+ }\r
+ else {\r
+ qab_spam* s;\r
+ \r
+ s = (qab_spam*)malloc(sizeof(qab_spam));\r
+ s->message = strdup(text);\r
+ s->next = 0;\r
+ bot->nextspam = bot->lastspam = s;\r
+ scheduleoneshot(bot->spamtime + bot->spam_interval, qabot_spam, (void*)bot);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ \r
+ case LU_PRIVMSG:\r
+ case LU_SECUREMSG:\r
+ sender = (nick*)args[0];\r
+ text = (char*)args[1];\r
+ time_t lastmsg;\r
+ \r
+ lastmsg = (time_t)sender->exts[qabot_spam_nickext];\r
+ \r
+ if ((lastmsg + bot->ask_wait) > time(0)) {\r
+ sendnoticetouser(me, sender, "You have already sent a question recently, please wait at least %d seconds between asking questions.", bot->ask_wait);\r
+ return;\r
+ }\r
+ else {\r
+ char hostbuf[NICKLEN + USERLEN + HOSTLEN + 3];\r
+ qab_block* b;\r
+ qab_question* q;\r
+ unsigned long crc;\r
+ int len;\r
+ \r
+ sendnoticetouser(me, sender, "Your question has been relayed to the %s staff.", bot->public_chan->name->content);\r
+ \r
+ if (!getnumerichandlefromchanhash(bot->public_chan->channel->users, sender->numeric))\r
+ return;\r
+ \r
+ if (*text == '<')\r
+ text++;\r
+ \r
+ len = strlen(text);\r
+ if ((len > 0) && (text[len - 1] == '>')) {\r
+ text[len - 1] = '\0';\r
+ len--;\r
+ }\r
+ \r
+ if ((len < 5) || !strchr(text, ' ') || (*text == 1))\r
+ return;\r
+ \r
+ if ((bot->flags & QAB_AUTHEDONLY) && !IsAccount(sender))\r
+ return;\r
+ \r
+ if (bot->flags & QAB_CONTROLCHAR) {\r
+ char* ch;\r
+ \r
+ for (ch = text; *ch; ch++)\r
+ if ((*ch == 2) || (*ch == 3) || (*ch == 22) || (*ch == 27) || (*ch == 31))\r
+ return;\r
+ }\r
+ else if (bot->flags & QAB_COLOUR) {\r
+ char* ch;\r
+ \r
+ for (ch = text; *ch; ch++)\r
+ if (*ch == 3)\r
+ return;\r
+ }\r
+ \r
+ if (bot->flags & QAB_FLOODDETECT) {\r
+ crc = crc32i(text);\r
+ if (crc == qab_lastq_crc) {\r
+ qab_lastq_count++;\r
+ if (qab_lastq_count >= 3) {\r
+ if ((qab_lastq_count == 3) || ((qab_lastq_count % 10) == 0))\r
+ sendmessagetochannel(me, bot->question_chan->channel, "WARNING: Possible question flood detected%s", (bot->flags & QAB_FLOODSTOP) ? " - AUTO IGNORED." : ".");\r
+ if (bot->flags & QAB_FLOODSTOP)\r
+ return;\r
+ }\r
+ }\r
+ else {\r
+ qab_lastq_crc = crc;\r
+ qab_lastq_count = 1;\r
+ }\r
+ }\r
+ \r
+ sprintf(hostbuf,"%s!%s@%s", sender->nick, sender->ident, sender->host->name->content);\r
+ \r
+ for (b = bot->blocks; b; b = b->next) {\r
+ switch (b->type) {\r
+ case QABBLOCK_ACCOUNT:\r
+ if (IsAccount(sender) && !ircd_strncmp(sender->authname, b->blockstr, ACCOUNTLEN))\r
+ return;\r
+ break;\r
+ \r
+ case QABBLOCK_HOST:\r
+ if (!match(b->blockstr, hostbuf))\r
+ return;\r
+ break;\r
+ \r
+ case QABBLOCK_TEXT:\r
+ if (!match(b->blockstr, text))\r
+ return;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ sender->exts[qabot_spam_nickext] = (void*)time(0);\r
+ \r
+ q = (qab_question*)malloc(sizeof(qab_question));\r
+ q->id = ++bot->lastquestionID;\r
+ q->question = strdup(text);\r
+ q->flags = QAQ_NEW;\r
+ strncpy(q->nick, sender->nick, NICKLEN);\r
+ q->nick[NICKLEN] = '\0';\r
+ q->numeric = sender->numeric;\r
+ q->crc = (bot->flags & QAB_FLOODDETECT) ? crc : 0;\r
+ q->answer = 0;\r
+ q->next = bot->questions[q->id % QUESTIONHASHSIZE];\r
+ \r
+ bot->questions[q->id % QUESTIONHASHSIZE] = q;\r
+ \r
+ sendmessagetochannel(me, bot->question_chan->channel, "ID: %3d <%s> %s", q->id, visiblehostmask(sender, hostbuf), text);\r
+ \r
+ if ((bot->flags & QAB_LINEBREAK) && ((bot->lastquestionID % 10) == 0))\r
+ sendmessagetochannel(me, bot->question_chan->channel, "-----------------------------------");\r
+ }\r
+ break;\r
+ \r
+ case LU_KILLED:\r
+ bot->np = NULL;\r
+ scheduleoneshot(time(NULL) + 1, &qabot_createbotfakeuser, (void*)bot);\r
+ break;\r
+\r
+ case LU_KICKED:\r
+ cp = (channel*)args[1];\r
+ if (cp) {\r
+ localjoinchannel(bot->np, cp);\r
+ localgetops(bot->np, cp);\r
+ }\r
+ break;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+char* qabot_getvictim(nick* np, char* target) {\r
+ if (*target != '#') {\r
+ nick* victim;\r
+ \r
+ if (!(victim = getnickbynick(target))) {\r
+ sendnoticetouser(qabot_nick, np, "No such nickname.");\r
+ return 0;\r
+ }\r
+ \r
+ if (!IsAccount(victim)) {\r
+ sendnoticetouser(qabot_nick, np, "%s is not authed.", victim->nick);\r
+ return 0;\r
+ }\r
+ \r
+ return victim->authname;\r
+ }\r
+ \r
+ return target + 1;\r
+}\r
+\r
+const char* qabot_uflagtostr(flag_t flags) {\r
+ static char buf[20];\r
+ int i = 0;\r
+ \r
+ buf[i++] = '+';\r
+ \r
+ if (flags & QAUFLAG_ADMIN) { buf[i++] = 'a'; }\r
+ if (flags & QAUFLAG_DEVELOPER) { buf[i++] = 'd'; }\r
+ if (flags & QAUFLAG_STAFF) { buf[i++] = 's'; }\r
+ \r
+ buf[i] = '\0';\r
+ \r
+ return buf;\r
+}\r
+\r
+const char* qabot_formattime(time_t tme) {\r
+ static char buf[50];\r
+ struct tm* tmp;\r
+ \r
+ tmp = gmtime(&tme);\r
+ strftime(buf, 15, "%d/%m/%y %H:%M", tmp);\r
+ \r
+ return buf;\r
+}\r
+\r
+qab_bot* qabot_getcurrentbot() {\r
+ return qabot_currentbot;\r
+}\r
+\r
+channel* qabot_getcurrentchannel() {\r
+ return qabot_currentchan;\r
+}\r
-/* qabot.h */
-#ifndef _QABOT_H
-#define _QABOT_H
-
-#define QABOT_NICK "QABot"
-#define QABOT_USER "qabot"
-#define QABOT_HOST "quakenet.org"
-#define QABOT_NAME "Question & Answer Bot v1.0"
-#define QABOT_ACCT "QABot"
-#define QABOT_UMDE UMODE_SERVICE|UMODE_OPER|UMODE_INV|UMODE_ACCOUNT
-#define QABOT_CHILD_UMODE UMODE_INV
-#define TUTOR_NAME "#tutorial bot"
-#define TUTOR_ACCOUNT "Tutor"
-
-#define QABOT_HOMECHAN "#qnet.pr"
-
-#define QAUFLAG_STAFF 0x01
-#define QAUFLAG_ADMIN 0x02
-#define QAUFLAG_DEVELOPER 0x04
-
-#define QAIsStaff(x) ((x)->flags & (QAUFLAG_STAFF|QAUFLAG_ADMIN|QAUFLAG_DEVELOPER))
-#define QAIsAdmin(x) ((x)->flags & (QAUFLAG_ADMIN|QAUFLAG_DEVELOPER))
-#define QAIsDeveloper(x) ((x)->flags & QAUFLAG_DEVELOPER)
-
-#define QUESTIONINTERVAL 30
-#define SPAMINTERVAL 10
-#define ASKWAIT 30
-#define QUEUEDQUESTIONINTERVAL 2
-#define QUESTIONHASHSIZE 1000
-
-#define QABOT_SAVEWAIT 3600
-
-#define QABOT_MICTIMEOUT 180
-
-#define QAB_CONTROLCHAR 0x01
-#define QAB_COLOUR 0x02
-#define QAB_AUTHEDONLY 0x04
-#define QAB_LINEBREAK 0x08
-#define QAB_FLOODDETECT 0x10
-#define QAB_FLOODSTOP 0x20
-#define QAB_BLOCKMARK 0x40
-/*#define QAB_
-#define QAB_*/
-
-#define QABBLOCK_ACCOUNT 0
-#define QABBLOCK_HOST 1
-#define QABBLOCK_TEXT 2
-
-#define QAQ_NEW 0x00
-#define QAQ_ANSWERED 0x01
-#define QAQ_OFFTOPIC 0x02
-#define QAQ_SPAM 0x03
-#define QAQ_QSTATE 0x07
-
-#define QAC_QUESTIONCHAN 0x01
-#define QAC_STAFFCHAN 0x02
-
-#define DEFAULTBOTFLAGS QAB_CONTROLCHAR|QAB_COLOUR|QAB_LINEBREAK|QAB_FLOODSTOP
-
-typedef struct qab_user {
- char authname[ACCOUNTLEN + 1];
- flag_t flags;
- time_t created;
-
- struct qab_user* next;
- struct qab_user* prev;
-} qab_user;
-
-typedef struct qab_spam {
- char* message;
-
- struct qab_spam* next;
-} qab_spam;
-
-typedef struct qab_question {
- int id;
- char* question;
- flag_t flags;
- char nick[NICKLEN + 1];
- unsigned long numeric;
- unsigned long crc;
- char* answer;
-
- struct qab_question* next;
-} qab_question;
-
-typedef struct qab_answer {
- qab_question* question;
- char nick[NICKLEN + 1];
-
- struct qab_answer* next;
-} qab_answer;
-
-typedef struct qab_block {
- char type;
- char creator[ACCOUNTLEN + 1];
- time_t created;
- char* blockstr;
-
- struct qab_block* next;
- struct qab_block* prev;
-} qab_block;
-
-typedef struct qab_textsection {
- qab_spam* lines;
- qab_spam* lines_tail;
- int line_count;
-
- struct qab_textsection* next;
- struct qab_textsection* prev;
-} qab_textsection;
-
-typedef struct qab_text {
- char name[NICKLEN + 1];
- qab_textsection* sections;
- qab_textsection* sections_tail;
- int section_count;
-
- struct qab_text* next;
- struct qab_text* prev;
-} qab_text;
-
-typedef struct qab_bot {
- char nick[NICKLEN + 1];
- char user[USERLEN + 1];
- char* host;
-
- nick* np;
-
- chanindex* public_chan;
- chanindex* question_chan;
- chanindex* staff_chan;
-
- flag_t flags;
-
- /*int question_interval;*/
- int spam_interval;
- int ask_wait;
- int queued_question_interval;
-
- time_t lastmic;
- int mic_timeout;
-
- qab_block* blocks;
- int block_count;
-
- qab_question* questions[QUESTIONHASHSIZE];
- int lastquestionID;
- int answered;
-
- int spammed;
-
- qab_spam* nextspam;
- qab_spam* lastspam;
- time_t spamtime;
-
- qab_answer* answers;
-
- unsigned long micnumeric;
-
- qab_textsection* recording_section;
- qab_text* texts;
-
- struct qab_bot* next;
- struct qab_bot* prev;
-} qab_bot;
-
-extern time_t qab_startime;
-extern int qabot_nickext;
-extern int qabot_spam_nickext;
-extern int qabot_chanext;
-extern nick* qabot_nick;
-extern CommandTree* qabot_commands;
-extern qab_user* qabot_users;
-extern qab_bot* qab_bots;
-extern unsigned long qab_lastq_crc;
-extern int qab_lastq_count;
-
-/* qabot.c */
-void qabot_lostnick(int hooknum, void* arg);
-void qabot_channel_part(int hooknum, void* arg);
-void qabot_createfakeuser(void* arg);
-void qabot_handler(nick* me, int type, void** args);
-void qabot_child_handler(nick* me, int type, void** args);
-char* qabot_getvictim(nick* np, char* target);
-const char* qabot_uflagtostr(flag_t flags);
-const char* qabot_formattime(time_t tme);
-
-/* qabot_bot.c */
-qab_bot* qabot_getbot();
-int qabot_addbot(char* nickname, char* user, char* host, char* pub_chan, char* qu_chan, char* stff_chan, flag_t flags, int spam_interval, int ask_wait, int queued_question_interval, nick* sender);
-void qabot_delbot(qab_bot* bot);
-channel* qabot_getchannel(char* channel_name);
-void qabot_spam(void* arg);
-void qabot_spamstored(void* arg);
-void qabot_createbotfakeuser(void* arg);
-qab_bot* qabot_getcurrentbot();
-channel* qabot_getcurrentchannel();
-void qabot_timer(void* arg);
-
-/* qabot_chancommands.c */
-int qabot_dochananswer(void* np, int cargc, char** cargv);
-int qabot_dochanblock(void* np, int cargc, char** cargv);
-int qabot_dochanclear(void* np, int cargc, char** cargv);
-int qabot_dochanclosechan(void* np, int cargc, char** cargv);
-int qabot_dochanconfig(void* np, int cargc, char** cargv);
-int qabot_dochanhelp(void* np, int cargc, char** cargv);
-int qabot_dochanlistblocks(void* np, int cargc, char** cargv);
-int qabot_dochanmic(void* np, int cargc, char** cargv);
-int qabot_dochanmoo(void* np, int cargc, char** cargv);
-int qabot_dochanofftopic(void* np, int cargc, char** cargv);
-int qabot_dochanopenchan(void* np, int cargc, char** cargv);
-int qabot_dochanping(void* np, int cargc, char** cargv);
-int qabot_dochanreset(void* np, int cargc, char** cargv);
-int qabot_dochanspam(void* np, int cargc, char** cargv);
-int qabot_dochanstatus(void* np, int cargc, char** cargv);
-int qabot_dochanunblock(void* np, int cargc, char** cargv);
-int qabot_dochanlisttexts(void* np, int cargc, char** cargv);
-int qabot_dochanshowsection(void* np, int cargc, char** cargv);
-int qabot_dochanaddtext(void* np, int cargc, char** cargv);
-int qabot_dochandeltext(void* np, int cargc, char** cargv);
-int qabot_dochanaddsection(void* np, int cargc, char** cargv);
-int qabot_dochandelsection(void* np, int cargc, char** cargv);
-int qabot_dochanrecord(void* np, int cargc, char** cargv);
-
-/* qabot_commands.c */
-int qabot_doshowcommands(void* sender, int cargc, char** cargv);
-int qabot_dohelp(void* sender, int cargc, char** cargv);
-int qabot_dohello(void* sender, int cargc, char** cargv);
-int qabot_dosave(void* sender, int cargc, char** cargv);
-int qabot_dolistbots(void* sender, int cargc, char** cargv);
-int qabot_dolistusers(void* sender, int cargc, char** cargv);
-int qabot_doshowbot(void* sender, int cargc, char** cargv);
-int qabot_doaddbot(void* sender, int cargc, char** cargv);
-int qabot_dodelbot(void* sender, int cargc, char** cargv);
-int qabot_doadduser(void* sender, int cargc, char** cargv);
-int qabot_dodeluser(void* sender, int cargc, char** cargv);
-int qabot_dochangelev(void* sender, int cargc, char** cargv);
-int qabot_dowhois(void* sender, int cargc, char** cargv);
-int qabot_dostatus(void* sender, int cargc, char** cargv);
-
-/* qabot_dbase.c */
-void qabot_loaddb();
-void qabot_savedb();
-void qabot_savetimer(void* arg);
-void qabot_adduser(const char* authname, flag_t flags, time_t created);
-void qabot_deluser(const char* authname);
-void qabot_squelchuser(qab_user* user);
-qab_user* qabot_getuser(const char* authname);
-qab_bot* qabot_findbot(const char* nickname);
-
-/* qabot_help.c */
-int qabot_showhelp(nick* np, char* arg);
-
-/* qabot_texts.c */
-void qabot_freetext(qab_bot* bot, qab_text* text);
-void qabot_freesection(qab_text* text, qab_textsection* section);
-
-#endif
+/* qabot.h */\r
+#ifndef _QABOT_H\r
+#define _QABOT_H\r
+\r
+#define QABOT_NICK "QABot"\r
+#define QABOT_USER "qabot"\r
+#define QABOT_HOST "quakenet.org"\r
+#define QABOT_NAME "Question & Answer Bot v1.0"\r
+#define QABOT_ACCT "QABot"\r
+#define QABOT_UMDE UMODE_SERVICE|UMODE_OPER|UMODE_INV|UMODE_ACCOUNT\r
+#define QABOT_CHILD_UMODE UMODE_INV\r
+#define TUTOR_NAME "#tutorial bot"\r
+#define TUTOR_ACCOUNT "Tutor"\r
+\r
+#define QABOT_HOMECHAN "#qnet.pr"\r
+\r
+#define QAUFLAG_STAFF 0x01\r
+#define QAUFLAG_ADMIN 0x02\r
+#define QAUFLAG_DEVELOPER 0x04\r
+\r
+#define QAIsStaff(x) ((x)->flags & (QAUFLAG_STAFF|QAUFLAG_ADMIN|QAUFLAG_DEVELOPER))\r
+#define QAIsAdmin(x) ((x)->flags & (QAUFLAG_ADMIN|QAUFLAG_DEVELOPER))\r
+#define QAIsDeveloper(x) ((x)->flags & QAUFLAG_DEVELOPER)\r
+\r
+#define QUESTIONINTERVAL 30\r
+#define SPAMINTERVAL 10\r
+#define ASKWAIT 30\r
+#define QUEUEDQUESTIONINTERVAL 2\r
+#define QUESTIONHASHSIZE 1000\r
+\r
+#define QABOT_SAVEWAIT 3600\r
+\r
+#define QABOT_MICTIMEOUT 180\r
+\r
+#define QAB_CONTROLCHAR 0x01\r
+#define QAB_COLOUR 0x02\r
+#define QAB_AUTHEDONLY 0x04\r
+#define QAB_LINEBREAK 0x08\r
+#define QAB_FLOODDETECT 0x10\r
+#define QAB_FLOODSTOP 0x20\r
+#define QAB_BLOCKMARK 0x40\r
+/*#define QAB_\r
+#define QAB_*/\r
+\r
+#define QABBLOCK_ACCOUNT 0\r
+#define QABBLOCK_HOST 1\r
+#define QABBLOCK_TEXT 2\r
+\r
+#define QAQ_NEW 0x00\r
+#define QAQ_ANSWERED 0x01\r
+#define QAQ_OFFTOPIC 0x02\r
+#define QAQ_SPAM 0x03\r
+#define QAQ_QSTATE 0x07\r
+\r
+#define QAC_QUESTIONCHAN 0x01\r
+#define QAC_STAFFCHAN 0x02\r
+\r
+#define DEFAULTBOTFLAGS QAB_CONTROLCHAR|QAB_COLOUR|QAB_LINEBREAK|QAB_FLOODSTOP\r
+\r
+typedef struct qab_user {\r
+ char authname[ACCOUNTLEN + 1];\r
+ flag_t flags;\r
+ time_t created;\r
+\r
+ struct qab_user* next;\r
+ struct qab_user* prev;\r
+} qab_user;\r
+\r
+typedef struct qab_spam {\r
+ char* message;\r
+ \r
+ struct qab_spam* next;\r
+} qab_spam;\r
+\r
+typedef struct qab_question {\r
+ int id;\r
+ char* question;\r
+ flag_t flags;\r
+ char nick[NICKLEN + 1];\r
+ unsigned long numeric;\r
+ unsigned long crc;\r
+ char* answer;\r
+ \r
+ struct qab_question* next;\r
+} qab_question;\r
+\r
+typedef struct qab_answer {\r
+ qab_question* question;\r
+ char nick[NICKLEN + 1];\r
+ \r
+ struct qab_answer* next;\r
+} qab_answer;\r
+\r
+typedef struct qab_block {\r
+ char type;\r
+ char creator[ACCOUNTLEN + 1];\r
+ time_t created;\r
+ char* blockstr;\r
+\r
+ struct qab_block* next;\r
+ struct qab_block* prev;\r
+} qab_block;\r
+\r
+typedef struct qab_bot {\r
+ char nick[NICKLEN + 1];\r
+ char user[USERLEN + 1];\r
+ char* host;\r
+ \r
+ nick* np;\r
+ \r
+ chanindex* public_chan;\r
+ chanindex* question_chan;\r
+ chanindex* staff_chan;\r
+ \r
+ flag_t flags;\r
+ \r
+ /*int question_interval;*/\r
+ int spam_interval;\r
+ int ask_wait;\r
+ int queued_question_interval;\r
+ \r
+ time_t lastmic;\r
+ int mic_timeout;\r
+ \r
+ qab_block* blocks;\r
+ int block_count;\r
+ \r
+ qab_question* questions[QUESTIONHASHSIZE];\r
+ int lastquestionID;\r
+ int answered;\r
+ \r
+ int spammed;\r
+ \r
+ qab_spam* nextspam;\r
+ qab_spam* lastspam;\r
+ time_t spamtime;\r
+ \r
+ qab_answer* answers;\r
+ \r
+ unsigned long micnumeric;\r
+\r
+ struct qab_bot* next;\r
+ struct qab_bot* prev;\r
+} qab_bot;\r
+\r
+extern time_t qab_startime;\r
+extern int qabot_nickext;\r
+extern int qabot_spam_nickext;\r
+extern int qabot_chanext;\r
+extern nick* qabot_nick;\r
+extern CommandTree* qabot_commands;\r
+extern qab_user* qabot_users;\r
+extern qab_bot* qab_bots;\r
+extern unsigned long qab_lastq_crc;\r
+extern int qab_lastq_count;\r
+\r
+/* qabot.c */\r
+void qabot_lostnick(int hooknum, void* arg);\r
+void qabot_channel_part(int hooknum, void* arg);\r
+void qabot_createfakeuser(void* arg);\r
+void qabot_handler(nick* me, int type, void** args);\r
+void qabot_child_handler(nick* me, int type, void** args);\r
+char* qabot_getvictim(nick* np, char* target);\r
+const char* qabot_uflagtostr(flag_t flags);\r
+const char* qabot_formattime(time_t tme);\r
+\r
+/* qabot_bot.c */\r
+qab_bot* qabot_getbot();\r
+int qabot_addbot(char* nickname, char* user, char* host, char* pub_chan, char* qu_chan, char* stff_chan, flag_t flags, int spam_interval, int ask_wait, int queued_question_interval, nick* sender);\r
+void qabot_delbot(qab_bot* bot);\r
+channel* qabot_getchannel(char* channel_name);\r
+void qabot_spam(void* arg);\r
+void qabot_spamstored(void* arg);\r
+void qabot_createbotfakeuser(void* arg);\r
+qab_bot* qabot_getcurrentbot();\r
+channel* qabot_getcurrentchannel();\r
+void qabot_timer(void* arg);\r
+\r
+/* qabot_chancommands.c */\r
+int qabot_dochananswer(void* np, int cargc, char** cargv);\r
+int qabot_dochanblock(void* np, int cargc, char** cargv);\r
+int qabot_dochanclear(void* np, int cargc, char** cargv);\r
+int qabot_dochanclosechan(void* np, int cargc, char** cargv);\r
+int qabot_dochanconfig(void* np, int cargc, char** cargv);\r
+int qabot_dochanhelp(void* np, int cargc, char** cargv);\r
+int qabot_dochanlistblocks(void* np, int cargc, char** cargv);\r
+int qabot_dochanmic(void* np, int cargc, char** cargv);\r
+int qabot_dochanmoo(void* np, int cargc, char** cargv);\r
+int qabot_dochanofftopic(void* np, int cargc, char** cargv);\r
+int qabot_dochanopenchan(void* np, int cargc, char** cargv);\r
+int qabot_dochanping(void* np, int cargc, char** cargv);\r
+int qabot_dochanreset(void* np, int cargc, char** cargv);\r
+int qabot_dochanspam(void* np, int cargc, char** cargv);\r
+int qabot_dochanstatus(void* np, int cargc, char** cargv);\r
+int qabot_dochanunblock(void* np, int cargc, char** cargv);\r
+\r
+/* qabot_commands.c */\r
+int qabot_doshowcommands(void* sender, int cargc, char** cargv);\r
+int qabot_dohelp(void* sender, int cargc, char** cargv);\r
+int qabot_dohello(void* sender, int cargc, char** cargv);\r
+int qabot_dosave(void* sender, int cargc, char** cargv);\r
+int qabot_dolistbots(void* sender, int cargc, char** cargv);\r
+int qabot_dolistusers(void* sender, int cargc, char** cargv);\r
+int qabot_doshowbot(void* sender, int cargc, char** cargv);\r
+int qabot_doaddbot(void* sender, int cargc, char** cargv);\r
+int qabot_dodelbot(void* sender, int cargc, char** cargv);\r
+int qabot_doadduser(void* sender, int cargc, char** cargv);\r
+int qabot_dodeluser(void* sender, int cargc, char** cargv);\r
+int qabot_dochangelev(void* sender, int cargc, char** cargv);\r
+int qabot_dowhois(void* sender, int cargc, char** cargv);\r
+int qabot_dostatus(void* sender, int cargc, char** cargv);\r
+\r
+/* qabot_dbase.c */\r
+void qabot_loaddb();\r
+void qabot_savedb();\r
+void qabot_savetimer(void* arg);\r
+void qabot_adduser(const char* authname, flag_t flags, time_t created);\r
+void qabot_deluser(const char* authname);\r
+void qabot_squelchuser(qab_user* user);\r
+qab_user* qabot_getuser(const char* authname);\r
+\r
+/* qabot_help.c */\r
+int qabot_showhelp(nick* np, char* arg);\r
+\r
+#endif\r
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-qab_bot* qabot_getbot() {
- qab_bot* bot;
- int i;
-
- bot = (qab_bot*)malloc(sizeof(qab_bot));
- bot->nick[0] = '\0';
- bot->user[0] = '\0';
- bot->host = 0;
- bot->np = 0;
- bot->public_chan = 0;
- bot->question_chan = 0;
- bot->staff_chan = 0;
- bot->blocks = 0;
- bot->block_count = 0;
-
- bot->spammed = 0;
-
- bot->flags = DEFAULTBOTFLAGS;
-
- /*bot->question_interval = QUESTIONINTERVAL;*/
- bot->spam_interval = SPAMINTERVAL;
- bot->ask_wait = ASKWAIT;
- bot->queued_question_interval = QUEUEDQUESTIONINTERVAL;
-
- bot->lastquestionID = 0;
- bot->answered = 0;
-
- for (i = 0; i < QUESTIONHASHSIZE; i++)
- bot->questions[i] = 0;
-
- bot->nextspam = 0;
- bot->lastspam = 0;
- bot->spamtime = 0;
- bot->answers = 0;
-
- bot->micnumeric = 0;
-
- bot->recording_section = 0;
- bot->texts = 0;
-
- bot->next = 0;
- bot->prev = 0;
-}
-
-int qabot_addbot(char* nickname, char* user, char* host, char* pub_chan, char* qu_chan, char* stff_chan, flag_t flags, int spam_interval,
- int ask_wait, int queued_question_interval, nick* sender) {
- qab_bot* bot;
- channel* cp;
-
- if (*pub_chan != '#') {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "Invalid public channel.");
- return 0;
- }
-
- if (*qu_chan != '#') {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "Invalid question channel.");
- return 0;
- }
-
- if (*stff_chan != '#') {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "Invalid staff channel.");
- return 0;
- }
-
- for (bot = qab_bots; bot; bot = bot->next) {
- if (!ircd_strcmp(bot->nick, nickname)) {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "That QABot already exists.");
- return 0;
- }
-
- if (!ircd_strcmp(bot->public_chan->name->content, pub_chan)) {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "That public channel is already in use by %s.", bot->nick);
- return 0;
- }
-
- if (!ircd_strcmp(bot->question_chan->name->content, qu_chan)) {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "That question channel is already in use by %s.", bot->nick);
- return 0;
- }
-
- if (!ircd_strcmp(bot->staff_chan->name->content, stff_chan)) {
- if (sender)
- sendnoticetouser(qabot_nick, sender, "That staff channel is already in use by %s.", bot->nick);
- return 0;
- }
- }
-
- bot = qabot_getbot();
- strncpy(bot->nick, nickname, NICKLEN);
- bot->nick[NICKLEN] = '\0';
- strncpy(bot->user, user, USERLEN);
- bot->user[USERLEN] = '\0';
- bot->host = strdup(host);
- if (!ircd_strcmp(nickname, "Tutor"))
- bot->np = registerlocaluser(nickname, user, host, TUTOR_NAME, TUTOR_ACCOUNT, QABOT_CHILD_UMODE|UMODE_ACCOUNT, &qabot_child_handler);
- else
- bot->np = registerlocaluser(nickname, user, host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);
-
- bot->flags = flags;
- bot->spam_interval = spam_interval;
- bot->ask_wait = ask_wait;
- bot->queued_question_interval = queued_question_interval;
-
- bot->mic_timeout = QABOT_MICTIMEOUT;
-
- bot->lastmic = 0;
-
- if ((cp = findchannel(pub_chan))) {
- localjoinchannel(bot->np, cp);
- localgetops(bot->np, cp);
- bot->public_chan = cp->index;
- }
- else {
- localcreatechannel(bot->np, pub_chan);
- cp = findchannel(pub_chan);
- bot->public_chan = cp->index;
- }
-
- if ((cp = findchannel(qu_chan))) {
- localjoinchannel(bot->np, cp);
- bot->question_chan = cp->index;
- }
- else {
- localcreatechannel(bot->np, qu_chan);
- cp = findchannel(qu_chan);
- bot->question_chan = cp->index;
- }
-
- if (!IsModerated(cp)) {
- irc_send("%s M %s +m\r\n", mynumeric->content, cp->index->name->content);
- SetModerated(cp);
- }
-
- if ((cp = findchannel(stff_chan))) {
- localjoinchannel(bot->np, cp);
- localgetops(bot->np, cp);
- bot->staff_chan = cp->index;
- }
- else {
- localcreatechannel(bot->np, stff_chan);
- cp = findchannel(stff_chan);
- bot->staff_chan = cp->index;
- }
-
- bot->next = qab_bots;
- if (qab_bots)
- qab_bots->prev = bot;
- qab_bots = bot;
-
- bot->np->exts[qabot_nickext] = (void*)bot;
-
- scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);
-
- return 1;
-}
-
-void qabot_delbot(qab_bot* bot) {
- qab_block* b;
- qab_question* q;
- qab_spam* s;
- qab_spam* ns;
- qab_answer* a;
- qab_answer* na;
- int i;
-
- deleteschedule(0, qabot_spam, (void*)bot);
- deleteschedule(0, qabot_spamstored, (void*)bot);
- deleteschedule(0, qabot_createbotfakeuser, (void*)bot);
- deleteschedule(0, qabot_timer, (void*)bot);
-
- while (bot->texts)
- qabot_freetext(bot, texts);
-
- while (bot->blocks) {
- b = bot->blocks;
- bot->blocks = bot->blocks->next;
- if (b->blockstr)
- free(b->blockstr);
- free(b);
- }
-
- for (i = 0; i < QUESTIONHASHSIZE; i++) {
- while (bot->questions[i]) {
- q = bot->questions[i];
- bot->questions[i] = bot->questions[i]->next;
- if (q->question)
- free(q->question);
- if (q->answer)
- free(q->answer);
- free(q);
- }
- }
-
- for (s = bot->nextspam; s; s = ns) {
- ns = s->next;
- free(s->message);
- free(s);
- }
-
- for (a = bot->answers; a; a = na) {
- na = a->next;
- free(a);
- }
-
- if (bot->host)
- free(bot->host);
- deregisterlocaluser(bot->np, "Bot deleted.");
-
- if (bot->next)
- bot->next->prev = bot->prev;
- if (bot->prev)
- bot->prev->next = bot->next;
- else
- qab_bots = bot->next;
-
- free(bot);
-}
-
-void qabot_spam(void* arg) {
- qab_bot* bot = (qab_bot*)arg;
- qab_spam* s;
-
- if (!bot->nextspam)
- return;
-
- if (bot->np) {
- sendmessagetochannel(bot->np, bot->public_chan->channel, "%s", bot->nextspam->message);
- bot->spammed++;
- }
-
- s = bot->nextspam;
- bot->nextspam = s->next;
-
- free(s->message);
- free(s);
-
- bot->spamtime = time(0);
-
- if (bot->nextspam)
- scheduleoneshot(bot->spamtime + bot->spam_interval, qabot_spam, (void*)bot);
- else {
- bot->lastspam = 0;
- if (!bot->micnumeric)
- qabot_spamstored((void*)bot);
- }
-}
-
-void qabot_spamstored(void* arg) {
- qab_bot* bot = (qab_bot*)arg;
- qab_answer* a;
-
- if (!bot->answers)
- return;
-
- if (bot->np) {
- sendmessagetochannel(bot->np, bot->public_chan->channel, "%s asked: %s", bot->answers->question->nick,
- bot->answers->question->question);
- sendmessagetochannel(bot->np, bot->public_chan->channel, "%s answered: %s", bot->answers->nick,
- bot->answers->question->answer);
- }
-
- a = bot->answers;
- bot->answers = a->next;
-
- free(a);
-
- if (bot->answers)
- scheduleoneshot(time(0) + bot->queued_question_interval, qabot_spamstored, (void*)bot);
-}
-
-void qabot_createbotfakeuser(void* arg) {
- qab_bot* bot = (qab_bot*)arg;
-
- if (bot->np)
- return;
-
- bot->np = registerlocaluser(bot->nick, bot->user, bot->host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);
-
- bot->np->exts[qabot_nickext] = (void*)bot;
-
- if (bot->public_chan->channel) {
- localjoinchannel(bot->np, bot->public_chan->channel);
- localgetops(bot->np, bot->public_chan->channel);
- }
- else
- localcreatechannel(bot->np, bot->public_chan->name->content);
-
- if (bot->question_chan->channel) {
- localjoinchannel(bot->np, bot->question_chan->channel);
- localgetops(bot->np, bot->question_chan->channel);
- }
- else
- localcreatechannel(bot->np, bot->question_chan->name->content);
-
- if (bot->staff_chan->channel) {
- localjoinchannel(bot->np, bot->staff_chan->channel);
- localgetops(bot->np, bot->staff_chan->channel);
- }
- else
- localcreatechannel(bot->np, bot->staff_chan->name->content);
-}
-
-void qabot_timer(void* arg) {
- qab_bot* bot = (qab_bot*)arg;
-
- if (!bot)
- return;
-
- if (bot->micnumeric && (bot->mic_timeout > 0) && (time(NULL) >= (bot->lastmic + bot->mic_timeout))) {
- bot->micnumeric = 0;
-
- sendmessagetochannel(bot->np, bot->staff_chan->channel, "%s deactivated (idle timeout).",
- bot->recording_section ? "Recorder" : "Mic");
- if (!bot->lastspam && !bot->recording_section)
- qabot_spamstored((void*)bot);
-
- bot->recording_section = 0;
- }
-
- scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);
-}
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+qab_bot* qabot_getbot() {\r
+ qab_bot* bot;\r
+ int i;\r
+ \r
+ bot = (qab_bot*)malloc(sizeof(qab_bot));\r
+ bot->nick[0] = '\0';\r
+ bot->user[0] = '\0';\r
+ bot->host = 0;\r
+ bot->np = 0;\r
+ bot->public_chan = 0;\r
+ bot->question_chan = 0;\r
+ bot->staff_chan = 0;\r
+ bot->blocks = 0;\r
+ bot->block_count = 0;\r
+ \r
+ bot->spammed = 0;\r
+ \r
+ bot->flags = DEFAULTBOTFLAGS;\r
+ \r
+ /*bot->question_interval = QUESTIONINTERVAL;*/\r
+ bot->spam_interval = SPAMINTERVAL;\r
+ bot->ask_wait = ASKWAIT;\r
+ bot->queued_question_interval = QUEUEDQUESTIONINTERVAL;\r
+ \r
+ bot->lastquestionID = 0;\r
+ bot->answered = 0;\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++)\r
+ bot->questions[i] = 0;\r
+ \r
+ bot->nextspam = 0;\r
+ bot->lastspam = 0;\r
+ bot->spamtime = 0;\r
+ bot->answers = 0;\r
+ \r
+ bot->micnumeric = 0;\r
+ \r
+ bot->next = 0;\r
+ bot->prev = 0;\r
+}\r
+\r
+int qabot_addbot(char* nickname, char* user, char* host, char* pub_chan, char* qu_chan, char* stff_chan, flag_t flags, int spam_interval, \r
+ int ask_wait, int queued_question_interval, nick* sender) {\r
+ qab_bot* bot;\r
+ channel* cp;\r
+ \r
+ if (*pub_chan != '#') {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "Invalid public channel.");\r
+ return 0;\r
+ }\r
+ \r
+ if (*qu_chan != '#') {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "Invalid question channel.");\r
+ return 0;\r
+ }\r
+ \r
+ if (*stff_chan != '#') {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "Invalid staff channel.");\r
+ return 0;\r
+ }\r
+ \r
+ for (bot = qab_bots; bot; bot = bot->next) {\r
+ if (!ircd_strcmp(bot->nick, nickname)) {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "That QABot already exists.");\r
+ return 0;\r
+ }\r
+ \r
+ if (!ircd_strcmp(bot->public_chan->name->content, pub_chan)) {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "That public channel is already in use by %s.", bot->nick);\r
+ return 0;\r
+ }\r
+ \r
+ if (!ircd_strcmp(bot->question_chan->name->content, qu_chan)) {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "That question channel is already in use by %s.", bot->nick);\r
+ return 0;\r
+ }\r
+ \r
+ if (!ircd_strcmp(bot->staff_chan->name->content, stff_chan)) {\r
+ if (sender)\r
+ sendnoticetouser(qabot_nick, sender, "That staff channel is already in use by %s.", bot->nick);\r
+ return 0;\r
+ }\r
+ }\r
+ \r
+ bot = qabot_getbot();\r
+ strncpy(bot->nick, nickname, NICKLEN);\r
+ bot->nick[NICKLEN] = '\0';\r
+ strncpy(bot->user, user, USERLEN);\r
+ bot->user[USERLEN] = '\0';\r
+ bot->host = strdup(host);\r
+ if (!ircd_strcmp(nickname, "Tutor"))\r
+ bot->np = registerlocaluser(nickname, user, host, TUTOR_NAME, TUTOR_ACCOUNT, QABOT_CHILD_UMODE|UMODE_ACCOUNT, &qabot_child_handler);\r
+ else\r
+ bot->np = registerlocaluser(nickname, user, host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);\r
+ \r
+ bot->flags = flags;\r
+ bot->spam_interval = spam_interval;\r
+ bot->ask_wait = ask_wait;\r
+ bot->queued_question_interval = queued_question_interval;\r
+ \r
+ bot->mic_timeout = QABOT_MICTIMEOUT;\r
+ \r
+ bot->lastmic = 0;\r
+ \r
+ if ((cp = findchannel(pub_chan))) {\r
+ localjoinchannel(bot->np, cp);\r
+ localgetops(bot->np, cp);\r
+ bot->public_chan = cp->index;\r
+ }\r
+ else {\r
+ localcreatechannel(bot->np, pub_chan);\r
+ cp = findchannel(pub_chan);\r
+ bot->public_chan = cp->index;\r
+ }\r
+ \r
+ if ((cp = findchannel(qu_chan))) {\r
+ localjoinchannel(bot->np, cp);\r
+ bot->question_chan = cp->index;\r
+ }\r
+ else {\r
+ localcreatechannel(bot->np, qu_chan);\r
+ cp = findchannel(qu_chan);\r
+ bot->question_chan = cp->index;\r
+ }\r
+ \r
+ if (!IsModerated(cp)) {\r
+ irc_send("%s M %s +m\r\n", mynumeric->content, cp->index->name->content);\r
+ SetModerated(cp);\r
+ }\r
+ \r
+ if ((cp = findchannel(stff_chan))) {\r
+ localjoinchannel(bot->np, cp);\r
+ localgetops(bot->np, cp);\r
+ bot->staff_chan = cp->index;\r
+ }\r
+ else {\r
+ localcreatechannel(bot->np, stff_chan);\r
+ cp = findchannel(stff_chan);\r
+ bot->staff_chan = cp->index;\r
+ }\r
+ \r
+ bot->next = qab_bots;\r
+ if (qab_bots)\r
+ qab_bots->prev = bot;\r
+ qab_bots = bot;\r
+ \r
+ bot->np->exts[qabot_nickext] = (void*)bot;\r
+ \r
+ scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);\r
+ \r
+ return 1;\r
+}\r
+\r
+void qabot_delbot(qab_bot* bot) {\r
+ qab_block* b;\r
+ qab_question* q;\r
+ qab_spam* s;\r
+ qab_spam* ns;\r
+ qab_answer* a;\r
+ qab_answer* na;\r
+ int i;\r
+ \r
+ deleteschedule(0, qabot_spam, (void*)bot);\r
+ deleteschedule(0, qabot_spamstored, (void*)bot);\r
+ deleteschedule(0, qabot_createbotfakeuser, (void*)bot);\r
+ deleteschedule(0, qabot_timer, (void*)bot);\r
+ \r
+ while (bot->blocks) {\r
+ b = bot->blocks;\r
+ bot->blocks = bot->blocks->next;\r
+ if (b->blockstr)\r
+ free(b->blockstr);\r
+ free(b);\r
+ }\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++) {\r
+ while (bot->questions[i]) {\r
+ q = bot->questions[i];\r
+ bot->questions[i] = bot->questions[i]->next;\r
+ if (q->question)\r
+ free(q->question);\r
+ if (q->answer)\r
+ free(q->answer);\r
+ free(q);\r
+ }\r
+ }\r
+ \r
+ for (s = bot->nextspam; s; s = ns) {\r
+ ns = s->next;\r
+ free(s->message);\r
+ free(s);\r
+ }\r
+ \r
+ for (a = bot->answers; a; a = na) {\r
+ na = a->next;\r
+ free(a);\r
+ }\r
+ \r
+ if (bot->host)\r
+ free(bot->host);\r
+ deregisterlocaluser(bot->np, "Bot deleted.");\r
+ \r
+ if (bot->next)\r
+ bot->next->prev = bot->prev;\r
+ if (bot->prev)\r
+ bot->prev->next = bot->next;\r
+ else\r
+ qab_bots = bot->next;\r
+ \r
+ free(bot);\r
+}\r
+\r
+void qabot_spam(void* arg) {\r
+ qab_bot* bot = (qab_bot*)arg;\r
+ qab_spam* s;\r
+ \r
+ if (!bot->nextspam)\r
+ return;\r
+ \r
+ if (bot->np) {\r
+ sendmessagetochannel(bot->np, bot->public_chan->channel, "%s", bot->nextspam->message);\r
+ bot->spammed++;\r
+ }\r
+ \r
+ s = bot->nextspam;\r
+ bot->nextspam = s->next;\r
+ \r
+ free(s->message);\r
+ free(s);\r
+ \r
+ bot->spamtime = time(0);\r
+ \r
+ if (bot->nextspam)\r
+ scheduleoneshot(bot->spamtime + bot->spam_interval, qabot_spam, (void*)bot);\r
+ else {\r
+ bot->lastspam = 0;\r
+ if (!bot->micnumeric)\r
+ qabot_spamstored((void*)bot);\r
+ }\r
+}\r
+\r
+void qabot_spamstored(void* arg) {\r
+ qab_bot* bot = (qab_bot*)arg;\r
+ qab_answer* a;\r
+ \r
+ if (!bot->answers)\r
+ return;\r
+ \r
+ if (bot->np) {\r
+ sendmessagetochannel(bot->np, bot->public_chan->channel, "%s asked: %s", bot->answers->question->nick, \r
+ bot->answers->question->question);\r
+ sendmessagetochannel(bot->np, bot->public_chan->channel, "%s answered: %s", bot->answers->nick, \r
+ bot->answers->question->answer);\r
+ }\r
+ \r
+ a = bot->answers;\r
+ bot->answers = a->next;\r
+ \r
+ free(a);\r
+ \r
+ if (bot->answers)\r
+ scheduleoneshot(time(0) + bot->queued_question_interval, qabot_spamstored, (void*)bot);\r
+}\r
+\r
+void qabot_createbotfakeuser(void* arg) {\r
+ qab_bot* bot = (qab_bot*)arg;\r
+ \r
+ if (bot->np)\r
+ return;\r
+ \r
+ bot->np = registerlocaluser(bot->nick, bot->user, bot->host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);\r
+ \r
+ bot->np->exts[qabot_nickext] = (void*)bot;\r
+ \r
+ if (bot->public_chan->channel) {\r
+ localjoinchannel(bot->np, bot->public_chan->channel);\r
+ localgetops(bot->np, bot->public_chan->channel);\r
+ }\r
+ else\r
+ localcreatechannel(bot->np, bot->public_chan->name->content);\r
+ \r
+ if (bot->question_chan->channel) {\r
+ localjoinchannel(bot->np, bot->question_chan->channel);\r
+ localgetops(bot->np, bot->question_chan->channel);\r
+ }\r
+ else\r
+ localcreatechannel(bot->np, bot->question_chan->name->content);\r
+ \r
+ if (bot->staff_chan->channel) {\r
+ localjoinchannel(bot->np, bot->staff_chan->channel);\r
+ localgetops(bot->np, bot->staff_chan->channel);\r
+ }\r
+ else\r
+ localcreatechannel(bot->np, bot->staff_chan->name->content);\r
+}\r
+\r
+void qabot_timer(void* arg) {\r
+ qab_bot* bot = (qab_bot*)arg;\r
+ \r
+ if (!bot)\r
+ return;\r
+ \r
+ if (bot->micnumeric && (bot->mic_timeout > 0) && (time(NULL) >= (bot->lastmic + bot->mic_timeout))) {\r
+ bot->micnumeric = 0;\r
+ \r
+ sendmessagetochannel(bot->np, bot->staff_chan->channel, "Mic deactivated (idle timeout).");\r
+ if (!bot->lastspam)\r
+ qabot_spamstored((void*)bot);\r
+ }\r
+ \r
+ scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);\r
+}\r
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-int qabot_dochananswer(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- int id;
- char* ch;
- qab_question* q;
-
- if (cargc < 2) {
- sendnoticetouser(bot->np, sender, "Syntax: !answer <id> <answer>");
- return CMD_ERROR;
- }
-
- id = strtol(cargv[0], NULL, 10);
- ch = cargv[1];
-
- if ((id < 1) || (id > bot->lastquestionID)) {
- sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);
- return CMD_ERROR;
- }
-
- for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)
- if (q->id == id)
- break;
-
- if (!q) {
- sendnoticetouser(bot->np, sender, "Can't find question %d.", id);
- return CMD_ERROR;
- }
-
- switch (q->flags & QAQ_QSTATE) {
- case QAQ_ANSWERED:
- sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);
- return CMD_ERROR;
-
- case QAQ_OFFTOPIC:
- sendnoticetouser(bot->np, sender, "Question %d has been marked as off-topic.", id);
- return CMD_ERROR;
-
- case QAQ_SPAM:
- sendnoticetouser(bot->np, sender, "Question %d has been marked as spam.", id);
- return CMD_ERROR;
-
- default:
- break;
- }
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_ANSWERED;
- q->answer = strdup(ch);
-
- bot->answered++;
-
- if (!bot->nextspam && !bot->micnumeric) {
- sendmessagetochannel(bot->np, bot->public_chan->channel, "%s asked: %s", q->nick, q->question);
- sendmessagetochannel(bot->np, bot->public_chan->channel, "%s answers: %s", sender->nick, ch);
- }
- else {
- qab_answer* a;
-
- a = (qab_answer*)malloc(sizeof(qab_answer));
- a->question = q;
- strncpy(a->nick, sender->nick, NICKLEN);
- a->nick[NICKLEN] = '\0';
- a->next = bot->answers;
- bot->answers = a;
-
- sendnoticetouser(bot->np, sender, "Can't send your answer right now. Answer was stored and will be sent later on.");
- return CMD_OK;
- }
-
- sendnoticetouser(bot->np, sender, "Answer to question %d has been sent and stored.", id);
-
- return CMD_OK;
-}
-
-int qabot_dochanblock(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- qab_block* b;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !block [-q|-t] <account|mask>");
- return CMD_ERROR;
- }
-
- if (cargc > 1) {
- if (!ircd_strncmp(cargv[0], "-q", 2)) {
- /* account block */
- char* target = cargv[1];
-
- if (*target == '#') {
- target++;
-
- if (strchr(target, '*') || strchr(target, '?')) {
- sendnoticetouser(bot->np, sender, "Wildcard account blocks are not supported.");
- return CMD_ERROR;
- }
- }
- else {
- nick* tnick;
-
- if (!(tnick = getnickbynick(target))) {
- sendnoticetouser(bot->np, sender, "Couldn't find user %s.", target);
- return CMD_ERROR;
- }
-
- if (!IsAccount(tnick)) {
- sendnoticetouser(bot->np, sender, "%s is not authed.", tnick->nick);
- return CMD_ERROR;
- }
-
- target = tnick->authname;
- }
-
- b = (qab_block*)malloc(sizeof(qab_block));
- b->type = QABBLOCK_ACCOUNT;
- b->created = time(0);
- strncpy(b->creator, IsAccount(sender) ? sender->authname : "UNKNOWN", ACCOUNTLEN);
- b->creator[ACCOUNTLEN] = '\0';
- b->blockstr = strdup(target);
- b->prev = 0;
- b->next = bot->blocks;
- if (bot->blocks)
- bot->blocks->prev = b;
- bot->blocks = b;
- bot->block_count++;
-
- sendnoticetouser(bot->np, sender, "Now blocking all messages from users with accountname %s.", target);
-
- if (bot->flags & QAB_BLOCKMARK) {
- qab_question* q;
- int i, spamqcount = 0;
- nick* qnick;
-
- for (i = 0; i < QUESTIONHASHSIZE; i++) {
- for (q = bot->questions[i]; q; q = q->next) {
- if ((q->flags & QAQ_QSTATE) != QAQ_NEW)
- continue;
-
- if (!(qnick = getnickbynumeric(q->numeric)))
- continue;
-
- if (!IsAccount(qnick))
- continue;
-
- if (ircd_strcmp(qnick->authname, b->blockstr))
- continue;
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;
- spamqcount++;
- }
- }
-
- sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");
- }
- }
- else if (!ircd_strncmp(cargv[0], "-t", 2)) {
- /* text block */
- char* mask = cargv[1];
-
- b = (qab_block*)malloc(sizeof(qab_block));
- b->type = QABBLOCK_TEXT;
- b->created = time(0);
- strncpy(b->creator, sender->authname, ACCOUNTLEN);
- b->creator[ACCOUNTLEN] = '\0';
- b->blockstr = strdup(mask);
- b->prev = 0;
- b->next = bot->blocks;
- if (bot->blocks)
- bot->blocks->prev = b;
- bot->blocks = b;
- bot->block_count++;
-
- sendnoticetouser(bot->np, sender, "Now blocking all questions which match %s.", mask);
-
- if (bot->flags & QAB_BLOCKMARK) {
- qab_question* q;
- int i, spamqcount = 0;
-
- for (i = 0; i < QUESTIONHASHSIZE; i++) {
- for (q = bot->questions[i]; q; q = q->next) {
- if ((q->flags & QAQ_QSTATE) != QAQ_NEW)
- continue;
-
- if (match(b->blockstr, q->question))
- continue;
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;
- spamqcount++;
- }
- }
-
- sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");
- }
- }
- else {
- sendnoticetouser(bot->np, sender, "Invalid flag.");
- return CMD_ERROR;
- }
- }
- else {
- /* hostmask block */
- char* mask = cargv[0];
-
- if (!strchr(mask, '@') || !strchr(mask, '!')) {
- sendnoticetouser(bot->np, sender, "%s is not a valid hostmask.", mask);
- return;
- }
-
- b = (qab_block*)malloc(sizeof(qab_block));
- b->type = QABBLOCK_HOST;
- b->created = time(0);
- strncpy(b->creator, sender->authname, ACCOUNTLEN);
- b->creator[ACCOUNTLEN] = '\0';
- b->blockstr = strdup(mask);
- b->prev = 0;
- b->next = bot->blocks;
- if (bot->blocks)
- bot->blocks->prev = b;
- bot->blocks = b;
- bot->block_count++;
-
- sendnoticetouser(bot->np, sender, "Now blocking all messages from users with a hostmask matching %s.", mask);
-
- if (bot->flags & QAB_BLOCKMARK) {
- qab_question* q;
- int i, spamqcount = 0;
- nick* qnick;
- char hostbuf[NICKLEN + USERLEN + HOSTLEN + 3];
-
- for (i = 0; i < QUESTIONHASHSIZE; i++) {
- for (q = bot->questions[i]; q; q = q->next) {
- if ((q->flags & QAQ_QSTATE) != QAQ_NEW)
- continue;
-
- if (!(qnick = getnickbynumeric(q->numeric)))
- continue;
-
- sprintf(hostbuf, "%s!%s@%s", qnick->nick, qnick->ident, qnick->host->name->content);
-
- if (match(b->blockstr, hostbuf))
- continue;
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;
- spamqcount++;
- }
- }
-
- sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");
- }
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanclear(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- qab_spam* s;
- qab_spam* ns;
- qab_answer* a;
- qab_answer* na;
-
- if (bot->recording_section) {
- sendmessagetochannel(bot->np, cp, "Deactivate recorder before using clear.");
- return CMD_ERROR;
- }
-
- for (s = bot->nextspam; s; s = ns) {
- ns = s->next;
- free(s->message);
- free(s);
- }
-
- bot->nextspam = bot->lastspam = 0;
-
- sendmessagetochannel(bot->np, cp, "Cleared message buffer.");
- if (bot->micnumeric) {
- bot->micnumeric = 0;
- sendmessagetochannel(bot->np, cp, "Mic deactivated.");
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanclosechan(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- modechanges changes;
-
- localsetmodeinit(&changes, bot->public_chan->channel, bot->np);
- localdosetmode_simple(&changes, CHANMODE_INVITEONLY, 0);
- localsetmodeflush(&changes, 1);
- sendnoticetouser(bot->np, sender, "Public channel has been closed.");
-
- return CMD_OK;
-}
-
-int qabot_dochanconfig(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- char* opt;
- char* value;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !config <option> [<value>]");
- sendnoticetouser(bot->np, sender, "Displays or sets configuration option. Valid options are:");
- sendnoticetouser(bot->np, sender, "blockcontrol - Block questions containing control chars.");
- sendnoticetouser(bot->np, sender, "blockcolour - Block questions containing colour.");
- sendnoticetouser(bot->np, sender, "blockmark - Mark questions affected by blocks as spam.");
- sendnoticetouser(bot->np, sender, "authedonly - Accept questions from authed users only.");
- sendnoticetouser(bot->np, sender, "linebreak - Separate questions with line breaks.");
- sendnoticetouser(bot->np, sender, "flooddetect - Attempt to detect floodclone spam.");
- sendnoticetouser(bot->np, sender, "floodblock - Automatically block floodclone spam.");
- sendnoticetouser(bot->np, sender, "spamint - Text spam interval.");
- sendnoticetouser(bot->np, sender, "nickblockint - Time to wait before sending another question.");
- sendnoticetouser(bot->np, sender, "queuedqint - Queued answer spam interval.");
- sendnoticetouser(bot->np, sender, "mictimeout - Idle time before mic is automatically disabled.");
- return CMD_ERROR;
- }
-
- opt = cargv[0];
- if (cargc == 2)
- value = cargv[1];
- else
- value = 0;
-
- if (!ircd_strcmp(opt, "blockcontrol")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_CONTROLCHAR;
- sendnoticetouser(bot->np, sender, "Questions containing control characters will now be blocked.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_CONTROLCHAR);
- sendnoticetouser(bot->np, sender, "Questions containing control characters will no longer be blocked.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Control characters are currently %s blocked.", (bot->flags & QAB_CONTROLCHAR) ? "being" : "not being");
- }
- else if (!ircd_strcmp(opt, "blockcolour")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_COLOUR;
- sendnoticetouser(bot->np, sender, "Questions containing colour will now be blocked.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_COLOUR);
- sendnoticetouser(bot->np, sender, "Questions containing colour will no longer be blocked.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Colours are currently %s blocked.", (bot->flags & QAB_COLOUR) ? "being" : "not being");
- }
- else if (!ircd_strcmp(opt, "blockmark")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_BLOCKMARK;
- sendnoticetouser(bot->np, sender, "New blocks will automatically mark affected questions as spam.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_BLOCKMARK);
- sendnoticetouser(bot->np, sender, "New blocks will no longer automatically mark affected questions as spam.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Blocks are currently %smarking affected questions as spam.", (bot->flags & QAB_BLOCKMARK) ? "" : "not ");
- }
- else if (!ircd_strcmp(opt, "authedonly")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_AUTHEDONLY;
- sendnoticetouser(bot->np, sender, "Questions from unauthed users will now be blocked.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_AUTHEDONLY);
- sendnoticetouser(bot->np, sender, "Questions from unauthed users will no longer be blocked.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Unauthed users may currently %ssend questions.", (bot->flags & QAB_AUTHEDONLY) ? "NOT " : "");
- }
- else if (!ircd_strcmp(opt, "linebreak")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_LINEBREAK;
- sendnoticetouser(bot->np, sender, "Line breaks are now enabled.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_LINEBREAK);
- sendnoticetouser(bot->np, sender, "Line breaks are now disabled.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Line breaks are currently %s.", (bot->flags & QAB_LINEBREAK) ? "enabled" : "disabled");
- }
- else if (!ircd_strcmp(opt, "flooddetect")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_FLOODDETECT;
- sendnoticetouser(bot->np, sender, "Flood detection is now enabled.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_FLOODDETECT);
- sendnoticetouser(bot->np, sender, "Flood detection is now disabled.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Flood detection is currently %s.", (bot->flags & QAB_FLOODDETECT) ? "enabled" : "disabled");
- }
- else if (!ircd_strcmp(opt, "floodblock")) {
- if (value) {
- if (!ircd_strcmp(value, "on")) {
- bot->flags |= QAB_FLOODSTOP;
- sendnoticetouser(bot->np, sender, "Flood blocking is now enabled.");
- }
- else if (!ircd_strcmp(value, "off")) {
- bot->flags &= (~QAB_FLOODSTOP);
- sendnoticetouser(bot->np, sender, "Flood blocking is now disabled.");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");
- }
- else
- sendnoticetouser(bot->np, sender, "Flood blocking is currently %s.", (bot->flags & QAB_FLOODSTOP) ? "enabled" : "disabled");
- }
- else if (!ircd_strcmp(opt, "mictimeout")) {
- if (value) {
- int v = (int)strtol(value, NULL, 10);
-
- if ((v < 0) || (v > 300)) {
- sendnoticetouser(bot->np, sender, "Value must be between 0 (off) and 300.");
- return CMD_ERROR;
- }
-
- bot->mic_timeout = v;
- sendnoticetouser(bot->np, sender, "Value set.");
- }
- else {
- if (bot->mic_timeout)
- sendnoticetouser(bot->np, sender, "Mic timeout is currently %d second%s.", bot->mic_timeout, (bot->mic_timeout == 1) ? "" : "s");
- else
- sendnoticetouser(bot->np, sender, "Mic timeout is currently disabled.");
- }
- }
- else if (!ircd_strcmp(opt, "spamint")) {
- if (value) {
- int v = (int)strtol(value, NULL, 10);
-
- if ((v < 1) || (v > 30)) {
- sendnoticetouser(bot->np, sender, "Value must be between 1 and 30.");
- return CMD_ERROR;
- }
-
- bot->spam_interval = v;
- sendnoticetouser(bot->np, sender, "Value set.");
- }
- else
- sendnoticetouser(bot->np, sender, "Spam interval is currently %d second%s.", bot->spam_interval, (bot->spam_interval == 1) ? "" : "s");
- }
- else if (!ircd_strcmp(opt, "nickblockint")) {
- if (value) {
- int v = (int)strtol(value, NULL, 10);
-
- if ((v < 1) || (v > 300)) {
- sendnoticetouser(bot->np, sender, "Value must be between 1 and 300.");
- return CMD_ERROR;
- }
-
- bot->ask_wait = v;
- sendnoticetouser(bot->np, sender, "Value set.");
- }
- else
- sendnoticetouser(bot->np, sender, "Nick block interval is currently %d second%s.", bot->ask_wait, (bot->ask_wait == 1) ? "" : "s");
- }
- else if (!ircd_strcmp(opt, "queuedqint")) {
- if (value) {
- int v = (int)strtol(value, NULL, 10);
-
- if ((v < 1) || (v > 20)) {
- sendnoticetouser(bot->np, sender, "Value must be between 1 and 20.");
- return CMD_ERROR;
- }
-
- bot->queued_question_interval = v;
- sendnoticetouser(bot->np, sender, "Value set.");
- }
- else
- sendnoticetouser(bot->np, sender, "Queued question interval is currently %d second%s.", bot->queued_question_interval, (bot->queued_question_interval == 1) ? "" : "s");
- }
- else
- sendnoticetouser(bot->np, sender, "Invalid configuration option.");
-
- return CMD_OK;
-}
-
-int qabot_dochanhelp(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- char* ch;
-
- if (cargc < 1)
- ch = "";
- else
- ch = cargv[0];
-
- if (*ch) {
- if (!ircd_strcmp(ch, "mic")) {
- sendnoticetouser(bot->np, sender, "Syntax: !mic");
- 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);
- }
- else if (!ircd_strcmp(ch, "clear")) {
- sendnoticetouser(bot->np, sender, "Syntax: !clear");
- sendnoticetouser(bot->np, sender, "Clear currently queued text to relay, and turn off the microphone.");
- }
- else if (!ircd_strcmp(ch, "ping")) {
- sendnoticetouser(bot->np, sender, "Syntax: !ping");
- sendnoticetouser(bot->np, sender, "Pings the bot.");
- }
- else if (!ircd_strcmp(ch, "config")) {
- sendnoticetouser(bot->np, sender, "Syntax: !config <option|help> [<value>]");
- sendnoticetouser(bot->np, sender, "Display or set bot configuration options.");
- }
- else if (!ircd_strcmp(ch, "answer")) {
- sendnoticetouser(bot->np, sender, "Syntax: !answer <id> <answer>");
- sendnoticetouser(bot->np, sender, "Answer a question.");
- }
- else if (!ircd_strcmp(ch, "block")) {
- sendnoticetouser(bot->np, sender, "Syntax: !block [<-q|-t>] <mask>");
- sendnoticetouser(bot->np, sender, "Add a block, where:");
- sendnoticetouser(bot->np, sender, "-q: blocks a Q account.");
- sendnoticetouser(bot->np, sender, "-t: blocks question text.");
- sendnoticetouser(bot->np, sender, "No flag results in a hostmask block.");
- }
- else if (!ircd_strcmp(ch, "listblocks")) {
- sendnoticetouser(bot->np, sender, "Syntax: !listblocks");
- sendnoticetouser(bot->np, sender, "View the currently added blocks.");
- }
- else if (!ircd_strcmp(ch, "spam")) {
- sendnoticetouser(bot->np, sender, "Syntax: !spam <id>");
- sendnoticetouser(bot->np, sender, "Mark a question as spam. This stops it being answered.");
- }
- else if (!ircd_strcmp(ch, "offtopic")) {
- sendnoticetouser(bot->np, sender, "Syntax: !offtopic <id>");
- sendnoticetouser(bot->np, sender, "Mark a question as off-topic. This stops it being answered.");
- }
- else if (!ircd_strcmp(ch, "unblock")) {
- sendnoticetouser(bot->np, sender, "Syntax: !unblock [<-q|-t>] <mask>");
- sendnoticetouser(bot->np, sender, "Removes a block. See \"!help block\" for a description of the flags.");
- }
- else if (!ircd_strcmp(ch, "reset")) {
- sendnoticetouser(bot->np, sender, "Syntax: !reset <all|questions|blocks|stats>");
- sendnoticetouser(bot->np, sender, "Reset the questions, blocks or both; or the stats.");
- }
- else if (!ircd_strcmp(ch, "closechan")) {
- sendnoticetouser(bot->np, sender, "Syntax: !closechan");
- sendnoticetouser(bot->np, sender, "Closes the public channel.");
- }
- else if (!ircd_strcmp(ch, "openchan")) {
- sendnoticetouser(bot->np, sender, "Syntax: !openchan");
- sendnoticetouser(bot->np, sender, "Opens the public channel.");
- }
- else if (!ircd_strcmp(ch, "status")) {
- sendnoticetouser(bot->np, sender, "Syntax: !status");
- sendnoticetouser(bot->np, sender, "Displays some status information and statistics.");
- }
- else if (!ircd_strcmp(ch, "help")) {
- sendnoticetouser(bot->np, sender, "Syntax !help [<command>]");
- sendnoticetouser(bot->np, sender, "List available commands or view help for a particular command.");
- }
- else {
- sendnoticetouser(bot->np, sender, "No help available for '%s'.", ch);
- }
- }
- else {
- sendnoticetouser(bot->np, sender, "The following channel commands are recognised:");
- sendnoticetouser(bot->np, sender, "!answer - Answer a question.");
- sendnoticetouser(bot->np, sender, "!block - Block a hostmask, account or string.");
- sendnoticetouser(bot->np, sender, "!clear - Clear currently queued text to spam.");
- sendnoticetouser(bot->np, sender, "!closechan - Close the public channel.");
- sendnoticetouser(bot->np, sender, "!config - Display or set bot configuration options.");
- sendnoticetouser(bot->np, sender, "!help - List commands or view the help for a command");
- sendnoticetouser(bot->np, sender, "!listblocks - List currently added blocks.");
- sendnoticetouser(bot->np, sender, "!mic - Turn the microphone on or off.");
- sendnoticetouser(bot->np, sender, "!offtopic - Mark a question or questions as off-topic.");
- sendnoticetouser(bot->np, sender, "!openchan - Open the public channel.");
- sendnoticetouser(bot->np, sender, "!ping - Ping the bot.");
- sendnoticetouser(bot->np, sender, "!reset - Clear all blocks, questions or both.");
- sendnoticetouser(bot->np, sender, "!spam - Mark a question or questions as spam.");
- sendnoticetouser(bot->np, sender, "!status - Display some status statistics.");
- sendnoticetouser(bot->np, sender, "!unblock - Remove a block.");
- sendnoticetouser(bot->np, sender, "End of list.");
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanlistblocks(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- qab_block* b;
-
- if (!(b = bot->blocks)) {
- sendnoticetouser(bot->np, sender, "There are no blocks currently added.");
- return;
- }
-
- sendnoticetouser(bot->np, sender, "Type: Hostmask/Account/Textmask:");
-
- for (; b; b = b->next) {
- if (b->type == QABBLOCK_ACCOUNT)
- sendnoticetouser(bot->np, sender, "A %s", b->blockstr);
- else if (b->type == QABBLOCK_HOST)
- sendnoticetouser(bot->np, sender, "H %s", b->blockstr);
- else
- sendnoticetouser(bot->np, sender, "T %s", b->blockstr);
- }
-
- sendnoticetouser(bot->np, sender, "End of list.");
-
- return CMD_OK;
-}
-
-int qabot_dochanmic(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
-
- if (bot->recording_section)
- sendmessagetochannel(bot->np, cp, "Deactivate recorder before attempting to use mic.");
- else if (bot->micnumeric) {
- if (bot->micnumeric == sender->numeric) {
- bot->micnumeric = 0;
- sendmessagetochannel(bot->np, cp, "Mic deactivated.");
- if (!bot->lastspam)
- qabot_spamstored((void*)bot);
- }
- else {
- bot->lastmic = time(NULL);
- bot->micnumeric = sender->numeric;
- sendmessagetochannel(bot->np, cp, "%s now has the mic. Anything said by %s will be relayed in %s.",
- sender->nick, sender->nick, bot->public_chan->name->content);
- deleteschedule(0, qabot_spamstored, (void*)bot);
- }
- }
- else {
- bot->lastmic = time(NULL);
- bot->micnumeric = sender->numeric;
- sendmessagetochannel(bot->np, cp, "Mic activated. Anything said by %s will be relayed in %s.",
- sender->nick, bot->public_chan->name->content);
- deleteschedule(0, qabot_spamstored, (void*)bot);
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanmoo(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- char moostr[50];
- int i, moocount = 5 + (rand() % 40);
-
- moostr[0] = 'm';
- for (i = 1; i < moocount; i++)
- moostr[i] = ((rand() % 100) > 50) ? 'o': '0';
- moostr[i] = '\0';
-
- sendmessagetochannel(bot->np, cp, "%s", moostr);
-
- return CMD_OK;
-}
-
-int qabot_dochanofftopic(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- int id;
- int i;
- qab_question* q;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !spam <id> [<id> ... <id>]");
- return CMD_ERROR;
- }
-
- for (i = 0; i < cargc; i++) {
- id = strtol(cargv[i], NULL, 10);
-
- if ((id < 1) || (id > bot->lastquestionID)) {
- sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);
- continue;
- }
-
- for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)
- if (q->id == id)
- break;
-
- if (!q) {
- sendnoticetouser(bot->np, sender, "Can't find question %d.", id);
- continue;
- }
-
- switch (q->flags & QAQ_QSTATE) {
- case QAQ_ANSWERED:
- sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);
- continue;
-
- case QAQ_OFFTOPIC:
- sendnoticetouser(bot->np, sender, "Question %d has already been marked as off-topic.", id);
- continue;
-
- case QAQ_SPAM:
- sendnoticetouser(bot->np, sender, "Question %d has already been marked as spam.", id);
- continue;
-
- default:
- break;
- }
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_OFFTOPIC;
- sendnoticetouser(bot->np, sender, "Question %d has been marked as off-topic.", id);
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanopenchan(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- modechanges changes;
-
- localsetmodeinit(&changes, bot->public_chan->channel, bot->np);
- localdosetmode_simple(&changes, CHANMODE_MODERATE|CHANMODE_DELJOINS, CHANMODE_INVITEONLY);
- localsetmodeflush(&changes, 1);
- sendnoticetouser(bot->np, sender, "Public channel has been opened.");
-
- return CMD_OK;
-}
-
-int qabot_dochanping(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
-
- sendmessagetochannel(bot->np, cp, "pong!");
-
- return CMD_OK;
-}
-
-int qabot_dochanreset(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- int r = 0;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !reset <blocks|questions|stats|all>");
- return CMD_ERROR;
- }
-
- if (!ircd_strcmp(cargv[0], "blocks"))
- r = 1;
- else if (!ircd_strcmp(cargv[0], "questions"))
- r = 2;
- else if (!ircd_strcmp(cargv[0], "stats"))
- r = 4;
- else if (!ircd_strcmp(cargv[0], "all"))
- r = 3;
- else {
- sendnoticetouser(bot->np, sender, "Unknown parameter: %s.", cargv[0]);
- return;
- }
-
- if (r & 1) {
- qab_block* b;
-
- while (bot->blocks) {
- b = bot->blocks;
- bot->blocks = bot->blocks->next;
- if (b->blockstr)
- free(b->blockstr);
- free(b);
- }
-
- bot->block_count = 0;
-
- sendnoticetouser(bot->np, sender, "Reset (blocks): Done.");
- }
-
- if (r & 2) {
- qab_question* q;
- int i;
-
- for (i = 0; i < QUESTIONHASHSIZE; i++) {
- while (bot->questions[i]) {
- q = bot->questions[i];
- bot->questions[i] = bot->questions[i]->next;
- if (q->question)
- free(q->question);
- if (q->answer)
- free(q->answer);
- free(q);
- }
- }
-
- bot->lastquestionID = 0;
- bot->answered = 0;
-
- sendnoticetouser(bot->np, sender, "Reset (questions): Done.");
- }
-
- if (r & 4) {
- bot->answered = 0;
- bot->spammed = 0;
- sendnoticetouser(bot->np, sender, "Reset (stats): Done.");
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanspam(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- int id;
- int i;
- qab_question* q;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !spam <id> [<id> ... <id>]");
- return CMD_ERROR;
- }
-
- for (i = 0; i < cargc; i++) {
- id = strtol(cargv[i], NULL, 10);
-
- if ((id < 1) || (id > bot->lastquestionID)) {
- sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);
- continue;
- }
-
- for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)
- if (q->id == id)
- break;
-
- if (!q) {
- sendnoticetouser(bot->np, sender, "Can't find question %d.", id);
- continue;
- }
-
- switch (q->flags & QAQ_QSTATE) {
- case QAQ_ANSWERED:
- sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);
- continue;
-
- case QAQ_OFFTOPIC:
- sendnoticetouser(bot->np, sender, "Question %d has already been marked as off-topic.", id);
- continue;
-
- case QAQ_SPAM:
- sendnoticetouser(bot->np, sender, "Question %d has already been marked as spam.", id);
- continue;
-
- default:
- break;
- }
-
- q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;
- sendnoticetouser(bot->np, sender, "Question %d has been marked as spam.", id);
- }
-
- return CMD_OK;
-}
-
-int qabot_dochanstatus(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
-
- sendnoticetouser(bot->np, sender, "Lines spammed: %d", bot->spammed);
- sendnoticetouser(bot->np, sender, "Questions asked: %d", bot->lastquestionID);
- sendnoticetouser(bot->np, sender, "Questions answered: %d", bot->answered);
- sendnoticetouser(bot->np, sender, "Blocks: %d", bot->block_count);
- /*sendnoticetouser(bot->np, sender, "Question interval: %d seconds", bot->question_interval);*/
- sendnoticetouser(bot->np, sender, "Spam interval: %d seconds", bot->spam_interval);
- sendnoticetouser(bot->np, sender, "Nick block interval: %d seconds", bot->ask_wait);
- sendnoticetouser(bot->np, sender, "Queued question interval: %d seconds", bot->queued_question_interval);
- sendnoticetouser(bot->np, sender, "Block control chars: %s", (bot->flags & QAB_CONTROLCHAR) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Block colour: %s", (bot->flags & QAB_COLOUR) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Authed users only: %s", (bot->flags & QAB_AUTHEDONLY) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Line break: %s", (bot->flags & QAB_LINEBREAK) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Question flood detection: %s", (bot->flags & QAB_FLOODDETECT) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Question flood blocking: %s", (bot->flags & QAB_FLOODSTOP) ? "Yes" : "No");
- sendnoticetouser(bot->np, sender, "Blocks mark as spam: %s", (bot->flags & QAB_BLOCKMARK) ? "Yes" : "No");
- if (bot->micnumeric) {
- nick* mnick = getnickbynumeric(bot->micnumeric);
-
- sendnoticetouser(bot->np, np, "Mic: Enabled (%s)", mnick ? mnick->nick : "UNKNOWN");
- }
- else
- sendnoticetouser(bot->np, np, "Mic: Disabled");
- sendnoticetouser(bot->np, sender, "Mic timeout: %d", bot->mic_timeout);
- /*sendnoticetouser(bot->np, sender, "");*/
-
- return CMD_OK;
-}
-
-int qabot_dochanunblock(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
- char* ch;
- qab_block* b;
- char type = -1;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !unblock [-q|-t] <account|mask>");
- return CMD_ERROR;
- }
-
- if (cargc > 1) {
- if (!ircd_strncmp(cargv[0], "-q", 2)) {
- type = QABBLOCK_ACCOUNT;
- ch = cargv[1];
-
- if (*ch == '#')
- ch++;
- }
- else if (!ircd_strncmp(cargv[0], "-t", 2)) {
- type = QABBLOCK_TEXT;
- ch = cargv[1];
- }
- else {
- sendnoticetouser(bot->np, sender, "Invalid flag.");
- return CMD_ERROR;
- }
- }
- else {
- type = QABBLOCK_HOST;
- ch = cargv[0];
- }
-
- for (b = bot->blocks; b; b = b->next) {
- if (b->type != type)
- continue;
-
- if (!ircd_strcmp(b->blockstr, ch)) {
- if (b->next)
- b->next->prev = b->prev;
- if (b->prev)
- b->prev->next = b->next;
- else
- bot->blocks = b->next;
-
- free(b->blockstr);
- free(b);
-
- bot->block_count--;
-
- sendnoticetouser(bot->np, sender, "Block removed.");
- return CMD_OK;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such block.");
-
- return CMD_ERROR;
-}
-
-int qabot_dochanlisttexts(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
-
- if (!texts) {
- sendnoticetouser(bot->np, sender, "There are no texts added.");
- return CMD_ERROR;
- }
-
- sendnoticetouser(bot->np, sender, "Name: Sections:");
- for (; texts; texts = texts->next) {
- sendnoticetouser(bot->np, sender, "%-15s %d", texts->name, texts->section_count);
- }
-
- sendnoticetouser(bot->np, sender, "End of list.");
-
- return CMD_OK;
-}
-
-int qabot_dochanshowsection(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
- qab_textsection* section;
- int count = 0;
-
- if (cargc < 2) {
- sendnoticetouser(bot->np, sender, "Syntax: !showsection <text name> <section number>");
- return CMD_ERROR;
- }
-
- if (!texts) {
- sendnoticetouser(bot->np, sender, "There are no texts added.");
- return CMD_ERROR;
- }
-
- id = (int)strtol(cargv[1]);
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- for (section = texts->sections; section && (count <= section->section_count); section = section->next) {
- if (++count == id) {
- qab_spam* lines;
- int lineno = 0;
-
- sendnoticetouser(bot->np, sender, "Section %d (of text %s) contents:", count, texts->name);
- for (lines = section->lines; lines; lines = lines->next)
- sendnoticetouser(bot->np, sender, "%-2d> %s", ++lineno, lines->message);
- sendnoticetouser(bot->np, sender, "End of section.");
-
- return CMD_OK;
- }
- }
- sendnoticetouser(bot->np, sender, "No such section.");
- return CMD_ERROR;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such text.");
-
- return CMD_ERROR;
-}
-
-int qabot_dochanaddtext(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !addtext <text name>");
- return CMD_ERROR;
- }
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- sendnoticetouser(bot->np, sender, "A text with this name already exists.");
- return CMD_ERROR;
- }
- }
-
- texts = (qab_text*)malloc(sizeof(qab_text));
- strncpy(texts->name, cargc[0], NICKLEN);
- texts->name[NICKLEN] = '\0';
- texts->sections = 0;
- texts->sections_tail = 0;
- texts->section_count = 0;
- texts->next = bot->texts;
- texts->prev = 0;
- if (bot->texts)
- bot->texts->prev = texts;
- bot->texts = texts;
-
- sendnoticetouser(bot->np, sender, "Added text '%s'.", texts->name);
-
- return CMD_OK;
-}
-
-int qabot_dochandeltext(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !deltext <text name>");
- return CMD_ERROR;
- }
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- sendnoticetouser(bot->np, sender, "Text '%s' deleted.", texts->name);
- qabot_freetext(bot, texts);
- return CMD_OK;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such text.");
-
- return CMD_ERROR;
-}
-
-int qabot_dochanaddsection(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
- qab_textsection* section;
-
- if (cargc < 1) {
- sendnoticetouser(bot->np, sender, "Syntax: !addsection <text name> [<section number>]");
- return CMD_ERROR;
- }
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- int num;
- if (cargc == 1 || !texts->sections_tail) {
- section = (qab_textsection*)malloc(sizeof(qab_textsection));
- section->lines = 0;
- section->lines_tail = 0;
- section->line_count = 0;
- section->prev = 0;
- section->next = 0;
- texts->sections = section;
- texts->sections_tail = section;
- texts->section_count++;
- num = 1;
- }
- else {
- }
-
- sendnoticetouser(bot->np, sender, "Section %d added.", num);
- return CMD_OK;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such text.");
-
- return CMD_ERROR;
-}
-
-int qabot_dochandelsection(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- qab_text* texts = bot->texts;
- qab_textsection* section;
-
- if (cargc < 2) {
- sendnoticetouser(bot->np, sender, "Syntax: !delsection <text name> <section number>");
- return CMD_ERROR;
- }
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- for (section = texts->sections; section && (count <= section->section_count); section = section->next) {
- if (++count == id) {
- qabot_freesection(texts, section);
- sendnoticetouser(bot->np, sender, "Section deleted.");
- return CMD_OK;
- }
- }
- sendnoticetouser(bot->np, sender, "No such section.");
- return CMD_ERROR;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such text.");
-
- return CMD_ERROR;
-}
-
-int qabot_dochanrecord(void* np, int cargc, char** cargv) {
- nick* sender = (nick*)np;
- qab_bot* bot = qabot_getcurrentbot();
- channel* cp = qabot_getcurrentchannel();
-
- if (bot->recording_section) {
- if (bot->micnumeric == sender->numeric) {
- bot->micnumeric = 0;
- bot->recording_section = 0;
- sendmessagetochannel(bot->np, cp, "Recorder deactivated.");
- }
- else {
- sendmessagetochannel(bot->np, cp, "The recorder is already in use.");
- }
- }
- else if (bot->micnumeric)
- sendmessagetochannel(bot->np, cp, "Deactivate mic before attempting to use recorder.");
- else if (cargc >= 2) {
- qab_text* texts = bot->texts;
- qab_textsection* section;
- int id = (int)strtol(cargv[1]);
-
- for (; texts; texts = texts->next) {
- if (!ircd_strcmp(texts->name, cargv[0])) {
- for (section = texts->sections; section && (count <= section->section_count); section = section->next) {
- if (++count == id) {
- bot->lastmic = time(NULL);
- bot->micnumeric = sender->numeric;
- bot->recording_section = count;
- sendmessagetochannel(bot->np, cp, "Recorder activated. Anything said by %s will be relayed in %s.",
- sender->nick, bot->public_chan->name->content);
- deleteschedule(0, qabot_spamstored, (void*)bot);
- return CMD_OK;
- }
- }
- sendnoticetouser(bot->np, sender, "No such section.");
- return CMD_ERROR;
- }
- }
-
- sendnoticetouser(bot->np, sender, "No such text.");
- return CMD_ERROR;
- }
- else
- sendmessagetochannel(bot->np, cp, "syntax: !record [<text name> <section number>]");
-
- return CMD_OK;
-}
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+int qabot_dochananswer(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ int id;\r
+ char* ch;\r
+ qab_question* q;\r
+ \r
+ if (cargc < 2) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !answer <id> <answer>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ id = strtol(cargv[0], NULL, 10);\r
+ ch = cargv[1];\r
+ \r
+ if ((id < 1) || (id > bot->lastquestionID)) {\r
+ sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)\r
+ if (q->id == id)\r
+ break;\r
+ \r
+ if (!q) {\r
+ sendnoticetouser(bot->np, sender, "Can't find question %d.", id);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ switch (q->flags & QAQ_QSTATE) {\r
+ case QAQ_ANSWERED:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);\r
+ return CMD_ERROR;\r
+ \r
+ case QAQ_OFFTOPIC:\r
+ sendnoticetouser(bot->np, sender, "Question %d has been marked as off-topic.", id);\r
+ return CMD_ERROR;\r
+ \r
+ case QAQ_SPAM:\r
+ sendnoticetouser(bot->np, sender, "Question %d has been marked as spam.", id);\r
+ return CMD_ERROR;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_ANSWERED;\r
+ q->answer = strdup(ch);\r
+ \r
+ bot->answered++;\r
+ \r
+ if (!bot->nextspam && !bot->micnumeric) {\r
+ sendmessagetochannel(bot->np, bot->public_chan->channel, "%s asked: %s", q->nick, q->question);\r
+ sendmessagetochannel(bot->np, bot->public_chan->channel, "%s answers: %s", sender->nick, ch);\r
+ }\r
+ else {\r
+ qab_answer* a;\r
+ \r
+ a = (qab_answer*)malloc(sizeof(qab_answer));\r
+ a->question = q;\r
+ strncpy(a->nick, sender->nick, NICKLEN);\r
+ a->nick[NICKLEN] = '\0';\r
+ a->next = bot->answers;\r
+ bot->answers = a;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Can't send your answer right now. Answer was stored and will be sent later on.");\r
+ return CMD_OK;\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "Answer to question %d has been sent and stored.", id);\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanblock(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ qab_block* b;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !block [-q|-t] <account|mask>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (cargc > 1) {\r
+ if (!ircd_strncmp(cargv[0], "-q", 2)) {\r
+ /* account block */\r
+ char* target = cargv[1];\r
+ \r
+ if (*target == '#') {\r
+ target++;\r
+ \r
+ if (strchr(target, '*') || strchr(target, '?')) {\r
+ sendnoticetouser(bot->np, sender, "Wildcard account blocks are not supported.");\r
+ return CMD_ERROR;\r
+ }\r
+ }\r
+ else {\r
+ nick* tnick;\r
+ \r
+ if (!(tnick = getnickbynick(target))) {\r
+ sendnoticetouser(bot->np, sender, "Couldn't find user %s.", target);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!IsAccount(tnick)) {\r
+ sendnoticetouser(bot->np, sender, "%s is not authed.", tnick->nick);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ target = tnick->authname;\r
+ }\r
+ \r
+ b = (qab_block*)malloc(sizeof(qab_block));\r
+ b->type = QABBLOCK_ACCOUNT;\r
+ b->created = time(0);\r
+ strncpy(b->creator, IsAccount(sender) ? sender->authname : "UNKNOWN", ACCOUNTLEN);\r
+ b->creator[ACCOUNTLEN] = '\0';\r
+ b->blockstr = strdup(target);\r
+ b->prev = 0;\r
+ b->next = bot->blocks;\r
+ if (bot->blocks)\r
+ bot->blocks->prev = b;\r
+ bot->blocks = b;\r
+ bot->block_count++;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Now blocking all messages from users with accountname %s.", target);\r
+ \r
+ if (bot->flags & QAB_BLOCKMARK) {\r
+ qab_question* q;\r
+ int i, spamqcount = 0;\r
+ nick* qnick;\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++) {\r
+ for (q = bot->questions[i]; q; q = q->next) {\r
+ if ((q->flags & QAQ_QSTATE) != QAQ_NEW)\r
+ continue;\r
+ \r
+ if (!(qnick = getnickbynumeric(q->numeric)))\r
+ continue;\r
+ \r
+ if (!IsAccount(qnick))\r
+ continue;\r
+ \r
+ if (ircd_strcmp(qnick->authname, b->blockstr))\r
+ continue;\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;\r
+ spamqcount++;\r
+ }\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");\r
+ }\r
+ }\r
+ else if (!ircd_strncmp(cargv[0], "-t", 2)) {\r
+ /* text block */\r
+ char* mask = cargv[1];\r
+ \r
+ b = (qab_block*)malloc(sizeof(qab_block));\r
+ b->type = QABBLOCK_TEXT;\r
+ b->created = time(0);\r
+ strncpy(b->creator, sender->authname, ACCOUNTLEN);\r
+ b->creator[ACCOUNTLEN] = '\0';\r
+ b->blockstr = strdup(mask);\r
+ b->prev = 0;\r
+ b->next = bot->blocks;\r
+ if (bot->blocks)\r
+ bot->blocks->prev = b;\r
+ bot->blocks = b;\r
+ bot->block_count++;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Now blocking all questions which match %s.", mask);\r
+ \r
+ if (bot->flags & QAB_BLOCKMARK) {\r
+ qab_question* q;\r
+ int i, spamqcount = 0;\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++) {\r
+ for (q = bot->questions[i]; q; q = q->next) {\r
+ if ((q->flags & QAQ_QSTATE) != QAQ_NEW)\r
+ continue;\r
+ \r
+ if (match(b->blockstr, q->question))\r
+ continue;\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;\r
+ spamqcount++;\r
+ }\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");\r
+ }\r
+ }\r
+ else {\r
+ sendnoticetouser(bot->np, sender, "Invalid flag.");\r
+ return CMD_ERROR;\r
+ }\r
+ }\r
+ else {\r
+ /* hostmask block */\r
+ char* mask = cargv[0];\r
+ \r
+ if (!strchr(mask, '@') || !strchr(mask, '!')) {\r
+ sendnoticetouser(bot->np, sender, "%s is not a valid hostmask.", mask);\r
+ return;\r
+ }\r
+ \r
+ b = (qab_block*)malloc(sizeof(qab_block));\r
+ b->type = QABBLOCK_HOST;\r
+ b->created = time(0);\r
+ strncpy(b->creator, sender->authname, ACCOUNTLEN);\r
+ b->creator[ACCOUNTLEN] = '\0';\r
+ b->blockstr = strdup(mask);\r
+ b->prev = 0;\r
+ b->next = bot->blocks;\r
+ if (bot->blocks)\r
+ bot->blocks->prev = b;\r
+ bot->blocks = b;\r
+ bot->block_count++;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Now blocking all messages from users with a hostmask matching %s.", mask);\r
+ \r
+ if (bot->flags & QAB_BLOCKMARK) {\r
+ qab_question* q;\r
+ int i, spamqcount = 0;\r
+ nick* qnick;\r
+ char hostbuf[NICKLEN + USERLEN + HOSTLEN + 3];\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++) {\r
+ for (q = bot->questions[i]; q; q = q->next) {\r
+ if ((q->flags & QAQ_QSTATE) != QAQ_NEW)\r
+ continue;\r
+ \r
+ if (!(qnick = getnickbynumeric(q->numeric)))\r
+ continue;\r
+ \r
+ sprintf(hostbuf,"%s!%s@%s", qnick->nick, qnick->ident, qnick->host->name->content);\r
+ \r
+ if (match(b->blockstr, hostbuf))\r
+ continue;\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;\r
+ spamqcount++;\r
+ }\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "Block caused %d message%s to be marked as spam.", spamqcount, (spamqcount == 1) ? "" : "s");\r
+ }\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanclear(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ qab_spam* s;\r
+ qab_spam* ns;\r
+ qab_answer* a;\r
+ qab_answer* na;\r
+ \r
+ for (s = bot->nextspam; s; s = ns) {\r
+ ns = s->next;\r
+ free(s->message);\r
+ free(s);\r
+ }\r
+ \r
+ bot->nextspam = bot->lastspam = 0;\r
+ \r
+ sendmessagetochannel(bot->np, cp, "Cleared message buffer.");\r
+ if (bot->micnumeric) {\r
+ bot->micnumeric = 0;\r
+ sendmessagetochannel(bot->np, cp, "Mic deactivated.");\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanclosechan(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ modechanges changes;\r
+ \r
+ localsetmodeinit(&changes, bot->public_chan->channel, bot->np);\r
+ localdosetmode_simple(&changes, CHANMODE_INVITEONLY, 0);\r
+ localsetmodeflush(&changes, 1);\r
+ sendnoticetouser(bot->np, sender, "Public channel has been closed.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanconfig(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ char* opt;\r
+ char* value;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !config <option> [<value>]");\r
+ sendnoticetouser(bot->np, sender, "Displays or sets configuration option. Valid options are:");\r
+ sendnoticetouser(bot->np, sender, "blockcontrol - Block questions containing control chars.");\r
+ sendnoticetouser(bot->np, sender, "blockcolour - Block questions containing colour.");\r
+ sendnoticetouser(bot->np, sender, "blockmark - Mark questions affected by blocks as spam.");\r
+ sendnoticetouser(bot->np, sender, "authedonly - Accept questions from authed users only.");\r
+ sendnoticetouser(bot->np, sender, "linebreak - Separate questions with line breaks.");\r
+ sendnoticetouser(bot->np, sender, "flooddetect - Attempt to detect floodclone spam.");\r
+ sendnoticetouser(bot->np, sender, "floodblock - Automatically block floodclone spam.");\r
+ sendnoticetouser(bot->np, sender, "spamint - Text spam interval.");\r
+ sendnoticetouser(bot->np, sender, "nickblockint - Time to wait before sending another question.");\r
+ sendnoticetouser(bot->np, sender, "queuedqint - Queued answer spam interval.");\r
+ sendnoticetouser(bot->np, sender, "mictimeout - Idle time before mic is automatically disabled.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ opt = cargv[0];\r
+ if (cargc == 2)\r
+ value = cargv[1];\r
+ else\r
+ value = 0;\r
+ \r
+ if (!ircd_strcmp(opt, "blockcontrol")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_CONTROLCHAR;\r
+ sendnoticetouser(bot->np, sender, "Questions containing control characters will now be blocked.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_CONTROLCHAR);\r
+ sendnoticetouser(bot->np, sender, "Questions containing control characters will no longer be blocked.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Control characters are currently %s blocked.", (bot->flags & QAB_CONTROLCHAR) ? "being" : "not being");\r
+ }\r
+ else if (!ircd_strcmp(opt, "blockcolour")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_COLOUR;\r
+ sendnoticetouser(bot->np, sender, "Questions containing colour will now be blocked.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_COLOUR);\r
+ sendnoticetouser(bot->np, sender, "Questions containing colour will no longer be blocked.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Colours are currently %s blocked.", (bot->flags & QAB_COLOUR) ? "being" : "not being");\r
+ }\r
+ else if (!ircd_strcmp(opt, "blockmark")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_BLOCKMARK;\r
+ sendnoticetouser(bot->np, sender, "New blocks will automatically mark affected questions as spam.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_BLOCKMARK);\r
+ sendnoticetouser(bot->np, sender, "New blocks will no longer automatically mark affected questions as spam.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Blocks are currently %smarking affected questions as spam.", (bot->flags & QAB_BLOCKMARK) ? "" : "not ");\r
+ }\r
+ else if (!ircd_strcmp(opt, "authedonly")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_AUTHEDONLY;\r
+ sendnoticetouser(bot->np, sender, "Questions from unauthed users will now be blocked.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_AUTHEDONLY);\r
+ sendnoticetouser(bot->np, sender, "Questions from unauthed users will no longer be blocked.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Unauthed users may currently %ssend questions.", (bot->flags & QAB_AUTHEDONLY) ? "NOT " : "");\r
+ }\r
+ else if (!ircd_strcmp(opt, "linebreak")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_LINEBREAK;\r
+ sendnoticetouser(bot->np, sender, "Line breaks are now enabled.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_LINEBREAK);\r
+ sendnoticetouser(bot->np, sender, "Line breaks are now disabled.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Line breaks are currently %s.", (bot->flags & QAB_LINEBREAK) ? "enabled" : "disabled");\r
+ }\r
+ else if (!ircd_strcmp(opt, "flooddetect")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_FLOODDETECT;\r
+ sendnoticetouser(bot->np, sender, "Flood detection is now enabled.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_FLOODDETECT);\r
+ sendnoticetouser(bot->np, sender, "Flood detection is now disabled.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Flood detection is currently %s.", (bot->flags & QAB_FLOODDETECT) ? "enabled" : "disabled");\r
+ }\r
+ else if (!ircd_strcmp(opt, "floodblock")) {\r
+ if (value) {\r
+ if (!ircd_strcmp(value, "on")) {\r
+ bot->flags |= QAB_FLOODSTOP;\r
+ sendnoticetouser(bot->np, sender, "Flood blocking is now enabled.");\r
+ }\r
+ else if (!ircd_strcmp(value, "off")) {\r
+ bot->flags &= (~QAB_FLOODSTOP);\r
+ sendnoticetouser(bot->np, sender, "Flood blocking is now disabled.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid option. Valid options are 'on' or 'off'.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Flood blocking is currently %s.", (bot->flags & QAB_FLOODSTOP) ? "enabled" : "disabled");\r
+ }\r
+ else if (!ircd_strcmp(opt, "mictimeout")) {\r
+ if (value) {\r
+ int v = (int)strtol(value, NULL, 10);\r
+ \r
+ if ((v < 0) || (v > 300)) {\r
+ sendnoticetouser(bot->np, sender, "Value must be between 0 (off) and 300.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot->mic_timeout = v;\r
+ sendnoticetouser(bot->np, sender, "Value set.");\r
+ }\r
+ else {\r
+ if (bot->mic_timeout)\r
+ sendnoticetouser(bot->np, sender, "Mic timeout is currently %d second%s.", bot->mic_timeout, (bot->mic_timeout == 1) ? "" : "s");\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Mic timeout is currently disabled.");\r
+ }\r
+ }\r
+ else if (!ircd_strcmp(opt, "spamint")) {\r
+ if (value) {\r
+ int v = (int)strtol(value, NULL, 10);\r
+ \r
+ if ((v < 1) || (v > 30)) {\r
+ sendnoticetouser(bot->np, sender, "Value must be between 1 and 30.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot->spam_interval = v;\r
+ sendnoticetouser(bot->np, sender, "Value set.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Spam interval is currently %d second%s.", bot->spam_interval, (bot->spam_interval == 1) ? "" : "s");\r
+ }\r
+ else if (!ircd_strcmp(opt, "nickblockint")) {\r
+ if (value) {\r
+ int v = (int)strtol(value, NULL, 10);\r
+ \r
+ if ((v < 1) || (v > 300)) {\r
+ sendnoticetouser(bot->np, sender, "Value must be between 1 and 300.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot->ask_wait = v;\r
+ sendnoticetouser(bot->np, sender, "Value set.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Nick block interval is currently %d second%s.", bot->ask_wait, (bot->ask_wait == 1) ? "" : "s");\r
+ }\r
+ else if (!ircd_strcmp(opt, "queuedqint")) {\r
+ if (value) {\r
+ int v = (int)strtol(value, NULL, 10);\r
+ \r
+ if ((v < 1) || (v > 20)) {\r
+ sendnoticetouser(bot->np, sender, "Value must be between 1 and 20.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot->queued_question_interval = v;\r
+ sendnoticetouser(bot->np, sender, "Value set.");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Queued question interval is currently %d second%s.", bot->queued_question_interval, (bot->queued_question_interval == 1) ? "" : "s");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, sender, "Invalid configuration option.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanhelp(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ char* ch;\r
+ \r
+ if (cargc < 1)\r
+ ch = "";\r
+ else\r
+ ch = cargv[0];\r
+ \r
+ if (*ch) {\r
+ if (!ircd_strcmp(ch, "mic")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !mic");\r
+ 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);\r
+ }\r
+ else if (!ircd_strcmp(ch, "clear")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !clear");\r
+ sendnoticetouser(bot->np, sender, "Clear currently queued text to relay, and turn off the microphone.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "ping")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !ping");\r
+ sendnoticetouser(bot->np, sender, "Pings the bot.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "config")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !config <option|help> [<value>]");\r
+ sendnoticetouser(bot->np, sender, "Display or set bot configuration options.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "answer")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !answer <id> <answer>");\r
+ sendnoticetouser(bot->np, sender, "Answer a question.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "block")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !block [<-q|-t>] <mask>");\r
+ sendnoticetouser(bot->np, sender, "Add a block, where:");\r
+ sendnoticetouser(bot->np, sender, "-q: blocks a Q account.");\r
+ sendnoticetouser(bot->np, sender, "-t: blocks question text.");\r
+ sendnoticetouser(bot->np, sender, "No flag results in a hostmask block.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "listblocks")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !listblocks");\r
+ sendnoticetouser(bot->np, sender, "View the currently added blocks.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "spam")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !spam <id>");\r
+ sendnoticetouser(bot->np, sender, "Mark a question as spam. This stops it being answered.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "offtopic")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !offtopic <id>");\r
+ sendnoticetouser(bot->np, sender, "Mark a question as off-topic. This stops it being answered.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "unblock")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !unblock [<-q|-t>] <mask>");\r
+ sendnoticetouser(bot->np, sender, "Removes a block. See \"!help block\" for a description of the flags.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "reset")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !reset <all|questions|blocks|stats>");\r
+ sendnoticetouser(bot->np, sender, "Reset the questions, blocks or both; or the stats.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "closechan")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !closechan");\r
+ sendnoticetouser(bot->np, sender, "Closes the public channel.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "openchan")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !openchan");\r
+ sendnoticetouser(bot->np, sender, "Opens the public channel.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "status")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !status");\r
+ sendnoticetouser(bot->np, sender, "Displays some status information and statistics.");\r
+ }\r
+ else if (!ircd_strcmp(ch, "help")) {\r
+ sendnoticetouser(bot->np, sender, "Syntax !help [<command>]");\r
+ sendnoticetouser(bot->np, sender, "List available commands or view help for a particular command.");\r
+ }\r
+ else {\r
+ sendnoticetouser(bot->np, sender, "No help available for '%s'.", ch);\r
+ }\r
+ }\r
+ else {\r
+ sendnoticetouser(bot->np, sender, "The following channel commands are recognised:");\r
+ sendnoticetouser(bot->np, sender, "!answer - Answer a question.");\r
+ sendnoticetouser(bot->np, sender, "!block - Block a hostmask, account or string.");\r
+ sendnoticetouser(bot->np, sender, "!clear - Clear currently queued text to spam.");\r
+ sendnoticetouser(bot->np, sender, "!closechan - Close the public channel.");\r
+ sendnoticetouser(bot->np, sender, "!config - Display or set bot configuration options.");\r
+ sendnoticetouser(bot->np, sender, "!help - List commands or view the help for a command");\r
+ sendnoticetouser(bot->np, sender, "!listblocks - List currently added blocks.");\r
+ sendnoticetouser(bot->np, sender, "!mic - Turn the microphone on or off.");\r
+ sendnoticetouser(bot->np, sender, "!offtopic - Mark a question or questions as off-topic.");\r
+ sendnoticetouser(bot->np, sender, "!openchan - Open the public channel.");\r
+ sendnoticetouser(bot->np, sender, "!ping - Ping the bot.");\r
+ sendnoticetouser(bot->np, sender, "!reset - Clear all blocks, questions or both.");\r
+ sendnoticetouser(bot->np, sender, "!spam - Mark a question or questions as spam.");\r
+ sendnoticetouser(bot->np, sender, "!status - Display some status statistics.");\r
+ sendnoticetouser(bot->np, sender, "!unblock - Remove a block.");\r
+ sendnoticetouser(bot->np, sender, "End of list.");\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanlistblocks(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ qab_block* b;\r
+ \r
+ if (!(b = bot->blocks)) {\r
+ sendnoticetouser(bot->np, sender, "There are no blocks currently added.");\r
+ return;\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "Type: Hostmask/Account/Textmask:");\r
+ \r
+ for (; b; b = b->next) {\r
+ if (b->type == QABBLOCK_ACCOUNT)\r
+ sendnoticetouser(bot->np, sender, "A %s", b->blockstr);\r
+ else if (b->type == QABBLOCK_HOST)\r
+ sendnoticetouser(bot->np, sender, "H %s", b->blockstr);\r
+ else\r
+ sendnoticetouser(bot->np, sender, "T %s", b->blockstr);\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "End of list.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanmic(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ \r
+ if (bot->micnumeric) {\r
+ if (bot->micnumeric == sender->numeric) {\r
+ bot->micnumeric = 0;\r
+ sendmessagetochannel(bot->np, cp, "Mic deactivated.");\r
+ if (!bot->lastspam)\r
+ qabot_spamstored((void*)bot);\r
+ }\r
+ else {\r
+ bot->lastmic = time(NULL);\r
+ bot->micnumeric = sender->numeric;\r
+ sendmessagetochannel(bot->np, cp, "%s now has the mic. Anything said by %s will be relayed in %s.", \r
+ sender->nick, sender->nick, bot->public_chan->name->content);\r
+ deleteschedule(0, qabot_spamstored, (void*)bot);\r
+ }\r
+ }\r
+ else {\r
+ bot->lastmic = time(NULL);\r
+ bot->micnumeric = sender->numeric;\r
+ sendmessagetochannel(bot->np, cp, "Mic activated. Anything said by %s will be relayed in %s.", \r
+ sender->nick, bot->public_chan->name->content);\r
+ deleteschedule(0, qabot_spamstored, (void*)bot);\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanmoo(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ char moostr[50];\r
+ int i, moocount = 5 + (rand() % 40);\r
+ \r
+ moostr[0] = 'm';\r
+ for (i = 1; i < moocount; i++)\r
+ moostr[i] = ((rand() % 100) > 50) ? 'o': '0';\r
+ moostr[i] = '\0';\r
+ \r
+ sendmessagetochannel(bot->np, cp, "%s", moostr);\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanofftopic(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ int id;\r
+ int i;\r
+ qab_question* q;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !spam <id> [<id> ... <id>]");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ for (i = 0; i < cargc; i++) {\r
+ id = strtol(cargv[i], NULL, 10);\r
+ \r
+ if ((id < 1) || (id > bot->lastquestionID)) {\r
+ sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);\r
+ continue;\r
+ }\r
+ \r
+ for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)\r
+ if (q->id == id)\r
+ break; \r
+ \r
+ if (!q) {\r
+ sendnoticetouser(bot->np, sender, "Can't find question %d.", id);\r
+ continue;\r
+ }\r
+ \r
+ switch (q->flags & QAQ_QSTATE) {\r
+ case QAQ_ANSWERED:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);\r
+ continue;\r
+ \r
+ case QAQ_OFFTOPIC:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been marked as off-topic.", id);\r
+ continue;\r
+ \r
+ case QAQ_SPAM:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been marked as spam.", id);\r
+ continue;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_OFFTOPIC;\r
+ sendnoticetouser(bot->np, sender, "Question %d has been marked as off-topic.", id);\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanopenchan(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ modechanges changes;\r
+ \r
+ localsetmodeinit(&changes, bot->public_chan->channel, bot->np);\r
+ localdosetmode_simple(&changes, CHANMODE_MODERATE|CHANMODE_DELJOINS, CHANMODE_INVITEONLY);\r
+ localsetmodeflush(&changes, 1);\r
+ sendnoticetouser(bot->np, sender, "Public channel has been opened.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanping(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ \r
+ sendmessagetochannel(bot->np, cp, "pong!");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanreset(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ int r = 0;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !reset <blocks|questions|stats|all>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!ircd_strcmp(cargv[0], "blocks"))\r
+ r = 1;\r
+ else if (!ircd_strcmp(cargv[0], "questions"))\r
+ r = 2;\r
+ else if (!ircd_strcmp(cargv[0], "stats"))\r
+ r = 4;\r
+ else if (!ircd_strcmp(cargv[0], "all"))\r
+ r = 3;\r
+ else {\r
+ sendnoticetouser(bot->np, sender, "Unknown parameter: %s.", cargv[0]);\r
+ return;\r
+ }\r
+ \r
+ if (r & 1) {\r
+ qab_block* b;\r
+ \r
+ while (bot->blocks) {\r
+ b = bot->blocks;\r
+ bot->blocks = bot->blocks->next;\r
+ if (b->blockstr)\r
+ free(b->blockstr);\r
+ free(b);\r
+ }\r
+ \r
+ bot->block_count = 0;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Reset (blocks): Done.");\r
+ }\r
+ \r
+ if (r & 2) {\r
+ qab_question* q;\r
+ int i;\r
+ \r
+ for (i = 0; i < QUESTIONHASHSIZE; i++) {\r
+ while (bot->questions[i]) {\r
+ q = bot->questions[i];\r
+ bot->questions[i] = bot->questions[i]->next;\r
+ if (q->question)\r
+ free(q->question);\r
+ if (q->answer)\r
+ free(q->answer);\r
+ free(q);\r
+ }\r
+ }\r
+ \r
+ bot->lastquestionID = 0;\r
+ bot->answered = 0;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Reset (questions): Done.");\r
+ }\r
+ \r
+ if (r & 4) {\r
+ bot->answered = 0;\r
+ bot->spammed = 0;\r
+ sendnoticetouser(bot->np, sender, "Reset (stats): Done.");\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanspam(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ int id;\r
+ int i;\r
+ qab_question* q;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !spam <id> [<id> ... <id>]");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ for (i = 0; i < cargc; i++) {\r
+ id = strtol(cargv[i], NULL, 10);\r
+ \r
+ if ((id < 1) || (id > bot->lastquestionID)) {\r
+ sendnoticetouser(bot->np, sender, "Invalid question ID %d.", id);\r
+ continue;\r
+ }\r
+ \r
+ for (q = bot->questions[id % QUESTIONHASHSIZE]; q; q = q->next)\r
+ if (q->id == id)\r
+ break; \r
+ \r
+ if (!q) {\r
+ sendnoticetouser(bot->np, sender, "Can't find question %d.", id);\r
+ continue;\r
+ }\r
+ \r
+ switch (q->flags & QAQ_QSTATE) {\r
+ case QAQ_ANSWERED:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been answered.", id);\r
+ continue;\r
+ \r
+ case QAQ_OFFTOPIC:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been marked as off-topic.", id);\r
+ continue;\r
+ \r
+ case QAQ_SPAM:\r
+ sendnoticetouser(bot->np, sender, "Question %d has already been marked as spam.", id);\r
+ continue;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+ \r
+ q->flags = ((q->flags) & ~QAQ_QSTATE) | QAQ_SPAM;\r
+ sendnoticetouser(bot->np, sender, "Question %d has been marked as spam.", id);\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanstatus(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ \r
+ sendnoticetouser(bot->np, sender, "Lines spammed: %d", bot->spammed);\r
+ sendnoticetouser(bot->np, sender, "Questions asked: %d", bot->lastquestionID);\r
+ sendnoticetouser(bot->np, sender, "Questions answered: %d", bot->answered);\r
+ sendnoticetouser(bot->np, sender, "Blocks: %d", bot->block_count);\r
+ /*sendnoticetouser(bot->np, sender, "Question interval: %d seconds", bot->question_interval);*/\r
+ sendnoticetouser(bot->np, sender, "Spam interval: %d seconds", bot->spam_interval);\r
+ sendnoticetouser(bot->np, sender, "Nick block interval: %d seconds", bot->ask_wait);\r
+ sendnoticetouser(bot->np, sender, "Queued question interval: %d seconds", bot->queued_question_interval);\r
+ sendnoticetouser(bot->np, sender, "Block control chars: %s", (bot->flags & QAB_CONTROLCHAR) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Block colour: %s", (bot->flags & QAB_COLOUR) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Authed users only: %s", (bot->flags & QAB_AUTHEDONLY) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Line break: %s", (bot->flags & QAB_LINEBREAK) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Question flood detection: %s", (bot->flags & QAB_FLOODDETECT) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Question flood blocking: %s", (bot->flags & QAB_FLOODSTOP) ? "Yes" : "No");\r
+ sendnoticetouser(bot->np, sender, "Blocks mark as spam: %s", (bot->flags & QAB_BLOCKMARK) ? "Yes" : "No");\r
+ if (bot->micnumeric) {\r
+ nick* mnick = getnickbynumeric(bot->micnumeric);\r
+ \r
+ sendnoticetouser(bot->np, np, "Mic: Enabled (%s)", mnick ? mnick->nick : "UNKNOWN");\r
+ }\r
+ else\r
+ sendnoticetouser(bot->np, np, "Mic: Disabled");\r
+ sendnoticetouser(bot->np, sender, "Mic timeout: %d", bot->mic_timeout);\r
+ /*sendnoticetouser(bot->np, sender, "");*/\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochanunblock(void* np, int cargc, char** cargv) {\r
+ nick* sender = (nick*)np;\r
+ qab_bot* bot = qabot_getcurrentbot();\r
+ channel* cp = qabot_getcurrentchannel();\r
+ char* ch;\r
+ qab_block* b;\r
+ char type = -1;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(bot->np, sender, "Syntax: !unblock [-q|-t] <account|mask>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (cargc > 1) {\r
+ if (!ircd_strncmp(cargv[0], "-q", 2)) {\r
+ type = QABBLOCK_ACCOUNT;\r
+ ch = cargv[1];\r
+ \r
+ if (*ch == '#')\r
+ ch++;\r
+ }\r
+ else if (!ircd_strncmp(cargv[0], "-t", 2)) {\r
+ type = QABBLOCK_TEXT;\r
+ ch = cargv[1];\r
+ }\r
+ else {\r
+ sendnoticetouser(bot->np, sender, "Invalid flag.");\r
+ return CMD_ERROR;\r
+ }\r
+ }\r
+ else {\r
+ type = QABBLOCK_HOST;\r
+ ch = cargv[0];\r
+ }\r
+ \r
+ for (b = bot->blocks; b; b = b->next) {\r
+ if (b->type != type)\r
+ continue;\r
+ \r
+ if (!ircd_strcmp(b->blockstr, ch)) {\r
+ if (b->next)\r
+ b->next->prev = b->prev;\r
+ if (b->prev)\r
+ b->prev->next = b->next;\r
+ else\r
+ bot->blocks = b->next;\r
+ \r
+ free(b->blockstr);\r
+ free(b);\r
+ \r
+ bot->block_count--;\r
+ \r
+ sendnoticetouser(bot->np, sender, "Block removed.");\r
+ return CMD_OK;\r
+ }\r
+ }\r
+ \r
+ sendnoticetouser(bot->np, sender, "No such block.");\r
+ \r
+ return CMD_ERROR;\r
+}\r
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-int qabot_doshowcommands(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- Command* cmdlist[150];
- int i, j;
-
- sendnoticetouser(qabot_nick, np, "The following commands are registered at present:");
- for (i = 0, j = getcommandlist(qabot_commands, cmdlist, 150); i < j; i++) {
- if (cmdlist[i]->level)
- sendnoticetouser(qabot_nick, np, "%s (%s)", cmdlist[i]->command->content, qabot_uflagtostr(cmdlist[i]->level));
- else
- sendnoticetouser(qabot_nick, np, "%s", cmdlist[i]->command->content);
- }
- sendnoticetouser(qabot_nick, np, "End of list.");
-
- return CMD_OK;
-}
-
-int qabot_dohelp(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: help <command>");
- return CMD_ERROR;
- }
-
- return qabot_showhelp(np, cargv[0]);
-}
-
-int qabot_dohello(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
-
- if (!IsOper(np)) {
- sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");
- return CMD_ERROR;
- }
-
- if (qabot_users) {
- sendnoticetouser(qabot_nick, np, "This command cannot be used once the initial account has been created.");
- return CMD_ERROR;
- }
-
- qabot_adduser(np->authname, QAUFLAG_STAFF|QAUFLAG_ADMIN|QAUFLAG_DEVELOPER, time(0));
- qabot_savedb();
- sendnoticetouser(qabot_nick, np, "An account has been created with admin privileges.");
-
- return CMD_OK;
-}
-
-int qabot_dosave(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
-
- sendnoticetouser(qabot_nick, np, "Saving...");
- qabot_savedb();
- sendnoticetouser(qabot_nick, np, "Done.");
-
- return CMD_OK;
-}
-
-int qabot_dolistbots(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- qab_bot* b;
-
- if (!qab_bots) {
- sendnoticetouser(qabot_nick, np, "There are no bots currently added.");
- return CMD_OK;
- }
-
- sendnoticetouser(qabot_nick, np, "The following bots are added:");
- for (b = qab_bots; b; b = b->next)
- sendnoticetouser(qabot_nick, np, "%s (%s@%s)", b->nick, b->user, b->host);
- sendnoticetouser(qabot_nick, np, "End of list.");
-}
-
-int qabot_dolistusers(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- qab_user* u;
-
- if (!qabot_users) {
- sendnoticetouser(qabot_nick, np, "There are no users currently added.");
- return CMD_OK;
- }
-
- sendnoticetouser(qabot_nick, np, "The following users are added:");
- for (u = qabot_users; u; u = u->next)
- sendnoticetouser(qabot_nick, np, "%-15s (%s)", u->authname, qabot_uflagtostr(u->flags));
- sendnoticetouser(qabot_nick, np, "End of list.");
-}
-
-int qabot_doshowbot(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- qab_bot* bot;
- nick* botnick;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: showbot <nick>");
- return CMD_ERROR;
- }
-
- if (!(botnick = getnickbynick(cargv[0]))) {
- sendnoticetouser(qabot_nick, np, "No such nickname.");
- return CMD_ERROR;
- }
-
- bot = botnick->exts[qabot_nickext];
- if (!bot) {
- sendnoticetouser(qabot_nick, np, "%s is not a QABot.", botnick->nick);
- return CMD_ERROR;
- }
-
- sendnoticetouser(qabot_nick, np, "- Information for %s ---", bot->nick);
- sendnoticetouser(qabot_nick, np, "User: %s", bot->user);
- sendnoticetouser(qabot_nick, np, "Host: %s", bot->host);
- sendnoticetouser(qabot_nick, np, "Public chan: %s", bot->public_chan->name->content);
- sendnoticetouser(qabot_nick, np, "Question chan: %s", bot->question_chan->name->content);
- sendnoticetouser(qabot_nick, np, "Staff chan: %s", bot->staff_chan->name->content);
- sendnoticetouser(qabot_nick, np, "Spam interval: %d", bot->spam_interval);
- sendnoticetouser(qabot_nick, np, "Nick block interval: %d", bot->ask_wait);
- sendnoticetouser(qabot_nick, np, "Queued question interval: %d", bot->queued_question_interval);
- sendnoticetouser(qabot_nick, np, "Lines spammed: %d", bot->spammed);
- sendnoticetouser(qabot_nick, np, "Questions asked: %d", bot->lastquestionID);
- sendnoticetouser(qabot_nick, np, "Questions answered: %d", bot->answered);
- sendnoticetouser(qabot_nick, np, "Blocks: %d", bot->block_count);
- sendnoticetouser(qabot_nick, np, "Block control chars: %s", (bot->flags & QAB_CONTROLCHAR) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Block colour: %s", (bot->flags & QAB_COLOUR) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Authed users only: %s", (bot->flags & QAB_AUTHEDONLY) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Line break: %s", (bot->flags & QAB_LINEBREAK) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Question flood detection: %s", (bot->flags & QAB_FLOODDETECT) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Question flood blocking: %s", (bot->flags & QAB_FLOODSTOP) ? "Yes" : "No");
- sendnoticetouser(qabot_nick, np, "Blocks mark as spam: %s", (bot->flags & QAB_BLOCKMARK) ? "Yes" : "No");
- if (bot->micnumeric) {
- nick* mnick = getnickbynumeric(bot->micnumeric);
-
- sendnoticetouser(qabot_nick, np, "Mic: Enabled (%s)", mnick ? mnick->nick : "UNKNOWN");
- }
- else
- sendnoticetouser(qabot_nick, np, "Mic: Disabled");
- sendnoticetouser(qabot_nick, sender, "Mic timeout: %d", bot->mic_timeout);
- sendnoticetouser(qabot_nick, np, "End of list.");
-
- return CMD_OK;
-}
-
-int qabot_doaddbot(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- qab_bot* bot;
- channel* cp;
-
- if (cargc < 3) {
- sendnoticetouser(qabot_nick, np, "Syntax: addbot <nick> <user> <host> <public channel> <question channel> <staff channel>");
- return CMD_ERROR;
- }
-
- if (!IsOper(np)) {
- sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");
- return CMD_ERROR;
- }
-
- if (!qabot_addbot(cargv[0], cargv[1], cargv[2], cargv[3], cargv[4], cargv[5], DEFAULTBOTFLAGS, SPAMINTERVAL, ASKWAIT, QUEUEDQUESTIONINTERVAL, np))
- return CMD_ERROR;
-
- sendnoticetouser(qabot_nick, np, "Created %s!%s@%s (%s, %s, %s).", cargv[0], cargv[1], cargv[2], cargv[3], cargv[4], cargv[5]);
-
- return CMD_OK;
-}
-
-int qabot_dodelbot(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- nick* botnick;
- qab_bot* bot;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: delbot <nick>");
- return CMD_ERROR;
- }
-
- if (!IsOper(np)) {
- sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");
- return CMD_ERROR;
- }
-
- if (!(botnick = getnickbynick(cargv[0]))) {
- sendnoticetouser(qabot_nick, np, "No such nickname.");
- return CMD_ERROR;
- }
-
- bot = botnick->exts[qabot_nickext];
- if (!bot) {
- sendnoticetouser(qabot_nick, np, "%s is not a QABot.", botnick->nick);
- return CMD_ERROR;
- }
-
- qabot_delbot(bot);
- sendnoticetouser(qabot_nick, np, "Bot deleted.");
-
- return CMD_OK;
-}
-
-int qabot_doadduser(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- nick* target;
- char* ch;
- flag_t flags = 0;
- char* victim;
-
- if (cargc < 2) {
- sendnoticetouser(qabot_nick, np, "Syntax: adduser <nick> <flags>");
- return CMD_ERROR;
- }
-
- if (!(victim = qabot_getvictim(np, cargv[0])))
- return CMD_ERROR;
-
- if (qabot_getuser(victim)) {
- sendnoticetouser(qabot_nick, np, "Account %s already exists.", target->authname);
- return CMD_ERROR;
- }
-
- for (ch = cargv[1]; *ch; ch++) {
- switch (*ch) {
- case '+':
- break;
-
- case 'a':
- flags |= (QAUFLAG_ADMIN|QAUFLAG_STAFF);
- break;
-
- case 'd':
- flags |= (QAUFLAG_DEVELOPER|QAUFLAG_ADMIN|QAUFLAG_STAFF);
-
- case 's':
- flags |= QAUFLAG_STAFF;
- break;
-
- default:
- sendnoticetouser(qabot_nick, np, "Unknown flag '%c'.", *ch);
- return;
- }
- }
-
- qabot_adduser(victim, flags, time(0));
- sendnoticetouser(qabot_nick, np, "Account created.");
-
- return CMD_OK;
-}
-
-int qabot_dodeluser(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- qab_user* u;
- char* victim;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: <account>");
- return CMD_ERROR;
- }
-
- if (!(victim = qabot_getvictim(np, cargv[0])))
- return CMD_ERROR;
-
- if (!(u = qabot_getuser(victim))) {
- sendnoticetouser(qabot_nick, np, "Account does not exist.");
- return CMD_ERROR;
- }
-
- if (!ircd_strcmp(u->authname, np->authname)) {
- sendnoticetouser(qabot_nick, np, "You cannot delete your own account.");
- return CMD_ERROR;
- }
-
- qabot_squelchuser(u);
- sendnoticetouser(qabot_nick, np, "Account deleted.");
-
- return CMD_OK;
-}
-
-int qabot_dochangelev(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- char* victim;
- qab_user* u;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: changelev <nick|#authname> <flags>");
- return CMD_ERROR;
- }
-
- if (!(victim = qabot_getvictim(np, cargv[0])))
- return CMD_ERROR;
-
- if (!(u = qabot_getuser(victim))) {
- sendnoticetouser(qabot_nick, np, "Account does not exist.");
- return CMD_ERROR;
- }
-
- sendnoticetouser(qabot_nick, np, "TODO: Finish this! :)");
-
- return CMD_OK;
-}
-
-int qabot_dowhois(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- char* victim;
- qab_user* u;
-
- if (cargc < 1) {
- sendnoticetouser(qabot_nick, np, "Syntax: whois <nick|#authname>");
- return CMD_ERROR;
- }
-
- if (!(victim = qabot_getvictim(np, cargv[0])))
- return CMD_ERROR;
-
- if (!(u = qabot_getuser(victim))) {
- sendnoticetouser(qabot_nick, np, "Account does not exist.");
- return CMD_ERROR;
- }
-
- sendnoticetouser(qabot_nick, np, "Account: %s", u->authname);
- sendnoticetouser(qabot_nick, np, "Flags: %s", qabot_uflagtostr(u->flags));
- sendnoticetouser(qabot_nick, np, "Created: %s", qabot_formattime(u->created));
-
- return CMD_OK;
-}
-
-int qabot_dostatus(void* sender, int cargc, char** cargv) {
- nick* np = (nick*)sender;
- int botc = 0, blockc = 0, userc = 0, spamc = 0, qc = 0, qac = 0;
- qab_bot* b;
- qab_user* u;
-
- for (b = qab_bots; b; b = b->next) {
- botc++;
- blockc += b->block_count;
- spamc += b->spammed;
- qc += b->lastquestionID;
- qac += b->answered;
- }
-
- for (u = qabot_users; u; u = u->next)
- userc++;
-
- sendnoticetouser(qabot_nick, np, "Up since: %s", qabot_formattime(qab_startime));
- sendnoticetouser(qabot_nick, np, "Bots: %d", botc);
- sendnoticetouser(qabot_nick, np, "Blocks: %d", blockc);
- sendnoticetouser(qabot_nick, np, "Users: %d", userc);
- sendnoticetouser(qabot_nick, np, "Total lines spammed: %d", spamc);
- sendnoticetouser(qabot_nick, np, "Total questions asked: %d", qc);
- sendnoticetouser(qabot_nick, np, "Total questions answered: %d", qac);
-
- return CMD_OK;
-}
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+int qabot_doshowcommands(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ Command* cmdlist[150];\r
+ int i, j;\r
+\r
+ sendnoticetouser(qabot_nick, np, "The following commands are registered at present:");\r
+ for (i = 0, j = getcommandlist(qabot_commands, cmdlist, 150); i < j; i++) {\r
+ if (cmdlist[i]->level)\r
+ sendnoticetouser(qabot_nick, np, "%s (%s)", cmdlist[i]->command->content, qabot_uflagtostr(cmdlist[i]->level));\r
+ else\r
+ sendnoticetouser(qabot_nick, np, "%s", cmdlist[i]->command->content);\r
+ }\r
+ sendnoticetouser(qabot_nick, np, "End of list.");\r
+\r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dohelp(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: help <command>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ return qabot_showhelp(np, cargv[0]);\r
+}\r
+\r
+int qabot_dohello(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+\r
+ if (!IsOper(np)) {\r
+ sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");\r
+ return CMD_ERROR;\r
+ }\r
+\r
+ if (qabot_users) {\r
+ sendnoticetouser(qabot_nick, np, "This command cannot be used once the initial account has been created.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ qabot_adduser(np->authname, QAUFLAG_STAFF|QAUFLAG_ADMIN|QAUFLAG_DEVELOPER, time(0));\r
+ qabot_savedb();\r
+ sendnoticetouser(qabot_nick, np, "An account has been created with admin privileges.");\r
+\r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dosave(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ \r
+ sendnoticetouser(qabot_nick, np, "Saving...");\r
+ qabot_savedb();\r
+ sendnoticetouser(qabot_nick, np, "Done.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dolistbots(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ qab_bot* b;\r
+ \r
+ if (!qab_bots) {\r
+ sendnoticetouser(qabot_nick, np, "There are no bots currently added.");\r
+ return CMD_OK;\r
+ }\r
+ \r
+ sendnoticetouser(qabot_nick, np, "The following bots are added:");\r
+ for (b = qab_bots; b; b = b->next)\r
+ sendnoticetouser(qabot_nick, np, "%s (%s@%s)", b->nick, b->user, b->host);\r
+ sendnoticetouser(qabot_nick, np, "End of list.");\r
+}\r
+\r
+int qabot_dolistusers(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ qab_user* u;\r
+ \r
+ if (!qabot_users) {\r
+ sendnoticetouser(qabot_nick, np, "There are no users currently added.");\r
+ return CMD_OK;\r
+ }\r
+ \r
+ sendnoticetouser(qabot_nick, np, "The following users are added:");\r
+ for (u = qabot_users; u; u = u->next)\r
+ sendnoticetouser(qabot_nick, np, "%-15s (%s)", u->authname, qabot_uflagtostr(u->flags));\r
+ sendnoticetouser(qabot_nick, np, "End of list.");\r
+}\r
+\r
+int qabot_doshowbot(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ qab_bot* bot;\r
+ nick* botnick;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: showbot <nick>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(botnick = getnickbynick(cargv[0]))) {\r
+ sendnoticetouser(qabot_nick, np, "No such nickname.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot = botnick->exts[qabot_nickext];\r
+ if (!bot) {\r
+ sendnoticetouser(qabot_nick, np, "%s is not a QABot.", botnick->nick);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ sendnoticetouser(qabot_nick, np, "- Information for %s ---", bot->nick);\r
+ sendnoticetouser(qabot_nick, np, "User: %s", bot->user);\r
+ sendnoticetouser(qabot_nick, np, "Host: %s", bot->host);\r
+ sendnoticetouser(qabot_nick, np, "Public chan: %s", bot->public_chan->name->content);\r
+ sendnoticetouser(qabot_nick, np, "Question chan: %s", bot->question_chan->name->content);\r
+ sendnoticetouser(qabot_nick, np, "Staff chan: %s", bot->staff_chan->name->content);\r
+ sendnoticetouser(qabot_nick, np, "Spam interval: %d", bot->spam_interval);\r
+ sendnoticetouser(qabot_nick, np, "Nick block interval: %d", bot->ask_wait);\r
+ sendnoticetouser(qabot_nick, np, "Queued question interval: %d", bot->queued_question_interval); \r
+ sendnoticetouser(qabot_nick, np, "Lines spammed: %d", bot->spammed);\r
+ sendnoticetouser(qabot_nick, np, "Questions asked: %d", bot->lastquestionID);\r
+ sendnoticetouser(qabot_nick, np, "Questions answered: %d", bot->answered);\r
+ sendnoticetouser(qabot_nick, np, "Blocks: %d", bot->block_count);\r
+ sendnoticetouser(qabot_nick, np, "Block control chars: %s", (bot->flags & QAB_CONTROLCHAR) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Block colour: %s", (bot->flags & QAB_COLOUR) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Authed users only: %s", (bot->flags & QAB_AUTHEDONLY) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Line break: %s", (bot->flags & QAB_LINEBREAK) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Question flood detection: %s", (bot->flags & QAB_FLOODDETECT) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Question flood blocking: %s", (bot->flags & QAB_FLOODSTOP) ? "Yes" : "No");\r
+ sendnoticetouser(qabot_nick, np, "Blocks mark as spam: %s", (bot->flags & QAB_BLOCKMARK) ? "Yes" : "No");\r
+ if (bot->micnumeric) {\r
+ nick* mnick = getnickbynumeric(bot->micnumeric);\r
+ \r
+ sendnoticetouser(qabot_nick, np, "Mic: Enabled (%s)", mnick ? mnick->nick : "UNKNOWN");\r
+ }\r
+ else\r
+ sendnoticetouser(qabot_nick, np, "Mic: Disabled");\r
+ sendnoticetouser(qabot_nick, sender, "Mic timeout: %d", bot->mic_timeout);\r
+ sendnoticetouser(qabot_nick, np, "End of list.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_doaddbot(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ qab_bot* bot;\r
+ channel* cp;\r
+ \r
+ if (cargc < 3) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: addbot <nick> <user> <host> <public channel> <question channel> <staff channel>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!IsOper(np)) {\r
+ sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!qabot_addbot(cargv[0], cargv[1], cargv[2], cargv[3], cargv[4], cargv[5], DEFAULTBOTFLAGS, SPAMINTERVAL, ASKWAIT, QUEUEDQUESTIONINTERVAL, np))\r
+ return CMD_ERROR;\r
+ \r
+ sendnoticetouser(qabot_nick, np, "Created %s!%s@%s (%s, %s, %s).", cargv[0], cargv[1], cargv[2], cargv[3], cargv[4], cargv[5]);\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dodelbot(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ nick* botnick;\r
+ qab_bot* bot;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: delbot <nick>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!IsOper(np)) {\r
+ sendnoticetouser(qabot_nick, np, "You must be opered to use this command.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(botnick = getnickbynick(cargv[0]))) {\r
+ sendnoticetouser(qabot_nick, np, "No such nickname.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ bot = botnick->exts[qabot_nickext];\r
+ if (!bot) {\r
+ sendnoticetouser(qabot_nick, np, "%s is not a QABot.", botnick->nick);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ qabot_delbot(bot);\r
+ sendnoticetouser(qabot_nick, np, "Bot deleted.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_doadduser(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ nick* target;\r
+ char* ch;\r
+ flag_t flags = 0;\r
+ char* victim;\r
+ \r
+ if (cargc < 2) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: adduser <nick> <flags>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(victim = qabot_getvictim(np, cargv[0])))\r
+ return CMD_ERROR;\r
+ \r
+ if (qabot_getuser(victim)) {\r
+ sendnoticetouser(qabot_nick, np, "Account %s already exists.", target->authname);\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ for (ch = cargv[1]; *ch; ch++) {\r
+ switch (*ch) {\r
+ case '+':\r
+ break;\r
+ \r
+ case 'a':\r
+ flags |= (QAUFLAG_ADMIN|QAUFLAG_STAFF);\r
+ break;\r
+ \r
+ case 'd':\r
+ flags |= (QAUFLAG_DEVELOPER|QAUFLAG_ADMIN|QAUFLAG_STAFF);\r
+ \r
+ case 's':\r
+ flags |= QAUFLAG_STAFF;\r
+ break;\r
+ \r
+ default:\r
+ sendnoticetouser(qabot_nick, np, "Unknown flag '%c'.", *ch);\r
+ return;\r
+ }\r
+ }\r
+ \r
+ qabot_adduser(victim, flags, time(0));\r
+ sendnoticetouser(qabot_nick, np, "Account created.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dodeluser(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ qab_user* u;\r
+ char* victim;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: <account>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(victim = qabot_getvictim(np, cargv[0])))\r
+ return CMD_ERROR;\r
+ \r
+ if (!(u = qabot_getuser(victim))) {\r
+ sendnoticetouser(qabot_nick, np, "Account does not exist.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!ircd_strcmp(u->authname, np->authname)) {\r
+ sendnoticetouser(qabot_nick, np, "You cannot delete your own account.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ qabot_squelchuser(u);\r
+ sendnoticetouser(qabot_nick, np, "Account deleted.");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dochangelev(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ char* victim;\r
+ qab_user* u;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: changelev <nick|#authname> <flags>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(victim = qabot_getvictim(np, cargv[0])))\r
+ return CMD_ERROR;\r
+ \r
+ if (!(u = qabot_getuser(victim))) {\r
+ sendnoticetouser(qabot_nick, np, "Account does not exist.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ sendnoticetouser(qabot_nick, np, "TODO: Finish this! :)");\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dowhois(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ char* victim;\r
+ qab_user* u;\r
+ \r
+ if (cargc < 1) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: whois <nick|#authname>");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ if (!(victim = qabot_getvictim(np, cargv[0])))\r
+ return CMD_ERROR;\r
+ \r
+ if (!(u = qabot_getuser(victim))) {\r
+ sendnoticetouser(qabot_nick, np, "Account does not exist.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ sendnoticetouser(qabot_nick, np, "Account: %s", u->authname);\r
+ sendnoticetouser(qabot_nick, np, "Flags: %s", qabot_uflagtostr(u->flags));\r
+ sendnoticetouser(qabot_nick, np, "Created: %s", qabot_formattime(u->created));\r
+ \r
+ return CMD_OK;\r
+}\r
+\r
+int qabot_dostatus(void* sender, int cargc, char** cargv) {\r
+ nick* np = (nick*)sender;\r
+ int botc = 0, blockc = 0, userc = 0, spamc = 0, qc = 0, qac = 0;\r
+ qab_bot* b;\r
+ qab_user* u;\r
+ \r
+ for (b = qab_bots; b; b = b->next) {\r
+ botc++;\r
+ blockc += b->block_count;\r
+ spamc += b->spammed;\r
+ qc += b->lastquestionID;\r
+ qac += b->answered;\r
+ }\r
+ \r
+ for (u = qabot_users; u; u = u->next)\r
+ userc++;\r
+ \r
+ sendnoticetouser(qabot_nick, np, "Up since: %s", qabot_formattime(qab_startime));\r
+ sendnoticetouser(qabot_nick, np, "Bots: %d", botc);\r
+ sendnoticetouser(qabot_nick, np, "Blocks: %d", blockc);\r
+ sendnoticetouser(qabot_nick, np, "Users: %d", userc);\r
+ sendnoticetouser(qabot_nick, np, "Total lines spammed: %d", spamc);\r
+ sendnoticetouser(qabot_nick, np, "Total questions asked: %d", qc);\r
+ sendnoticetouser(qabot_nick, np, "Total questions answered: %d", qac);\r
+ \r
+ return CMD_OK;\r
+}\r
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-qab_user* qabot_users = 0;
-
-void qabot_loaddb() {
- FILE* f;
- char buf[2049];
- char* args[100];
- time_t created;
- flag_t flags;
- int spam_interval;
- int ask_wait;
- int queued_question_interval;
- qab_bot* bot;
- qab_block* b;
- char blocktype;
-
- if (!(f = fopen("qab_users", "r")))
- return;
-
- while (!feof(f)) {
- if (fgets(buf, 2048, f)) {
- buf[2048] = '\0';
- if (splitline(buf, args, 50, 0) != 3) {
- fclose(f);
- return;
- }
-
- flags = (flag_t)strtoul(args[1], NULL, 10);
- created = strtoul(args[2], NULL, 10);
-
- qabot_adduser(args[0], flags, created);
- }
- }
-
- fclose(f);
-
- if (!(f = fopen("qab_bots", "r")))
- return;
-
- while (!feof(f)) {
- if (fgets(buf, 2048, f)) {
- buf[2048] = '\0';
- if (splitline(buf, args, 50, 0) != 10) {
- fclose(f);
- return;
- }
-
- qabot_addbot(args[0], args[1], args[2], args[3], args[4], args[5], (flag_t)strtol(args[6], NULL, 10),
- (int)strtol(args[7], NULL, 10), (int)strtol(args[8], NULL, 10), (int)strtol(args[9], NULL, 10), 0);
- }
- }
-
- fclose(f);
-
- if (!(f = fopen("qab_blocks", "r")))
- return;
-
- while (!feof(f)) {
- if (fgets(buf, 2048, f)) {
- buf[2048] = '\0';
- if (splitline(buf, args, 50, 0) != 5) {
- fclose(f);
- return;
- }
-
- /* args[0] = botname
- args[1] = type
- args[2] = creator
- args[3] = created
- args[4] = blockstr */
- if (!strcmp(args[0], "q")) {
- /* account block */
- if (strchr(args[4], '*') || args[4](target, '?'))
- continue; /* wildcard account blocks are not supported */
-
- blocktype = QABBLOCK_ACCOUNT;
- }
- else if (!strcmp(args[0], "t")) {
- /* text block */
- blocktype = QABBLOCK_TEXT;
- }
- else if (!strcmp(args[0], "h")) {
- /* hostmask block */
- blocktype = QABBLOCK_HOST;
- }
- else
- continue; /* unknown block, lets skip and hope everything works out */
-
- if (!(bot = qabot_findbot(args[0])))
- continue; /* no such bot added */
-
- b = (qab_block*)malloc(sizeof(qab_block));
- b->type = blocktype;
- b->created = (long)strol(args[3]);
- strncpy(b->creator, args[2], ACCOUNTLEN);
- b->creator[ACCOUNTLEN] = '\0';
- b->blockstr = strdup(args[4]);
- b->prev = 0;
- b->next = bot->blocks;
- if (bot->blocks)
- bot->blocks->prev = b;
- bot->blocks = b;
- bot->block_count++;
- }
- }
-
- fclose(f);
-}
-
-void qabot_savedb() {
- FILE* f;
- qab_user* u;
- qab_bot* b;
- qab_block* block;
-
- if (!(f = fopen("qab_users", "w")))
- return;
-
- for (u = qabot_users; u; u = u->next)
- fprintf(f, "%s %d %ld\n", u->authname, (int)u->flags, u->created);
-
- fclose(f);
-
- if (!(f = fopen("qab_bots", "w")))
- return;
-
- for (b = qab_bots; b; b = b->next)
- fprintf(f, "%s %s %s %s %s %s %d %d %d %d\n", b->nick, b->user, b->host, b->public_chan->name->content,
- b->question_chan->name->content, b->staff_chan->name->content, (int)b->flags, b->spam_interval,
- b->ask_wait, b->queued_question_interval);
-
- fclose(f);
-
- if (!(f = fopen("qab_blocks", "w")))
- return;
-
- for (b = qab_bots; b; b = b->next)
- for (block = b->blocks; block; block = block->next)
- fprintf(f, "%s %c %s %ld %s\n", b->nick, block->type == QABBLOCK_ACCOUNT ? 'q' : block->type == QABBLOCK_HOST ? 'h' : 't',
- block->creator, block->created, block->blockstr);
-
- fclose(f);
-}
-
-void qabot_savetimer(void* arg) {
- qabot_savedb();
-}
-
-void qabot_adduser(const char* authname, flag_t flags, time_t created) {
- qab_user* u;
-
- if ((u = qabot_getuser(authname)))
- return;
-
- u = (qab_user*)malloc(sizeof(qab_user));
- strncpy(u->authname, authname, ACCOUNTLEN);
- u->authname[ACCOUNTLEN] = '\0';
- u->flags = flags;
- u->created = created;
-
- u->prev = 0;
- u->next = qabot_users;
- if (qabot_users)
- qabot_users->prev = u;
- qabot_users = u;
-}
-
-void qabot_deluser(const char* authname) {
- qab_user* u = qabot_getuser(authname);
-
- if (!u)
- return;
-
- qabot_squelchuser(u);
-}
-
-void qabot_squelchuser(qab_user* user) {
- if (user->next)
- user->next->prev = user->prev;
- if (user->prev)
- user->prev->next = user->next;
- else
- qabot_users = user->next;
-
- free(user);
-}
-
-qab_user* qabot_getuser(const char* authname) {
- qab_user* u;
-
- for (u = qabot_users; u; u = u->next)
- if (!ircd_strcmp(u->authname, authname))
- return u;
-
- return 0;
-}
-
-qab_bot* qabot_findbot(const char* nickname) {
- qab_bot* bot;
-
- for (bot = qab_bots; bot; bot = bot->next)
- if (!ircd_strcmp(bot->nick, nickname))
- return bot;
-
- return 0;
-}
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+qab_user* qabot_users = 0;\r
+\r
+void qabot_loaddb() {\r
+ FILE* f;\r
+ char buf[2049];\r
+ char* args[100];\r
+ time_t created;\r
+ flag_t flags;\r
+ int spam_interval;\r
+ int ask_wait;\r
+ int queued_question_interval;\r
+ qab_bot* b;\r
+ \r
+ if (!(f = fopen("qab_users", "r")))\r
+ return;\r
+ \r
+ while (!feof(f)) {\r
+ if (fgets(buf, 2048, f)) {\r
+ buf[2048] = '\0';\r
+ if (splitline(buf, args, 50, 0) != 3) {\r
+ fclose(f);\r
+ return;\r
+ }\r
+ \r
+ flags = (flag_t)strtoul(args[1], NULL, 10);\r
+ created = strtoul(args[2], NULL, 10);\r
+ \r
+ qabot_adduser(args[0], flags, created);\r
+ }\r
+ }\r
+ \r
+ fclose(f);\r
+ \r
+ if (!(f = fopen("qab_bots", "r")))\r
+ return;\r
+ \r
+ while (!feof(f)) {\r
+ if (fgets(buf, 2048, f)) {\r
+ buf[2048] = '\0';\r
+ if (splitline(buf, args, 50, 0) != 10) {\r
+ fclose(f);\r
+ return;\r
+ }\r
+ \r
+ qabot_addbot(args[0], args[1], args[2], args[3], args[4], args[5], (flag_t)strtol(args[6], NULL, 10), \r
+ (int)strtol(args[7], NULL, 10), (int)strtol(args[8], NULL, 10), (int)strtol(args[9], NULL, 10), 0);\r
+ }\r
+ }\r
+ \r
+ fclose(f);\r
+}\r
+\r
+void qabot_savedb() {\r
+ FILE* f;\r
+ qab_user* u;\r
+ qab_bot* b;\r
+ \r
+ if (!(f = fopen("qab_users", "w")))\r
+ return;\r
+ \r
+ for (u = qabot_users; u; u = u->next)\r
+ fprintf(f, "%s %d %ld\n", u->authname, (int)u->flags, u->created);\r
+ \r
+ fclose(f);\r
+ \r
+ if (!(f = fopen("qab_bots", "w")))\r
+ return;\r
+ \r
+ for (b = qab_bots; b; b = b->next)\r
+ fprintf(f, "%s %s %s %s %s %s %d %d %d %d\n", b->nick, b->user, b->host, b->public_chan->name->content, \r
+ b->question_chan->name->content, b->staff_chan->name->content, (int)b->flags, b->spam_interval, \r
+ b->ask_wait, b->queued_question_interval);\r
+ \r
+ fclose(f);\r
+}\r
+\r
+void qabot_savetimer(void* arg) {\r
+ qabot_savedb();\r
+}\r
+\r
+void qabot_adduser(const char* authname, flag_t flags, time_t created) {\r
+ qab_user* u;\r
+\r
+ if ((u = qabot_getuser(authname)))\r
+ return;\r
+\r
+ u = (qab_user*)malloc(sizeof(qab_user));\r
+ strncpy(u->authname, authname, ACCOUNTLEN);\r
+ u->authname[ACCOUNTLEN] = '\0';\r
+ u->flags = flags;\r
+ u->created = created;\r
+\r
+ u->prev = 0;\r
+ u->next = qabot_users;\r
+ if (qabot_users)\r
+ qabot_users->prev = u;\r
+ qabot_users = u;\r
+}\r
+\r
+void qabot_deluser(const char* authname) {\r
+ qab_user* u = qabot_getuser(authname);\r
+\r
+ if (!u)\r
+ return;\r
+\r
+ qabot_squelchuser(u);\r
+}\r
+\r
+void qabot_squelchuser(qab_user* user) {\r
+ if (user->next)\r
+ user->next->prev = user->prev;\r
+ if (user->prev)\r
+ user->prev->next = user->next;\r
+ else\r
+ qabot_users = user->next;\r
+\r
+ free(user);\r
+}\r
+\r
+qab_user* qabot_getuser(const char* authname) {\r
+ qab_user* u;\r
+\r
+ for (u = qabot_users; u; u = u->next)\r
+ if (!ircd_strcmp(u->authname, authname))\r
+ return u;\r
+\r
+ return 0;\r
+}\r
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include "../nick/nick.h"
-#include "../localuser/localuserchannel.h"
-#include "../core/hooks.h"
-#include "../core/schedule.h"
-#include "../lib/array.h"
-#include "../lib/base64.h"
-#include "../lib/irc_string.h"
-#include "../lib/splitline.h"
-
-#include "qabot.h"
-
-int qabot_showhelp(nick* np, char* arg) {
- if (!ircd_strcmp(arg, "showcommands")) {
- sendnoticetouser(qabot_nick, np, "Syntax: showcommands");
- sendnoticetouser(qabot_nick, np, "Display commands the bot provides.");
- }
- else if (!ircd_strcmp(arg, "help")) {
- sendnoticetouser(qabot_nick, np, "Syntax: help <command>");
- sendnoticetouser(qabot_nick, np, "View help for a particular command.");
- }
- else if (!ircd_strcmp(arg, "hello")) {
- sendnoticetouser(qabot_nick, np, "Syntax: hello");
- sendnoticetouser(qabot_nick, np, "Create the initial user account on the bot.");
- }
- else if (!ircd_strcmp(arg, "save")) {
- sendnoticetouser(qabot_nick, np, "Syntax: save");
- sendnoticetouser(qabot_nick, np, "Save the user and bot databases.");
- }
- else if (!ircd_strcmp(arg, "listbots")) {
- sendnoticetouser(qabot_nick, np, "Syntax: listbots");
- sendnoticetouser(qabot_nick, np, "List currently added bots.");
- }
- else if (!ircd_strcmp(arg, "listusers")) {
- sendnoticetouser(qabot_nick, np, "Syntax: listusers");
- sendnoticetouser(qabot_nick, np, "List currently added users.");
- }
- else if (!ircd_strcmp(arg, "showbot")) {
- sendnoticetouser(qabot_nick, np, "Syntax: showbot <nick>");
- sendnoticetouser(qabot_nick, np, "Show information about a particular bot.");
- }
- else if (!ircd_strcmp(arg, "addbot")) {
- sendnoticetouser(qabot_nick, np, "Syntax: addbot <nick> <user> <host> <public chan> <question chan> <staff chan>");
- sendnoticetouser(qabot_nick, np, "Add a new bot.");
- }
- else if (!ircd_strcmp(arg, "delbot")) {
- sendnoticetouser(qabot_nick, np, "Syntax: delbot <nick>");
- sendnoticetouser(qabot_nick, np, "Delete a bot.");
- }
- else if (!ircd_strcmp(arg, "adduser")) {
- sendnoticetouser(qabot_nick, np, "Syntax: adduser <nick|#authname> <flags>");
- sendnoticetouser(qabot_nick, np, "Add a user. Flags may consist of:");
- sendnoticetouser(qabot_nick, np, "+a: administrator");
- sendnoticetouser(qabot_nick, np, "+d: developer");
- sendnoticetouser(qabot_nick, np, "+s: staff");
- }
- else if (!ircd_strcmp(arg, "deluser")) {
- sendnoticetouser(qabot_nick, np, "Syntax: deluser <nick|#authname>");
- sendnoticetouser(qabot_nick, np, "Delete a user.");
- }
- else if (!ircd_strcmp(arg, "changelev")) {
- sendnoticetouser(qabot_nick, np, "Syntax: changelev <nick|#authname> <flags>");
- sendnoticetouser(qabot_nick, np, "Change a user's level. Flags may consist of:");
- sendnoticetouser(qabot_nick, np, "+a: administrator");
- sendnoticetouser(qabot_nick, np, "+d: developer");
- sendnoticetouser(qabot_nick, np, "+s: staff");
- }
- else if (!ircd_strcmp(arg, "whois")) {
- sendnoticetouser(qabot_nick, np, "Syntax: whois <nick|#authname>");
- sendnoticetouser(qabot_nick, np, "Display information about a particular user.");
- }
- else if (!ircd_strcmp(arg, "status")) {
- sendnoticetouser(qabot_nick, np, "Syntax: status");
- sendnoticetouser(qabot_nick, np, "Display some status information.");
- }
- else {
- sendnoticetouser(qabot_nick, np, "No such command.");
- return CMD_ERROR;
- }
-
- return CMD_OK;
-}
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#include "../nick/nick.h"\r
+#include "../localuser/localuserchannel.h"\r
+#include "../core/hooks.h"\r
+#include "../core/schedule.h"\r
+#include "../lib/array.h"\r
+#include "../lib/base64.h"\r
+#include "../lib/irc_string.h"\r
+#include "../lib/splitline.h"\r
+\r
+#include "qabot.h"\r
+\r
+int qabot_showhelp(nick* np, char* arg) {\r
+ if (!ircd_strcmp(arg, "showcommands")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: showcommands");\r
+ sendnoticetouser(qabot_nick, np, "Display commands the bot provides.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "help")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: help <command>");\r
+ sendnoticetouser(qabot_nick, np, "View help for a particular command.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "hello")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: hello");\r
+ sendnoticetouser(qabot_nick, np, "Create the initial user account on the bot.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "save")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: save");\r
+ sendnoticetouser(qabot_nick, np, "Save the user and bot databases.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "listbots")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: listbots");\r
+ sendnoticetouser(qabot_nick, np, "List currently added bots.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "listusers")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: listusers");\r
+ sendnoticetouser(qabot_nick, np, "List currently added users.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "showbot")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: showbot <nick>");\r
+ sendnoticetouser(qabot_nick, np, "Show information about a particular bot.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "addbot")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: addbot <nick> <user> <host> <public chan> <question chan> <staff chan>");\r
+ sendnoticetouser(qabot_nick, np, "Add a new bot.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "delbot")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: delbot <nick>");\r
+ sendnoticetouser(qabot_nick, np, "Delete a bot.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "adduser")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: adduser <nick|#authname> <flags>");\r
+ sendnoticetouser(qabot_nick, np, "Add a user. Flags may consist of:");\r
+ sendnoticetouser(qabot_nick, np, "+a: administrator");\r
+ sendnoticetouser(qabot_nick, np, "+d: developer");\r
+ sendnoticetouser(qabot_nick, np, "+s: staff");\r
+ }\r
+ else if (!ircd_strcmp(arg, "deluser")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: deluser <nick|#authname>");\r
+ sendnoticetouser(qabot_nick, np, "Delete a user.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "changelev")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: changelev <nick|#authname> <flags>");\r
+ sendnoticetouser(qabot_nick, np, "Change a user's level. Flags may consist of:");\r
+ sendnoticetouser(qabot_nick, np, "+a: administrator");\r
+ sendnoticetouser(qabot_nick, np, "+d: developer");\r
+ sendnoticetouser(qabot_nick, np, "+s: staff");\r
+ }\r
+ else if (!ircd_strcmp(arg, "whois")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: whois <nick|#authname>");\r
+ sendnoticetouser(qabot_nick, np, "Display information about a particular user.");\r
+ }\r
+ else if (!ircd_strcmp(arg, "status")) {\r
+ sendnoticetouser(qabot_nick, np, "Syntax: status");\r
+ sendnoticetouser(qabot_nick, np, "Display some status information.");\r
+ }\r
+ else {\r
+ sendnoticetouser(qabot_nick, np, "No such command.");\r
+ return CMD_ERROR;\r
+ }\r
+ \r
+ return CMD_OK;\r
+}\r