added new multi log system
[NeonServV5.git] / src / modules / NeonServ.mod / cmd_neonserv_unvisited.c
index 5e639b2836bce8cfb861cbb1330d22610b8c9ef9..5f1572e17ee823fc4075f1ce1f8359d064bf9768 100644 (file)
@@ -1,4 +1,4 @@
-/* cmd_neonserv_unvisited.c - NeonServ v5.4
+/* cmd_neonserv_unvisited.c - NeonServ v5.6
  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
  * 
  * This program is free software: you can redistribute it and/or modify
  */
 
 #include "cmd_neonserv.h"
+#include "../botid.h"
 
 struct neonserv_cmd_unvisited_cache {
     struct ClientSocket *client, *textclient;
     struct UserNode *user;
-    int duration;
+    int duration, unregister_matches;
     int who_count, matches;
 };
 
 static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup);
-static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration);
+static void neonserv_check_unvisited(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, int duration, int unregister_matches);
+static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration, int unregister_matches);
 static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache);
+static void neonserv_cmd_unvisited_unreg(struct ClientSocket *client, char *channel);
+static TIMEQ_CALLBACK(neonserv_check_unvisited_timer);
 
 CMD_BIND(neonserv_cmd_unvisited) {
     int duration = (argc ? strToTime(user, argv[0]) : 60*60*24*7*3);
-    reply(getTextBot(), user, "NS_SEARCH_HEADER");
+    reply(textclient, user, "NS_SEARCH_HEADER");
+    int unreg = 0;
+    if(argc > 1 && !stricmp(argv[1], "unregister")) 
+        unreg = 1;
+    neonserv_check_unvisited(client, textclient, user, duration, unreg);
+}
+
+void neonserv_cmd_unvisited_init() {
+    if(!timeq_name_exists("neonserv_unvisited"))
+        timeq_add_name("neonserv_unvisited", 1200, module_id, neonserv_check_unvisited_timer, NULL);
+}
+
+static TIMEQ_CALLBACK(neonserv_check_unvisited_timer) {
+    char tmp[200];
+    char *modname = get_module_name(module_id);
+    sprintf(tmp, "modules.%s.chan_expire_freq", modname);
+    char *check_freq_str = get_string_field(tmp);
+    int check_freq;
+    if(!check_freq_str || (check_freq = strToTime(NULL, check_freq_str)) < (60*60)) {
+        timeq_add_name("neonserv_unvisited", 1800, module_id, neonserv_check_unvisited_timer, NULL);
+        return;
+    }
+    sprintf(tmp, "modules.%s.chan_expire_delay", modname);
+    char *check_expire_str = get_string_field(tmp);
+    int duration;
+    if(!check_expire_str || (duration = strToTime(NULL, check_expire_str)) < 60*60*24*7) return;
+    neonserv_check_unvisited(NULL, NULL, NULL, duration, 1);
+}
+
+static void neonserv_check_unvisited(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, int duration, int unregister_matches) {
     MYSQL_RES *res, *res2;
     MYSQL_ROW row, row2;
     struct ChanNode *channel;
     struct neonserv_cmd_unvisited_cache *cache = malloc(sizeof(*cache));
     if (!cache) {
-        perror("malloc() failed");
+        printf_log("neonserv", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
         return;
     }
     cache->client = client;
-    cache->textclient = getTextBot();
+    cache->textclient = textclient;
     cache->user = user;
     cache->duration = duration;
+    cache->unregister_matches = unregister_matches;
     cache->who_count = 1; /* small fake to prevent the cache to be freed too early */
     cache->matches = 0;
-    printf_mysql_query("SELECT `channel_id`, `channel_name`, `channel_nodelete` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid);
+    int botid;
+    if(client)
+        botid = client->botid;
+    else
+        botid = NEONSERV_BOTID;
+    printf_mysql_query("SELECT `channel_id`, `channel_name`, `channel_nodelete` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", botid);
     res = mysql_use();
     while ((row = mysql_fetch_row(res)) != NULL) {
         if(!strcmp(row[2], "1")) continue;
@@ -59,11 +98,14 @@ CMD_BIND(neonserv_cmd_unvisited) {
             channel->channel_id = atoi(row[0]);
             get_userlist_with_invisible(channel, module_id, neonserv_cmd_unvisited_userlist_lookup, cache);
         } else {
-            reply(getTextBot(), user, "%s", row[1]);
+            if(textclient)
+                reply(textclient, user, "%s", row[1]);
+            if(unregister_matches)
+                neonserv_cmd_unvisited_unreg(client, row[1]);
             cache->matches++;
         }   
     }
-    cache->who_count--; //see fix on line 46
+    cache->who_count--; //see fix on line 78
     if(cache->who_count == 0) {
         neonserv_cmd_unvisited_async2(cache);
     }
@@ -71,7 +113,7 @@ CMD_BIND(neonserv_cmd_unvisited) {
 
 static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup) {
     struct neonserv_cmd_unvisited_cache *cache = data;
-    if(neonserv_cmd_unvisited_async1(cache->client, cache->textclient, cache->user, chan, cache->duration))
+    if(neonserv_cmd_unvisited_async1(cache->client, cache->textclient, cache->user, chan, cache->duration, cache->unregister_matches))
         cache->matches++;
     cache->who_count--;
     if(cache->who_count == 0) {
@@ -79,7 +121,7 @@ static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup) {
     }
 }
 
-static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration) {
+static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration, int unregister_matches) {
     struct ChanUser *chanuser;
     MYSQL_RES *res2;
     MYSQL_ROW row2;
@@ -97,12 +139,74 @@ static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct Cli
         }
     }
     if(!active) {
-        reply(textclient, user, "%s", chan->name);
+        if(textclient)
+            reply(textclient, user, "%s", chan->name);
+        if(unregister_matches)
+            neonserv_cmd_unvisited_unreg(client, chan->name);
     }
     return !active;
 }
 
 static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache) {
-    reply(cache->textclient, cache->user, "NS_TABLE_COUNT", cache->matches);
+    if(cache->textclient)
+        reply(cache->textclient, cache->user, "NS_TABLE_COUNT", cache->matches);
     free(cache);
 }
+
+static void neonserv_cmd_unvisited_unreg(struct ClientSocket *client, char *channel) {
+    MYSQL_RES *res;
+    MYSQL_ROW row;
+    int sync_neonspam_unreg = get_int_field("General.sync_neonspam_unreg");
+    int botid;
+    if(client)
+        botid = client->botid;
+    else
+        botid = NEONSERV_BOTID;
+    printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended`, `channels`.`channel_nodelete` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), botid);
+    res = mysql_use();
+    if ((row = mysql_fetch_row(res)) == NULL) {
+        return;
+    }
+    int clientid = atoi(row[0]);
+    struct ClientSocket *bot;
+    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+        if(bot->clientid == clientid)
+            break;
+    }
+    if(!strcmp(row[3], "1")) return;
+    printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]);
+    if(bot && strcmp(row[2], "1")) {
+        putsock(bot, "PART %s :Channel unregistered.", channel);
+    }
+    if(botid == NEONSERV_BOTID && sync_neonspam_unreg) {
+        botid = NEONSPAM_BOTID;
+        printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), botid);
+        res = mysql_use();
+        if ((row = mysql_fetch_row(res)) == NULL) {
+            return;
+        }
+        clientid = atoi(row[0]);
+        for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+            if(bot->clientid == clientid)
+                break;
+        }
+        printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]);
+        if(bot && strcmp(row[2], "1")) {
+            putsock(bot, "PART %s :Channel unregistered.", channel);
+        }
+    }
+    if(botid == NEONSERV_BOTID) {
+        char setting[128];
+        sprintf(setting, "modules.%s.auto_backup_unregister", get_module_name(module_id));
+        if(get_int_field(setting))
+            module_global_cmd_unregister_neonbackup(channel);
+    }
+    char *alertchan = get_string_field("General.alertchan");
+    if(alertchan) {
+        struct ChanNode *alertchan_chan = getChanByName(alertchan);
+        struct ClientSocket *alertclient;
+        if(alertchan_chan && (alertclient = getChannelBot(alertchan_chan, 0)) != NULL) {
+            putsock(alertclient, "PRIVMSG %s :Unregistered %s (unvisited)", alertchan_chan->name, channel);
+        }
+    }
+}