]>
Commit | Line | Data |
---|---|---|
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 | ||
15 | qab_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 | ||
58 | int 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 | ||
176 | void 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 | ||
235 | void 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 | ||
264 | void 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 | ||
287 | void 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 | ||
319 | void 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 | } |