added NeonBackup bot
authorpk910 <philipp@zoelle1.de>
Sat, 30 Jun 2012 16:20:34 +0000 (18:20 +0200)
committerpk910 <philipp@zoelle1.de>
Sun, 1 Jul 2012 09:53:46 +0000 (11:53 +0200)
33 files changed:
Makefile.am
neonserv.example.conf
src/ClientSocket.h
src/IRCParser.c
src/ModuleFunctions.c [new file with mode: 0644]
src/ModuleFunctions.h [new file with mode: 0644]
src/bots.c
src/bots.h
src/main.c
src/modules.c
src/modules/DummyServ.mod/bot_DummyServ.c
src/modules/NeonBackup.mod/bot_NeonBackup.c [new file with mode: 0644]
src/modules/NeonBackup.mod/bot_NeonBackup.h [new file with mode: 0644]
src/modules/NeonBackup.mod/cmd_neonbackup.c [new file with mode: 0644]
src/modules/NeonBackup.mod/cmd_neonbackup.h [new file with mode: 0644]
src/modules/NeonBackup.mod/module.c [new file with mode: 0644]
src/modules/NeonFun.mod/bot_NeonFun.c
src/modules/NeonHelp.mod/bot_NeonHelp.c
src/modules/NeonServ.mod/bot_NeonServ.c
src/modules/NeonServ.mod/cmd_neonserv.h
src/modules/NeonServ.mod/cmd_neonserv_csuspend.c
src/modules/NeonServ.mod/cmd_neonserv_cunsuspend.c
src/modules/NeonServ.mod/cmd_neonserv_set.c
src/modules/NeonServ.mod/cmd_neonserv_unvisited.c
src/modules/NeonServ.mod/event_neonserv_invite.c
src/modules/NeonServ.mod/event_neonserv_join.c
src/modules/NeonSpam.mod/bot_NeonSpam.c
src/modules/botid.h
src/modules/global.mod/cmd_global.h
src/modules/global.mod/cmd_global_register.c
src/modules/global.mod/cmd_global_unregister.c
src/modules/module.h
src/version.h

index e125423a63664036c31551184b08a71240ab0f5d..82b3e8e7b1e46c0c14e5b5af2450a005ca9dceee 100644 (file)
@@ -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 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
 
 libDummyServ_la_SOURCES = src/modules/DummyServ.mod/bot_DummyServ.c \
       src/modules/DummyServ.mod/module.c
@@ -64,6 +64,12 @@ libNeonHelp_la_SOURCES = src/modules/NeonHelp.mod/bot_NeonHelp.c \
 libNeonHelp_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined
 libNeonHelp_la_LIBADD = $(MYSQL_LIBS)
 
+libNeonBackup_la_SOURCES = src/modules/NeonBackup.mod/bot_NeonBackup.c \
+      src/modules/NeonBackup.mod/cmd_neonbackup.c \
+      src/modules/NeonBackup.mod/module.c
+libNeonBackup_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined
+libNeonBackup_la_LIBADD = $(MYSQL_LIBS)
+
 libNeonServ_la_SOURCES = src/modules/NeonServ.mod/bot_NeonServ.c \
       src/modules/NeonServ.mod/cmd_neonserv.c \
       src/modules/NeonServ.mod/cmd_neonserv_access.c \
@@ -192,6 +198,7 @@ neonserv_SOURCES = src/version.c \
       src/QServer.c \
       src/modules.c \
       src/module_commands.c \
+      src/ModuleFunctions.c \
       src/memoryDebug.c
 
 neonserv_LDADD = $(MYSQL_LIBS) $(SYSTEM_LIBS)
index bc09736bab25a7c59961c0fdfe2f6cc5672f790e..d93cd4242ba5b83460d2f481e9ccd6eee99099fc 100644 (file)
         "chan_expire_freq" = "3d";
         // How long is a channel unvisited (by masters or above) before it can be expired?
         "chan_expire_delay" = "30d";
+        // Automatically register a Backup bot with NeonServ
+        "auto_backup_register" = 0;
+        // Automatically unregister all Backup when NeonServ gets removed
+        "auto_backup_unregister" = 1;
+        // BackupServ channel setting
+        "channel_backup_setting" = 1;
+    };
+    "libNeonBackup" {
+        "enabled" = 1;
+        "protected" = 0;
     };
     "libNeonSpam" {
         "enabled" = 1;
index a65dfdfb00edefe2c5681b0db8c0fa05d2f7b9ba..9261be3a62ea6239fb169fec7855e1d23f9d33bf 100644 (file)
 
 #include "main.h"
 
-#define SOCKET_FLAG_DEAD      0x01
-#define SOCKET_FLAG_CONNECTED 0x02
-#define SOCKET_FLAG_READY     0x04
-#define SOCKET_FLAG_PREFERRED 0x08 /* prefered bot to send datas to the IRC World (NOTICE's WHO's etc pp) */
-#define SOCKET_FLAG_USE_QUEUE 0x10
-#define SOCKET_FLAG_RECONNECT 0x20
-#define SOCKET_FLAG_SSL       0x40
-#define SOCKET_FLAG_HAVE_SSL  0x80
-#define SOCKET_FLAG_QUITTED   0x100
-#define SOCKET_FLAG_FAST_JUMP 0x200
-#define SOCKET_FLAG_SILENT    0x400
-#define SOCKET_FLAG_CHANGENICK 0x800
+#define SOCKET_FLAG_DEAD           0x01
+#define SOCKET_FLAG_CONNECTED      0x02
+#define SOCKET_FLAG_READY          0x04
+#define SOCKET_FLAG_PREFERRED      0x08 /* prefered bot to send datas to the IRC World (NOTICE's WHO's etc pp) */
+#define SOCKET_FLAG_USE_QUEUE      0x10
+#define SOCKET_FLAG_RECONNECT      0x20
+#define SOCKET_FLAG_SSL            0x40
+#define SOCKET_FLAG_HAVE_SSL       0x80
+#define SOCKET_FLAG_QUITTED        0x100
+#define SOCKET_FLAG_FAST_JUMP      0x200
+#define SOCKET_FLAG_SILENT         0x400
+#define SOCKET_FLAG_CHANGENICK     0x800
+#define SOCKET_FLAG_REQUEST_INVITE 0x1000
 
 #define SOCKET_HAVE_BOTCLASSVALUE1 0x10000000
 #define SOCKET_HAVE_BOTCLASSVALUE2 0x20000000
index 2ff95c8ba066b3e2b440d1b6250e4242060e1042..ca42770bd8370725feacc467294230b86dd662c1 100644 (file)
@@ -27,6 +27,7 @@
 #include "BanNode.h"
 #include "ModeNode.h"
 #include "tools.h"
+#include "bots.h"
 
 struct irc_cmd *irc_commands = NULL;
 static struct UserNode *registering_users = NULL;
@@ -798,6 +799,15 @@ static IRC_CMD(raw_005) {
     return 1;
 }
 
+static IRC_CMD(raw_nojoin) {
+    if(from == NULL || argc < 3) return 0;
+    struct ChanNode *chan = getChanByName(argv[1]);
+    if(chan == NULL) return 0;
+    if(client->flags & SOCKET_FLAG_REQUEST_INVITE)
+        requestInvite(client->user, chan);
+    return 1;
+}
+
 void init_parser() {
     //all the raws we receive...
     register_irc_function("437", raw_437);
@@ -808,6 +818,10 @@ void init_parser() {
     register_irc_function("324", raw_324);
     register_irc_function("332", raw_332);
     register_irc_function("367", raw_367);
+    register_irc_function("471", raw_nojoin);
+    register_irc_function("473", raw_nojoin);
+    register_irc_function("474", raw_nojoin);
+    register_irc_function("475", raw_nojoin);
     register_irc_function("INVITE", raw_invite);
     register_irc_function("NOTICE", raw_notice);
     register_irc_function("TOPIC", raw_topic);
diff --git a/src/ModuleFunctions.c b/src/ModuleFunctions.c
new file mode 100644 (file)
index 0000000..250de3f
--- /dev/null
@@ -0,0 +1,90 @@
+/* ModuleFunctions.c - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#include "ModuleFunctions.h"
+#include "modules.h"
+#include "ChanNode.h"
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#define FUNCTION_GLOBAL_CMD_REGISTER_NEONBACKUP   0
+#define FUNCTION_GLOBAL_CMD_UNREGISTER_NEONBACKUP 1
+#define FUNCTION_NEONBACKUP_RECOVER_CHAN          2
+
+#define TOTAL_FUNCTIONS                           3
+
+struct module_function {
+    struct ModuleInfo *module;
+    void *function;
+};
+
+static struct module_function module_functions[TOTAL_FUNCTIONS];
+
+void init_modulefunctions() {
+    int i;
+    for(i = 0; i < TOTAL_FUNCTIONS; i++) {
+        module_functions[i].function = NULL;
+    }
+}
+
+void scan_module(struct ModuleInfo *module) {
+    char *function_names[] = {
+        "global_cmd_register_neonbackup",   /* FUNCTION_GLOBAL_CMD_REGISTER_NEONBACKUP */
+        "global_cmd_unregister_neonbackup", /* FUNCTION_GLOBAL_CMD_UNREGISTER_NEONBACKUP */
+        "neonbackup_recover_chan"           /* FUNCTION_NEONBACKUP_RECOVER_CHAN */
+    };
+    int i;
+    for(i = 0; i < TOTAL_FUNCTIONS; i++) {
+        #ifndef WIN32
+        void* func = dlsym(module->module, function_names[i]);
+        #else
+        FARPROC func = GetProcAddress(module->module, function_names[i]);
+        #endif
+        if(func) {
+            module_functions[i].module = module;
+            module_functions[i].function = func;
+        }
+    }
+}
+
+void free_module_functions(struct ModuleInfo *module) {
+    int i;
+    for(i = 0; i < TOTAL_FUNCTIONS; i++) {
+        if(module_functions[i].module == module) {
+            module_functions[i].function = NULL;
+        }
+    }
+}
+
+/* function handlers */
+void module_global_cmd_register_neonbackup(char *chan) {
+    if(!module_functions[FUNCTION_GLOBAL_CMD_REGISTER_NEONBACKUP].function)
+        return;
+    ((void (*)(char *)) module_functions[FUNCTION_GLOBAL_CMD_REGISTER_NEONBACKUP].function)(chan);
+}
+
+void module_global_cmd_unregister_neonbackup(char *chan) {
+    if(!module_functions[FUNCTION_GLOBAL_CMD_UNREGISTER_NEONBACKUP].function)
+        return;
+    ((void (*)(char *)) module_functions[FUNCTION_GLOBAL_CMD_UNREGISTER_NEONBACKUP].function)(chan);
+}
+
+void module_neonbackup_recover_chan(struct ChanNode *chan) {
+    if(!module_functions[FUNCTION_NEONBACKUP_RECOVER_CHAN].function)
+        return;
+    ((void (*)(struct ChanNode *)) module_functions[FUNCTION_NEONBACKUP_RECOVER_CHAN].function)(chan);
+}
diff --git a/src/ModuleFunctions.h b/src/ModuleFunctions.h
new file mode 100644 (file)
index 0000000..51281d3
--- /dev/null
@@ -0,0 +1,34 @@
+/* ModuleFunctions.h - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _ModuleFunctions_h
+#define _ModuleFunctions_h
+#include "overall.h"
+
+#ifndef DND_FUNCTIONS
+struct ModuleInfo;
+struct ChanNode;
+
+void init_modulefunctions();
+void scan_module(struct ModuleInfo *module);
+void free_module_functions(struct ModuleInfo *module);
+
+/* MODULAR ACCESSIBLE */ void module_global_cmd_register_neonbackup(char *chan);
+/* MODULAR ACCESSIBLE */ void module_global_cmd_unregister_neonbackup(char *chan);
+/* MODULAR ACCESSIBLE */ void module_neonbackup_recover_chan(struct ChanNode *chan);
+
+#endif
+#endif
index 7ada74312aac2d40f3dfa190f0d0f7cca9f9494f..1fe8cea4ff1b94aeefa6f218662d9cc0f220322d 100644 (file)
@@ -157,6 +157,22 @@ void requestOp(struct UserNode *user, struct ChanNode *chan) {
     }
 }
 
+void requestInvite(struct UserNode *user, struct ChanNode *chan) {
+    struct ClientSocket *bot, *userbot = NULL;
+    struct ChanUser *chanuser = getChanUser(user, chan);
+    char invited = 0;
+    if(chanuser) return;
+    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+        if(!invited && (chanuser = getChanUser(bot->user, chan)) != NULL && (chanuser->flags & CHANUSERFLAG_OPPED)) {
+            invited = 1;
+            putsock(bot, "INVITE %s %s", user->nick, chan->name);
+        }
+        if(bot->user == user) {
+            userbot = bot;
+        }
+    }
+}
+
 TIMEQ_CALLBACK(channel_ban_timeout) {
     char *str_banid = data;
     MYSQL_RES *res;
index b0712e8785ac69d8839b4716e017c101c09aa6d9..dd40e34cb5ec8a6a6c44732536afe3ca65b00422 100644 (file)
@@ -29,6 +29,7 @@ void init_bots();
 
 /* MODULAR ACCESSIBLE */ struct ClientSocket *getChannelBot(struct ChanNode *chan, int botid);
 /* MODULAR ACCESSIBLE */ void requestOp(struct UserNode *user, struct ChanNode *chan);
+/* MODULAR ACCESSIBLE */ void requestInvite(struct UserNode *user, struct ChanNode *chan);
 /* MODULAR ACCESSIBLE */ TIMEQ_CALLBACK(channel_ban_timeout);
 /* MODULAR ACCESSIBLE */ void general_event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text);
 /* MODULAR ACCESSIBLE */ void set_bot_alias(int botid, char *alias);
index f3afaaf8a18c97a9bfd50a452eac5c2bd2a9feb5..08193780344d6b59b4257ececd6c636b4342c824 100644 (file)
@@ -40,6 +40,7 @@
 #include "version.h"
 #include "modules.h"
 #include "module_commands.h"
+#include "ModuleFunctions.h"
 
 time_t start_time;
 static int running, hard_restart;
@@ -295,6 +296,7 @@ main:
     register_module_commands();
     init_handleinfohandler();
     init_tools();
+    init_modulefunctions();
     loadModules();
     init_bots();
     init_DBHelper();
index 4372c48433d1bec7140922c977e862a754acffce..5ada206c563b31888380fc027ef9c016dbb8a669 100644 (file)
@@ -46,6 +46,8 @@
 /* 184-188 */ #include "version.h"
 /* 189     */ /* modules.h */
 /* 190     */ /* UserNode.h */
+/* 191-193 */ #include "ModuleFunctions.h"
+/* 194     */ /* bots.h */
 
 #define Function void *
 
@@ -251,7 +253,11 @@ void *global_functions[] = {
 /* 187 */ (Function) get_codelines,
 /* 188 */ (Function) get_patchlevel,
 /* 189 */ (Function) get_module_name,
-/* 190 */ (Function) isUserModeSet
+/* 190 */ (Function) isUserModeSet,
+/* 191 */ (Function) module_global_cmd_register_neonbackup,
+/* 192 */ (Function) module_global_cmd_unregister_neonbackup,
+/* 193 */ (Function) module_neonbackup_recover_chan,
+/* 194 */ (Function) requestInvite
 };
 
 static int module_id_counter = 1;
@@ -348,6 +354,7 @@ struct ModuleInfo *loadModule(char *name) {
     modinfo->state = 0;
     modinfo->next = modules;
     modules = modinfo;
+    scan_module(modinfo);
     return modinfo;
 }
 
@@ -388,6 +395,7 @@ int ext_unload_module(char *name) {
             unregister_module_hooks(old_modinfo->module_id);
             ((void (*)(int)) old_modinfo->stopfunc)(MODSTATE_STARTSTOP);
             closemodule(old_modinfo->module);
+            free_module_functions(old_modinfo);
             free(old_modinfo->name);
             free(old_modinfo);
             return 1;
@@ -410,6 +418,7 @@ int ext_reload_module(char *name) {
             unregister_module_hooks(old_modinfo->module_id);
             ((void (*)(int)) old_modinfo->stopfunc)(MODSTATE_RELOAD);
             closemodule(old_modinfo->module);
+            free_module_functions(old_modinfo);
             free(old_modinfo->name);
             free(old_modinfo);
             break;
@@ -456,6 +465,7 @@ void stop_modules() {
         unregister_module_hooks(modinfo->module_id);
         ((void (*)(int)) modinfo->stopfunc)(MODSTATE_STARTSTOP);
         closemodule(modinfo->module);
+        free_module_functions(modinfo);
         free(modinfo->name);
         free(modinfo);
     }
@@ -466,6 +476,7 @@ static void unregister_module_hooks(int module_id) {
     unregister_module_commands(module_id);
     unregister_module_events(module_id);
     unregister_module_timers(module_id);
+    
 }
 
 int module_loaded(int module_id) {
@@ -487,3 +498,5 @@ char *get_module_name(int module_id) {
     }
     return NULL;
 }
+
+
index 2911b23f7e399f55cb4507dc340ecef1604a2376..1b078ec00d073569cb224cd1158fa6e68454415f 100644 (file)
@@ -108,6 +108,33 @@ static void start_bots(int type) {
     bind_unbound_required_functions(BOTID);
 }
 
+static void dummyserv_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);
+    }
+}
+
 void init_DummyServ(int type) {
     set_bot_alias(BOTID, BOTALIAS);
     start_bots(type);
@@ -116,6 +143,7 @@ void init_DummyServ(int type) {
     
     //register events
     bind_bot_ready(dummyserv_bot_ready, module_id);
+       bind_invite(dummyserv_event_invite, module_id);
     
     set_trigger_callback(BOTID, module_id, dummyserv_trigger_callback);
 }
diff --git a/src/modules/NeonBackup.mod/bot_NeonBackup.c b/src/modules/NeonBackup.mod/bot_NeonBackup.c
new file mode 100644 (file)
index 0000000..916e3b2
--- /dev/null
@@ -0,0 +1,203 @@
+/* bot_NeonBackup.c - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#include "../module.h"
+#include "../botid.h"
+
+#include "bot_NeonBackup.h"
+#include "../../modcmd.h"
+#include "cmd_neonbackup.h"
+#include "../../lang.h"
+#include "../../mysqlConn.h"
+#include "../../ClientSocket.h"
+#include "../../UserNode.h"
+#include "../../ChanNode.h"
+#include "../../ChanUser.h"
+#include "../../IRCEvents.h"
+#include "../../IRCParser.h"
+#include "../../bots.h"
+#include "../../DBHelper.h"
+#include "../../WHOHandler.h"
+
+#define BOTID NEONBACKUP_BOTID
+#define BOTALIAS "NeonBackup"
+
+static const struct default_language_entry msgtab[] = {
+    {NULL, NULL}
+};
+
+static void neonbackup_bot_ready(struct ClientSocket *client) {
+    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 neonbackup_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) {
+    MYSQL_RES *res;
+    MYSQL_ROW row;
+    loadChannelSettings(chan);
+    if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
+        strcpy(trigger, "!");
+        return;
+    }
+    printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID);
+    res = mysql_use();
+    if(!(row = mysql_fetch_row(res))) {
+        strcpy(trigger, "+");
+        return;
+    }
+    if(row[0] && *row[0])
+        strcpy(trigger, row[0]);
+    else
+        strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "+"));
+}
+
+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` 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 |= SOCKET_FLAG_REQUEST_INVITE;
+            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);
+}
+
+void neonbackup_recover_chan(struct ChanNode *chan) {
+    
+}
+
+static void neonbackup_event_join(struct ChanUser *chanuser) {
+    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);
+        neonbackup_recover_chan(chanuser->chan);
+    }
+}
+
+static void neonbackup_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")) {
+        reply(client, user, "MODCMD_CHAN_SUSPENDED");
+        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)) {
+            reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
+        } else
+            putsock(bot, "JOIN %s", channel);
+    }
+}
+
+void init_NeonBackup(int type) {
+    set_bot_alias(BOTID, BOTALIAS);
+    start_bots(type);
+    
+    if(type == MODSTATE_REBIND) return;
+    
+    //register events
+    bind_bot_ready(neonbackup_bot_ready, module_id);
+    bind_join(neonbackup_event_join, module_id);
+       bind_invite(neonbackup_event_invite, module_id);
+    
+    set_trigger_callback(BOTID, module_id, neonbackup_trigger_callback);
+    
+    register_default_language_table(msgtab);
+}
+
+void loop_NeonBackup() {
+    
+}
+
+void free_NeonBackup(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/NeonBackup.mod/bot_NeonBackup.h b/src/modules/NeonBackup.mod/bot_NeonBackup.h
new file mode 100644 (file)
index 0000000..a805c3c
--- /dev/null
@@ -0,0 +1,26 @@
+/* bot_NeonBackup.h - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _bot_NeonBackup_h
+#define _bot_NeonBackup_h
+
+#include "../../main.h"
+
+void init_NeonBackup(int type);
+void loop_NeonBackup();
+void free_NeonBackup(int type);
+
+#endif
\ No newline at end of file
diff --git a/src/modules/NeonBackup.mod/cmd_neonbackup.c b/src/modules/NeonBackup.mod/cmd_neonbackup.c
new file mode 100644 (file)
index 0000000..3c3eaf0
--- /dev/null
@@ -0,0 +1,28 @@
+/* cmd_neonbackup.c - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#include "../module.h"
+#include "cmd_neonbackup.h"
+#include "../../modcmd.h"
+#include "../../ConfigParser.h"
+
+void register_commands() {
+    //NeonBackup Commands
+    register_command_alias(6, "NeonBackup");
+    
+    
+    
+}
\ No newline at end of file
diff --git a/src/modules/NeonBackup.mod/cmd_neonbackup.h b/src/modules/NeonBackup.mod/cmd_neonbackup.h
new file mode 100644 (file)
index 0000000..f4f36a2
--- /dev/null
@@ -0,0 +1,36 @@
+/* cmd_neonbackup.h - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _cmd_neonbackup_h
+#define _cmd_neonbackup_h
+#include "../module.h"
+#include "../../main.h"
+#include "../../modcmd.h"
+#include "../../mysqlConn.h"
+#include "../../ClientSocket.h"
+#include "../../UserNode.h"
+#include "../../ChanNode.h"
+#include "../../ChanUser.h"
+#include "../../DBHelper.h"
+#include "../../IRCParser.h"
+#include "bot_NeonBackup.h"
+#include "../../lang.h"
+#include "../../tools.h"
+
+void register_commands();
+
+
+#endif
diff --git a/src/modules/NeonBackup.mod/module.c b/src/modules/NeonBackup.mod/module.c
new file mode 100644 (file)
index 0000000..4fb205e
--- /dev/null
@@ -0,0 +1,38 @@
+/* module.c - NeonServ v5.4
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#include "../module.h"
+#include "bot_NeonBackup.h"
+#include "cmd_neonbackup.h"
+
+static int module_initialize() {
+    register_commands();
+    return 0;
+}
+
+static void module_start(int type) {
+    init_NeonBackup(type);
+}
+
+static void module_loop() {
+    loop_NeonBackup();
+}
+
+static void module_stop(int type) {
+    free_NeonBackup(type);
+}
+
+MODULE_HEADER(module_initialize, module_start, module_loop, module_stop);
index e5706ae8cc875f2d059f01a23a2e73817270fce9..49364a2134d6fad22c446f3ac2c9ad4c9f33d233 100644 (file)
@@ -99,6 +99,7 @@ static void start_bots(int type) {
             client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0);
             client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0);
             client->flags |= SOCKET_FLAG_SILENT;
+            client->flags |= SOCKET_FLAG_REQUEST_INVITE;
             client->botid = BOTID;
             client->clientid = atoi(row[7]);
             connect_socket(client);
@@ -141,6 +142,36 @@ static int neonfun_freechan(struct ChanNode *chan) {
     return 0;
 }
 
+static void neonfun_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")) {
+        reply(client, user, "MODCMD_CHAN_SUSPENDED");
+        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)) {
+            reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
+        } else
+            putsock(bot, "JOIN %s", channel);
+    }
+}
+
 void init_NeonFun(int type) {
     set_bot_alias(BOTID, BOTALIAS);
     start_bots(type);
@@ -152,7 +183,8 @@ void init_NeonFun(int type) {
     bind_part(neonfun_parted, module_id);
     bind_quit(neonfun_quitted, module_id);
     bind_freechan(neonfun_freechan, module_id);
-    
+    bind_invite(neonfun_event_invite, module_id);
+       
     set_trigger_callback(BOTID, module_id, neonfun_trigger_callback);
 }
 
index 614d0df4a6b346edcae945cf7959bc0248fe9dad..68cf6626013bb3bb7bd07e54e86afdda32a675aa 100644 (file)
@@ -125,6 +125,7 @@ static void start_bots(int type) {
             client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0);
             client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0);
             client->flags |= SOCKET_FLAG_SILENT;
+            client->flags |= SOCKET_FLAG_REQUEST_INVITE;
             client->botid = BOTID;
             client->clientid = atoi(row[7]);
             connect_socket(client);
@@ -515,6 +516,36 @@ static void neonhelp_event_quit(struct UserNode *target, char *reason) {
     }
 }
 
+static void neonhelp_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")) {
+        reply(client, user, "MODCMD_CHAN_SUSPENDED");
+        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)) {
+            reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
+        } else
+            putsock(bot, "JOIN %s", channel);
+    }
+}
+
 void init_NeonHelp(int type) {
     set_bot_alias(BOTID, BOTALIAS);
     start_bots(type);
@@ -528,6 +559,7 @@ void init_NeonHelp(int type) {
     bind_part(neonhelp_event_part, module_id);
     bind_kick(neonhelp_event_kick, module_id);
     bind_quit(neonhelp_event_quit, module_id);
+       bind_invite(neonhelp_event_invite, module_id);
     
     set_trigger_callback(BOTID, module_id, neonhelp_trigger_callback);
     
index 83f329b3506544a7be71dfdc9525e4def2d510b2..16d6dbdfe5d943568b1deeb64c53a97f13967364 100644 (file)
@@ -471,6 +471,7 @@ static void start_bots(int type) {
             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 |= SOCKET_FLAG_REQUEST_INVITE;
             client->botid = BOTID;
             client->clientid = atoi(row[7]);
             connect_socket(client);
index 49afad593f65f0bcb4ebab2b5f364aa5dacfa00e..d5f0b5fd2604a2b9a7bd03c4e7ad0aab1079ff52 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _cmd_neonserv_h
 #define _cmd_neonserv_h
 #include "../module.h"
+#include "../botid.h"
 #include "../../main.h"
 #include "../../modcmd.h"
 #include "../../IRCParser.h"
index c264b6408695096acded44e10bc3ba9c3bf43185..1dad37dd21fc5424399f238ea3a1260a11a90a66 100644 (file)
@@ -56,6 +56,12 @@ CMD_BIND(neonserv_cmd_csuspend) {
     if(bot) {
         putsock(bot, "PART %s :Channel suspended.", channel);
     }
+    if(client->botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_unregister", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_unregister_neonbackup(channel);
+    }
     printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '1' WHERE `id` = '%s'", row[1]);
     reply(getTextBot(), user, "NS_CSUSPEND_DONE", channel);
     logEvent(event);
index eccc76af683263f3fd1a1290a500706c8faacb39..b9c6a368968050b3a32b4be7e5d4d8cb253ed789 100644 (file)
@@ -56,6 +56,12 @@ CMD_BIND(neonserv_cmd_cunsuspend) {
     if(bot) {
         putsock(bot, "JOIN %s", channel);
     }
+    if(client->botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_register", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_register_neonbackup(channel);
+    }
     printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '0' WHERE `id` = '%s'", row[1]);
     reply(getTextBot(), user, "NS_CUNSUSPEND_DONE", channel);
     logEvent(event);
index 2ebb96828dac0eac072e9b28359b17967d30d422..2243c0df38e0401d0122ccfb149c638016a62b66 100644 (file)
@@ -23,6 +23,7 @@ static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNo
 static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
 static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
 static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+static char* neonserv_cmd_set_backupbot(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
 
 #define NS_VALID_FUNCTION 0x01
 #define NS_VALID_STRING   0x02
@@ -80,6 +81,7 @@ static const struct {
     {"TOYS",            "channel_toys",         NS_VALID_OPTIONS | NS_HAS_OPT,      "3"},
     {"DYNLIMIT",        "channel_dynlimit",     NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
     {"NODELETE",        "channel_nodelete",     NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
+    {"BACKUPBOT",       NULL,                   NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_backupbot},
     {NULL, NULL, 0, NULL}
 };
 
@@ -132,6 +134,14 @@ CMD_BIND(neonserv_cmd_set) {
         while(channel_settings[i].setting) {
             if(!stricmp(channel_settings[i].setting, argv[0]) && (!(channel_settings[i].valid & NS_VALID_IF_HALFOP) || with_halfops)) {
                 //setting found
+                if(!stricmp(channel_settings[i].setting, "BACKUPBOT")) {
+                    char setting[128];
+                    sprintf(setting, "modules.%s.channel_backup_setting", get_module_name(module_id));
+                    if(!get_int_field(setting)) {
+                        i++;
+                        continue;
+                    }
+                }
                 if(channel_settings[i].valid & NS_VALID_FUNCTION) {
                     neonserv_cmd_set_function *func = channel_settings[i].parameter;
                     func(client, user, chan, event, channel_settings[i].setting, args);
@@ -155,6 +165,7 @@ CMD_BIND(neonserv_cmd_set) {
         struct Table *table;
         char *content[2];
         int with_halfops = get_int_field("General.have_halfop");
+        int channel_backup_setting;
         i = 0;
         j = 0;
         while(channel_settings[i].setting) {
@@ -163,6 +174,16 @@ CMD_BIND(neonserv_cmd_set) {
                 i++;
                 continue;
             }
+            if(!stricmp(channel_settings[i].setting, "BACKUPBOT")) {
+                char setting[128];
+                sprintf(setting, "modules.%s.channel_backup_setting", get_module_name(module_id));
+                channel_backup_setting = get_int_field(setting);
+                if(!channel_backup_setting) {
+                    i++;
+                    j++;
+                    continue;
+                }
+            }
             if(channel_settings[i].chanfield)
                 querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
             i++;
@@ -183,6 +204,10 @@ CMD_BIND(neonserv_cmd_set) {
                 i++;
                 continue;
             }
+            if(!stricmp(channel_settings[i].setting, "BACKUPBOT") && !channel_backup_setting) {
+                i++;
+                continue;
+            }
             if(channel_settings[i].chanfield) {
                 j++;
                 org_value = (row[j] ? row[j] : defaults[j]);
@@ -468,4 +493,38 @@ static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserN
     return value;
 }
 
+static char* neonserv_cmd_set_backupbot(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
+    int backupbot;
+    //get current trigger
+    MYSQL_RES *res;
+    printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, NEONBACKUP_BOTID);
+    res = mysql_use();
+    if(mysql_fetch_row(res))
+        backupbot = 1;
+    else 
+        backupbot = 0;
+    if(argument) {
+        //change the channel setting
+        if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
+            if(backupbot) {
+                module_global_cmd_unregister_neonbackup(chan->name);
+                backupbot = 0;
+            }
+        } else if(!strcmp(argument, "1") || !strcmp(argument, "on") || !strcmp(argument, get_language_string(user, "NS_SET_ON"))) {
+            if(!backupbot) {
+                module_global_cmd_register_neonbackup(chan->name);
+                backupbot = 1;
+            }
+        } else {
+            reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
+            return NULL;
+        }
+        logEvent(event);
+    }
+    if(setting) {
+        reply(getTextBot(), user, "\002%s\002 %s", setting, (backupbot ? "1" : "0"));
+    }
+    return (backupbot ? "1" : "0");
+}
+
 #undef MAX_QUERY_LEN
index 455583c26a359d8a22f1d4c21686097597733dcc..62f86c0bd2cfaaf4e93f8671865658240f715db4 100644 (file)
@@ -49,14 +49,14 @@ void neonserv_cmd_unvisited_init() {
 static TIMEQ_CALLBACK(neonserv_check_unvisited_timer) {
     char tmp[200];
     char *modname = get_module_name(module_id);
-    sprintf(tmp, "modules/%s/chan_expire_freq", modname);
+    sprintf(tmp, "modules.%s.chan_expire_freq", modname);
     char *check_freq_str = get_string_field(tmp);
     int check_freq;
     if(!check_freq_str || (check_freq = strToTime(NULL, check_freq_str)) < (60*60)) {
         timeq_add_name("neonserv_unvisited", 1800, module_id, neonserv_check_unvisited_timer, NULL);
         return;
     }
-    sprintf(tmp, "modules/%s/chan_expire_delay", modname);
+    sprintf(tmp, "modules.%s.chan_expire_delay", modname);
     char *check_expire_str = get_string_field(tmp);
     int duration;
     if(!check_expire_str || (duration = strToTime(NULL, check_expire_str)) < 60*60*24*7) return;
@@ -156,7 +156,7 @@ static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *c
 static void neonserv_cmd_unvisited_unreg(struct ClientSocket *client, char *channel) {
     MYSQL_RES *res;
     MYSQL_ROW row;
-    int sync_neonspam_unreg = get_int_field("General/sync_neonspam_unreg");
+    int sync_neonspam_unreg = get_int_field("General.sync_neonspam_unreg");
     int botid;
     if(client)
         botid = client->botid;
@@ -195,6 +195,12 @@ static void neonserv_cmd_unvisited_unreg(struct ClientSocket *client, char *chan
             putsock(bot, "PART %s :Channel unregistered.", channel);
         }
     }
+    if(client->botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_unregister", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_unregister_neonbackup(channel);
+    }
     char *alertchan = get_string_field("General.alertchan");
     if(alertchan) {
         struct ChanNode *alertchan_chan = getChanByName(alertchan);
index 40922086b4ef21e63239a8504d7530d242601a18..3dc36fb919b02e75988578fd47ce52b92f9e4b8b 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 static void neonserv_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);
index e2c54a57994b9995ea00c3b4f84a396f8ac96038..5f8d1440237321d666847a207e310274aa1bd8fe 100644 (file)
@@ -31,6 +31,7 @@ static void neonserv_event_join(struct ChanUser *chanuser) {
     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;
index b4db7243f8bae67f2cff0309542c98d51dcfbc53..de645c2470edf4ea752fc579b6c1762c107660de 100644 (file)
@@ -183,6 +183,7 @@ static void start_bots(int type) {
             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 |= SOCKET_FLAG_REQUEST_INVITE;
             client->botid = BOTID;
             client->clientid = atoi(row[7]);
             connect_socket(client);
@@ -373,6 +374,36 @@ static int neonspam_event_freechan(struct ChanNode *chan) {
     return 1;
 }
 
+static void neonspam_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")) {
+        reply(client, user, "MODCMD_CHAN_SUSPENDED");
+        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)) {
+            reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
+        } else
+            putsock(bot, "JOIN %s", channel);
+    }
+}
+
 void init_NeonSpam(int type) {
     
     set_bot_alias(BOTID, BOTALIAS);
@@ -387,7 +418,8 @@ void init_NeonSpam(int type) {
     bind_privctcp(general_event_privctcp, module_id);
     bind_kick(neonspam_event_kick, module_id);
     bind_freechan(neonspam_event_freechan, module_id);
-    
+    bind_invite(neonspam_event_invite, module_id);
+       
     set_trigger_callback(BOTID, module_id, neonspam_trigger_callback);
     
     register_default_language_table(msgtab);
index b0209fa144057a983f4f1ee33edef93fdef45ffe..34c6b816b9f2d35f48cadbf66964a3dc369599f6 100644 (file)
@@ -22,5 +22,6 @@
 #define DUMMYSERV_BOTID 3
 #define NEONHELP_BOTID 4
 #define NEONFUN_BOTID 5
+#define NEONBACKUP_BOTID 6
 
 #endif
\ No newline at end of file
index b1f80beb2642093c1316f0b7600693ef8344eac1..d44a18fe8ce834d047ad6ffd7f8c6b3c5357a458 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _cmd_global_h
 #define _cmd_global_h
 #include "../module.h"
+#include "../botid.h"
 #include "../../main.h"
 #include "../../modcmd.h"
 #include "../../IRCParser.h"
@@ -71,4 +72,5 @@ CMD_BIND(global_cmd_unbind);
 CMD_BIND(global_cmd_unregister);
 CMD_BIND(global_cmd_version);
 
+
 #endif
\ No newline at end of file
index 1f4690af578e84c59637a7034a4fad740ab204a1..81e018014b26bb4cdaef743a4cfd1bb52df7cdc4 100644 (file)
@@ -114,7 +114,7 @@ CMD_BIND(global_cmd_register) {
         struct UserNode *cuser = getUserByNick(argv[1]);
         if(!cuser) {
             cuser = createTempUser(argv[1]);
-                       if(!cuser) {
+            if(!cuser) {
                 reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[1]);
                 return;
             }
@@ -262,5 +262,52 @@ static void global_cmd_register_async1(struct ClientSocket *client, struct Clien
         reply(textclient, user, "NS_REGISTER_DONE", channel, auth);
     } else
         reply(textclient, user, "NS_REGISTER_DONE_NOAUTH", channel);
+    // NeonBackup SubBlock
+    if(client->botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_register", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_register_neonbackup(channel);
+    }
     logEvent(event);
 }
+
+void global_cmd_register_neonbackup(char *channel) {
+    MYSQL_RES *res;
+    MYSQL_ROW row, row2;
+    printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s' AND botclass = '%d'", escape_string(channel), NEONBACKUP_BOTID);
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) != NULL)
+        return;
+    int chanid;
+    printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) != NULL) {
+        chanid = atoi(row[0]);
+    } else
+        return;
+    printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger`, `nick` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1' ORDER BY `register_priority` DESC", NEONBACKUP_BOTID);
+    res = mysql_use();
+    int botid = 0;
+    while ((row = mysql_fetch_row(res)) != NULL) {
+        //check channel count
+        printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
+        row2 = mysql_fetch_row(mysql_use());
+        if(atoi(row2[0]) < atoi(row[1])) {
+            botid = atoi(row[0]);
+            break;
+        }
+    }
+    if(!botid)
+        return;
+    struct ClientSocket *bot;
+    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+        if(bot->clientid == botid)
+            break;
+    }
+    if(bot) {
+        putsock(bot, "JOIN %s", channel);
+    }
+    printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', NULL)", botid, chanid);
+}
+
index 97ef4f9a8fc8ee60191b98a4aa62d33d90d4d830..daa173715825188f974c3265ed78d1753af111ed 100644 (file)
@@ -46,7 +46,7 @@ CMD_BIND(global_cmd_unregister) {
         reply(getTextBot(), user, "NS_UNREGISTER_NODELETE", channel);
         return;
     }
-    int sync_neonspam_unreg = get_int_field("General/sync_neonspam_unreg");
+    int sync_neonspam_unreg = get_int_field("General.sync_neonspam_unreg");
     if(client->botid == 0)
         printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '0' AND `botid` = '%d'", chanid, client->clientid);
     else
@@ -83,5 +83,38 @@ CMD_BIND(global_cmd_unregister) {
             putsock(bot, "PART %s :Channel unregistered.", channel);
         }
     }
+    // NeonBackup SubBlock
+    if(client->botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_unregister", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_unregister_neonbackup(channel);
+    }
     logEvent(event);
 }
+
+void global_cmd_unregister_neonbackup(char *channel) {
+       MYSQL_RES *res;
+    MYSQL_ROW row;
+    int chanid;
+    printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) != NULL) {
+        chanid = atoi(row[0]);
+    } else 
+        return;
+    printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, NEONBACKUP_BOTID);
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) == NULL)
+        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;
+    }
+    printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]);
+    if(bot && strcmp(row[2], "1")) {
+        putsock(bot, "PART %s :Channel unregistered.", channel);
+    }
+}
index b780ac16a495499d43c009373e586c0226052443..2efec3992c81a8a5cb72ce66267ecc4234bffc68 100644 (file)
@@ -220,6 +220,10 @@ extern int module_id;
 /* 188 */ #define get_patchlevel ((const int (*)(void))global[188])
 /* 189 */ #define get_module_name ((char * (*)(int))global[189])
 /* 190 */ #define isUserModeSet ((int (*)(struct UserNode *, char))global[190])
+/* 191 */ #define module_global_cmd_register_neonbackup ((void (*)(char *))global[191])
+/* 192 */ #define module_global_cmd_unregister_neonbackup ((void (*)(char *))global[192])
+/* 193 */ #define module_neonbackup_recover_chan ((void (*)(struct ChanNode *))global[193])
+/* 194 */ #define requestInvite ((void (*)(struct UserNode *, struct ChanNode *))global[194])
 
 #define MODULE_HEADER(initfunc,startfunc,loopfunc,stopfunc) \
     void **global = NULL; \
index 063c73d5d0631e46bc692ca6a8d143a6f994fa1a..e4dc9eaef5e3c761cd42fb9ff8fcfea9557bd9e9 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "main.h"
 
-#define MODULE_VERSION 3
+#define MODULE_VERSION 4
 
 #ifndef DND_FUNCTIONS
 extern const char *compilation;