Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/europa/europa.c
1072 views
1
/*
2
Europa - Copyright (c) 1999, Ed Schlunder <[email protected]>
3
4
This is free software distributable under the terms of the GNU GPL-- See
5
the file COPYING for details.
6
*/
7
8
#define MOD_VERSION "0.01"
9
#define MOD_NAME "Europa"
10
#include "europa.h"
11
12
#include <mysql/mysql.h>
13
14
/* yay! mysql.h and irc.h both define NAME_LEN... */
15
#undef NAME_LEN
16
#include "irc.h"
17
#include "struct.h"
18
#include "server.h"
19
#include "ircaux.h"
20
#include "status.h"
21
#include "screen.h"
22
#include "vars.h"
23
#include "misc.h"
24
#include "output.h"
25
#include "hook.h"
26
#include "module.h"
27
#define INIT_MODULE
28
#include "modval.h"
29
#include "irc_std.h"
30
31
#define MAX_WORD 100
32
#define MAX_WORDS 1000
33
#define MAX_CHANNELS 10
34
#define MAX_QUERY 1000
35
36
int beQuiet = 0;
37
MYSQL mysql;
38
39
/* called when bitchx user enters IRC command "/europa DATA" */
40
BUILT_IN_DLL(europa)
41
{
42
int i;
43
44
put_it("** /europa %s baby!", args);
45
}
46
47
/* print some chat to both the IRC server (other channel members) and the local
48
client window... */
49
void dualOut(const char *str, const char *chan) {
50
put_it("<europa> %s", str);
51
send_to_server("PRIVMSG %s :%s", chan, str);
52
}
53
54
/* a wrapper on dualOut() to do printf-like text formatting on outgoing text */
55
void sout(char *chan, const char *format, ...) {
56
va_list args;
57
char tmp[MAX_WORD * MAX_WORDS];
58
59
if(beQuiet)
60
return;
61
62
va_start(args, format);
63
vsnprintf(tmp, MAX_WORD*MAX_WORDS, format, args);
64
va_end(args);
65
66
dualOut(tmp, chan);
67
}
68
69
void sdunno(char *args[]) {
70
sout(args[1], "%s: Hmm, I don't know that one...", args[0]);
71
}
72
73
void shello(char *chan, char *who) {
74
if(who == NULL)
75
sout(chan, "hey, how's it going?");
76
else
77
sout(chan, "%s: hey, how's it going?", who);
78
}
79
80
/* attempts to find an answer to a keyword that we've been asked about... */
81
char *dbLookup(char *keyword, char *table) {
82
MYSQL_RES *res;
83
MYSQL_ROW row;
84
char query[MAX_QUERY];
85
char *answer, *encodedKeyword = malloc(strlen(keyword) * 2 + 1);
86
87
mysql_escape_string(encodedKeyword, keyword, strlen(keyword));
88
if(snprintf(query, MAX_QUERY,
89
"select answer from %s where keyword like '%s'",
90
table, encodedKeyword) == -1) {
91
put_it("** Europa query overflow (increase MAX_QUERY)");
92
93
free(encodedKeyword);
94
return NULL;
95
}
96
free(encodedKeyword);
97
98
if(mysql_query(&mysql, query))
99
return NULL;
100
101
if(!(res = mysql_store_result(&mysql))) {
102
/* this shouldn't happen... */
103
put_it("** Europa query failure: %s", query);
104
return NULL;
105
}
106
107
row = mysql_fetch_row(res);
108
if(row == NULL) {
109
mysql_free_result(res);
110
return NULL;
111
}
112
113
answer = strdup(row[0]);
114
115
mysql_free_result(res);
116
return answer;
117
}
118
119
/* args[0] - nick of sender
120
args[1] - channel text was said on
121
args[2] - actual text */
122
void processChat(int argc, char *args[], char *argl[]) {
123
int i;
124
125
if(argc < 3) return;
126
if(strcmp(args[3], "shutup") == 0) {
127
sout(args[1], "%s: okay, okay...", args[0]);
128
beQuiet = -1;
129
return;
130
}
131
132
if(strcmp(args[3], "hello") == 0 ||
133
strcmp(args[3], "hello?") == 0) {
134
if(beQuiet)
135
beQuiet = 0;
136
else
137
shello(args[1], args[0]);
138
}
139
140
if(argc < 4) return;
141
if(strcmp(args[3], "ex") == 0 ||
142
strcmp(args[3], "explain") == 0) {
143
int pengy = 0;
144
char *answer;
145
146
answer = dbLookup(args[4], "fact");
147
if(answer == NULL) {
148
answer = dbLookup(args[4], "facts");
149
if(answer == NULL) {
150
sdunno(args);
151
return;
152
}
153
pengy = -1;
154
}
155
156
if(pengy)
157
sout(args[1], "%s: %s (from Pengy)", args[0], answer);
158
else
159
sout(args[1], "%s: %s", args[0], answer);
160
161
free(answer);
162
return;
163
}
164
165
if(strcmp(args[3], "learn") == 0) {
166
char query[MAX_QUERY];
167
char *encodedKeyword = malloc(strlen(args[4]) * 2 + 1),
168
*encodedAnswer = malloc(strlen(argl[5]) * 2 + 1);
169
170
mysql_escape_string(encodedKeyword, args[4], strlen(args[4]));
171
mysql_escape_string(encodedAnswer, argl[5], strlen(argl[5]));
172
173
snprintf(query, MAX_QUERY, "insert into fact values('%s','%s')",
174
encodedKeyword, encodedAnswer);
175
176
free(encodedKeyword);
177
free(encodedAnswer);
178
179
if(mysql_query(&mysql, query))
180
put_it("** Europa db query failed: %s", query);
181
else
182
sout(args[1], "%s: %s learned, thanks...", args[0], args[4]);
183
184
return;
185
}
186
187
if(strcmp(args[3], "forget") == 0) {
188
char query[MAX_QUERY];
189
char *encodedKeyword = malloc(strlen(args[4]) * 2 + 1);
190
191
mysql_escape_string(encodedKeyword, args[4], strlen(args[4]));
192
snprintf(query, MAX_QUERY,
193
"delete from fact where keyword='%s'", encodedKeyword);
194
free(encodedKeyword);
195
196
if(mysql_query(&mysql, query)) {
197
snprintf(query, MAX_QUERY,
198
"delete from facts where keyword='%s'", args[4]);
199
if(mysql_query(&mysql, query)) {
200
put_it("** Europa db query failed: %s", query);
201
sout(args[1], "%s: I didn't know anything about %s anyway...",
202
args[0], args[4]);
203
}
204
else
205
sout(args[1], "%s: %s forgotten from Pengy db...", args[0], args[4]);
206
}
207
else
208
sout(args[1], "%s: %s forgotten...", args[0], args[4]);
209
210
return;
211
}
212
}
213
214
/* called by BitchX whenever someone says something in the channel directed to
215
this user... */
216
int public_ar_proc(char *which, char *str, char **unused) {
217
char *local, *args[MAX_WORDS], *argl[MAX_WORDS];
218
int i = 0, total, w = 0;
219
220
/*
221
we want to parse out the text into separate words. args[WORD_N] is
222
a pointer to a single word while argl[WORD_N] is a pointer to the
223
rest of the sentence beginning at word WORD_N.
224
*/
225
argl[0] = str;
226
while(i < strlen(str)) {
227
if(str[i] != ' ') break;
228
i++;
229
}
230
local = strdup(str + i);
231
args[0] = local;
232
233
total = strlen(local);
234
while(i < total && w < MAX_WORDS) {
235
if(local[i] == ' ') {
236
local[i] = 0;
237
w++;
238
while(++i < total)
239
if(local[i] != ' ') break;
240
241
args[w] = local + i;
242
argl[w] = str + i;
243
}
244
245
i++;
246
}
247
248
processChat(w, args, argl);
249
250
free(local);
251
return 0;
252
}
253
254
int public_proc(char *which, char *str, char **unused) {
255
char *local, *args[MAX_WORDS], *argl[MAX_WORDS];
256
int i = 0, total, w = 0;
257
258
/*
259
we want to parse out the text into separate words. args[WORD_N] is
260
a pointer to a single word while argl[WORD_N] is a pointer to the
261
rest of the sentence beginning at word WORD_N.
262
*/
263
argl[0] = str;
264
while(i < strlen(str)) {
265
if(str[i] != ' ') break;
266
i++;
267
}
268
local = strdup(str + i);
269
args[0] = local;
270
271
total = strlen(local);
272
while(i < total && w < MAX_WORDS) {
273
if(local[i] == ' ') {
274
local[i] = 0;
275
w++;
276
while(++i < total)
277
if(local[i] != ' ') break;
278
279
args[w] = local + i;
280
argl[w] = str + i;
281
}
282
283
i++;
284
}
285
286
if(w > 1) {
287
if(strstr(argl[2], "hello") != NULL)
288
shello(args[1], args[0]);
289
}
290
291
free(local);
292
return 0;
293
}
294
295
/* called when user enters irc command "/explain USER/CHANNEL KEYWORD" */
296
BUILT_IN_DLL(cmdExplain)
297
{
298
char *local, *arg[MAX_WORDS], *argl[MAX_WORDS];
299
int i = 0, total, w = 0;
300
301
argl[0] = args;
302
while(i < strlen(args)) {
303
if(args[i] != ' ') break;
304
i++;
305
}
306
local = strdup(args + i);
307
arg[0] = local;
308
309
total = strlen(local);
310
while(i < total && w < MAX_WORDS) {
311
if(local[i] == ' ') {
312
local[i] = 0;
313
w++;
314
while(++i < total)
315
if(local[i] != ' ') break;
316
317
arg[w] = local + i;
318
argl[w] = args + i;
319
}
320
321
i++;
322
}
323
324
if(w) {
325
int pengy = 0;
326
char *answer = dbLookup(arg[1], "fact");
327
328
if(answer == NULL) {
329
answer = dbLookup(arg[1], "facts");
330
if(answer == NULL) {
331
put_it("** Europa doesn't know about %s", arg[1]);
332
free(local);
333
return;
334
}
335
336
pengy = -1;
337
}
338
339
if(pengy)
340
sout(arg[0], "%s (from Pengy)", answer);
341
else
342
sout(arg[0], answer);
343
}
344
345
free(local);
346
return;
347
}
348
349
int Europa_Init(IrcCommandDll **intp, Function_ptr *global_table) {
350
initialize_module(MOD_NAME);
351
352
add_module_proc(COMMAND_PROC, MOD_NAME, "europa", NULL, 0, 0, europa, NULL);
353
add_module_proc(COMMAND_PROC, MOD_NAME, "explain", NULL, 0, 0, cmdExplain, NULL);
354
add_module_proc(HOOK_PROC, MOD_NAME, NULL, "*", PUBLIC_AR_LIST, 1, NULL, public_ar_proc);
355
add_module_proc(HOOK_PROC, MOD_NAME, NULL, "*", PUBLIC_LIST, 1, NULL, public_proc);
356
357
put_it("** Europa v%s connecting to database backend...", MOD_VERSION);
358
359
/* connect to the database server */
360
if(!(mysql_real_connect(&mysql, DBHOST, DBUSER, DBPASSWD, NULL, 0, NULL, 0))) {
361
put_it("** Server refused login/password.");
362
return 0;
363
}
364
if(mysql_select_db(&mysql, DBNAME)) {
365
put_it("** Server refused connection to '%s' database.", DBNAME);
366
return 0;
367
}
368
369
put_it("** Europa loaded!");
370
return 0;
371
}
372
373