692823e09d1e5dc4ff3dc9a15c7b0e6591a151bb
[NeonServV5.git] / src / modules / NeonServ.mod / cmd_neonserv_set.c
1 /* cmd_neonserv_set.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
21 static void neonserv_cmd_set_setting(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument);
22 static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
23 static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
24 static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
25 static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
26 static char* neonserv_cmd_set_backupbot(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
27
28 #define NS_VALID_FUNCTION 0x01
29 #define NS_VALID_STRING   0x02
30 #define NS_VALID_ACCESS   0x04
31 #define NS_VALID_NO501    0x08
32 #define NS_VALID_OPTIONS  0x10
33 #define NS_VALID_NUMERIC  0x20
34 #define NS_VALID_BOOLEAN  0x40
35 #define NS_VALID_IF_HALFOP 0x80
36
37 #define NS_HAS_OPT  0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
38 #define NS_HAS_HELP 0x200 /* help    (SET_HELP_{NAME}) - only shown if help is requested */
39
40 static const struct {
41     const char *setting;
42     const char *chanfield;
43     unsigned int valid;
44     void *parameter;
45 } channel_settings[] = {
46     {"TRIGGER",         NULL,                   NS_VALID_FUNCTION,                  neonserv_cmd_set_trigger},
47     {"DEFAULTTOPIC",    "channel_defaulttopic", NS_VALID_STRING,                    NULL},
48     {"TOPICMASK",       "channel_topicmask",    NS_VALID_STRING,                    NULL},
49     {"ADVANCEDTOPIC",   "channel_exttopic",     NS_VALID_BOOLEAN | NS_HAS_OPT,      NULL},
50     {"GREETING",        "channel_greeting",     NS_VALID_STRING,                    NULL},
51     {"USERGREETING",    "channel_usergreeting", NS_VALID_STRING,                    NULL},
52     {"USERINFO",        "channel_userinfo",     NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
53     {"WIPEINFO",        "channel_wipeinfo",     NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
54     {"MODES",           "channel_modes",        NS_VALID_FUNCTION,                  neonserv_cmd_set_modes},
55     {"INVITEME",        "channel_getinvite",    NS_VALID_ACCESS,                    NULL},
56     {"GIVEOPS",         "channel_getop",        NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
57     {"GIVEHALFOPS",     "channel_gethalfop",    NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL},
58     {"GIVEVOICE",       "channel_getvoice",     NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
59     {"ENFOPS",          "channel_canop",        NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
60     {"ENFHALFOPS",      "channel_canhalfop",    NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL},
61     {"ENFVOICE",        "channel_canvoice",     NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
62     {"KICK",            "channel_cankick",      NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
63     {"BAN",             "channel_canban",       NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
64     {"STATICBAN",       "channel_staticban",    NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
65     {"PUBCMD",          "channel_pubcmd",       NS_VALID_ACCESS,                    NULL},
66     {"ENFMODES",        "channel_enfmodes",     NS_VALID_ACCESS,                    NULL},
67     {"ENFTOPIC",        "channel_enftopic",     NS_VALID_ACCESS,                    NULL},
68     {"TOPICSNARF",      "channel_topicsnarf",   NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
69     {"CHANGETOPIC",     "channel_changetopic",  NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
70     {"SETTERS",         "channel_setters",      NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL},
71     {"ADDUSER",         "channel_canadd",       NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
72     {"DELUSER",         "channel_candel",       NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
73     {"CLVL",            "channel_canclvl",      NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
74     {"RESYNC",          "channel_canresync",    NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
75     {"SUSPEND",         "channel_cansuspend",   NS_VALID_ACCESS | NS_HAS_HELP,      NULL},
76     {"NOTICEUSERS",     "channel_notice",       NS_VALID_ACCESS,                    NULL},
77     {"NOTICEREACTION",  "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT,    "4"},
78     {"CTCPUSERS",       "channel_ctcp",         NS_VALID_ACCESS,                    NULL},
79     {"CTCPREACTION",    "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT,      "4"},
80     {"PROTECT",         "channel_protect",      NS_VALID_OPTIONS | NS_HAS_OPT,      "4"},
81     {"TOYS",            "channel_toys",         NS_VALID_OPTIONS | NS_HAS_OPT,      "3"},
82     {"DYNLIMIT",        "channel_dynlimit",     NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
83     {"NODELETE",        "channel_nodelete",     NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
84     {"BACKUPBOT",       NULL,                   NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_backupbot},
85     {NULL, NULL, 0, NULL}
86 };
87
88 #define MAX_QUERY_LEN 1024
89 CMD_BIND(neonserv_cmd_set) {
90     int i, j;
91     if(argc && !strcmp(argv[0], "defaults")) {
92         //reset channel settings
93         int uaccess = getChannelAccess(user, chan);
94         if(uaccess < 500) {
95             if(isGodMode(user)) {
96                 event->flags |= CMDFLAG_OPLOG;
97             } else {
98                 reply(textclient, user, "NS_SET_DEFAULTS_OWNER", chan->name);
99                 return;
100             }
101         }
102         int seed = 0;
103         char *tmp;
104         static char defaultskey[16];
105         for(tmp = user->auth; *tmp; tmp++)
106             seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
107         for(tmp = chan->name; *tmp; tmp++)
108             seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
109         sprintf(defaultskey, "%08x", seed);
110         if(argc > 1 && !strcmp(argv[1], defaultskey)) {
111             char query[MAX_QUERY_LEN];
112             int querypos = 0;
113             i = 0;
114             while(channel_settings[i].setting) {
115                 if(channel_settings[i].chanfield)
116                     querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield);
117                 i++;
118             }
119             if(querypos) {
120                 query[querypos-2] = '\0';
121             }
122             printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id);
123             reply(textclient, user, "NS_SET_DEFAULTS_DONE", chan->name);
124             logEvent(event);
125         } else {
126             reply(textclient, user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
127         }
128     } else if(argc && strcmp(argv[0], "help")) {
129         //find the correct command
130         i = 0;
131         j = 0;
132         char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
133         int with_halfops = get_int_field("General.have_halfop");
134         while(channel_settings[i].setting) {
135             if(!stricmp(channel_settings[i].setting, argv[0]) && (!(channel_settings[i].valid & NS_VALID_IF_HALFOP) || with_halfops)) {
136                 //setting found
137                 if(!stricmp(channel_settings[i].setting, "BACKUPBOT")) {
138                     char setting[128];
139                     sprintf(setting, "modules.%s.channel_backup_setting", get_module_name(module_id));
140                     if(!get_int_field(setting)) {
141                         i++;
142                         continue;
143                     }
144                 }
145                 if(channel_settings[i].valid & NS_VALID_FUNCTION) {
146                     neonserv_cmd_set_function *func = channel_settings[i].parameter;
147                     func(client, textclient, user, chan, event, channel_settings[i].setting, args);
148                 } else {
149                     neonserv_cmd_set_setting(client, textclient, user, chan, event, i, args);
150                 }
151                 j = 1;
152                 break;
153             }
154             i++;
155         }
156         if(j == 0) {
157             //unknown setting
158             reply(textclient, user, "NS_SET_UNKNOWN_SETTING", argv[0]);
159         }
160     } else {
161         char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64];
162         int querypos = 0;
163         MYSQL_RES *res, *defaults_res;
164         MYSQL_ROW row, defaults;
165         struct Table *table;
166         char *content[2];
167         int with_halfops = get_int_field("General.have_halfop");
168         int channel_backup_setting;
169         i = 0;
170         j = 0;
171         while(channel_settings[i].setting) {
172             if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) {
173                 j++;
174                 i++;
175                 continue;
176             }
177             if(!stricmp(channel_settings[i].setting, "BACKUPBOT")) {
178                 char setting[128];
179                 sprintf(setting, "modules.%s.channel_backup_setting", get_module_name(module_id));
180                 channel_backup_setting = get_int_field(setting);
181                 if(!channel_backup_setting) {
182                     i++;
183                     j++;
184                     continue;
185                 }
186             }
187             if(channel_settings[i].chanfield)
188                 querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
189             i++;
190         }
191         table = table_init(2, i-j, 0);
192         table_set_bold(table, 0, 1);
193         printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query);
194         defaults_res = mysql_use();
195         defaults = mysql_fetch_row(defaults_res);
196         printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id);
197         res = mysql_use();
198         row = mysql_fetch_row(res);
199         i = 0;
200         j = 0;
201         reply(textclient, user, "NS_SET_HEADER", chan->name);
202         while(channel_settings[i].setting) {
203             if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) {
204                 i++;
205                 continue;
206             }
207             if(!stricmp(channel_settings[i].setting, "BACKUPBOT") && !channel_backup_setting) {
208                 i++;
209                 continue;
210             }
211             if(channel_settings[i].chanfield) {
212                 j++;
213                 org_value = (row[j] ? row[j] : defaults[j]);
214             } else if(channel_settings[i].valid & NS_VALID_FUNCTION) {
215                 neonserv_cmd_set_function *func = channel_settings[i].parameter;
216                 org_value = func(client, textclient, user, chan, event, NULL, NULL);
217             } else
218                 org_value = "0";
219             value = org_value;
220             if(channel_settings[i].valid & NS_VALID_BOOLEAN) {
221                 if(!strcmp(value, "0"))
222                     value = get_language_string(user, "NS_SET_OFF");
223                 else
224                     value = get_language_string(user, "NS_SET_ON");
225             }
226             strcpy(query, value);
227             querypos = strlen(query);
228             if(channel_settings[i].valid & NS_HAS_OPT) {
229                 sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value);
230                 tmp = get_language_string(user, nameBuf);
231                 if(tmp) {
232                     querypos += sprintf(query+querypos, " - %s", tmp);
233                 }
234             }
235             if(argc && channel_settings[i].valid & NS_HAS_HELP) {
236                 sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting);
237                 tmp = get_language_string(user, nameBuf);
238                 if(tmp) {
239                     querypos += sprintf(query+querypos, " - %s", tmp);
240                 }
241             }
242             content[0] = (char*)channel_settings[i].setting;
243             content[1] = query;
244             table_add(table, content);
245             i++;
246         }
247         char **table_lines = table_end(table);
248         for(i = 0; i < table->entrys; i++) {
249             reply(textclient, user, table_lines[i]);
250         }
251         table_free(table);
252     }
253 }
254
255 static void neonserv_cmd_set_setting(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) {
256     char *value;
257     char nameBuf[64];
258     //get current value
259     MYSQL_RES *res;
260     MYSQL_ROW row;
261     printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id);
262     res = mysql_use();
263     row = mysql_fetch_row(res);
264     if(row[0] == NULL) {
265         printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield);
266         res = mysql_use();
267         row = mysql_fetch_row(res);
268     }
269     value = row[0];
270     if(args) {
271         //change the channel setting
272         //check the new argument
273         int valid = channel_settings[setting].valid;
274         if(valid & NS_VALID_STRING) {
275             if(!strcmp(args, "*")) {
276                 args = "";
277             }
278         }
279         if(valid & NS_VALID_ACCESS) {
280             int caccess = atoi(args);
281             int max = ((valid & NS_VALID_NO501) ? 500 : 501);
282             if(caccess < 0 || caccess > max) {
283                 reply(textclient, user, "NS_INVALID_ACCESS", caccess);
284                 return;
285             }
286             int uaccess = getChannelAccess(user, chan);
287             if(uaccess == 500) uaccess++;
288             if(atoi(value) > uaccess) {
289                 if(isGodMode(user)) {
290                     event->flags |= CMDFLAG_OPLOG;
291                 } else {
292                     reply(textclient, user, "NS_SET_CANNOT_SET");
293                     return;
294                 }
295             }
296             if(caccess > uaccess) {
297                 if(isGodMode(user)) {
298                     event->flags |= CMDFLAG_OPLOG;
299                 } else {
300                     reply(textclient, user, "NS_SET_BADLEVEL");
301                     return;
302                 }
303             }
304             sprintf(nameBuf, "%d", caccess);
305             args = nameBuf;
306         }
307         if(valid & NS_VALID_OPTIONS) {
308             int options = atoi((char *) channel_settings[setting].parameter);
309             int coption = atoi(args);
310             if(coption < 0 || coption >= options) {
311                 reply(textclient, user, "NS_SET_INVALID_OPTION", coption);
312                 int i;
313                 int nameBufPos = 0;
314                 if(valid & NS_HAS_OPT) {
315                     for(i = 0; i < options; i++) {
316                         sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i);
317                         reply(textclient, user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
318                     }
319                 } else {
320                     for(i = 0; i < options; i++) {
321                         nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
322                     }
323                     if(nameBufPos) {
324                         nameBuf[nameBufPos-2] = '\0';
325                         reply(textclient, user, nameBuf);
326                     }
327                 }
328                 return;
329             }
330         }
331         if(valid & NS_VALID_NUMERIC) {
332             sprintf(nameBuf, "%d", atoi(args));
333             args = nameBuf;
334         }
335         if(valid & NS_VALID_BOOLEAN) {
336             if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) {
337                 args = "0";
338             } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) {
339                 args = "1";
340             } else {
341                 reply(textclient, user, "NS_SET_INVALID_BOOLEAN", args);
342                 return;
343             }
344         }
345         //valid - set it
346         value = args;
347         printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id);
348         logEvent(event);
349     }
350     if(channel_settings[setting].valid & NS_HAS_OPT) {
351         sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[setting].setting, value);
352         char *tmp = get_language_string(user, nameBuf);
353         if(tmp)
354             reply(textclient, user, "\002%s\002 %s - %s", channel_settings[setting].setting, value, tmp);
355         else
356             reply(textclient, user, "\002%s\002 %s", channel_settings[setting].setting, value);
357     } else
358         reply(textclient, user, "\002%s\002 %s", channel_settings[setting].setting, value);
359     if(channel_settings[setting].valid & NS_HAS_HELP) {
360          sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting);
361          reply(textclient, user, "  %s", get_language_string(user, nameBuf));
362     }
363 }
364
365 static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
366     char *trigger;
367     //get current trigger
368     MYSQL_RES *res;
369     MYSQL_ROW row;
370     if(client->botid)
371         printf_mysql_query("SELECT `trigger`, `defaulttrigger`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
372     else
373         printf_mysql_query("SELECT `trigger`, `defaulttrigger`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
374     res = mysql_use();
375     row = mysql_fetch_row(res);
376     trigger = (row[0] ? row[0] : row[1]);
377     if(argument) {
378         int uaccess = getChannelAccess(user, chan);
379         if(uaccess < 500) {
380             if(isGodMode(user)) {
381                 event->flags |= CMDFLAG_OPLOG;
382             } else {
383                 reply(textclient, user, "NS_SET_TRIGGER_OWNER", chan->name);
384                 return NULL;
385             }
386         }
387         if(strlen(argument) > 15)
388             argument[15] = '\0';
389         printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `id` = '%d'", escape_string(argument), row[2]);
390         trigger = argument;
391         if(client->botid)
392             changeChannelTrigger(client->botid, chan, trigger);
393         else
394             changeBotwiseChannelTrigger(client->botid, client->clientid, chan, trigger);
395         logEvent(event);
396     }
397     if(setting) {
398         reply(textclient, user, "\002%s\002 %s", setting, trigger);
399     }
400     return trigger;
401 }
402
403 static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
404     char *value;
405     char valueBuf[MAXLEN];
406     //get current value
407     MYSQL_RES *res;
408     MYSQL_ROW row;
409     printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
410     res = mysql_use();
411     row = mysql_fetch_row(res);
412     if(row[0] == NULL) {
413         printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
414         res = mysql_use();
415         row = mysql_fetch_row(res);
416     }
417     value = row[0];
418     if(argument) {
419         //change the channel setting
420         struct ModeNode *modenode = createModeNode(NULL);
421         parseModeString(modenode, argument);
422         getFullModeString(modenode, valueBuf);
423         value = valueBuf;
424         printf_mysql_query("UPDATE `channels` SET `channel_modes` = '%s' WHERE `channel_id` = '%d'", escape_string(value), chan->channel_id);
425         //TODO: set modelock
426         freeModeNode(modenode);
427     }
428     if(setting) {
429         reply(textclient, user, "\002%s\002 %s", setting, value);
430     }
431     return value;
432 }
433
434 static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
435     char *value;
436     char tmp[64];
437     //get current value
438     MYSQL_RES *res;
439     MYSQL_ROW row;
440     printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
441     res = mysql_use();
442     row = mysql_fetch_row(res);
443     if(row[0] == NULL) {
444         printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'");
445         res = mysql_use();
446         row = mysql_fetch_row(res);
447     }
448     value = row[0];
449     if(argument) {
450         //change the channel setting
451         sprintf(tmp, "%d", atoi(argument));
452         argument = tmp;
453         printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
454         if(strcmp(argument, "0"))
455             putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument)));
456         else if(isModeSet(chan->modes, 'l'))
457             putsock(client, "MODE %s -l", chan->name);
458         value = argument;
459         logEvent(event);
460     }
461     if(setting) {
462         reply(textclient, user, "\002%s\002 %s", setting, value);
463     }
464     return value;
465 }
466
467 static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
468     char *value;
469     //get current value
470     MYSQL_RES *res;
471     MYSQL_ROW row;
472     printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
473     res = mysql_use();
474     row = mysql_fetch_row(res);
475     if(row[0] == NULL) {
476         printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'");
477         res = mysql_use();
478         row = mysql_fetch_row(res);
479     }
480     value = row[0];
481     if(argument && isGodMode(user)) {
482         //change the channel setting
483         if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
484             argument = "0";
485         } else if(!strcmp(argument, "1") || !strcmp(argument, "on") || !strcmp(argument, get_language_string(user, "NS_SET_ON"))) {
486             argument = "1";
487         } else {
488             reply(textclient, user, "NS_SET_INVALID_BOOLEAN", argument);
489             return NULL;
490         }
491         printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
492         event->flags |= CMDFLAG_OPLOG;
493         value = argument;
494         logEvent(event);
495     }
496     if(setting) {
497         reply(textclient, user, "\002%s\002 %s", setting, value);
498     }
499     return value;
500 }
501
502 static char* neonserv_cmd_set_backupbot(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
503     int backupbot;
504     //get current trigger
505     MYSQL_RES *res;
506     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);
507     res = mysql_use();
508     if(mysql_fetch_row(res))
509         backupbot = 1;
510     else 
511         backupbot = 0;
512     if(argument) {
513         //change the channel setting
514         if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
515             if(backupbot) {
516                 module_global_cmd_unregister_neonbackup(chan->name);
517                 backupbot = 0;
518             }
519         } else if(!strcmp(argument, "1") || !strcmp(argument, "on") || !strcmp(argument, get_language_string(user, "NS_SET_ON"))) {
520             if(!backupbot) {
521                 module_global_cmd_register_neonbackup(chan->name);
522                 backupbot = 1;
523             }
524         } else {
525             reply(textclient, user, "NS_SET_INVALID_BOOLEAN", argument);
526             return NULL;
527         }
528         logEvent(event);
529     }
530     if(setting) {
531         reply(textclient, user, "\002%s\002 %s", setting, (backupbot ? "1" : "0"));
532     }
533     return (backupbot ? "1" : "0");
534 }
535
536 #undef MAX_QUERY_LEN