summaryrefslogtreecommitdiff
path: root/modules/stats
diff options
context:
space:
mode:
Diffstat (limited to 'modules/stats')
-rw-r--r--modules/stats/cs_fantasy_stats.cpp179
-rw-r--r--modules/stats/cs_fantasy_top.cpp191
-rw-r--r--modules/stats/irc2sql/CMakeLists.txt2
-rw-r--r--modules/stats/irc2sql/irc2sql.cpp285
-rw-r--r--modules/stats/irc2sql/irc2sql.h77
-rw-r--r--modules/stats/irc2sql/tables.cpp382
-rw-r--r--modules/stats/irc2sql/utils.cpp61
-rw-r--r--modules/stats/m_chanstats.cpp630
8 files changed, 0 insertions, 1807 deletions
diff --git a/modules/stats/cs_fantasy_stats.cpp b/modules/stats/cs_fantasy_stats.cpp
deleted file mode 100644
index 43f7eb04a..000000000
--- a/modules/stats/cs_fantasy_stats.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Chanstats core functions
- *
- * (C) 2003-2014 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-#include "modules/sql.h"
-
-class MySQLInterface : public SQL::Interface
-{
- public:
- MySQLInterface(Module *o) : SQL::Interface(o) { }
-
- void OnResult(const SQL::Result &r) anope_override
- {
- }
-
- void OnError(const SQL::Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "Chanstats: Error executing query: " << r.GetError();
- }
-};
-
-
-class CommandCSStats : public Command
-{
- public:
- CommandCSStats(Module *creator) : Command (creator, "chanserv/stats", 0, 2)
- {
- this->SetDesc(_("Displays your Channel Stats"));
- this->SetSyntax(_("[\037channel\037] [\037nick\037]"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-class CommandCSGStats : public Command
-{
- public:
- CommandCSGStats(Module *creator) : Command (creator, "chanserv/gstats", 0, 2)
- {
- this->SetDesc(_("Displays your Global Stats"));
- this->SetSyntax(_("\037nick\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-
-class CSStats;
-static CSStats *me;
-class CSStats : public Module
-{
- CommandCSStats commandcsstats;
- CommandCSGStats commandcsgstats;
- ServiceReference<SQL::Provider> sql;
- MySQLInterface sqlinterface;
- Anope::string prefix;
- public:
- CSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcsstats(this), commandcsgstats(this), sql("", ""), sqlinterface(this)
- {
- me = this;
-
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- prefix = conf->GetModule("m_chanstats")->Get<const Anope::string>("prefix");
- if (prefix.empty())
- prefix = "anope_";
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("m_chanstats")->Get<const Anope::string>("engine"));
- }
-
- SQL::Result RunQuery(const SQL::Query &query)
- {
- if (!this->sql)
- throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
-
- SQL::Result res = this->sql->RunQuery(query);
- if (!res.GetError().empty())
- throw SQL::Exception(res.GetError());
- return res;
- }
-
- void DoStats(CommandSource &source, const bool is_global, const std::vector<Anope::string> &params)
- {
- Anope::string display, channel;
-
- /*
- * possible parameters are:
- * stats [channel] [nick]
- * stats [channel]
- * stats [nick]
- * stats
- */
-
- switch (params.size())
- {
- case 2:
- channel = params[0];
- display = params[1];
- break;
- case 1:
- if (params[0][0] == '#')
- channel = params[0];
- else
- {
- if (NickAlias *na = NickAlias::Find(params[0]))
- display = na->nc->display;
- else
- {
- source.Reply(_("%s not found."), params[0].c_str());
- return;
- }
- }
- break;
- }
-
- if (display.empty())
- display = source.nc->display;
-
- try
- {
- SQL::Query query;
- query = "SELECT letters, words, line, smileys_happy+smileys_sad+smileys_other as smileys,"
- "actions FROM `" + prefix + "chanstats` "
- "WHERE `nick` = @nick@ AND `chan` = @channel@ AND `type` = 'total';";
- if (is_global || channel.empty())
- query.SetValue("channel", "");
- else
- query.SetValue("channel", channel);
- query.SetValue("nick", display);
- SQL::Result res = this->RunQuery(query);
-
- if (res.Rows() > 0)
- {
- if (is_global)
- source.Reply(_("Network stats for %s:"), display.c_str());
- else
- source.Reply(_("Channel stats for %s on %s:"), display.c_str(), channel.c_str());
-
- source.Reply(_("letters: %s, words: %s, lines: %s, smileys %s, actions: %s"),
- res.Get(0, "letters").c_str(), res.Get(0, "words").c_str(),
- res.Get(0, "line").c_str(), res.Get(0, "smileys").c_str(),
- res.Get(0, "actions").c_str());
- }
- else
- source.Reply(_("No stats for %s."), display.c_str());
- }
- catch (const SQL::Exception &ex)
- {
- Log(LOG_DEBUG) << ex.GetReason();
- }
-
- }
-};
-
-void CommandCSStats::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoStats(source, false, params);
-}
-
-void CommandCSGStats::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoStats(source, true, params);
-}
-
-MODULE_INIT(CSStats)
-
diff --git a/modules/stats/cs_fantasy_top.cpp b/modules/stats/cs_fantasy_top.cpp
deleted file mode 100644
index f747bebd8..000000000
--- a/modules/stats/cs_fantasy_top.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Chanstats core functions
- *
- * (C) 2003-2014 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-#include "modules/sql.h"
-
-class MySQLInterface : public SQL::Interface
-{
- public:
- MySQLInterface(Module *o) : SQL::Interface(o) { }
-
- void OnResult(const SQL::Result &r) anope_override
- {
- }
-
- void OnError(const SQL::Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "Chanstats: Error executing query: " << r.GetError();
- }
-};
-
-class CommandCSTop : public Command
-{
- public:
- CommandCSTop(Module *creator) : Command (creator, "chanserv/top", 0, 2)
- {
- this->SetDesc(_("Displays the top 3 users of a channel"));
- this->SetSyntax(_("\037channel\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-class CommandCSTop10 : public Command
-{
- public:
- CommandCSTop10(Module *creator) : Command (creator, "chanserv/top10", 0, 2)
- {
- this->SetDesc(_("Displays the top 10 users of a channel"));
- this->SetSyntax(_("\037channel\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-class CommandCSGTop : public Command
-{
- public:
- CommandCSGTop(Module *creator) : Command (creator, "chanserv/gtop", 0, 1)
- {
- this->SetDesc(_("Displays the top 3 users of the network"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-class CommandCSGTop10 : public Command
-{
- public:
- CommandCSGTop10(Module *creator) : Command (creator, "chanserv/gtop10", 0, 1)
- {
- this->SetDesc(_("Displays the top 10 users of the network"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params);
-};
-
-
-class CSTop;
-static CSTop *me;
-class CSTop : public Module
-{
- CommandCSTop commandcstop;
- CommandCSGTop commandcsgtop;
- CommandCSTop10 commandcstop10;
- CommandCSGTop10 commandcsgtop10;
- ServiceReference<SQL::Provider> sql;
- MySQLInterface sqlinterface;
- Anope::string prefix;
-
- public:
- CSTop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcstop(this), commandcsgtop(this), commandcstop10(this), commandcsgtop10(this), sql("", ""),
- sqlinterface(this)
- {
- me = this;
-
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- prefix = conf->GetModule("m_chanstats")->Get<const Anope::string>("prefix");
- if (prefix.empty())
- prefix = "anope_";
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("m_chanstats")->Get<const Anope::string>("engine"));
- }
-
- SQL::Result RunQuery(const SQL::Query &query)
- {
- if (!this->sql)
- throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
-
- SQL::Result res = sql->RunQuery(query);
- if (!res.GetError().empty())
- throw SQL::Exception(res.GetError());
- return res;
- }
-
- void DoTop(CommandSource &source, const std::vector<Anope::string> &params, bool is_global, int limit = 1)
- {
-
- Anope::string channel;
- if (!params.empty())
- channel = params[0];
- else if (source.c && source.c->ci)
- channel = source.c->ci->name;
-
- if (!is_global && channel.empty())
- is_global = true;
-
- try
- {
- SQL::Query query;
- query = "SELECT nick, letters, words, line, actions,"
- "smileys_happy+smileys_sad+smileys_other as smileys "
- "FROM `" + prefix + "chanstats` "
- "WHERE `nick` != '' AND `chan` = @channel@ AND `type` = 'total' "
- "ORDER BY `letters` DESC LIMIT @limit@;";
- query.SetValue("limit", limit, false);
-
- if (is_global)
- query.SetValue("channel", "");
- else
- query.SetValue("channel", channel.c_str());
-
- SQL::Result res = this->RunQuery(query);
-
- if (res.Rows() > 0)
- {
- source.Reply(_("Top %i of %s"), limit, (is_global ? "Network" : channel.c_str()));
- for (int i = 0; i < res.Rows(); ++i)
- {
- source.Reply(_("%2lu \002%-16s\002 letters: %s, words: %s, lines: %s, smileys %s, actions: %s"),
- i+1, res.Get(i, "nick").c_str(), res.Get(i, "letters").c_str(),
- res.Get(i, "words").c_str(), res.Get(i, "line").c_str(),
- res.Get(0, "smileys").c_str(), res.Get(0, "actions").c_str());
- }
- }
- else
- source.Reply(_("No stats for %s."), is_global ? "Network" : channel.c_str());
- }
- catch (const SQL::Exception &ex)
- {
- Log(LOG_DEBUG) << ex.GetReason();
- }
- }
-};
-
-void CommandCSTop::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoTop(source, params, false, 3);
-}
-
-void CommandCSTop10::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoTop(source, params, false, 10);
-}
-
-void CommandCSGTop::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoTop(source, params, true, 3);
-}
-
-void CommandCSGTop10::Execute(CommandSource &source, const std::vector<Anope::string> &params)
-{
- me->DoTop(source, params, true, 10);
-}
-
-
-MODULE_INIT(CSTop)
diff --git a/modules/stats/irc2sql/CMakeLists.txt b/modules/stats/irc2sql/CMakeLists.txt
deleted file mode 100644
index 9d36c6e8d..000000000
--- a/modules/stats/irc2sql/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
-
diff --git a/modules/stats/irc2sql/irc2sql.cpp b/modules/stats/irc2sql/irc2sql.cpp
deleted file mode 100644
index a537f184c..000000000
--- a/modules/stats/irc2sql/irc2sql.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-#include "irc2sql.h"
-
-void IRC2SQL::OnShutdown() anope_override
-{
- // TODO: test if we really have to use blocking query here
- // (sometimes m_mysql get unloaded before the other thread executed all queries)
- SQL::Result r = this->sql->RunQuery(SQL::Query("CALL " + prefix + "OnShutdown()"));
- quitting = true;
-}
-
-void IRC2SQL::OnReload(Configuration::Conf *conf) anope_override
-{
- Configuration::Block *block = Config->GetModule(this);
- prefix = block->Get<const Anope::string>("prefix", "anope_");
- UseGeoIP = block->Get<bool>("GeoIPLookup", "no");
- GeoIPDB = block->Get<const Anope::string>("GeoIPDatabase", "country");
- ctcpuser = block->Get<bool>("ctcpuser", "no");
- ctcpeob = block->Get<bool>("ctcpeob", "yes");
- Anope::string engine = block->Get<const Anope::string>("engine");
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
- if (sql)
- this->CheckTables();
- else
- Log() << "IRC2SQL: no database connection to " << engine;
-
- const Anope::string &snick = block->Get<const Anope::string>("client");
- if (snick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
- StatServ = BotInfo::Find(snick, true);
- if (!StatServ)
- throw ConfigException(Module::name + ": no bot named " + snick);
-
- if (firstrun)
- {
- firstrun = false;
-
- for (Anope::map<Server *>::const_iterator it = Servers::ByName.begin(); it != Servers::ByName.end(); ++it)
- {
- this->OnNewServer(it->second);
- }
-
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
- {
- this->OnChannelCreate(it->second);
- }
-
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- {
- User *u = it->second;
- bool exempt = false;
- this->OnUserConnect(u, exempt);
- for (User::ChanUserList::const_iterator cit = u->chans.begin(), cit_end = u->chans.end(); cit != cit_end; ++cit)
- {
- this->OnJoinChannel(u, cit->second->chan);
- }
- }
- }
-
-}
-
-void IRC2SQL::OnNewServer(Server *server) anope_override
-{
- query = "INSERT DELAYED INTO `" + prefix + "server` (name, hops, comment, link_time, online, ulined) "
- "VALUES (@name@, @hops@, @comment@, now(), 'Y', @ulined@) "
- "ON DUPLICATE KEY UPDATE name=VALUES(name), hops=VALUES(hops), comment=VALUES(comment), "
- "link_time=VALUES(link_time), online=VALUES(online), ulined=(ulined)";
- query.SetValue("name", server->GetName());
- query.SetValue("hops", server->GetHops());
- query.SetValue("comment", server->GetDescription());
- query.SetValue("ulined", server->IsULined() ? "Y" : "N");
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnServerQuit(Server *server) anope_override
-{
- if (quitting)
- return;
-
- query = "CALL " + prefix + "ServerQuit(@name@)";
- query.SetValue("name", server->GetName());
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnUserConnect(User *u, bool &exempt) anope_override
-{
- if (!introduced_myself)
- {
- this->OnNewServer(Me);
- introduced_myself = true;
- }
-
- query = "CALL " + prefix + "UserConnect(@nick@,@host@,@vhost@,@chost@,@realname@,@ip@,@ident@,@vident@,"
- "@account@,@secure@,@fingerprint@,@signon@,@server@,@uuid@,@modes@,@oper@)";
- query.SetValue("nick", u->nick);
- query.SetValue("host", u->host);
- query.SetValue("vhost", u->vhost);
- query.SetValue("chost", u->chost);
- query.SetValue("realname", u->realname);
- query.SetValue("ip", u->ip);
- query.SetValue("ident", u->GetIdent());
- query.SetValue("vident", u->GetVIdent());
- query.SetValue("secure", u->HasMode("SSL") || u->HasExt("ssl") ? "Y" : "N");
- query.SetValue("account", u->Account() ? u->Account()->display : "");
- query.SetValue("fingerprint", u->fingerprint);
- query.SetValue("signon", u->signon);
- query.SetValue("server", u->server->GetName());
- query.SetValue("uuid", u->GetUID());
- query.SetValue("modes", u->GetModes());
- query.SetValue("oper", u->HasMode("OPER") ? "Y" : "N");
- this->RunQuery(query);
-
- if (ctcpuser && (Me->IsSynced() || ctcpeob) && u->server != Me)
- IRCD->SendPrivmsg(StatServ, u->GetUID(), "\1VERSION\1");
-
-}
-
-void IRC2SQL::OnUserQuit(User *u, const Anope::string &msg) anope_override
-{
- if (quitting || u->server->IsQuitting())
- return;
-
- query = "CALL " + prefix + "UserQuit(@nick@)";
- query.SetValue("nick", u->nick);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
-{
- query = "UPDATE `" + prefix + "user` SET nick=@newnick@ WHERE nick=@oldnick@";
- query.SetValue("newnick", u->nick);
- query.SetValue("oldnick", oldnick);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnFingerprint(User *u) anope_override
-{
- query = "UPDATE `" + prefix + "user` SET secure=@secure@, fingerprint=@fingerprint@ WHERE nick=@nick@";
- query.SetValue("secure", u->HasMode("SSL") || u->HasExt("ssl") ? "Y" : "N");
- query.SetValue("fingerprint", u->fingerprint);
- query.SetValue("nick", u->nick);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnUserModeSet(User *u, const Anope::string &mname) anope_override
-{
- query = "UPDATE `" + prefix + "user` SET modes=@modes@, oper=@oper@ WHERE nick=@nick@";
- query.SetValue("nick", u->nick);
- query.SetValue("modes", u->GetModes());
- query.SetValue("oper", u->HasMode("OPER") ? "Y" : "N");
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnUserModeUnset(User *u, const Anope::string &mname) anope_override
-{
- this->OnUserModeSet(u, mname);
-}
-
-void IRC2SQL::OnUserLogin(User *u)
-{
- query = "UPDATE `" + prefix + "user` SET account=@account@ WHERE nick=@nick@";
- query.SetValue("nick", u->nick);
- query.SetValue("account", u->Account() ? u->Account()->display : "");
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnNickLogout(User *u) anope_override
-{
- this->OnUserLogin(u);
-}
-
-void IRC2SQL::OnSetDisplayedHost(User *u) anope_override
-{
- query = "UPDATE `" + prefix + "user` "
- "SET vhost=@vhost@ "
- "WHERE nick=@nick@";
- query.SetValue("vhost", u->GetDisplayedHost());
- query.SetValue("nick", u->nick);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnChannelCreate(Channel *c) anope_override
-{
- query = "INSERT INTO `" + prefix + "chan` (channel, topic, topicauthor, topictime, modes) "
- "VALUES (@channel@,@topic@,@topicauthor@,@topictime@,@modes@) "
- "ON DUPLICATE KEY UPDATE channel=VALUES(channel), topic=VALUES(topic),"
- "topicauthor=VALUES(topicauthor), topictime=VALUES(topictime), modes=VALUES(modes)";
- query.SetValue("channel", c->name);
- query.SetValue("topic", c->topic);
- query.SetValue("topicauthor", c->topic_setter);
- query.SetValue("topictime", c->topic_ts);
- query.SetValue("modes", c->GetModes(true,true));
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnChannelDelete(Channel *c) anope_override
-{
- query = "DELETE FROM `" + prefix + "chan` WHERE channel=@channel@";
- query.SetValue("channel", c->name);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnJoinChannel(User *u, Channel *c) anope_override
-{
- Anope::string modes;
- ChanUserContainer *cu = u->FindChannel(c);
- if (cu)
- modes = cu->status.Modes();
-
- query = "CALL " + prefix + "JoinUser(@nick@,@channel@,@modes@)";
- query.SetValue("nick", u->nick);
- query.SetValue("channel", c->name);
- query.SetValue("modes", modes);
- this->RunQuery(query);
-}
-
-EventReturn IRC2SQL::OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
-{
- query = "UPDATE `" + prefix + "chan` SET modes=@modes@ WHERE channel=@channel@";
- query.SetValue("channel", c->name);
- query.SetValue("modes", c->GetModes(true,true));
- this->RunQuery(query);
- return EVENT_CONTINUE;
-}
-
-EventReturn IRC2SQL::OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
-{
- this->OnChannelModeSet(c, setter, mode, param);
- return EVENT_CONTINUE;
-}
-
-void IRC2SQL::OnLeaveChannel(User *u, Channel *c) anope_override
-{
- if (quitting)
- return;
- /*
- * user is quitting, we already received a OnUserQuit()
- * at this point the user is already removed from SQL and all channels
- */
- if (u->Quitting())
- return;
- query = "CALL " + prefix + "PartUser(@nick@,@channel@)";
- query.SetValue("nick", u->nick);
- query.SetValue("channel", c->name);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
-{
- query = "UPDATE `" + prefix + "chan` "
- "SET topic=@topic@, topicauthor=@author@, topictime=FROM_UNIXTIME(@time@) "
- "WHERE channel=@channel@";
- query.SetValue("topic", c->topic);
- query.SetValue("author", c->topic_setter);
- query.SetValue("time", c->topic_ts);
- query.SetValue("channel", c->name);
- this->RunQuery(query);
-}
-
-void IRC2SQL::OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_override
-{
- Anope::string versionstr;
- if (bi != StatServ)
- return;
- if (message[0] == '\1' && message[message.length() - 1] == '\1')
- {
- if (message.substr(0, 9).equals_ci("\1VERSION "))
- {
- if (u->HasExt("CTCPVERSION"))
- return;
- u->Extend<bool>("CTCPVERSION");
-
- versionstr = Anope::NormalizeBuffer(message.substr(9, message.length() - 10));
- if (versionstr.empty())
- return;
- query = "UPDATE `" + prefix + "user` "
- "SET version=@version@ "
- "WHERE nick=@nick@";
- query.SetValue("version", versionstr);
- query.SetValue("nick", u->nick);
- this->RunQuery(query);
- }
- }
-}
-
-MODULE_INIT(IRC2SQL)
diff --git a/modules/stats/irc2sql/irc2sql.h b/modules/stats/irc2sql/irc2sql.h
deleted file mode 100644
index b5fc8c37f..000000000
--- a/modules/stats/irc2sql/irc2sql.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "module.h"
-#include "modules/sql.h"
-
-class MySQLInterface : public SQL::Interface
-{
- public:
- MySQLInterface(Module *o) : SQL::Interface(o) { }
-
- void OnResult(const SQL::Result &r) anope_override
- {
- }
-
- void OnError(const SQL::Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "m_irc2sql: Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "m_irc2sql: Error executing query: " << r.GetError();
- }
-};
-
-class IRC2SQL : public Module
-{
- ServiceReference<SQL::Provider> sql;
- MySQLInterface sqlinterface;
- SQL::Query query;
- std::vector<Anope::string> TableList, ProcedureList, EventList;
- Anope::string prefix, GeoIPDB;
- bool quitting, introduced_myself, UseGeoIP, ctcpuser, ctcpeob, firstrun;
- BotInfo *StatServ;
- PrimitiveExtensibleItem<bool> versionreply;
-
- void RunQuery(const SQL::Query &q);
- void GetTables();
-
- bool HasTable(const Anope::string &table);
- bool HasProcedure(const Anope::string &table);
- bool HasEvent(const Anope::string &table);
-
- void CheckTables();
-
- public:
- IRC2SQL(const Anope::string &modname, const Anope::string &creator) :
- Module(modname, creator, EXTRA | VENDOR), sql("", ""), sqlinterface(this), versionreply(this, "CTCPVERSION")
- {
- firstrun = true;
- quitting = false;
- introduced_myself = false;
- }
-
- void OnShutdown() anope_override;
- void OnReload(Configuration::Conf *config) anope_override;
- void OnNewServer(Server *server) anope_override;
- void OnServerQuit(Server *server) anope_override;
- void OnUserConnect(User *u, bool &exempt) anope_override;
- void OnUserQuit(User *u, const Anope::string &msg) anope_override;
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override;
- void OnFingerprint(User *u) anope_override;
- void OnUserModeSet(User *u, const Anope::string &mname) anope_override;
- void OnUserModeUnset(User *u, const Anope::string &mname) anope_override;
- void OnUserLogin(User *u) anope_override;
- void OnNickLogout(User *u) anope_override;
- void OnSetDisplayedHost(User *u) anope_override;
-
- void OnChannelCreate(Channel *c) anope_override;
- void OnChannelDelete(Channel *c) anope_override;
- void OnLeaveChannel(User *u, Channel *c) anope_override;
- void OnJoinChannel(User *u, Channel *c) anope_override;
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
-
- void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
-
- void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_override;
-};
-
-
diff --git a/modules/stats/irc2sql/tables.cpp b/modules/stats/irc2sql/tables.cpp
deleted file mode 100644
index d80f37535..000000000
--- a/modules/stats/irc2sql/tables.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-#include "irc2sql.h"
-
-void IRC2SQL::CheckTables()
-{
- Anope::string geoquery("");
-
- if (firstrun)
- {
- /*
- * reset some tables to make sure they are really empty
- */
- this->sql->RunQuery("TRUNCATE TABLE " + prefix + "user");
- this->sql->RunQuery("TRUNCATE TABLE " + prefix + "chan");
- this->sql->RunQuery("TRUNCATE TABLE " + prefix + "ison");
- this->sql->RunQuery("UPDATE `" + prefix + "server` SET currentusers=0, online='N'");
- }
-
- this->GetTables();
-
- if (UseGeoIP && GeoIPDB.equals_ci("country") && !this->HasTable(prefix + "geoip_country"))
- {
- query = "CREATE TABLE `" + prefix + "geoip_country` ("
- "`start` INT UNSIGNED NOT NULL,"
- "`end` INT UNSIGNED NOT NULL,"
- "`countrycode` varchar(2),"
- "`countryname` varchar(50),"
- "PRIMARY KEY `end` (`end`),"
- "KEY `start` (`start`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (UseGeoIP && GeoIPDB.equals_ci("city") && !this->HasTable(prefix + "geoip_city_blocks"))
- {
- query = "CREATE TABLE `" + prefix + "geoip_city_blocks` ("
- "`start` INT UNSIGNED NOT NULL,"
- "`end` INT UNSIGNED NOT NULL,"
- "`locId` INT UNSIGNED NOT NULL,"
- "PRIMARY KEY `end` (`end`),"
- "KEY `start` (`start`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
-
- }
- if (UseGeoIP && GeoIPDB.equals_ci("city") && !this->HasTable(prefix + "geoip_city_location"))
- {
- query = "CREATE TABLE `" + prefix + "geoip_city_location` ("
- "`locId` INT UNSIGNED NOT NULL,"
- "`country` CHAR(2) NOT NULL,"
- "`region` CHAR(2) NOT NULL,"
- "`city` VARCHAR(50),"
- "`latitude` FLOAT,"
- "`longitude` FLOAT,"
- "`areaCode` INT,"
- "PRIMARY KEY (`locId`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (UseGeoIP && GeoIPDB.equals_ci("city") && !this->HasTable(prefix + "geoip_city_region"))
- { query = "CREATE TABLE `" + prefix + "geoip_city_region` ("
- "`country` CHAR(2) NOT NULL,"
- "`region` CHAR(2) NOT NULL,"
- "`regionname` VARCHAR(100) NOT NULL,"
- "PRIMARY KEY (`country`,`region`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (!this->HasTable(prefix + "server"))
- {
- query = "CREATE TABLE `" + prefix + "server` ("
- "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
- "`name` varchar(64) NOT NULL,"
- "`hops` tinyint(3) NOT NULL,"
- "`comment` varchar(255) NOT NULL,"
- "`link_time` datetime DEFAULT NULL,"
- "`split_time` datetime DEFAULT NULL,"
- "`version` varchar(127) NOT NULL,"
- "`currentusers` int(15) NOT NULL,"
- "`online` enum('Y','N') NOT NULL DEFAULT 'Y',"
- "`ulined` enum('Y','N') NOT NULL DEFAULT 'N',"
- "PRIMARY KEY (`id`),"
- "UNIQUE KEY `name` (`name`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (!this->HasTable(prefix + "chan"))
- {
- query = "CREATE TABLE `" + prefix + "chan` ("
- "`chanid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
- "`channel` varchar(255) NOT NULL,"
- "`currentusers` int(15) NOT NULL DEFAULT 0,"
- "`topic` varchar(255) DEFAULT NULL,"
- "`topicauthor` varchar(255) DEFAULT NULL,"
- "`topictime` datetime DEFAULT NULL,"
- "`modes` varchar(512) DEFAULT NULL,"
- "PRIMARY KEY (`chanid`),"
- "UNIQUE KEY `channel`(`channel`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (!this->HasTable(prefix + "user"))
- {
- query = "CREATE TABLE `" + prefix + "user` ("
- "`nickid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
- "`nick` varchar(255) NOT NULL DEFAULT '',"
- "`host` varchar(255) NOT NULL DEFAULT '',"
- "`vhost` varchar(255) NOT NULL DEFAULT '',"
- "`chost` varchar(255) NOT NULL DEFAULT '',"
- "`realname` varchar(255) NOT NULL DEFAULT '',"
- "`ip` varchar(255) NOT NULL DEFAULT '',"
- "`ident` varchar(32) NOT NULL DEFAULT '',"
- "`vident` varchar(32) NOT NULL DEFAULT '',"
- "`modes` varchar(255) NOT NULL DEFAULT '',"
- "`account` varchar(255) NOT NULL DEFAULT '',"
- "`secure` enum('Y','N') NOT NULL DEFAULT 'N',"
- "`fingerprint` varchar(128) NOT NULL DEFAULT '',"
- "`signon` datetime DEFAULT NULL,"
- "`server` varchar(255) NOT NULL DEFAULT '',"
- "`servid` int(11) UNSIGNED NOT NULL DEFAULT '0',"
- "`uuid` varchar(32) NOT NULL DEFAULT '',"
- "`oper` enum('Y','N') NOT NULL DEFAULT 'N',"
- "`away` enum('Y','N') NOT NULL DEFAULT 'N',"
- "`awaymsg` varchar(255) NOT NULL DEFAULT '',"
- "`version` varchar(255) NOT NULL DEFAULT '',"
- "`geocode` varchar(16) NOT NULL DEFAULT '',"
- "`geocountry` varchar(64) NOT NULL DEFAULT '',"
- "`georegion` varchar(100) NOT NULL DEFAULT '',"
- "`geocity` varchar(128) NOT NULL DEFAULT '',"
- "`locId` INT UNSIGNED,"
- "PRIMARY KEY (`nickid`),"
- "UNIQUE KEY `nick` (`nick`),"
- "KEY `servid` (`servid`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (!this->HasTable(prefix + "ison"))
- {
- query = "CREATE TABLE `" + prefix + "ison` ("
- "`nickid` int(11) unsigned NOT NULL default '0',"
- "`chanid` int(11) unsigned NOT NULL default '0',"
- "`modes` varchar(255) NOT NULL default '',"
- "PRIMARY KEY (`nickid`,`chanid`),"
- "KEY `modes` (`modes`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (!this->HasTable(prefix + "maxusers"))
- {
- query = "CREATE TABLE `" + prefix + "maxusers` ("
- "`name` VARCHAR(255) NOT NULL,"
- "`maxusers` INT(15) NOT NULL,"
- "`maxtime` DATETIME NOT NULL,"
- "`lastused` DATETIME NOT NULL,"
- "UNIQUE KEY `name` (`name`)"
- ") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- if (this->HasProcedure(prefix + "UserConnect"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "UserConnect"));
-
- if (UseGeoIP)
- {
- if (GeoIPDB.equals_ci("country"))
- geoquery = "UPDATE `" + prefix + "user` AS u "
- "JOIN ( SELECT `countrycode`, `countryname` "
- "FROM `" + prefix + "geoip_country` "
- "WHERE INET_ATON(ip_) <= `end` "
- "AND `start` <= INET_ATON(ip_) "
- "ORDER BY `end` ASC LIMIT 1 ) as c "
- "SET u.geocode = c.countrycode, u.geocountry = c.countryname "
- "WHERE u.nick = nick_; ";
- else if (GeoIPDB.equals_ci("city"))
- geoquery = "UPDATE `" + prefix + "user` as u "
- "JOIN ( SELECT * FROM `" + prefix + "geoip_city_location` "
- "WHERE `locID` = ( SELECT `locID` "
- "FROM `" + prefix + "geoip_city_blocks` "
- "WHERE INET_ATON(ip_) <= `end` "
- "AND `start` <= INET_ATON(ip_) "
- "ORDER BY `end` ASC LIMIT 1 ) "
- ") as l "
- "SET u.geocode = l.country, "
- "u.geocity = l.city, "
- "u.locID = l.locID, "
- "u.georegion = ( SELECT `regionname` "
- "FROM `" + prefix + "geoip_city_region` "
- "WHERE `country` = l.country "
- "AND `region` = l.region )"
- "WHERE u.nick = nick_;";
- }
- query = "CREATE PROCEDURE `" + prefix + "UserConnect`"
- "(nick_ varchar(255), host_ varchar(255), vhost_ varchar(255), "
- "chost_ varchar(255), realname_ varchar(255), ip_ varchar(255), "
- "ident_ varchar(255), vident_ varchar(255), account_ varchar(255), "
- "secure_ enum('Y','N'), fingerprint_ varchar(255), signon_ int(15), "
- "server_ varchar(255), uuid_ varchar(32), modes_ varchar(255), "
- "oper_ enum('Y','N')) "
- "BEGIN "
- "DECLARE cur int(15);"
- "DECLARE max int(15);"
- "INSERT INTO `" + prefix + "user` "
- "(nick, host, vhost, chost, realname, ip, ident, vident, account, "
- "secure, fingerprint, signon, server, uuid, modes, oper) "
- "VALUES (nick_, host_, vhost_, chost_, realname_, ip_, ident_, vident_, "
- "account_, secure_, fingerprint_, FROM_UNIXTIME(signon_), server_, "
- "uuid_, modes_, oper_) "
- "ON DUPLICATE KEY UPDATE host=VALUES(host), vhost=VALUES(vhost), "
- "chost=VALUES(chost), realname=VALUES(realname), ip=VALUES(ip), "
- "ident=VALUES(ident), vident=VALUES(vident), account=VALUES(account), "
- "secure=VALUES(secure), fingerprint=VALUES(fingerprint), signon=VALUES(signon), "
- "server=VALUES(server), uuid=VALUES(uuid), modes=VALUES(modes), "
- "oper=VALUES(oper);"
- "UPDATE `" + prefix + "user` as `u`, `" + prefix + "server` as `s`"
- "SET u.servid = s.id, "
- "s.currentusers = s.currentusers + 1 "
- "WHERE s.name = server_ AND u.nick = nick_;"
- "SELECT `currentusers` INTO cur FROM `" + prefix + "server` WHERE name=server_;"
- "SELECT `maxusers` INTO max FROM `" + prefix + "maxusers` WHERE name=server_;"
- "IF found_rows() AND cur <= max THEN "
- "UPDATE `" + prefix + "maxusers` SET lastused=now() WHERE name=server_;"
- "ELSE "
- "INSERT INTO `" + prefix + "maxusers` (name, maxusers, maxtime, lastused) "
- "VALUES ( server_, cur, now(), now() ) "
- "ON DUPLICATE KEY UPDATE "
- "name=VALUES(name), maxusers=VALUES(maxusers),"
- "maxtime=VALUES(maxtime), lastused=VALUES(lastused);"
- "END IF;"
- + geoquery +
- "END";
- this->RunQuery(query);
-
- if (this->HasProcedure(prefix + "ServerQuit"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "ServerQuit"));
- query = "CREATE PROCEDURE " + prefix + "ServerQuit(sname_ varchar(255)) "
- "BEGIN "
- /* 1.
- * loop through all channels and decrease the user count
- * by the number of users that are on this channel AND
- * on the splitting server
- *
- * we dont have to care about channels that get empty, there will be
- * an extra OnChannelDelete event triggered from anope.
- */
- "DECLARE no_more_rows BOOLEAN DEFAULT FALSE;"
- "DECLARE channel_ varchar(255);"
- "DECLARE ucount_ int;"
- "DECLARE channel_cursor CURSOR FOR "
- "SELECT c.channel "
- "FROM `" + prefix + "chan` as c, `" + prefix + "ison` as i, "
- "`" + prefix + "user` as u, `" + prefix + "server` as s "
- "WHERE c.chanid = i.chanid "
- "AND i.nickid = u.nickid "
- "AND u.servid = s.id "
- "AND s.name = sname_;"
- "DECLARE CONTINUE HANDLER FOR NOT FOUND "
- "SET no_more_rows = TRUE;"
- "OPEN channel_cursor;"
- "the_loop: LOOP "
- "FETCH channel_cursor INTO channel_;"
- "IF no_more_rows THEN "
- "CLOSE channel_cursor;"
- "LEAVE the_loop;"
- "END IF;"
- "SELECT COUNT(*) INTO ucount_ "
- "FROM `" + prefix + "ison` AS i, `" + prefix + "chan` AS c,"
- "`" + prefix + "user` AS u, `" + prefix + "server` AS s "
- "WHERE i.nickid = u.nickid "
- "AND u.servid = s.id "
- "AND i.chanid = c.chanid "
- "AND c.channel = channel_ "
- "AND s.name = sname_; "
- "UPDATE `" + prefix + "chan` "
- "SET currentusers = currentusers - ucount_ "
- "WHERE channel = channel_;"
- "END LOOP;"
-
- /* 2.
- * remove all users on the splitting server from the ison table
- */
- "DELETE i FROM `" + prefix + "ison` AS i "
- "INNER JOIN `" + prefix + "server` AS s "
- "INNER JOIN `" + prefix + "user` AS u "
- "WHERE i.nickid = u.nickid "
- "AND u.servid = s.id "
- "AND s.name = sname_;"
-
- /* 3.
- * remove all users on the splitting server from the user table
- */
- "DELETE u FROM `" + prefix + "user` AS u "
- "INNER JOIN `" + prefix + "server` AS s "
- "WHERE s.id = u.servid "
- "AND s.name = sname_;"
-
- /* 4.
- * on the splitting server, set usercount = 0, split_time = now(), online = 'N'
- */
- "UPDATE `" + prefix + "server` SET currentusers = 0, split_time = now(), online = 'N' "
- "WHERE name = sname_;"
- "END;"; // end of the procedure
- this->RunQuery(query);
-
-
- if (this->HasProcedure(prefix + "UserQuit"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "UserQuit"));
- query = "CREATE PROCEDURE `" + prefix + "UserQuit`"
- "(nick_ varchar(255)) "
- "BEGIN "
- /* decrease usercount on the server where the user was on */
- "UPDATE `" + prefix + "user` AS `u`, `" + prefix + "server` AS `s` "
- "SET s.currentusers = s.currentusers - 1 "
- "WHERE u.nick=nick_ AND u.servid = s.id; "
- /* decrease the usercount on all channels where the user was on */
- "UPDATE `" + prefix + "user` AS u, `" + prefix + "ison` AS i, "
- "`" + prefix + "chan` AS c "
- "SET c.currentusers = c.currentusers - 1 "
- "WHERE u.nick=nick_ AND u.nickid = i.nickid "
- "AND i.chanid = c.chanid; "
- /* remove from all channels where the user was on */
- "DELETE i FROM `" + prefix + "ison` AS i "
- "INNER JOIN `" + prefix + "user` as u "
- "WHERE u.nick = nick_ "
- "AND i.nickid = u.nickid;"
- /* remove the user from the user table */
- "DELETE FROM `" + prefix + "user` WHERE nick = nick_; "
- "END";
- this->RunQuery(query);
-
- if (this->HasProcedure(prefix + "ShutDown"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "ShutDown"));
- query = "CREATE PROCEDURE `" + prefix + "ShutDown`()"
- "BEGIN "
- "UPDATE `" + prefix + "server` "
- "SET currentusers=0, online='N', split_time=now();"
- "TRUNCATE TABLE `" + prefix + "user`;"
- "TRUNCATE TABLE `" + prefix + "chan`;"
- "TRUNCATE TABLE `" + prefix + "ison`;"
- "END";
- this->RunQuery(query);
-
- if (this->HasProcedure(prefix + "JoinUser"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "JoinUser"));
- query = "CREATE PROCEDURE `"+ prefix + "JoinUser`"
- "(nick_ varchar(255), channel_ varchar(255), modes_ varchar(255)) "
- "BEGIN "
- "DECLARE cur int(15);"
- "DECLARE max int(15);"
- "INSERT INTO `" + prefix + "ison` (nickid, chanid, modes) "
- "SELECT u.nickid, c.chanid, modes_ "
- "FROM " + prefix + "user AS u, " + prefix + "chan AS c "
- "WHERE u.nick=nick_ AND c.channel=channel_;"
- "UPDATE `" + prefix + "chan` SET currentusers=currentusers+1 "
- "WHERE channel=channel_;"
- "SELECT `currentusers` INTO cur FROM `" + prefix + "chan` WHERE channel=channel_;"
- "SELECT `maxusers` INTO max FROM `" + prefix + "maxusers` WHERE name=channel_;"
- "IF found_rows() AND cur <= max THEN "
- "UPDATE `" + prefix + "maxusers` SET lastused=now() WHERE name=channel_;"
- "ELSE "
- "INSERT INTO `" + prefix + "maxusers` (name, maxusers, maxtime, lastused) "
- "VALUES ( channel_, cur, now(), now() ) "
- "ON DUPLICATE KEY UPDATE "
- "name=VALUES(name), maxusers=VALUES(maxusers),"
- "maxtime=VALUES(maxtime), lastused=VALUES(lastused);"
- "END IF;"
- "END";
- this->RunQuery(query);
-
- if (this->HasProcedure(prefix + "PartUser"))
- this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "PartUser"));
- query = "CREATE PROCEDURE `" + prefix + "PartUser`"
- "(nick_ varchar(255), channel_ varchar(255)) "
- "BEGIN "
- "DELETE i FROM `" + prefix + "ison` AS i "
- "INNER JOIN `" + prefix + "user` AS u "
- "INNER JOIN `" + prefix + "chan` AS c "
- "WHERE i.nickid = u.nickid "
- "AND u.nick = nick_ "
- "AND i.chanid = c.chanid "
- "AND c.channel = channel_;"
- "UPDATE `" + prefix + "chan` SET currentusers=currentusers-1 "
- "WHERE channel=channel_;"
- "END";
- this->RunQuery(query);
-}
diff --git a/modules/stats/irc2sql/utils.cpp b/modules/stats/irc2sql/utils.cpp
deleted file mode 100644
index 0c35b13fa..000000000
--- a/modules/stats/irc2sql/utils.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "irc2sql.h"
-
-void IRC2SQL::RunQuery(const SQL::Query &q)
-{
- if (sql)
- sql->Run(&sqlinterface, q);
-}
-
-void IRC2SQL::GetTables()
-{
- TableList.clear();
- ProcedureList.clear();
- EventList.clear();
- if (!sql)
- return;
-
- SQL::Result r = this->sql->RunQuery(this->sql->GetTables(prefix));
- for (int i = 0; i < r.Rows(); ++i)
- {
- const std::map<Anope::string, Anope::string> &map = r.Row(i);
- for (std::map<Anope::string, Anope::string>::const_iterator it = map.begin(); it != map.end(); ++it)
- TableList.push_back(it->second);
- }
- query = "SHOW PROCEDURE STATUS WHERE `Db` = Database();";
- r = this->sql->RunQuery(query);
- for (int i = 0; i < r.Rows(); ++i)
- {
- ProcedureList.push_back(r.Get(i, "Name"));
- }
- query = "SHOW EVENTS WHERE `Db` = Database();";
- r = this->sql->RunQuery(query);
- for (int i = 0; i < r.Rows(); ++i)
- {
- EventList.push_back(r.Get(i, "Name"));
- }
-}
-
-bool IRC2SQL::HasTable(const Anope::string &table)
-{
- for (std::vector<Anope::string>::const_iterator it = TableList.begin(); it != TableList.end(); ++it)
- if (*it == table)
- return true;
- return false;
-}
-
-bool IRC2SQL::HasProcedure(const Anope::string &table)
-{
- for (std::vector<Anope::string>::const_iterator it = ProcedureList.begin(); it != ProcedureList.end(); ++it)
- if (*it == table)
- return true;
- return false;
-}
-
-bool IRC2SQL::HasEvent(const Anope::string &table)
-{
- for (std::vector<Anope::string>::const_iterator it = EventList.begin(); it != EventList.end(); ++it)
- if (*it == table)
- return true;
- return false;
-}
-
diff --git a/modules/stats/m_chanstats.cpp b/modules/stats/m_chanstats.cpp
deleted file mode 100644
index 13958dcc3..000000000
--- a/modules/stats/m_chanstats.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-#include "module.h"
-#include "modules/sql.h"
-
-class CommandCSSetChanstats : public Command
-{
- public:
- CommandCSSetChanstats(Module *creator) : Command(creator, "chanserv/set/chanstats", 2, 2)
- {
- this->SetDesc(_("Turn chanstats statistics on or off"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (!ci)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- ci->Extend<bool>("CS_STATS");
- source.Reply(_("Chanstats statistics are now enabled for this channel."));
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable chanstats";
- }
- else if (params[1].equals_ci("OFF"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable chanstats";
- ci->Shrink<bool>("CS_STATS");
- source.Reply(_("Chanstats statistics are now disabled for this channel."));
- }
- else
- this->OnSyntaxError(source, "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply("Turn Chanstats channel statistics ON or OFF.");
- return true;
- }
-};
-
-class CommandNSSetChanstats : public Command
-{
- public:
- CommandNSSetChanstats(Module *creator, const Anope::string &sname = "nickserv/set/chanstats", size_t min = 1 ) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Turn chanstats statistics on or off"));
- this->SetSyntax("{ON | OFF}");
- }
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param, bool saset = false)
- {
- NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, na->nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable chanstats for " << na->nc->display;
- na->nc->Extend<bool>("NS_STATS");
- if (saset)
- source.Reply(_("Chanstats statistics are now enabled for %s"), na->nc->display.c_str());
- else
- source.Reply(_("Chanstats statistics are now enabled for your nick."));
- }
- else if (param.equals_ci("OFF"))
- {
- Log(na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable chanstats for " << na->nc->display;
- na->nc->Shrink<bool>("NS_STATS");
- if (saset)
- source.Reply(_("Chanstats statistics are now disabled for %s"), na->nc->display.c_str());
- else
- source.Reply(_("Chanstats statistics are now disabled for your nick."));
- }
- else
- this->OnSyntaxError(source, "CHANSTATS");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns Chanstats statistics ON or OFF."));
- return true;
- }
-};
-
-class CommandNSSASetChanstats : public CommandNSSetChanstats
-{
- public:
- CommandNSSASetChanstats(Module *creator) : CommandNSSetChanstats(creator, "nickserv/saset/chanstats", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1], true);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns chanstats channel statistics ON or OFF for this user."));
- return true;
- }
-};
-
-class MySQLInterface : public SQL::Interface
-{
- public:
- MySQLInterface(Module *o) : SQL::Interface(o) { }
-
- void OnResult(const SQL::Result &r) anope_override
- {
- }
-
- void OnError(const SQL::Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "Chanstats: Error executing query: " << r.GetError();
- }
-};
-
-class MChanstats : public Module
-{
- SerializableExtensibleItem<bool> cs_stats, ns_stats;
-
- CommandCSSetChanstats commandcssetchanstats;
-
- CommandNSSetChanstats commandnssetchanstats;
- CommandNSSASetChanstats commandnssasetchanstats;
-
- ServiceReference<SQL::Provider> sql;
- MySQLInterface sqlinterface;
- SQL::Query query;
- Anope::string SmileysHappy, SmileysSad, SmileysOther, prefix;
- std::vector<Anope::string> TableList, ProcedureList, EventList;
-
- void RunQuery(const SQL::Query &q)
- {
- if (sql)
- sql->Run(&sqlinterface, q);
- }
-
- size_t CountWords(const Anope::string &msg)
- {
- size_t words = 0;
- for (size_t pos = 0; pos != Anope::string::npos; pos = msg.find(" ", pos+1))
- words++;
- return words;
- }
- size_t CountSmileys(const Anope::string &msg, const Anope::string &smileylist)
- {
- size_t smileys = 0;
- spacesepstream sep(smileylist);
- Anope::string buf;
-
- while (sep.GetToken(buf) && !buf.empty())
- {
- for (size_t pos = msg.find(buf, 0); pos != Anope::string::npos; pos = msg.find(buf, pos+1))
- smileys++;
- }
- return smileys;
- }
-
- const Anope::string GetDisplay(User *u)
- {
- if (u && u->Account() && ns_stats.HasExt(u->Account()))
- return u->Account()->display;
- else
- return "";
- }
-
- void GetTables()
- {
- TableList.clear();
- ProcedureList.clear();
- EventList.clear();
- if (!sql)
- return;
-
- SQL::Result r = this->sql->RunQuery(this->sql->GetTables(prefix));
- for (int i = 0; i < r.Rows(); ++i)
- {
- const std::map<Anope::string, Anope::string> &map = r.Row(i);
- for (std::map<Anope::string, Anope::string>::const_iterator it = map.begin(); it != map.end(); ++it)
- TableList.push_back(it->second);
- }
- query = "SHOW PROCEDURE STATUS WHERE `Db` = Database();";
- r = this->sql->RunQuery(query);
- for (int i = 0; i < r.Rows(); ++i)
- {
- ProcedureList.push_back(r.Get(i, "Name"));
- }
- query = "SHOW EVENTS WHERE `Db` = Database();";
- r = this->sql->RunQuery(query);
- for (int i = 0; i < r.Rows(); ++i)
- {
- EventList.push_back(r.Get(i, "Name"));
- }
- }
-
- bool HasTable(const Anope::string &table)
- {
- for (std::vector<Anope::string>::const_iterator it = TableList.begin(); it != TableList.end(); ++it)
- if (*it == table)
- return true;
- return false;
- }
-
- bool HasProcedure(const Anope::string &table)
- {
- for (std::vector<Anope::string>::const_iterator it = ProcedureList.begin(); it != ProcedureList.end(); ++it)
- if (*it == table)
- return true;
- return false;
- }
-
- bool HasEvent(const Anope::string &table)
- {
- for (std::vector<Anope::string>::const_iterator it = EventList.begin(); it != EventList.end(); ++it)
- if (*it == table)
- return true;
- return false;
- }
-
-
- void CheckTables()
- {
- this->GetTables();
- if (!this->HasTable(prefix +"chanstats"))
- {
- query = "CREATE TABLE `" + prefix + "chanstats` ("
- "`id` int(11) NOT NULL AUTO_INCREMENT,"
- "`chan` varchar(64) NOT NULL DEFAULT '',"
- "`nick` varchar(64) NOT NULL DEFAULT '',"
- "`type` ENUM('total', 'monthly', 'weekly', 'daily') NOT NULL,"
- "`letters` int(10) unsigned NOT NULL DEFAULT '0',"
- "`words` int(10) unsigned NOT NULL DEFAULT '0',"
- "`line` int(10) unsigned NOT NULL DEFAULT '0',"
- "`actions` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_happy` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_sad` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_other` int(10) unsigned NOT NULL DEFAULT '0',"
- "`kicks` int(10) unsigned NOT NULL DEFAULT '0',"
- "`kicked` int(10) unsigned NOT NULL DEFAULT '0',"
- "`modes` int(10) unsigned NOT NULL DEFAULT '0',"
- "`topics` int(10) unsigned NOT NULL DEFAULT '0',"
- "`time0` int(10) unsigned NOT NULL default '0',"
- "`time1` int(10) unsigned NOT NULL default '0',"
- "`time2` int(10) unsigned NOT NULL default '0',"
- "`time3` int(10) unsigned NOT NULL default '0',"
- "`time4` int(10) unsigned NOT NULL default '0',"
- "`time5` int(10) unsigned NOT NULL default '0',"
- "`time6` int(10) unsigned NOT NULL default '0',"
- "`time7` int(10) unsigned NOT NULL default '0',"
- "`time8` int(10) unsigned NOT NULL default '0',"
- "`time9` int(10) unsigned NOT NULL default '0',"
- "`time10` int(10) unsigned NOT NULL default '0',"
- "`time11` int(10) unsigned NOT NULL default '0',"
- "`time12` int(10) unsigned NOT NULL default '0',"
- "`time13` int(10) unsigned NOT NULL default '0',"
- "`time14` int(10) unsigned NOT NULL default '0',"
- "`time15` int(10) unsigned NOT NULL default '0',"
- "`time16` int(10) unsigned NOT NULL default '0',"
- "`time17` int(10) unsigned NOT NULL default '0',"
- "`time18` int(10) unsigned NOT NULL default '0',"
- "`time19` int(10) unsigned NOT NULL default '0',"
- "`time20` int(10) unsigned NOT NULL default '0',"
- "`time21` int(10) unsigned NOT NULL default '0',"
- "`time22` int(10) unsigned NOT NULL default '0',"
- "`time23` int(10) unsigned NOT NULL default '0',"
- "PRIMARY KEY (`id`),"
- "UNIQUE KEY `chan` (`chan`,`nick`,`type`),"
- "KEY `nick` (`nick`),"
- "KEY `chan_` (`chan`),"
- "KEY `type` (`type`)"
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
- this->RunQuery(query);
- }
- /* There is no CREATE OR REPLACE PROCEDURE in MySQL */
- if (this->HasProcedure(prefix + "chanstats_proc_update"))
- {
- query = "DROP PROCEDURE " + prefix + "chanstats_proc_update";
- this->RunQuery(query);
- }
- query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_update`"
- "(chan_ VARCHAR(255), nick_ VARCHAR(255), line_ INT(10), letters_ INT(10),"
- "words_ INT(10), actions_ INT(10), sm_h_ INT(10), sm_s_ INT(10), sm_o_ INT(10),"
- "kicks_ INT(10), kicked_ INT(10), modes_ INT(10), topics_ INT(10))"
- "BEGIN "
- "DECLARE time_ VARCHAR(20);"
- "SET time_ = CONCAT('time', hour(now()));"
- "INSERT IGNORE INTO `" + prefix + "chanstats` (`nick`,`chan`, `type`) VALUES "
- "('', chan_, 'total'), ('', chan_, 'monthly'),"
- "('', chan_, 'weekly'), ('', chan_, 'daily');"
- "IF nick_ != '' THEN "
- "INSERT IGNORE INTO `" + prefix + "chanstats` (`nick`,`chan`, `type`) VALUES "
- "(nick_, chan_, 'total'), (nick_, chan_, 'monthly'),"
- "(nick_, chan_, 'weekly'),(nick_, chan_, 'daily'),"
- "(nick_, '', 'total'), (nick_, '', 'monthly'),"
- "(nick_, '', 'weekly'), (nick_, '', 'daily');"
- "END IF;"
- "SET @update_query = CONCAT('UPDATE `" + prefix + "chanstats` SET line=line+', line_, ',"
- "letters=letters+', letters_, ' , words=words+', words_, ', actions=actions+', actions_, ', "
- "smileys_happy=smileys_happy+', sm_h_, ', smileys_sad=smileys_sad+', sm_s_, ', "
- "smileys_other=smileys_other+', sm_o_, ', kicks=kicks+', kicks_, ', kicked=kicked+', kicked_, ', "
- "modes=modes+', modes_, ', topics=topics+', topics_, ', ', time_ , '=', time_, '+', line_ ,' "
- "WHERE (nick='''' OR nick=''', nick_, ''') AND (chan='''' OR chan=''', chan_, ''')');"
- "PREPARE update_query FROM @update_query;"
- "EXECUTE update_query;"
- "DEALLOCATE PREPARE update_query;"
- "END";
- this->RunQuery(query);
-
- if (this->HasProcedure(prefix + "chanstats_proc_chgdisplay"))
- {
- query = "DROP PROCEDURE " + prefix + "chanstats_proc_chgdisplay;";
- this->RunQuery(query);
- }
- query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_chgdisplay`"
- "(old_nick varchar(255), new_nick varchar(255))"
- "BEGIN "
- "DECLARE res_count int(10) unsigned;"
- "SELECT COUNT(nick) INTO res_count FROM `" + prefix + "chanstats` WHERE nick = new_nick;"
- "IF res_count = 0 THEN "
- "UPDATE `" + prefix + "chanstats` SET `nick` = new_nick WHERE `nick` = old_nick;"
- "ELSE "
- "my_cursor: BEGIN "
- "DECLARE no_more_rows BOOLEAN DEFAULT FALSE;"
- "DECLARE chan_ VARCHAR(255);"
- "DECLARE type_ ENUM('total', 'monthly', 'weekly', 'daily');"
- "DECLARE letters_, words_, line_, actions_, smileys_happy_,"
- "smileys_sad_, smileys_other_, kicks_, kicked_, modes_, topics_,"
- "time0_, time1_, time2_, time3_, time4_, time5_, time6_, time7_, time8_, time9_,"
- "time10_, time11_, time12_, time13_, time14_, time15_, time16_, time17_, time18_,"
- "time19_, time20_, time21_, time22_, time23_ INT(10) unsigned;"
- "DECLARE stats_cursor CURSOR FOR "
- "SELECT chan, type, letters, words, line, actions, smileys_happy,"
- "smileys_sad, smileys_other, kicks, kicked, modes, topics, time0, time1,"
- "time2, time3, time4, time5, time6, time7, time8, time9, time10, time11,"
- "time12, time13, time14, time15, time16, time17, time18, time19, time20,"
- "time21, time22, time23 "
- "FROM `" + prefix + "chanstats` "
- "WHERE `nick` = old_nick;"
- "DECLARE CONTINUE HANDLER FOR NOT FOUND "
- "SET no_more_rows = TRUE;"
- "OPEN stats_cursor;"
- "the_loop: LOOP "
- "FETCH stats_cursor "
- "INTO chan_, type_, letters_, words_, line_, actions_, smileys_happy_,"
- "smileys_sad_, smileys_other_, kicks_, kicked_, modes_, topics_,"
- "time0_, time1_, time2_, time3_, time4_, time5_, time6_, time7_, time8_,"
- "time9_, time10_, time11_, time12_, time13_, time14_, time15_, time16_,"
- "time17_, time18_, time19_, time20_, time21_, time22_, time23_;"
- "IF no_more_rows THEN "
- "CLOSE stats_cursor;"
- "LEAVE the_loop;"
- "END IF;"
- "INSERT INTO `" + prefix + "chanstats` "
- "(chan, nick, type, letters, words, line, actions, smileys_happy, "
- "smileys_sad, smileys_other, kicks, kicked, modes, topics, time0, time1, "
- "time2, time3, time4, time5, time6, time7, time8, time9, time10, time11,"
- "time12, time13, time14, time15, time16, time17, time18, time19, time20,"
- "time21, time22, time23)"
- "VALUES (chan_, new_nick, type_, letters_, words_, line_, actions_, smileys_happy_,"
- "smileys_sad_, smileys_other_, kicks_, kicked_, modes_, topics_,"
- "time0_, time1_, time2_, time3_, time4_, time5_, time6_, time7_, time8_, "
- "time9_, time10_, time11_, time12_, time13_, time14_, time15_, time16_, "
- "time17_, time18_, time19_, time20_, time21_, time22_, time23_)"
- "ON DUPLICATE KEY UPDATE letters=letters+VALUES(letters), words=words+VALUES(words),"
- "line=line+VALUES(line), actions=actions+VALUES(actions),"
- "smileys_happy=smileys_happy+VALUES(smileys_happy),"
- "smileys_sad=smileys_sad+VALUES(smileys_sad),"
- "smileys_other=smileys_other+VALUES(smileys_other),"
- "kicks=kicks+VALUES(kicks), kicked=kicked+VALUES(kicked),"
- "modes=modes+VALUES(modes), topics=topics+VALUES(topics),"
- "time1=time1+VALUES(time1), time2=time2+VALUES(time2), time3=time3+VALUES(time3),"
- "time4=time4+VALUES(time4), time5=time5+VALUES(time5), time6=time6+VALUES(time6),"
- "time7=time7+VALUES(time7), time8=time8+VALUES(time8), time9=time9+VALUES(time9),"
- "time10=time10+VALUES(time10), time11=time11+VALUES(time11), time12=time12+VALUES(time12),"
- "time13=time13+VALUES(time13), time14=time14+VALUES(time14), time15=time15+VALUES(time15),"
- "time16=time16+VALUES(time16), time17=time17+VALUES(time17), time18=time18+VALUES(time18),"
- "time19=time19+VALUES(time19), time20=time20+VALUES(time20), time21=time21+VALUES(time21),"
- "time22=time22+VALUES(time22), time23=time23+VALUES(time23);"
- "END LOOP;"
- "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = old_nick;"
- "END my_cursor;"
- "END IF;"
- "END;";
- this->RunQuery(query);
-
- /* dont prepend any database prefix to events so we can always delete/change old events */
- if (this->HasEvent("chanstats_event_cleanup_daily"))
- {
- query = "DROP EVENT chanstats_event_cleanup_daily";
- this->RunQuery(query);
- }
- query = "CREATE EVENT `chanstats_event_cleanup_daily` "
- "ON SCHEDULE EVERY 1 DAY STARTS CURRENT_DATE "
- "DO UPDATE `" + prefix + "chanstats` SET letters=0, words=0, line=0, actions=0, smileys_happy=0,"
- "smileys_sad=0, smileys_other=0, kicks=0, modes=0, topics=0, time0=0, time1=0, time2=0,"
- "time3=0, time4=0, time5=0, time6=0, time7=0, time8=0, time9=0, time10=0, time11=0,"
- "time12=0, time13=0, time14=0, time15=0, time16=0, time17=0, time18=0, time19=0,"
- "time20=0, time21=0, time22=0, time23=0 "
- "WHERE type='daily';";
- this->RunQuery(query);
-
- if (this->HasEvent("chanstats_event_cleanup_weekly"))
- {
- query = "DROP EVENT `chanstats_event_cleanup_weekly`";
- this->RunQuery(query);
- }
- query = "CREATE EVENT `chanstats_event_cleanup_weekly` "
- "ON SCHEDULE EVERY 1 WEEK STARTS ADDDATE(CURDATE(), INTERVAL 1-DAYOFWEEK(CURDATE()) DAY) "
- "DO UPDATE `" + prefix + "chanstats` SET letters=0, words=0, line=0, actions=0, smileys_happy=0,"
- "smileys_sad=0, smileys_other=0, kicks=0, modes=0, topics=0, time0=0, time1=0, time2=0,"
- "time3=0, time4=0, time5=0, time6=0, time7=0, time8=0, time9=0, time10=0, time11=0,"
- "time12=0, time13=0, time14=0, time15=0, time16=0, time17=0, time18=0, time19=0,"
- "time20=0, time21=0, time22=0, time23=0 "
- "WHERE type='weekly';";
- this->RunQuery(query);
-
- if (this->HasEvent("chanstats_event_cleanup_monthly"))
- {
- query = "DROP EVENT `chanstats_event_cleanup_monthly`;";
- this->RunQuery(query);
- }
- query = "CREATE EVENT `chanstats_event_cleanup_monthly` "
- "ON SCHEDULE EVERY 1 MONTH STARTS LAST_DAY(CURRENT_TIMESTAMP) + INTERVAL 1 DAY "
- "DO BEGIN "
- "UPDATE `" + prefix + "chanstats` SET letters=0, words=0, line=0, actions=0, smileys_happy=0,"
- "smileys_sad=0, smileys_other=0, kicks=0, modes=0, topics=0, time0=0, time1=0, time2=0,"
- "time3=0, time4=0, time5=0, time6=0, time7=0, time8=0, time9=0, time10=0, time11=0,"
- "time12=0, time13=0, time14=0, time15=0, time16=0, time17=0, time18=0, time19=0, "
- "time20=0, time21=0, time22=0, time23=0 "
- "WHERE type='monthly';"
- "OPTIMIZE TABLE `" + prefix + "chanstats`;"
- "END;";
- this->RunQuery(query);
- }
-
-
- public:
- MChanstats(const Anope::string &modname, const Anope::string &creator) :
- Module(modname, creator, EXTRA | VENDOR),
- cs_stats(this, "CS_STATS"), ns_stats(this, "NS_STATS"),
- commandcssetchanstats(this), commandnssetchanstats(this), commandnssasetchanstats(this),
- sqlinterface(this)
- {
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- Configuration::Block *block = conf->GetModule(this);
- prefix = block->Get<const Anope::string>("prefix", "anope_");
- SmileysHappy = block->Get<const Anope::string>("SmileysHappy");
- SmileysSad = block->Get<const Anope::string>("SmileysSad");
- SmileysOther = block->Get<const Anope::string>("SmileysOther");
-
- Anope::string engine = block->Get<const Anope::string>("engine");
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
- if (sql)
- this->CheckTables();
- else
- Log(this) << "no database connection to " << engine;
- }
-
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
- {
- if (!show_all)
- return;
- if (cs_stats.HasExt(ci))
- info.AddOption(_("Chanstats"));
- }
-
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
- {
- if (!show_hidden)
- return;
- if (ns_stats.HasExt(na->nc))
- info.AddOption(_("Chanstats"));
- }
-
- void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
- {
- User *u = User::Find(user);
- if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
- return;
- query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
- query.SetValue("channel", c->name);
- query.SetValue("nick", GetDisplay(u));
- this->RunQuery(query);
- }
-
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
- {
- this->OnModeChange(c, setter.GetUser());
- return EVENT_CONTINUE;
- }
-
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *, const Anope::string &param) anope_override
- {
- this->OnModeChange(c, setter.GetUser());
- return EVENT_CONTINUE;
- }
-
- private:
- void OnModeChange(Channel *c, User *u)
- {
- if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
- return;
-
- query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
- query.SetValue("channel", c->name);
- query.SetValue("nick", GetDisplay(u));
- this->RunQuery(query);
- }
-
- public:
- void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) anope_override
- {
- if (!cu->chan->ci || !cs_stats.HasExt(cu->chan->ci))
- return;
-
- query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);";
- query.SetValue("channel", cu->chan->name);
- query.SetValue("nick", GetDisplay(cu->user));
- this->RunQuery(query);
-
- query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);";
- query.SetValue("channel", cu->chan->name);
- query.SetValue("nick", GetDisplay(source.GetUser()));
- this->RunQuery(query);
- }
-
- void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
- {
- if (!c->ci || !cs_stats.HasExt(c->ci))
- return;
-
- size_t letters = msg.length();
- size_t words = this->CountWords(msg);
-
- size_t action = 0;
- if (msg.find("\01ACTION")!=Anope::string::npos)
- {
- action = 1;
- letters = letters - 7;
- words--;
- }
-
- // count smileys
- size_t smileys_happy = CountSmileys(msg, SmileysHappy);
- size_t smileys_sad = CountSmileys(msg, SmileysSad);
- size_t smileys_other = CountSmileys(msg, SmileysOther);
-
- // do not count smileys as words
- words = words - smileys_happy - smileys_sad - smileys_other;
- query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 1, @letters@, @words@, @action@, "
- "@smileys_happy@, @smileys_sad@, @smileys_other@, '0', '0', '0', '0');";
- query.SetValue("channel", c->name);
- query.SetValue("nick", GetDisplay(u));
- query.SetValue("letters", letters);
- query.SetValue("words", words);
- query.SetValue("action", action);
- query.SetValue("smileys_happy", smileys_happy);
- query.SetValue("smileys_sad", smileys_sad);
- query.SetValue("smileys_other", smileys_other);
- this->RunQuery(query);
- }
-
- void OnDelCore(NickCore *nc) anope_override
- {
- query = "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = @nick@;";
- query.SetValue("nick", nc->display);
- this->RunQuery(query);
- }
-
- void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
- {
- query = "CALL " + prefix + "chanstats_proc_chgdisplay(@old_display@, @new_display@);";
- query.SetValue("old_display", nc->display);
- query.SetValue("new_display", newdisplay);
- this->RunQuery(query);
- }
-
- void OnDelChan(ChannelInfo *ci) anope_override
- {
- query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
- query.SetValue("channel", ci->name);
- this->RunQuery(query);
- }
-};
-
-MODULE_INIT(MChanstats)
-