X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fbot_NeonHelp.c;h=1ff01ccf2a30b7f267a1cba58e839d134747c06b;hb=989cb8324ec8fe9caba511d89051552638dbc776;hp=fa54af5b553d73782f3596169b25eee567e47eec;hpb=3dc533e1df504f9d0158a76e5cb1b906ec33b0ed;p=NeonServV5.git 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() {