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