]> jfr.im git - irc/quakenet/newserv.git/blame - qabot/qabot_bot.c
add module version
[irc/quakenet/newserv.git] / qabot / qabot_bot.c
CommitLineData
f011b15a
CP
1#include <stdio.h>
2#include <time.h>
3
4#include "../nick/nick.h"
5#include "../localuser/localuserchannel.h"
6#include "../core/hooks.h"
7#include "../core/schedule.h"
8#include "../lib/array.h"
9#include "../lib/base64.h"
10#include "../lib/irc_string.h"
11#include "../lib/splitline.h"
12
13#include "qabot.h"
14
15qab_bot* qabot_getbot() {
16 qab_bot* bot;
17 int i;
18
19 bot = (qab_bot*)malloc(sizeof(qab_bot));
20 bot->nick[0] = '\0';
21 bot->user[0] = '\0';
22 bot->host = 0;
23 bot->np = 0;
24 bot->public_chan = 0;
25 bot->question_chan = 0;
26 bot->staff_chan = 0;
27 bot->blocks = 0;
28 bot->block_count = 0;
29
30 bot->spammed = 0;
31
32 bot->flags = DEFAULTBOTFLAGS;
33
34 /*bot->question_interval = QUESTIONINTERVAL;*/
35 bot->spam_interval = SPAMINTERVAL;
36 bot->ask_wait = ASKWAIT;
37 bot->queued_question_interval = QUEUEDQUESTIONINTERVAL;
38
39 bot->lastquestionID = 0;
40 bot->answered = 0;
41
42 for (i = 0; i < QUESTIONHASHSIZE; i++)
43 bot->questions[i] = 0;
44
45 bot->nextspam = 0;
46 bot->lastspam = 0;
47 bot->spamtime = 0;
48 bot->answers = 0;
49
50 bot->micnumeric = 0;
51
52 bot->next = 0;
53 bot->prev = 0;
54
55 return bot;
56}
57
58int qabot_addbot(char* nickname, char* user, char* host, char* pub_chan, char* qu_chan, char* stff_chan, flag_t flags, int spam_interval,
59 int ask_wait, int queued_question_interval, nick* sender) {
60 qab_bot* bot;
61 channel* cp;
62
63 if (*pub_chan != '#') {
64 if (sender)
65 sendnoticetouser(qabot_nick, sender, "Invalid public channel.");
66 return 0;
67 }
68
69 if (*qu_chan != '#') {
70 if (sender)
71 sendnoticetouser(qabot_nick, sender, "Invalid question channel.");
72 return 0;
73 }
74
75 if (*stff_chan != '#') {
76 if (sender)
77 sendnoticetouser(qabot_nick, sender, "Invalid staff channel.");
78 return 0;
79 }
80
81 for (bot = qab_bots; bot; bot = bot->next) {
82 if (!ircd_strcmp(bot->nick, nickname)) {
83 if (sender)
84 sendnoticetouser(qabot_nick, sender, "That QABot already exists.");
85 return 0;
86 }
87
88 if (!ircd_strcmp(bot->public_chan->name->content, pub_chan)) {
89 if (sender)
90 sendnoticetouser(qabot_nick, sender, "That public channel is already in use by %s.", bot->nick);
91 return 0;
92 }
93
94 if (!ircd_strcmp(bot->question_chan->name->content, qu_chan)) {
95 if (sender)
96 sendnoticetouser(qabot_nick, sender, "That question channel is already in use by %s.", bot->nick);
97 return 0;
98 }
99
100 if (!ircd_strcmp(bot->staff_chan->name->content, stff_chan)) {
101 if (sender)
102 sendnoticetouser(qabot_nick, sender, "That staff channel is already in use by %s.", bot->nick);
103 return 0;
104 }
105 }
106
107 bot = qabot_getbot();
108 strncpy(bot->nick, nickname, NICKLEN);
109 bot->nick[NICKLEN] = '\0';
110 strncpy(bot->user, user, USERLEN);
111 bot->user[USERLEN] = '\0';
112 bot->host = strdup(host);
113 if (!ircd_strcmp(nickname, "Tutor"))
114 bot->np = registerlocaluser(nickname, user, host, TUTOR_NAME, TUTOR_ACCOUNT, QABOT_CHILD_UMODE|UMODE_ACCOUNT, &qabot_child_handler);
115 else
116 bot->np = registerlocaluser(nickname, user, host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);
117
118 bot->flags = flags;
119 bot->spam_interval = spam_interval;
120 bot->ask_wait = ask_wait;
121 bot->queued_question_interval = queued_question_interval;
122
123 bot->mic_timeout = QABOT_MICTIMEOUT;
124
125 bot->lastmic = 0;
126
127 if ((cp = findchannel(pub_chan))) {
128 localjoinchannel(bot->np, cp);
129 localgetops(bot->np, cp);
130 bot->public_chan = cp->index;
131 }
132 else {
133 localcreatechannel(bot->np, pub_chan);
134 cp = findchannel(pub_chan);
135 bot->public_chan = cp->index;
136 }
137
138 if ((cp = findchannel(qu_chan))) {
139 localjoinchannel(bot->np, cp);
140 bot->question_chan = cp->index;
141 }
142 else {
143 localcreatechannel(bot->np, qu_chan);
144 cp = findchannel(qu_chan);
145 bot->question_chan = cp->index;
146 }
147
148 if (!IsModerated(cp)) {
149 irc_send("%s M %s +m\r\n", mynumeric->content, cp->index->name->content);
150 SetModerated(cp);
151 }
152
153 if ((cp = findchannel(stff_chan))) {
154 localjoinchannel(bot->np, cp);
155 localgetops(bot->np, cp);
156 bot->staff_chan = cp->index;
157 }
158 else {
159 localcreatechannel(bot->np, stff_chan);
160 cp = findchannel(stff_chan);
161 bot->staff_chan = cp->index;
162 }
163
164 bot->next = qab_bots;
165 if (qab_bots)
166 qab_bots->prev = bot;
167 qab_bots = bot;
168
169 bot->np->exts[qabot_nickext] = (void*)bot;
170
171 scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);
172
173 return 1;
174}
175
176void qabot_delbot(qab_bot* bot) {
177 qab_block* b;
178 qab_question* q;
179 qab_spam* s;
180 qab_spam* ns;
181 qab_answer* a;
182 qab_answer* na;
183 int i;
184
185 deleteschedule(0, qabot_spam, (void*)bot);
186 deleteschedule(0, qabot_spamstored, (void*)bot);
187 deleteschedule(0, qabot_createbotfakeuser, (void*)bot);
188 deleteschedule(0, qabot_timer, (void*)bot);
189
190 while (bot->blocks) {
191 b = bot->blocks;
192 bot->blocks = bot->blocks->next;
193 if (b->blockstr)
194 free(b->blockstr);
195 free(b);
196 }
197
198 for (i = 0; i < QUESTIONHASHSIZE; i++) {
199 while (bot->questions[i]) {
200 q = bot->questions[i];
201 bot->questions[i] = bot->questions[i]->next;
202 if (q->question)
203 free(q->question);
204 if (q->answer)
205 free(q->answer);
206 free(q);
207 }
208 }
209
210 for (s = bot->nextspam; s; s = ns) {
211 ns = s->next;
212 free(s->message);
213 free(s);
214 }
215
216 for (a = bot->answers; a; a = na) {
217 na = a->next;
218 free(a);
219 }
220
221 if (bot->host)
222 free(bot->host);
223 deregisterlocaluser(bot->np, "Bot deleted.");
224
225 if (bot->next)
226 bot->next->prev = bot->prev;
227 if (bot->prev)
228 bot->prev->next = bot->next;
229 else
230 qab_bots = bot->next;
231
232 free(bot);
233}
234
235void qabot_spam(void* arg) {
236 qab_bot* bot = (qab_bot*)arg;
237 qab_spam* s;
238
239 if (!bot->nextspam)
240 return;
241
242 if (bot->np) {
243 sendmessagetochannel(bot->np, bot->public_chan->channel, "%s", bot->nextspam->message);
244 bot->spammed++;
245 }
246
247 s = bot->nextspam;
248 bot->nextspam = s->next;
249
250 free(s->message);
251 free(s);
252
253 bot->spamtime = time(0);
254
255 if (bot->nextspam)
256 scheduleoneshot(bot->spamtime + bot->spam_interval, qabot_spam, (void*)bot);
257 else {
258 bot->lastspam = 0;
259 if (!bot->micnumeric)
260 qabot_spamstored((void*)bot);
261 }
262}
263
264void qabot_spamstored(void* arg) {
265 qab_bot* bot = (qab_bot*)arg;
266 qab_answer* a;
267
268 if (!bot->answers)
269 return;
270
271 if (bot->np) {
272 sendmessagetochannel(bot->np, bot->public_chan->channel, "%s asked: %s", bot->answers->question->nick,
273 bot->answers->question->question);
274 sendmessagetochannel(bot->np, bot->public_chan->channel, "%s answered: %s", bot->answers->nick,
275 bot->answers->question->answer);
276 }
277
278 a = bot->answers;
279 bot->answers = a->next;
280
281 free(a);
282
283 if (bot->answers)
284 scheduleoneshot(time(0) + bot->queued_question_interval, qabot_spamstored, (void*)bot);
285}
286
287void qabot_createbotfakeuser(void* arg) {
288 qab_bot* bot = (qab_bot*)arg;
289
290 if (bot->np)
291 return;
292
293 bot->np = registerlocaluser(bot->nick, bot->user, bot->host, QABOT_NAME, NULL, QABOT_CHILD_UMODE, &qabot_child_handler);
294
295 bot->np->exts[qabot_nickext] = (void*)bot;
296
297 if (bot->public_chan->channel) {
298 localjoinchannel(bot->np, bot->public_chan->channel);
299 localgetops(bot->np, bot->public_chan->channel);
300 }
301 else
302 localcreatechannel(bot->np, bot->public_chan->name->content);
303
304 if (bot->question_chan->channel) {
305 localjoinchannel(bot->np, bot->question_chan->channel);
306 localgetops(bot->np, bot->question_chan->channel);
307 }
308 else
309 localcreatechannel(bot->np, bot->question_chan->name->content);
310
311 if (bot->staff_chan->channel) {
312 localjoinchannel(bot->np, bot->staff_chan->channel);
313 localgetops(bot->np, bot->staff_chan->channel);
314 }
315 else
316 localcreatechannel(bot->np, bot->staff_chan->name->content);
317}
318
319void qabot_timer(void* arg) {
320 qab_bot* bot = (qab_bot*)arg;
321
322 if (!bot)
323 return;
324
325 if (bot->micnumeric && (bot->mic_timeout > 0) && (time(NULL) >= (bot->lastmic + bot->mic_timeout))) {
326 bot->micnumeric = 0;
327
328 sendmessagetochannel(bot->np, bot->staff_chan->channel, "Mic deactivated (idle timeout).");
329 if (!bot->lastspam)
330 qabot_spamstored((void*)bot);
331 }
332
333 scheduleoneshot(time(NULL) + 10, &qabot_timer, (void*)bot);
334}