From 989cb8324ec8fe9caba511d89051552638dbc776 Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 4 Jan 2012 23:40:03 +0100 Subject: [PATCH] added first helpserv functions --- Makefile.am | 2 + src/ClientSocket.h | 8 ++ src/bot_NeonHelp.c | 281 ++++++++++++++++++++++++++++++++++++++ src/bot_NeonHelp.h | 11 ++ src/cmd_neonhelp.h | 2 +- src/cmd_neonhelp_delete.c | 85 ++++++++++++ src/cmd_neonhelp_next.c | 108 +++++++++++++++ src/commands.c | 7 + src/mysqlConn.c | 19 +++ src/mysqlConn.h | 1 + 10 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 src/cmd_neonhelp_delete.c create mode 100644 src/cmd_neonhelp_next.c diff --git a/Makefile.am b/Makefile.am index 2b367d5..3403d4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -125,6 +125,8 @@ neonserv_SOURCES = src/version.c \ src/cmd_global_delbot.c \ src/cmd_global_reconnect.c \ src/cmd_global_modcmd.c \ + src/cmd_neonhelp_next.c \ + src/cmd_neonhelp_delete.c \ src/cmd_funcmds.c \ src/ConfigParser.c diff --git a/src/ClientSocket.h b/src/ClientSocket.h index a5ba352..a9d9b4b 100644 --- a/src/ClientSocket.h +++ b/src/ClientSocket.h @@ -30,6 +30,10 @@ #define SOCKET_FLAG_QUITTED 0x100 #define SOCKET_FLAG_FAST_JUMP 0x200 +#define SOCKET_HAVE_BOTCLASSVALUE1 0x10000000 +#define SOCKET_HAVE_BOTCLASSVALUE2 0x20000000 +#define SOCKET_HAVE_BOTCLASSVALUE3 0x40000000 + #define BUF_SIZ 512 struct UserNode; @@ -65,6 +69,10 @@ struct ClientSocket { int botid : 16; int clientid : 16; + void *botclassvalue1; + void *botclassvalue2; + void *botclassvalue3; + struct ClientSocket *next; }; diff --git a/src/bot_NeonHelp.c b/src/bot_NeonHelp.c index fa54af5..1ff01cc 100644 --- a/src/bot_NeonHelp.c +++ b/src/bot_NeonHelp.c @@ -31,6 +31,26 @@ #define BOTID 4 #define BOTALIAS "NeonHelp" +static const struct default_language_entry msgtab[] = { + {"NH_NOT_ON_CHAN_1", "You cannot open this request as you are not in %s."}, /* {ARGS: "#test"} */ + {"NH_NOT_ON_CHAN_2", "You cannot open this request as you are not in %s or %s."}, /* {ARGS: "test", "#test-support"} */ + {"NH_REQUEST_RECORDED", "Your message has been recorded and assigned request ID#%d A helper should contact you shortly."}, /* {ARGS: 5} */ + {"NH_REQUEST_OTHERS_0", "There are no other unhandled requests."}, + {"NH_REQUEST_OTHERS_1", "There is 1 other unhandled request."}, + {"NH_REQUEST_OTHERS_2", "There are %d other unhandled requests."}, /* {ARGS: 1337} */ + {"NH_REQUEST_FOOTER_1", "Everything you tell me until you are helped (or you leave %s) will be recorded. If you part %s, your request will be lost."}, /* {ARGS: "#test"} */ + {"NH_REQUEST_FOOTER_2", "Everything you tell me until you are helped (or you leave %s or %s) will be recorded. If you part %s or %s, your request will be lost."}, /* {ARGS: "#test", "#test-support"} */ + {"NH_NEW_REQUEST", "New request #%d by %s: %s"}, /* {ARGS: 5, "pk910", "Help, I've fallen and I can't get up!"} */ + {"NH_NEXT_NONE", "No more requests."}, + {"NH_NEXT_NOT_FOUND", "No request found."}, + {"NH_NEXT_HEADER", "$bNext request: #%d %s$b"}, /* {ARGS: 5, "pk910"} */ + {"NH_NEXT_HELPER", "Your helper for request ID#%d is %s (Current nick: %s)."}, /* {ARGS: 5, "pk910", "Skynet"} */ + {"NH_NEXT_JOIN", "Please /join %s now."}, /* {ARGS: "#test-support"} */ + {"NH_DELETED", "Your request ID#%d has been deleted."}, /* {ARGS: 5} */ + {"NH_DELETED_STAFF", "Request deleted: #%d (%s)"}, /* {ARGS: 5, "pk910"} */ + {NULL, NULL} +}; + static void neonhelp_bot_ready(struct ClientSocket *client) { MYSQL_RES *res; MYSQL_ROW row; @@ -104,6 +124,261 @@ static void start_bots() { bind_unbound_required_functions(BOTID); } +static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message); +static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup); +struct neonhelp_event_privmsg_cache { + struct ClientSocket *client; + struct UserNode *user, *target; + char *message; +}; + +static void neonhelp_event_privmsg(struct UserNode *user, struct UserNode *target, char *message) { + struct ClientSocket *client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->user == target) { + if(client->botid != BOTID) return; + break; + } + } + if(!client) return; //we got the message but we have no client that could receive it??? + if(user->flags & USERFLAG_ISAUTHED) { + neonhelp_event_privmsg_async(client, user, target, message); + } else { + struct neonhelp_event_privmsg_cache *cache = malloc(sizeof(*cache)); + if(!cache) return; + cache->client = client; + cache->user = user; + cache->target = target; + cache->message = strdup(message); + get_userauth(user, neonhelp_event_privmsg_nick_lookup, cache); + } +} + +static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup) { + struct neonhelp_event_privmsg_cache *cache = data; + neonhelp_event_privmsg_async(cache->client, cache->user, cache->target, cache->message); + free(cache->message); + free(cache); +} + +static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message) { + MYSQL_RES *res; + MYSQL_ROW row, row2; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int caccess = 0; + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + if(caccess) return; //ignore messages from supporters + } + //check if the user is in one of the bot's channels + struct ChanUser *chanuser; + struct ChanNode *chan; + for(chanuser = getUserChannels(target, NULL); chanuser; chanuser = getUserChannels(target, chanuser)) { + chan = chanuser->chan; + if((!stricmp(chan->name, row[0]) || (row[1] && !stricmp(chan->name, row[1]))) && isUserOnChan(user, chan)) + break; + } + if(!chanuser) { + if(row[1]) + reply(client, user, "NH_NOT_ON_CHAN_2", row[0], row[1]); + else + reply(client, user, "NH_NOT_ON_CHAN_1", row[0]); + return; + } + //check if there is already a support request + int others = 0; + if(client->flags & SOCKET_HAVE_HELPNODE) { + struct NeonHelpNode *helpnode; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == user) { + //simply append the message to the database + printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = %d", helpnode->suppid); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + char *old_msg = escape_string(row2[0]); + char *new_msg = escape_string(message); + printf_long_mysql_query(1024 + strlen(old_msg) + strlen(new_msg), "UPDATE `helpserv_requests` SET `text` = '%s\n%s' WHERE `id` = %d", old_msg, new_msg, helpnode->suppid); + } + return; + } + others++; + } + } + //add new request + struct NeonHelpNode *helpnode = malloc(sizeof(*helpnode)); + if(!helpnode) return; + helpnode->user = user; + helpnode->status = 0; + printf_mysql_query("INSERT INTO `helpserv_requests` (`host`, `hand`, `nick`, `status`, `supporter`, `time`, `text`) VALUES ('%s@%s', '%s', '%s', '0', '-1', UNIX_TIMESTAMP(), '%s')", escape_string(user->ident), escape_string(user->host), ((user->flags & USERFLAG_ISAUTHED) ? escape_string(user->auth) : "*"), escape_string(user->nick), escape_string(message)); + helpnode->suppid = (int) mysql_insert_id(mysql_conn); + helpnode->next = ((client->flags & SOCKET_HAVE_HELPNODE) ? client->botclass_helpnode : NULL); + client->botclass_helpnode = helpnode; + client->flags |= SOCKET_HAVE_HELPNODE; + //build the user reply... + char user_reply[MAXLEN]; + int user_reply_pos = 0; + char reply_buff[MAXLEN]; + //1st part: NH_REQUEST_RECORDED + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_RECORDED", helpnode->suppid)); + user_reply_pos += strlen(reply_buff); + //2nd part: NH_REQUEST_OTHERS_0 / NH_REQUEST_OTHERS_1 / NH_REQUEST_OTHERS_2 + user_reply[user_reply_pos++] = ' '; + if(others <= 1) + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, (others ? "NH_REQUEST_OTHERS_1" : "NH_REQUEST_OTHERS_0"))); + else + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_OTHERS_2", others)); + user_reply_pos += strlen(reply_buff); + //3th part: NH_REQUEST_FOOTER_1 / NH_REQUEST_FOOTER_2 + user_reply[user_reply_pos++] = ' '; + if(row[1]) + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_2", row[0], row[1])); + else + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_1", row[0])); + user_reply_pos += strlen(reply_buff); + reply(client, user, "%s", user_reply); + //sent a message to the internal channel / onotice to supp channel + build_language_string(user, reply_buff, "NH_NEW_REQUEST", helpnode->suppid, user->nick, message); + if(row[2]) { + putsock(client, "PRIVMSG %s :%s", row[2], reply_buff); + } else { + putsock(client, "NOTICE @%s :%s", row[0], reply_buff); + } +} + +static void destroy_support_request(struct ClientSocket *client, struct NeonHelpNode *helpnode, int reply) { + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `id` = %d", helpnode->suppid); + if(reply) { + reply(client, helpnode->user, "NH_DELETED", helpnode->suppid); + } + free(helpnode); +} + +static void neonhelp_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { + struct ClientSocket *client; + MYSQL_RES *res; + MYSQL_ROW row; + struct ChanNode *support, *public; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target->user) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) continue; + support = getChanByName(row[0]); + public = (row[1] ? getChanByName(row[1]) : NULL); + if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 1); + } + } + } +} + +static void neonhelp_event_part(struct ChanUser *target, char *reason) { + struct ClientSocket *client; + MYSQL_RES *res; + MYSQL_ROW row; + struct ChanNode *support, *public; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target->user) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) continue; + support = getChanByName(row[0]); + public = (row[1] ? getChanByName(row[1]) : NULL); + if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 1); + } + } + } +} + +static void neonhelp_event_quit(struct UserNode *target, char *reason) { + struct ClientSocket *client; + MYSQL_RES *res; + MYSQL_ROW row; + struct ChanNode *support, *public; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 0); + } + } +} + void init_NeonHelp() { set_bot_alias(BOTID, BOTALIAS); @@ -111,8 +386,14 @@ void init_NeonHelp() { //register events bind_bot_ready(neonhelp_bot_ready); + bind_privmsg(neonhelp_event_privmsg); + bind_part(neonhelp_event_part); + bind_kick(neonhelp_event_kick); + bind_quit(neonhelp_event_quit); set_trigger_callback(BOTID, neonhelp_trigger_callback); + + register_default_language_table(msgtab); } void loop_NeonHelp() { diff --git a/src/bot_NeonHelp.h b/src/bot_NeonHelp.h index da6c422..52d6389 100644 --- a/src/bot_NeonHelp.h +++ b/src/bot_NeonHelp.h @@ -19,6 +19,17 @@ #include "main.h" +/* definition for ClientSocket struct */ +#define botclass_helpnode botclassvalue1 +#define SOCKET_HAVE_HELPNODE SOCKET_HAVE_BOTCLASSVALUE1 + +struct NeonHelpNode { + struct UserNode *user; + int suppid; + char status; + struct NeonHelpNode *next; +}; + void init_NeonHelp(); void loop_NeonHelp(); void free_NeonHelp(); diff --git a/src/cmd_neonhelp.h b/src/cmd_neonhelp.h index 5a73a62..5f61657 100644 --- a/src/cmd_neonhelp.h +++ b/src/cmd_neonhelp.h @@ -19,6 +19,6 @@ #include "main.h" #include "modcmd.h" - +CMD_BIND(neonhelp_cmd_next); #endif \ No newline at end of file diff --git a/src/cmd_neonhelp_delete.c b/src/cmd_neonhelp_delete.c new file mode 100644 index 0000000..3f589d5 --- /dev/null +++ b/src/cmd_neonhelp_delete.c @@ -0,0 +1,85 @@ +/* cmd_neonhelp_delete.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* argv[0] suppid +*/ + +CMD_BIND(neonhelp_cmd_delete) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { + reply(getTextBot(), user, "NH_NEXT_NONE"); + return; + } + struct NeonHelpNode *helpnode, *next_helpnode = NULL, *prev_helpnode = NULL; + int lowest_id = -1; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(atoi(argv[0]) == helpnode->suppid) { + next_helpnode = helpnode; + break; + } else + prev_helpnode = helpnode; + } + if(!next_helpnode) { + reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); + return; + } + char sendbuf[MAXLEN]; + reply(client, next_helpnode->user, "NH_DELETED", next_helpnode->suppid); + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `id` = '%d'", next_helpnode->suppid); + if(prev_helpnode) + prev_helpnode->next = next_helpnode->next; + else + client->botclass_helpnode = next_helpnode->next; + reply(getTextBot(), user, "NH_DELETED_STAFF", next_helpnode->suppid, next_helpnode->user->nick); + free(next_helpnode); +} diff --git a/src/cmd_neonhelp_next.c b/src/cmd_neonhelp_next.c new file mode 100644 index 0000000..666b1a5 --- /dev/null +++ b/src/cmd_neonhelp_next.c @@ -0,0 +1,108 @@ +/* cmd_neonhelp_next.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* argv[0] (optional) suppid +*/ + +CMD_BIND(neonhelp_cmd_next) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { + reply(getTextBot(), user, "NH_NEXT_NONE"); + return; + } + struct NeonHelpNode *helpnode, *next_helpnode = NULL; + int lowest_id = -1; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->status == 0) { + if(argc) { + if(atoi(argv[0]) == helpnode->suppid) { + next_helpnode = helpnode; + break; + } + } else { + if(helpnode->suppid < lowest_id || lowest_id == -1) { + lowest_id = helpnode->suppid; + next_helpnode = helpnode; + } + } + } + } + if(!next_helpnode) { + reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); + return; + } + printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = '%d'", next_helpnode->suppid); + res = mysql_use(); + if (!(row2 = mysql_fetch_row(res))) return; + reply(getTextBot(), user, "NH_NEXT_HEADER", next_helpnode->suppid, next_helpnode->user->nick); + char *a, *b = row2[0]; + do { + a = strstr("\n", b); + if(a) *a = '\0'; + reply(getTextBot(), user, " %s", b); + if(a) { + *a = '\n'; + b = a+1; + } + } while(a); + if(row[1]) + putsock(client, "INVITE %s %s", next_helpnode->user->nick, row[0]); + else + putsock(client, "MODE %s +v %s", row[0], next_helpnode->user->nick); + char sendbuf1[MAXLEN]; + char sendbuf2[MAXLEN]; + char *join_now = (row[1] ? build_language_string(user, sendbuf2, "NH_NEXT_JOIN", row[1]) : ""); + putsock(client, "PRIVMSG %s :%s %s", next_helpnode->user->nick, build_language_string(user, sendbuf1, "NH_NEXT_HELPER", next_helpnode->suppid, user->auth, user->nick), join_now); + next_helpnode->status = 1; + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '1' WHERE `id` = '%d'", next_helpnode->suppid); +} diff --git a/src/commands.c b/src/commands.c index 533b5ab..5ea34ec 100644 --- a/src/commands.c +++ b/src/commands.c @@ -154,6 +154,13 @@ void register_commands() { USER_COMMAND("cookie", funcmd_cookie, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); #undef USER_COMMAND + //NeonHelp Commands + register_command_alias(4, "NeonHelp"); + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(2, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) + // NAME FUNCTION PARAMS PRIVS FLAGS + USER_COMMAND("next", neonhelp_cmd_next, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("delete", neonhelp_cmd_delete, 1, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + #undef USER_COMMAND } \ No newline at end of file diff --git a/src/mysqlConn.c b/src/mysqlConn.c index 75bb426..d2430f0 100644 --- a/src/mysqlConn.c +++ b/src/mysqlConn.c @@ -203,6 +203,25 @@ void printf_mysql_query(const char *text, ...) { } } +void printf_long_mysql_query(int len, const char *text, ...) { + va_list arg_list; + char queryBuf[len]; + int pos; + queryBuf[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(queryBuf, len - 2, text, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (len - 2)) pos = len - 2; + queryBuf[pos] = '\0'; + printf("MySQL: %s\n", queryBuf); + if(mysql_query(mysql_conn, queryBuf)) { + check_mysql(); + if(mysql_query(mysql_conn, queryBuf)) { + show_mysql_error(); + } + } +} + char* escape_string(const char *str) { struct escaped_string *escapedstr = malloc(sizeof(*escapedstr)); if (!escapedstr) { diff --git a/src/mysqlConn.h b/src/mysqlConn.h index 4e11d8c..c5152d2 100644 --- a/src/mysqlConn.h +++ b/src/mysqlConn.h @@ -32,6 +32,7 @@ void init_mysql(char *host, int port, char *user, char *pass, char *base); void free_mysql(); void show_mysql_error(); void printf_mysql_query(const char *text, ...) PRINTF_LIKE(1, 2); +void printf_long_mysql_query(int len, const char *text, ...) PRINTF_LIKE(2, 3); char* escape_string(const char *str); #endif \ No newline at end of file -- 2.20.1