2 typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument);
3 static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int setting, char *argument);
4 static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument);
5 static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument);
6 static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument);
7 static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument);
9 #define NS_VALID_FUNCTION 0x01
10 #define NS_VALID_STRING 0x02
11 #define NS_VALID_ACCESS 0x04
12 #define NS_VALID_NO501 0x08
13 #define NS_VALID_OPTIONS 0x10
14 #define NS_VALID_NUMERIC 0x20
15 #define NS_VALID_BOOLEAN 0x40
17 #define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
18 #define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */
22 const char *chanfield;
25 } channel_settings[] = {
26 {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger},
27 {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL},
28 {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL},
29 {"GREETING", "channel_greeting", NS_VALID_STRING, NULL},
30 {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL},
31 {"USERINFO", "channel_userinfo", NS_VALID_ACCESS, NULL},
32 {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS, NULL},
33 {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes},
34 {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL},
35 {"GIVEOPS", "channel_getop", NS_VALID_ACCESS, NULL},
36 {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS, NULL},
37 {"ENFOPS", "channel_canop", NS_VALID_ACCESS, NULL},
38 {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS, NULL},
39 {"KICK", "channel_cankick", NS_VALID_ACCESS, NULL},
40 {"BAN", "channel_canban", NS_VALID_ACCESS, NULL},
41 {"STATICBAN", "channel_staticban", NS_VALID_ACCESS, NULL},
42 {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL},
43 {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL},
44 {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL},
45 {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS, NULL},
46 {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS, NULL},
47 {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501, NULL},
48 {"ADDUSER", "channel_canadd", NS_VALID_ACCESS, NULL},
49 {"DELUSER", "channel_candel", NS_VALID_ACCESS, NULL},
50 {"CLVL", "channel_canclvl", NS_VALID_ACCESS, NULL},
51 {"RESYNC", "channel_canresync", NS_VALID_ACCESS, NULL},
52 {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS, NULL},
53 {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL},
54 {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
55 {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL},
56 {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
57 {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
58 {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"},
59 {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
60 {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
64 #define MAX_QUERY_LEN 1024
65 static CMD_BIND(neonserv_cmd_set) {
67 if(argc && !strcmp(argv[0], "defaults")) {
68 //reset channel settings
69 int uaccess = getChannelAccess(user, chan, 1);
71 reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name);
76 static char defaultskey[16];
77 for(tmp = user->auth; *tmp; tmp++)
78 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
79 for(tmp = chan->name; *tmp; tmp++)
80 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
81 sprintf(defaultskey, "%08x", seed);
82 if(argc > 1 && !strcmp(argv[1], defaultskey)) {
83 char query[MAX_QUERY_LEN];
87 while(channel_settings[i].setting) {
88 if(channel_settings[i].chanfield)
89 querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield);
93 query[querypos-2] = '\0';
95 printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id);
96 reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name);
98 reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
100 } else if(argc && strcmp(argv[0], "help")) {
101 //find the correct command
104 char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
105 while(channel_settings[i].setting) {
106 if(!stricmp(channel_settings[i].setting, argv[0])) {
108 if(channel_settings[i].valid & NS_VALID_FUNCTION) {
109 neonserv_cmd_set_function *func = channel_settings[i].parameter;
110 func(client, user, chan, channel_settings[i].setting, args);
112 neonserv_cmd_set_setting(client, user, chan, i, args);
121 reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
125 char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64];
127 MYSQL_RES *res, *defaults_res;
128 MYSQL_ROW row, defaults;
132 while(channel_settings[i].setting) {
133 if(channel_settings[i].chanfield)
134 querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
137 table = table_init(2, i, 0);
138 table_set_bold(table, 0, 1);
139 printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query);
140 defaults_res = mysql_use();
141 defaults = mysql_fetch_row(defaults_res);
142 printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id);
144 row = mysql_fetch_row(res);
147 reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
148 while(channel_settings[i].setting) {
149 if(channel_settings[i].chanfield) {
151 org_value = (row[j] ? row[j] : defaults[j]);
152 } else if(channel_settings[i].valid & NS_VALID_FUNCTION) {
153 neonserv_cmd_set_function *func = channel_settings[i].parameter;
154 org_value = func(client, user, chan, NULL, NULL);
158 if(channel_settings[i].valid & NS_VALID_BOOLEAN) {
159 if(!strcmp(value, "0"))
160 value = get_language_string(user, "NS_SET_OFF");
162 value = get_language_string(user, "NS_SET_ON");
164 strcpy(query, value);
165 querypos = strlen(query);
166 if(channel_settings[i].valid & NS_HAS_OPT) {
167 sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value);
168 tmp = get_language_string(user, nameBuf);
170 querypos += sprintf(query+querypos, " - %s", tmp);
173 if(argc && channel_settings[i].valid & NS_HAS_HELP) {
174 sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting);
175 tmp = get_language_string(user, nameBuf);
177 querypos += sprintf(query+querypos, " - %s", tmp);
180 content[0] = (char*)channel_settings[i].setting;
182 table_add(table, content);
185 char **table_lines = table_end(table);
186 for(i = 0; i < table->entrys; i++) {
187 reply(getTextBot(), user, table_lines[i]);
193 static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int setting, char *args) {
200 printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id);
202 row = mysql_fetch_row(res);
204 printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield);
206 row = mysql_fetch_row(res);
210 //change the channel setting
211 //check the new argument
212 int valid = channel_settings[setting].valid;
213 if(valid & NS_VALID_STRING) {
214 if(!strcmp(args, "*")) {
218 if(valid & NS_VALID_ACCESS) {
219 int caccess = atoi(args);
220 int max = ((valid & NS_VALID_NO501) ? 500 : 501);
221 if(caccess < 0 || caccess > max) {
222 reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
225 int uaccess = getChannelAccess(user, chan, 1);
226 if(uaccess == 500) uaccess++;
227 if(atoi(value) > uaccess) {
228 reply(getTextBot(), user, "NS_SET_CANNOT_SET");
231 if(caccess > uaccess) {
232 reply(getTextBot(), user, "NS_SET_BADLEVEL");
236 if(valid & NS_VALID_OPTIONS) {
237 int options = atoi((char *) channel_settings[setting].parameter);
238 int coption = atoi(args);
239 if(coption < 0 || coption >= options) {
240 reply(getTextBot(), user, "NS_SET_INVALID_OPTION", args);
243 if(valid & NS_HAS_OPT) {
244 for(i = 0; i < options; i++) {
245 sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i);
246 reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
249 for(i = 0; i < options; i++) {
250 nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
253 nameBuf[nameBufPos-2] = '\0';
254 reply(getTextBot(), user, nameBuf);
260 if(valid & NS_VALID_NUMERIC) {
261 sprintf(nameBuf, "%d", atoi(args));
264 if(valid & NS_VALID_BOOLEAN) {
265 if(!strcmp(args, "0") || !strcmp(args, "off") || !strcmp(args, get_language_string(user, "NS_SET_OFF"))) {
267 } else if(!strcmp(args, "0") || !strcmp(args, "off") || !strcmp(args, get_language_string(user, "NS_SET_OFF"))) {
270 reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args);
276 printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id);
278 reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value);
279 if(channel_settings[setting].valid & NS_HAS_HELP) {
280 sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting);
281 reply(getTextBot(), user, " %s", get_language_string(user, nameBuf));
285 static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) {
287 //get current trigger
291 printf_mysql_query("SELECT `trigger` FROM `bot_channels` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
293 row = mysql_fetch_row(res);
296 int uaccess = getChannelAccess(user, chan, 1);
298 reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name);
301 if(strlen(argument) > 15)
303 printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
305 changeChannelTrigger(client->botid, chan, trigger);
308 reply(getTextBot(), user, "\002%s\002 %s", setting, trigger);
313 static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) {
319 printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
321 row = mysql_fetch_row(res);
323 printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
325 row = mysql_fetch_row(res);
329 //change the channel setting
330 //TODO: parse, check and set modelock
333 reply(getTextBot(), user, "\002%s\002 %s", setting, value);
338 static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) {
345 printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
347 row = mysql_fetch_row(res);
349 printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'");
351 row = mysql_fetch_row(res);
355 //change the channel setting
356 sprintf(tmp, "%d", atoi(argument));
358 printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
359 if(strcmp(argument, "0"))
360 putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument)));
361 else if(isModeSet(chan, 'l'))
362 putsock(client, "MODE %s -l", chan->name);
365 reply(getTextBot(), user, "\002%s\002 %s", setting, value);
370 static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) {
376 printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
378 row = mysql_fetch_row(res);
380 printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'");
382 row = mysql_fetch_row(res);
385 if(argument && isGodMode(user)) {
386 //change the channel setting
387 if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
389 } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
392 reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
395 printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
398 reply(getTextBot(), user, "\002%s\002 %s", setting, value);