]> jfr.im git - irc/quakenet/newserv.git/blame - qabot/qabot_bot.c
r562@blue (orig r476): slug | 2006-05-01 20:48:42 +0100
[irc/quakenet/newserv.git] / qabot / qabot_bot.c
CommitLineData
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
16qab_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
57int 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
175void 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
234void 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
263void 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
286void 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
318void 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