-/* cmd_neonserv_unvisited.c - NeonServ v5.3
+/* cmd_neonserv_unvisited.c - NeonServ v5.4
* 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");
+ int unreg = 0;
+ if(argc > 1 && !stricmp(argv[1], "unregister"))
+ unreg = 1;
+ neonserv_check_unvisited(client, getTextBot(), 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;
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;
if(channel) {
cache->who_count++;
channel->channel_id = atoi(row[0]);
- get_userlist_with_invisible(channel, neonserv_cmd_unvisited_userlist_lookup, cache);
+ 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);
}
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) {
}
}
-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;
}
}
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);
+ }
+ }
+ 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);
+ }
+ }
+}