Another year is about to end... So we have to update these damn copyright information :P
[NeonServV5.git] / src / cmd_funcmds.c
index d4b2642fa63ba1ac33fb90b4f7a9caa431565006..4cf6c9062f66a7d170820b5df5157d6a894c798c 100644 (file)
@@ -1,5 +1,5 @@
-/* cmd_funcmds.c - NeonServ v5.2
- * Copyright (C) 2011  Philipp Kreil (pk910)
+/* cmd_funcmds.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
 #include "UserNode.h"
 #include "ChanNode.h"
 #include "lang.h"
+#include "tools.h"
+#include "DBHelper.h"
 
 static const struct default_language_entry msgtab[] = {
     {"FUN_DICE", "$b%s$b: A $b%d$b shows on the %d-sided die."}, /* {ARGS: "TestUser", 5, 6} */
     {"FUN_DICE_NUM", "I do not understand $b%s$b. Please use a single number above 1."}, /* {ARGS: "bla"} */
+    {"FUN_8BALL", "$b%s$b: %s"}, /* {ARGS: "TestUser", "Not a chance."} */
+    {"FUN_8BALL_REPLIES", "Not a chance.|In your dreams.|Absolutely!|Could be, could be.|No!"},
+    {"FUN_COOKIE", "gives %1$s a very big chocolate cookie. %1$s has got %2$d cookies until now (%3$d in this channel)."}, /* {ARGS: "TestUser", 20, 50} */
     {NULL, NULL}
 };
 
 void init_funcmds() {
     register_default_language_table(msgtab);
+    srand(time(NULL));
 }
 
 struct current_funcmd_header {
@@ -62,21 +68,30 @@ current_funcmd.chan = chan; \
         current_funcmd.send_notice = 0; \
 }
 
-static void funcmd_reply(const char *text, ...) {
+#define REPLYTYPE_NORMAL 0
+#define REPLYTYPE_ACTION 1
+static void funcmd_reply(const char *text, int type, ...) {
+    if (!(current_funcmd.client->flags & SOCKET_FLAG_CONNECTED)) return;
     const char *reply_format = get_language_string(current_funcmd.user, text);
     if(reply_format)
         text = reply_format;
     char formatBuf[MAXLEN];
-    if(current_funcmd.send_notice)
-        sprintf(formatBuf, "NOTICE %s :%s", current_funcmd.user->nick, text);
-    else
-        sprintf(formatBuf, "PRIVMSG %s :%s", current_funcmd.chan->name, text);
+    if(current_funcmd.send_notice) {
+        if(type == REPLYTYPE_ACTION)
+            sprintf(formatBuf, "NOTICE %s :%s %s", current_funcmd.user->nick, current_funcmd.client->user->nick, text);
+        else
+            sprintf(formatBuf, "NOTICE %s :%s", current_funcmd.user->nick, text);
+    } else {
+        if(type == REPLYTYPE_ACTION)
+            sprintf(formatBuf, "PRIVMSG %s :\001ACTION %s\001", current_funcmd.chan->name, text);
+        else
+            sprintf(formatBuf, "PRIVMSG %s :%s", current_funcmd.chan->name, text);
+    }
     va_list arg_list;
     char sendBuf[MAXLEN];
     int pos;
-    if (!(current_funcmd.client->flags & SOCKET_FLAG_CONNECTED)) return;
     sendBuf[0] = '\0';
-    va_start(arg_list, text);
+    va_start(arg_list, type);
     pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list);
     va_end(arg_list);
     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
@@ -85,14 +100,57 @@ static void funcmd_reply(const char *text, ...) {
     write_socket(current_funcmd.client, sendBuf, pos+1);
 }
 
+static char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) {
+    char *uname = "";
+    int cid = 0;
+    MYSQL_RES *res;
+    MYSQL_ROW row;
+    if(user) {
+        uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*");
+    }
+    if(chan) {
+        loadChannelSettings(chan);
+        if(chan->flags & CHANFLAG_CHAN_REGISTERED)
+            cid = chan->channel_id;
+    }
+    printf_mysql_query("SELECT `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting));
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) != NULL) {
+        return row[0];
+    } else
+        return NULL;
+}
+
+static void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value) {
+    char *uname = "";
+    int cid = 0;
+    MYSQL_RES *res;
+    MYSQL_ROW row;
+    if(user) {
+        uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*");
+    }
+    if(chan) {
+        loadChannelSettings(chan);
+        if(chan->flags & CHANFLAG_CHAN_REGISTERED)
+            cid = chan->channel_id;
+    }
+    printf_mysql_query("SELECT `id`, `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting));
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) != NULL) {
+        if(strcmp(row[1], value))
+            printf_mysql_query("UPDATE `fundata` SET `value` = '%s' WHERE `id` = '%s'", escape_string(value), row[0]);
+    } else
+        printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value));
+}
+
 CMD_BIND(funcmd_ping) {
     FUNCMD_HEADER;
-    funcmd_reply("\002%s\002: Pong!", user->nick);
+    funcmd_reply("\002%s\002: Pong!", REPLYTYPE_NORMAL, user->nick);
 }
 
 CMD_BIND(funcmd_pong) {
     FUNCMD_HEADER;
-    funcmd_reply("\002%s\002: Ping!", user->nick);
+    funcmd_reply("\002%s\002: Ping!", REPLYTYPE_NORMAL, user->nick);
 }
 
 CMD_BIND(funcmd_dice) {
@@ -100,7 +158,59 @@ CMD_BIND(funcmd_dice) {
     int max = atoi(argv[0]);
     if(max > 1) {
         int val = (rand() % max) + 1;
-        funcmd_reply("FUN_DICE", user->nick, val, max);
+        funcmd_reply("FUN_DICE", REPLYTYPE_NORMAL, user->nick, val, max);
     } else
-        funcmd_reply("FUN_DICE_NUM", argv[0]);
+        funcmd_reply("FUN_DICE_NUM", REPLYTYPE_NORMAL, argv[0]);
+}
+
+CMD_BIND(funcmd_8ball) {
+    FUNCMD_HEADER;
+    char *message = merge_argv(argv, 0, argc);
+    const char *const_replies = get_language_string(current_funcmd.user, "FUN_8BALL_REPLIES");
+    char replies[MAXLEN];
+    int i, reply_count = 1;
+    for(i = 0; const_replies[i]; i++) {
+        if(const_replies[i] == '|')
+            reply_count++;
+        replies[i] = const_replies[i];
+    }
+    replies[i] = '\0';
+    unsigned int crc32_val = (crc32(message)) % reply_count;
+    char *creply = (crc32_val == 0 ? replies : NULL);
+    reply_count = 0;
+    for(i = 0; replies[i]; i++) {
+        if(replies[i] == '|') {
+            if(creply) {
+                replies[i] = '\0';
+                break;
+            } else {
+                reply_count++;
+                if(reply_count == crc32_val) {
+                    creply = &replies[i+1];
+                }
+            }
+        }
+    }
+    if(creply) {
+        funcmd_reply("FUN_8BALL", REPLYTYPE_NORMAL, user->nick, creply);
+    }
+}
+
+CMD_BIND(funcmd_cookie) {
+    FUNCMD_HEADER;
+    if(argc) {
+        if(!(user = getUserByNick(argv[0])))
+            reply(current_funcmd.client, current_funcmd.user, "NS_USER_UNKNOWN", argv[0]);
+    }
+    char *tmp;
+    int user_count = ((tmp = getSetting(user, chan, "cookies")) ? atoi(tmp) : 0);
+    int total_count = ((tmp = getSetting(user, NULL, "cookies")) ? atoi(tmp) : 0);
+    user_count++;
+    total_count++;
+    char buf[10];
+    sprintf(buf, "%d", user_count);
+    setSetting(user, chan, "cookies", buf);
+    sprintf(buf, "%d", total_count);
+    setSetting(user, NULL, "cookies", buf);
+    funcmd_reply("FUN_COOKIE", REPLYTYPE_ACTION, user->nick, total_count, user_count);
 }