From: pk910 Date: Thu, 6 Sep 2012 09:15:59 +0000 (+0200) Subject: added NeonKick bot (just kicking users from channels they have no access in - e.g... X-Git-Tag: v5.5~1 X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=5174c2812df795d525190d33604bfc4645913703 added NeonKick bot (just kicking users from channels they have no access in - e.g. #kick :D) --- diff --git a/Makefile.am b/Makefile.am index 14de200..6f9dce4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ checkversion: cd src && chmod +x version.sh && ./version.sh && cd .. noinst_PROGRAMS = neonserv -noinst_LTLIBRARIES = libDummyServ.la libfuncmds.la libglobalcmd.la libNeonHelp.la libNeonBackup.la libNeonServ.la libNeonSpam.la libstats.la libNeonFun.la +noinst_LTLIBRARIES = libDummyServ.la libfuncmds.la libglobalcmd.la libNeonHelp.la libNeonBackup.la libNeonServ.la libNeonSpam.la libstats.la libNeonFun.la libNeonKick.la libDummyServ_la_SOURCES = src/modules/DummyServ.mod/bot_DummyServ.c \ src/modules/DummyServ.mod/module.c @@ -171,6 +171,11 @@ libNeonFun_la_SOURCES = src/modules/NeonFun.mod/bot_NeonFun.c \ libNeonFun_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined libNeonFun_la_LIBADD = $(MYSQL_LIBS) +libNeonKick_la_SOURCES = src/modules/NeonKick.mod/bot_NeonKick.c \ + src/modules/NeonKick.mod/module.c +libNeonKick_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined +libNeonKick_la_LIBADD = $(MYSQL_LIBS) + neonserv_SOURCES = src/version.c \ src/IOEngine_epoll.c \ src/IOEngine_kevent.c \ diff --git a/src/modules/NeonKick.mod/bot_NeonKick.c b/src/modules/NeonKick.mod/bot_NeonKick.c new file mode 100644 index 0000000..a391769 --- /dev/null +++ b/src/modules/NeonKick.mod/bot_NeonKick.c @@ -0,0 +1,216 @@ +/* bot_NeonKick.c - NeonServ v5.5 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "../botid.h" + +#include "bot_NeonKick.h" +#include "../../modcmd.h" +#include "../../IRCParser.h" +#include "../../IRCEvents.h" +#include "../../UserNode.h" +#include "../../ChanNode.h" +#include "../../ChanUser.h" +#include "../../ModeNode.h" +#include "../../BanNode.h" +#include "../../ClientSocket.h" +#include "../../mysqlConn.h" +#include "../../lang.h" +#include "../../HandleInfoHandler.h" +#include "../../WHOHandler.h" +#include "../../DBHelper.h" +#include "../../tools.h" +#include "../../timeq.h" +#include "../../version.h" +#include "../../EventLogger.h" +#include "../../bots.h" + +#define BOTID NEONKICK_BOTID +#define BOTALIAS "NeonKick" + +static void neonkick_bot_ready(struct ClientSocket *client) { + if(client->botid != BOTID) + return; + MYSQL_RES *res; + MYSQL_ROW row; + + printf_mysql_query("SELECT `automodes`, `oper_user`, `oper_pass` FROM `bots` WHERE `id` = '%d'", client->clientid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(row[1] && row[2]) { + putsock(client, "OPER %s %s", row[1], row[2]); + } + putsock(client, "MODE %s +%s", client->user->nick, row[0]); + } + + printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "JOIN %s %s", row[0], row[1]); + } +} + +static void neonkick_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { + //this bot doesn't have a trigger + strcpy(trigger, ""); +} + +static void start_bots(int type) { + struct ClientSocket *client; + MYSQL_RES *res, *res2; + MYSQL_ROW row; + + if(type == MODSTATE_STARTSTOP) { + printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind`, `secret` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); + client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); + client->flags |= (strcmp(row[11], "0") ? SOCKET_FLAG_SECRET_BOT : 0); + client->flags |= SOCKET_FLAG_SILENT; + client->botid = BOTID; + client->clientid = atoi(row[7]); + connect_socket(client); + } + } + + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); + res2 = mysql_use(); + while ((row = mysql_fetch_row(res2)) != NULL) { + if(bind_cmd_to_command(BOTID, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_set_parameters(BOTID, row[0], row[2]); + } + if(row[3]) { + bind_set_global_access(BOTID, row[0], atoi(row[3])); + } + if(row[4]) { + bind_set_channel_access(BOTID, row[0], row[4]); + } + if(strcmp(row[5], "0")) + bind_set_bind_flags(BOTID, row[0], atoi(row[5])); + } + } + bind_unbound_required_functions(BOTID); +} + +static void neonkick_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) { + if(client->botid != BOTID) + return; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick); + return; + } + if(!strcmp(row[2], "1")) { + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + struct ChanNode *chan = getChanByName(channel); + if(!(chan && isUserOnChan(bot->user, chan))) + putsock(bot, "JOIN %s", channel); + } +} + +static char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) { + char *uname = ""; + int cid = 0; + MYSQL_RES *res; + MYSQL_ROW row; + if(user) { + uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); + } + if(chan) { + loadChannelSettings(chan); + if(chan->flags & CHANFLAG_CHAN_REGISTERED) + cid = chan->channel_id; + } + printf_mysql_query("SELECT `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + return row[0]; + } else + return NULL; +} + +static void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value) { + char *uname = ""; + int cid = 0; + MYSQL_RES *res; + MYSQL_ROW row; + if(user) { + uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); + } + if(chan) { + loadChannelSettings(chan); + if(chan->flags & CHANFLAG_CHAN_REGISTERED) + cid = chan->channel_id; + } + printf_mysql_query("SELECT `id`, `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(strcmp(row[1], value)) + printf_mysql_query("UPDATE `fundata` SET `value` = '%s' WHERE `id` = '%s'", escape_string(value), row[0]); + } else + printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value)); +} + +#include "event_neonkick_join.c" + +void init_NeonKick(int type) { + set_bot_alias(BOTID, BOTALIAS); + start_bots(type); + + if(type == MODSTATE_REBIND) return; + + //register events + bind_bot_ready(neonkick_bot_ready, module_id); + bind_invite(neonkick_event_invite, module_id); + bind_join(neonkick_event_join, module_id); + + set_trigger_callback(BOTID, module_id, neonkick_trigger_callback); +} + +void free_NeonKick(int type) { + unbind_allcmd(BOTID); + if(type == MODSTATE_STARTSTOP) { + //disconnect all our bots + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->botid == BOTID) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } +} + +#undef BOTID +#undef BOTALIAS diff --git a/src/modules/NeonKick.mod/bot_NeonKick.h b/src/modules/NeonKick.mod/bot_NeonKick.h new file mode 100644 index 0000000..da009cb --- /dev/null +++ b/src/modules/NeonKick.mod/bot_NeonKick.h @@ -0,0 +1,25 @@ +/* bot_NeonKick.h - NeonServ v5.5 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _bot_NeonKick_h +#define _bot_NeonKick_h + +#include "../../main.h" + +void init_NeonKick(int type); +void free_NeonKick(int type); + +#endif \ No newline at end of file diff --git a/src/modules/NeonKick.mod/event_neonkick_join.c b/src/modules/NeonKick.mod/event_neonkick_join.c new file mode 100644 index 0000000..c00625b --- /dev/null +++ b/src/modules/NeonKick.mod/event_neonkick_join.c @@ -0,0 +1,98 @@ +/* event_neonkick_join.c - NeonServ v5.5 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonkick_event_join_cache { + struct ClientSocket *client; + struct ChanUser *chanuser; +}; + +static USERAUTH_CALLBACK(neonkick_event_join_nick_lookup); +static void neonkick_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser); + +static void neonkick_event_join(struct ChanUser *chanuser) { + struct UserNode *user = chanuser->user; + struct ClientSocket *client = getChannelBot(chanuser->chan, BOTID); + if(!client) return; //we can't "see" this event + if(chanuser->user == client->user) { + requestOp(client->user, chanuser->chan); + module_neonbackup_recover_chan(chanuser->chan); + return; + } + if(chanuser->user->flags & USERFLAG_ISBOT) return; + loadChannelSettings(chanuser->chan); + if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonkick_event_join_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->chanuser = chanuser; + get_userauth(user, module_id, neonkick_event_join_nick_lookup, cache); + } else + neonkick_event_join_async1(client, chanuser); +} + +static USERAUTH_CALLBACK(neonkick_event_join_nick_lookup) { + struct neonkick_event_join_cache *cache = data; + if(user) + neonkick_event_join_async1(cache->client, cache->chanuser); + free(cache); +} + +static void neonkick_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser) { + struct ChanNode *chan = chanuser->chan; + struct UserNode *user = chanuser->user; + MYSQL_RES *res; + MYSQL_ROW chanuserrow; + + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuserrow = mysql_fetch_row(res); + } else + chanuserrow = NULL; + int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0); + int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0); + if(uaccess > 0) + return; //no kick :D + char *tmp; + int global_kick_count = ((tmp = getSetting(NULL, chan, "kicks")) ? atoi(tmp) : 0); + int kick_count = ((tmp = getSetting(user, chan, "kicks")) ? atoi(tmp) : 0); + global_kick_count++; + kick_count++; + char buf[MAXLEN]; + char reason[MAXLEN]; + sprintf(buf, "%d", global_kick_count); + setSetting(NULL, chan, "kicks", buf); + sprintf(buf, "%d", kick_count); + setSetting(user, chan, "kicks", buf); + char *banmask = generate_banmask(chanuser->user, buf); + sprintf(reason, "Kick #%d (#%d for you)", global_kick_count, kick_count); + putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason); + putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); + { // add timed ban + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + 10), 0, escape_string(reason)); + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, 10, module_id, channel_ban_timeout, strdup(banidBuf)); + } +} diff --git a/src/modules/NeonKick.mod/module.c b/src/modules/NeonKick.mod/module.c new file mode 100644 index 0000000..8e81a63 --- /dev/null +++ b/src/modules/NeonKick.mod/module.c @@ -0,0 +1,32 @@ +/* module.c - NeonServ v5.5 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "bot_NeonKick.h" + +static int module_initialize() { + return 0; +} + +static void module_start(int type) { + init_NeonKick(type); +} + +static void module_stop(int type) { + free_NeonKick(type); +} + +MODULE_HEADER(module_initialize, module_start, module_stop); diff --git a/src/modules/botid.h b/src/modules/botid.h index 964790c..bebbeb8 100644 --- a/src/modules/botid.h +++ b/src/modules/botid.h @@ -23,5 +23,6 @@ #define NEONHELP_BOTID 4 #define NEONFUN_BOTID 5 #define NEONBACKUP_BOTID 6 +#define NEONKICK_BOTID 7 #endif \ No newline at end of file