]> jfr.im git - irc/evilnet/x3.git/blob - src/mod-webtv.c
Rewrote PHP X3 DB parser function sample code as a class and faster code
[irc/evilnet/x3.git] / src / mod-webtv.c
1 /* mod-webtv.c - WebTV Module for X3
2 * Copyright 2007 X3 Development Team
3 *
4 * This file is part of x3.
5 *
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21 /*
22 *
23 * /msg opserv bind opserv service *modcmd.joiner
24 * /msg opserv bind opserv service\ add *modcmd.service\ add
25 * /msg opserv bind opserv service\ rename *modcmd.service\ rename
26 * /msg opserv bind opserv service\ trigger *modcmd.service\ trigger
27 * /msg opserv bind opserv service\ remove *modcmd.service\ remove
28 * Add the bot:
29 * /msg opserv service add IRC WebTV Service Bot
30 * /msg opserv bind IRC help *modcmd.help
31 * Restart X3 with the updated conf file (as above, butwith "bot"
32 * "IRC"), and bind the commands to it:
33 * /msg opserv bind IRC * *webtv.*
34 */
35
36 #include "chanserv.h"
37 #include "conf.h"
38 #include "modcmd.h"
39 #include "nickserv.h"
40 #include "opserv.h"
41 #include "saxdb.h"
42 #include "timeq.h"
43
44 #define MAX_CHANNELS_WHOIS 50
45
46 static const struct message_entry msgtab[] = {
47 { "WBMSG_NOT_MARKED", "You are not a WebTV client." },
48
49 { "WBMSG_NICK_PARAMS", "You need to specify a nickname." },
50 { "WBMSG_NICK_SAME", "You are already $b%s$b." },
51 { "WBMSG_NICK_INVALID", "The nickname $b%s$b is invalid." },
52 { "WBMSG_NICK_IN_USE", "The nickname $b%s$b is in use, please choose another." },
53
54 { "WBMSG_CHANNEL_BANNED", "You are banned on %s." },
55 { "WBMSG_CHANNEL_LIMIT", "%s has reached the maximum allowed chatters." },
56 { "WBMSG_CHANNEL_INVITE", "%s is invite only." },
57 { "WBMSG_CHANNEL_PASSWORD", "%s is password protected." },
58
59 { "WBMSG_WHOIS_NICKIDENT", "[%s] (%s@%s): %s" },
60 { "WBMSG_WHOIS_CHANNELS", "On %s" },
61 { "WBMSG_WHOIS_SERVER", "[%s] %s : %s" },
62 { "WBMSG_WHOIS_OPER", "[%s] is an IRC Operator" },
63 { "WBMSG_WHOIS_SERVICE", "[%s] is an IRC Service" },
64 { "WBMSG_WHOIS_ACCOUNT", "[%s] is logged in as %s" },
65 { "WBMSG_WHOIS_REALHOST", "[%s] realhost %s@%s %s" },
66 { "WBMSG_WHOIS_SWHOIS", "[%s] %s" },
67 { "WBMSG_WHOIS_DNSBL", "[%s] is DNSBL listed on %s" },
68 { "WBMSG_WHOIS_CONNECTED", "[%s] %s" },
69 { "WBMSG_WHOIS_END", "[%s] End of WHOIS list." },
70
71 { "WBMSG_ALREADY_JOINED", "I am already in $b%s$b." },
72 { "WBMSG_JOIN_DONE", "I have joined $b%s$b." },
73
74 { NULL, NULL }
75 };
76
77 struct userNode *webtv;
78
79 #define WEBTV_FUNC(NAME) MODCMD_FUNC(NAME)
80 #define WEBTV_SYNTAX() svccmd_send_help_brief(user, webtv, cmd)
81 #define WEBTV_MIN_PARAMS(N) if(argc < (N)) { \
82 reply("MSG_MISSING_PARAMS", argv[0]); \
83 WEBTV_SYNTAX(); \
84 return 0; }
85
86 static struct {
87 struct userNode *bot;
88 int required_mark;
89 struct string_list *valid_marks;
90 } webtv_conf;
91
92 #define OPTION_FUNC(NAME) int NAME(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
93 typedef OPTION_FUNC(option_func_t);
94
95 extern struct string_list *autojoin_channels;
96 const char *webtv_module_deps[] = { NULL };
97 static struct module *webtv_module;
98 static struct log_type *WB_LOG;
99 static char *his_servername;
100 static char *his_servercomment;
101
102
103 int check_mark(struct svccmd *cmd, struct userNode *user, UNUSED_ARG(struct handle_info *hi), UNUSED_ARG(unsigned int override), UNUSED_ARG(unsigned int argc), UNUSED_ARG(char *argv[]))
104 {
105 unsigned int y = 0;
106
107 if ((webtv_conf.required_mark == 0) || IsOper(user))
108 return 1;
109 else {
110 if (!user->mark) {
111 reply("WBMSG_NOT_MARKED");
112 return 0;
113 }
114 for (y = 0; y < webtv_conf.valid_marks->used; y++) {
115 if (!strcasecmp(webtv_conf.valid_marks->list[y], user->mark))
116 return 1;
117 }
118 reply("WBMSG_NOT_MARKED");
119 return 0;
120 }
121 }
122
123 static MODCMD_FUNC(cmd_nick)
124 {
125 struct userNode *nick;
126
127 if (!check_mark(cmd, user, NULL, 0, 0, NULL))
128 return 0;
129
130 if (argc < 2) {
131 reply("WBMSG_NICK_PARAMS");
132 return 0;
133 }
134
135 if (!strcasecmp(argv[1], user->nick)) {
136 reply("WBMSG_NICK_SAME", argv[1]);
137 return 0;
138 }
139
140 if (!is_valid_nick(argv[1])) {
141 reply("WBMSG_NICK_INVALID", argv[1]);
142 return 0;
143 }
144
145 nick = GetUserH(argv[1]);
146 if (nick) {
147 reply("WBMSG_NICK_IN_USE", argv[1]);
148 return 0;
149 }
150
151 irc_svsnick(webtv, user, argv[1]);
152 return 1;
153 }
154
155 void
156 webtv_ison(struct userNode *bot, struct userNode *tell, struct userNode *target, const char *message)
157 {
158 struct modeNode *mn;
159 unsigned int count, here_len, n, maxlen;
160 char buff[MAXLEN];
161
162 maxlen = tell->handle_info ? tell->handle_info->screen_width : 0;
163 if (!maxlen)
164 maxlen = MAX_LINE_SIZE;
165 for (n=count=0; n<target->channels.used; n++) {
166 mn = target->channels.list[n];
167 if ((mn->channel->modes & (MODE_PRIVATE|MODE_SECRET)))
168 continue;
169
170 here_len = strlen(mn->channel->name);
171 if ((count + here_len + 4) > maxlen) {
172 buff[count] = 0;
173 send_message(tell, bot, message, buff);
174 count = 0;
175 }
176 if (mn->modes & MODE_CHANOP)
177 buff[count++] = '@';
178 if (mn->modes & MODE_HALFOP)
179 buff[count++] = '%';
180 if (mn->modes & MODE_VOICE)
181 buff[count++] = '+';
182 memcpy(buff+count, mn->channel->name, here_len);
183 count += here_len;
184 buff[count++] = ' ';
185 }
186 if (count) {
187 buff[count] = 0;
188 send_message(tell, bot, message, buff);
189 }
190 }
191
192 static MODCMD_FUNC(cmd_whois)
193 {
194 struct userNode *target;
195
196 if (!check_mark(cmd, user, NULL, 0, 0, NULL))
197 return 0;
198
199 if (argc < 2) {
200 reply("WBMSG_NICK_PARAMS");
201 return 0;
202 }
203
204 target = GetUserH(argv[1]);
205 if (target) {
206 reply("WBMSG_WHOIS_NICKIDENT", target->nick, target->ident,
207 IsFakeHost(target) ? target->fakehost : target->hostname, target->info);
208
209 if ((target->channels.used <= MAX_CHANNELS_WHOIS) && !IsService(target))
210 webtv_ison(cmd->parent->bot, user, target, "WBMSG_WHOIS_CHANNELS");
211
212 if (target == user)
213 reply("WBMSG_WHOIS_SERVER", target->nick, target->uplink->name, target->uplink->description);
214 else {
215 reply("WBMSG_WHOIS_SERVER", target->nick, his_servername ? his_servername : target->uplink->name,
216 his_servercomment ? his_servercomment : target->uplink->description);
217 }
218
219 if (IsOper(target))
220 reply("WBMSG_WHOIS_OPER", target->nick);
221
222 if (IsService(target))
223 reply("WBMSG_WHOIS_SERVICE", target->nick);
224
225 if (target->handle_info)
226 reply("WBMSG_WHOIS_ACCOUNT", target->nick, target->handle_info->handle);
227
228 if ((target == user) && (target->fakehost || IsHiddenHost(target)))
229 reply("WBMSG_WHOIS_REALHOST", target->nick, target->ident, target->hostname, irc_ntoa(&target->ip));
230
231 if (target->handle_info) {
232 if (target->handle_info->epithet)
233 reply("WBMSG_WHOIS_SWHOIS", target->nick, target->handle_info->epithet);
234 }
235
236 if (target->mark)
237 reply("WBMSG_WHOIS_DNSBL", target->nick, target->mark);
238
239 reply("WBMSG_WHOIS_END", target->nick);
240 } else {
241 reply("MSG_NICK_UNKNOWN", argv[1]);
242 return 0;
243 }
244
245 return 1;
246 }
247
248 void
249 part_all_channels(struct userNode *target)
250 {
251 unsigned int n=0;
252 struct modeNode *mn;
253
254 for (n=0; n<target->channels.used; n++) {
255 mn = target->channels.list[n];
256 irc_svspart(webtv, target, mn->channel);
257 }
258
259 return;
260 }
261
262 static MODCMD_FUNC(cmd_sjoin)
263 {
264 struct userNode *bot = cmd->parent->bot;
265
266 if (!IsChannelName(argv[1])) {
267 reply("MSG_NOT_CHANNEL_NAME");
268 return 0;
269 } else if (!(channel = GetChannel(argv[1]))) {
270 channel = AddChannel(argv[1], now, NULL, NULL, NULL);
271 AddChannelUser(bot, channel)->modes |= MODE_CHANOP;
272 } else if (GetUserMode(channel, bot)) {
273 reply("WBMSG_ALREADY_JOINED", channel->name);
274 return 0;
275 } else {
276 struct mod_chanmode change;
277 mod_chanmode_init(&change);
278 change.argc = 1;
279 change.args[0].mode = MODE_CHANOP;
280 change.args[0].u.member = AddChannelUser(bot, channel);
281 modcmd_chanmode_announce(&change);
282 }
283 irc_fetchtopic(bot, channel->name);
284 reply("WBMSG_JOIN_DONE", channel->name);
285 return 1;
286 }
287
288 static MODCMD_FUNC(cmd_join)
289 {
290 struct chanNode *target;
291
292 if (!check_mark(cmd, user, NULL, 0, 0, NULL))
293 return 0;
294
295 if(!(target = GetChannel(argv[1])))
296 {
297 reply("MSG_INVALID_CHANNEL");
298 return 0;
299 }
300
301 if (trace_check_bans(user, target) == 1) {
302 reply("WBMSG_CHANNEL_BANNED", argv[1]);
303 return 0;
304 }
305
306 if (target->modes & MODE_INVITEONLY) {
307 reply("WBMSG_CHANNEL_INVITE", argv[1]);
308 return 0;
309 }
310
311
312 if (target->limit > 0) {
313 if (target->members.used >= target->limit) {
314 reply("WBMSG_CHANNEL_LIMIT", argv[1]);
315 return 0;
316 }
317 }
318
319
320 if (*target->key) {
321 if (argc > 2) {
322 if (strcmp(argv[2], target->key)) {
323 reply("WBMSG_CHANNEL_PASSWORD", argv[1]);
324 return 0;
325 }
326 } else {
327 reply("WBMSG_CHANNEL_PASSWORD", argv[1]);
328 return 0;
329 }
330 }
331
332 part_all_channels(user);
333 irc_svsjoin(webtv, user, target);
334 return 1;
335 }
336
337 static MODCMD_FUNC(cmd_part)
338 {
339 struct mod_chanmode change;
340 struct chanNode *target;
341
342 if (!check_mark(cmd, user, NULL, 0, 0, NULL))
343 return 0;
344
345 if(!(target = GetChannel(argv[1])))
346 {
347 reply("MSG_INVALID_CHANNEL");
348 return 0;
349 }
350
351 mod_chanmode_init(&change);
352 change.argc = 1;
353 change.args[0].u.member = GetUserMode(target, user);
354 if(!change.args[0].u.member)
355 {
356 if(argc)
357 reply("MSG_CHANNEL_ABSENT", target->name);
358 return 0;
359 }
360
361 irc_svspart(webtv, user, target);
362 return 1;
363 }
364
365 static void
366 webtv_conf_read(void)
367 {
368 dict_t conf_node;
369 const char *str;
370 struct string_list *strlist;
371
372 str = "modules/webtv";
373 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
374 log_module(WB_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
375 return;
376 }
377
378 str = database_get_data(conf_node, "required_mark", RECDB_QSTRING);
379 webtv_conf.required_mark = str ? atoi(str) : 0;
380
381 free_string_list(webtv_conf.valid_marks);
382 strlist = database_get_data(conf_node, "valid_marks", RECDB_STRING_LIST);
383 if(strlist)
384 strlist = string_list_copy(strlist);
385 else
386 strlist = alloc_string_list(4);
387 webtv_conf.valid_marks = strlist;
388
389 str = conf_get_data("server/his_servername", RECDB_QSTRING);
390 his_servername = str ? strdup(str) : NULL;
391 str = conf_get_data("server/his_servercomment", RECDB_QSTRING);
392 his_servercomment = str ? strdup(str) : NULL;
393 }
394
395 static void
396 webtv_cleanup(void)
397 {
398 }
399
400 int
401 webtv_init(void)
402 {
403 WB_LOG = log_register_type("WebTV", "file:webtv.log");
404
405 conf_register_reload(webtv_conf_read);
406 reg_exit_func(webtv_cleanup, NULL);
407
408 webtv_module = module_register("WebTV", WB_LOG, "mod-webtv.help", NULL);
409 modcmd_register(webtv_module, "nick", cmd_nick, 1, 0, NULL);
410 modcmd_register(webtv_module, "join", cmd_join, 1, 0, NULL);
411 modcmd_register(webtv_module, "part", cmd_part, 1, 0, NULL);
412 modcmd_register(webtv_module, "whois", cmd_whois, 1, 0, NULL);
413
414 modcmd_register(webtv_module, "sjoin", cmd_sjoin, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
415
416 message_register_table(msgtab);
417 return 1;
418 }
419
420 int
421 webtv_finalize(void) {
422 struct chanNode *chan;
423 unsigned int i;
424 dict_t conf_node;
425 const char *str;
426
427 str = "modules/webtv";
428 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
429 log_module(WB_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
430 return 0;
431 }
432
433 str = database_get_data(conf_node, "bot", RECDB_QSTRING);
434 if (str) {
435 webtv = webtv_conf.bot;
436 const char *modes = conf_get_data("modules/webtv/modes", RECDB_QSTRING);
437 webtv = AddLocalUser(str, str, NULL, "WebTV IRC Service", modes);
438 } else {
439 log_module(WB_LOG, LOG_ERROR, "database_get_data for webtv_conf.bot failed!");
440 exit(1);
441 }
442
443 if (autojoin_channels && webtv) {
444 for (i = 0; i < autojoin_channels->used; i++) {
445 chan = AddChannel(autojoin_channels->list[i], now, "+nt", NULL, NULL);
446 AddChannelUser(webtv, chan)->modes |= MODE_CHANOP;
447 }
448 }
449
450 return 1;
451 }