summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-06-01 04:43:26 -0400
committerAdam <Adam@anope.org>2012-06-01 04:43:26 -0400
commit437944d41689b0ab090bada7fba9791086b7e1fe (patch)
tree1dc2c3c20f0f39256fe6e0226d3412625cdf05df
parent1e49e9b9dc6ccded06e2855b99223a13d69200b7 (diff)
parentdb37b1c6345dff1415fb144cc21d7c782acb1296 (diff)
Merge branch '1.9' of anope.git.sf.net:/gitroot/anope/anope into 1.9
-rw-r--r--data/chanstats.example.conf5
-rw-r--r--modules/commands/cs_fantasy_stats.cpp17
-rw-r--r--modules/commands/cs_fantasy_top.cpp26
-rw-r--r--modules/commands/ns_group.cpp3
-rw-r--r--modules/extra/m_chanstats.cpp352
-rw-r--r--modules/extra/m_mysql.cpp2
6 files changed, 300 insertions, 105 deletions
diff --git a/data/chanstats.example.conf b/data/chanstats.example.conf
index ab07b2713..11f97a937 100644
--- a/data/chanstats.example.conf
+++ b/data/chanstats.example.conf
@@ -14,6 +14,11 @@ chanstats
engine = "mysql/main"
+ /*
+ * An optional prefix to prepended to the name of each created table.
+ * Do not use the same prefix for other programs.
+ */
+ prefix = "anope_"
smileyshappy = ":) :-) ;) :D :-D"
smileyssad = ":( :-( ;( ;-("
diff --git a/modules/commands/cs_fantasy_stats.cpp b/modules/commands/cs_fantasy_stats.cpp
index 3e9d482b8..a8f6fe2fc 100644
--- a/modules/commands/cs_fantasy_stats.cpp
+++ b/modules/commands/cs_fantasy_stats.cpp
@@ -68,6 +68,7 @@ class CSStats : public Module
CommandCSGStats commandcsgstats;
service_reference<SQLProvider> sql;
MySQLInterface sqlinterface;
+ Anope::string prefix;
public:
CSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
commandcsstats(this), commandcsgstats(this), sql("", ""), sqlinterface(this)
@@ -83,6 +84,7 @@ class CSStats : public Module
void OnReload() anope_override
{
ConfigReader config;
+ prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
this->sql = service_reference<SQLProvider>("SQLProvider", engine);
}
@@ -117,19 +119,14 @@ class CSStats : public Module
try
{
SQLQuery 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)
- query = "SELECT sum(letters) as letters, sum(words) as words, sum(line) as line,"
- " sum(smileys) as smileys, sum(actions) as actions"
- " FROM `anope_bs_chanstats_view_sum_all`"
- " WHERE `nickserv_display` = @display@";
+ query.setValue("channel", "");
else
- {
- query = "SELECT letters, words, line, smileys, actions "
- " FROM `anope_bs_chanstats_view_sum_all` "
- " WHERE `nickserv_display` = @display@ AND `chanserv_name` = @channel@;";
query.setValue("channel", source.c->ci->name);
- }
- query.setValue("display", display);
+ query.setValue("nick", display);
SQLResult res = this->RunQuery(query);
if (res.Rows() > 0)
diff --git a/modules/commands/cs_fantasy_top.cpp b/modules/commands/cs_fantasy_top.cpp
index 7e4c0bb3b..b85849ed5 100644
--- a/modules/commands/cs_fantasy_top.cpp
+++ b/modules/commands/cs_fantasy_top.cpp
@@ -95,6 +95,7 @@ class CSTop : public Module
CommandCSGTop10 commandcsgtop10;
service_reference<SQLProvider> sql;
MySQLInterface sqlinterface;
+ Anope::string prefix;
public:
CSTop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
@@ -112,6 +113,7 @@ class CSTop : public Module
void OnReload() anope_override
{
ConfigReader config;
+ prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
this->sql = service_reference<SQLProvider>("SQLProvider", engine);
}
@@ -146,25 +148,17 @@ class CSTop : public Module
try
{
SQLQuery 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 = Anope::printf("SELECT nickserv_display, sum(letters) as letters, sum(words) as words,"
- " sum(line) as line, sum(smileys) as smileys, sum(actions) as actions"
- " FROM `anope_bs_chanstats_view_sum_all`"
- " WHERE nickserv_display IS NOT NULL"
- " GROUP BY nickserv_display ORDER BY letters DESC LIMIT %i;", limit);
- }
+ query.setValue("channel", "");
else
- {
- query = Anope::printf("SELECT nickserv_display, sum(letters) as letters, sum(words) as words,"
- " sum(line) as line, sum(smileys) as smileys, sum(actions) as actions"
- " FROM `anope_bs_chanstats_view_sum_all`"
- " WHERE nickserv_display IS NOT NULL AND `chanserv_name` = @channel@"
- " GROUP BY nickserv_display ORDER BY letters DESC LIMIT %i;", limit);
query.setValue("channel", channel.c_str());
- }
SQLResult res = this->RunQuery(query);
@@ -174,7 +168,7 @@ class CSTop : public Module
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, "nickserv_display").c_str(), res.Get(i, "letters").c_str(),
+ 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());
}
diff --git a/modules/commands/ns_group.cpp b/modules/commands/ns_group.cpp
index e35d760e1..8b611e6f2 100644
--- a/modules/commands/ns_group.cpp
+++ b/modules/commands/ns_group.cpp
@@ -94,7 +94,10 @@ class CommandNSGroup : public Command
* If not, check that it is valid.
*/
if (na)
+ {
+ FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(na->nc, u->nick));
na->destroy();
+ }
else
{
size_t prefixlen = Config->NSGuestNickPrefix.length();
diff --git a/modules/extra/m_chanstats.cpp b/modules/extra/m_chanstats.cpp
index 9da3f0b10..5cde232d0 100644
--- a/modules/extra/m_chanstats.cpp
+++ b/modules/extra/m_chanstats.cpp
@@ -24,8 +24,8 @@ class MChanstats : public Module
service_reference<SQLProvider> sql;
MySQLInterface sqlinterface;
SQLQuery query;
- Anope::string SmileysHappy, SmileysSad, SmileysOther;
- std::vector<Anope::string> TableList;
+ Anope::string SmileysHappy, SmileysSad, SmileysOther, prefix;
+ std::vector<Anope::string> TableList, ProcedureList, EventList;
void RunQuery(const SQLQuery &q)
{
@@ -33,12 +33,6 @@ class MChanstats : public Module
sql->Run(&sqlinterface, q);
}
- void SetQuery()
- {
- query = "INSERT DELAYED INTO `anope_bs_chanstats` (chanserv_name, nickserv_display, day, hour, @what@) "
- "VALUES (@chanserv_name@, @nickserv_display@, CURRENT_DATE, HOUR(NOW()), '1') "
- "ON DUPLICATE KEY UPDATE @what@=@what@+1;";
- }
size_t CountWords(const Anope::string &msg)
{
size_t words = 0;
@@ -60,19 +54,41 @@ class MChanstats : public Module
return smileys;
}
+ const Anope::string GetDisplay(User *u)
+ {
+ if (u && u->Account() && u->Account()->HasFlag(NI_STATS))
+ return u->Account()->display;
+ else
+ return "";
+ }
+
void GetTables()
{
TableList.clear();
+ ProcedureList.clear();
+ EventList.clear();
if (!sql)
return;
- SQLResult r = this->sql->RunQuery(this->sql->GetTables("anope_bs_"));
+ SQLResult 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)
@@ -83,17 +99,33 @@ class MChanstats : public Module
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("anope_bs_chanstats"))
+ if (!this->HasTable(prefix +"chanstats"))
{
- query = "CREATE TABLE `anope_bs_chanstats` ("
+ query = "CREATE TABLE `" + prefix + "chanstats` ("
"`id` int(11) NOT NULL AUTO_INCREMENT,"
- "`chanserv_name` varchar(255) NOT NULL DEFAULT '',"
- "`nickserv_display` varchar(255) NOT NULL DEFAULT '',"
- "`day` date NOT NULL,"
- "`hour` tinyint(2) NOT NULL,"
+ "`chan` varchar(255) NOT NULL DEFAULT '',"
+ "`nick` varchar(255) 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',"
@@ -105,42 +137,203 @@ class MChanstats : public Module
"`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 `chanserv_name` (`chanserv_name`,`nickserv_display`,`day`,`hour`),"
- "KEY `nickserv_display` (`nickserv_display`), "
- "KEY `day` (`day`),"
- "KEY `hour` (`hour`)"
+ "UNIQUE KEY `chan` (`chan`,`nick`,`type`),"
+ "KEY `nick` (`nick`),"
+ "KEY `chan_` (`chan`),"
+ "KEY `type` (`type`)"
") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
this->RunQuery(query);
}
- if (!this->HasTable("anope_bs_chanstats_view_sum_all"))
+ /* 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 (DATE(CURRENT_TIMESTAMP)-WEEKDAY(CURRENT_TIMESTAMP)) "
+ "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 = "CREATE OR REPLACE VIEW `anope_bs_chanstats_view_sum_all` AS "
- "SELECT `anope_bs_chanstats`.`chanserv_name` AS `chanserv_name`,"
- "`anope_bs_chanstats`.`nickserv_display` AS `nickserv_display`,"
- "sum(`anope_bs_chanstats`.`letters`) AS `letters`,"
- "sum(`anope_bs_chanstats`.`words`) AS `words`,"
- "sum(`anope_bs_chanstats`.`line`) AS `line`,"
- "sum(`anope_bs_chanstats`.`actions`) AS `actions`,"
- "((sum(`anope_bs_chanstats`.`smileys_happy`) "
- "+ sum(`anope_bs_chanstats`.`smileys_sad`)) "
- "+ sum(`anope_bs_chanstats`.`smileys_other`)) AS `smileys`,"
- "sum(`anope_bs_chanstats`.`smileys_happy`) AS `smileys_happy`,"
- "sum(`anope_bs_chanstats`.`smileys_sad`) AS `smileys_sad`,"
- "sum(`anope_bs_chanstats`.`smileys_other`) AS `smileys_other`,"
- "sum(`anope_bs_chanstats`.`kicks`) AS `kicks`,"
- "sum(`anope_bs_chanstats`.`kicked`) AS `kicked`,"
- "sum(`anope_bs_chanstats`.`modes`) AS `modes`,"
- "sum(`anope_bs_chanstats`.`topics`) AS `topics` "
- "FROM `anope_bs_chanstats` "
- "GROUP BY `anope_bs_chanstats`.`chanserv_name`,`anope_bs_chanstats`.`nickserv_display`;";
- this->RunQuery(query);
+ 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) :
+ MChanstats(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, CORE), sql("", ""), sqlinterface(this)
{
this->SetAuthor("Anope");
@@ -150,6 +343,9 @@ class MChanstats : public Module
I_OnChannelModeSet,
I_OnChannelModeUnset,
I_OnTopicUpdated,
+ I_OnDelCore,
+ I_OnChangeCoreDisplay,
+ I_OnChanDrop,
I_OnReload};
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
this->OnReload();
@@ -157,6 +353,7 @@ class MChanstats : public Module
void OnReload() anope_override
{
ConfigReader config;
+ prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
SmileysHappy = config.ReadValue("chanstats", "SmileysHappy", ":) :-) ;) :D :-D", 0);
SmileysSad = config.ReadValue("chanstats", "SmileysSad", ":( :-( ;( ;-(", 0);
SmileysOther = config.ReadValue("chanstats", "SmileysOther", ":/", 0);
@@ -172,13 +369,9 @@ class MChanstats : public Module
{
if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS))
return;
-
- bool has_display = u->Account()->HasFlag(NI_STATS);
-
- this->SetQuery();
- query.setValue("chanserv_name", c->name);
- query.setValue("nickserv_display", has_display ? u->Account()->display : "");
- query.setValue("what", "topics", false);
+ 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, User *setter, ChannelModeName Name, const Anope::string &param) anope_override
@@ -196,12 +389,9 @@ class MChanstats : public Module
if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS))
return;
- bool has_display = u->Account()->HasFlag(NI_STATS);
-
- this->SetQuery();
- query.setValue("chanserv_name", c->name);
- query.setValue("nickserv_display", has_display ? u->Account()->display : "");
- query.setValue("what", "modes", false);
+ 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);
}
void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) anope_override
@@ -209,22 +399,14 @@ class MChanstats : public Module
if (!c->ci || !c->ci->HasFlag(CI_STATS))
return;
-
- bool has_display = target && target->Account() && target->Account()->HasFlag(NI_STATS);
-
- this->SetQuery();
- query.setValue("chanserv_name", c->name);
- query.setValue("nickserv_display", has_display ? target->Account()->display : "");
- query.setValue("what", "kicked", false);
+ query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);";
+ query.setValue("channel", c->name);
+ query.setValue("nick", GetDisplay(target));
this->RunQuery(query);
- User *kicker = finduser(source);
- has_display = kicker && kicker->Account() && kicker->Account()->HasFlag(NI_STATS);
-
- this->SetQuery();
- query.setValue("chanserv_name", c->name);
- query.setValue("nickserv_display", has_display ? kicker->Account()->display : "");
- query.setValue("what", "kicks", false);
+ query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);";
+ query.setValue("channel", c->name);
+ query.setValue("nick", GetDisplay(finduser(source)));
this->RunQuery(query);
}
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
@@ -250,24 +432,38 @@ class MChanstats : public Module
// do not count smileys as words
words = words - smileys_happy - smileys_sad - smileys_other;
- bool has_display = u && u->Account() && u->Account()->HasFlag(NI_STATS);
- query = "INSERT DELAYED INTO `anope_bs_chanstats` (chanserv_name, nickserv_display, day, hour, letters, words, line, actions, smileys_happy, smileys_sad, smileys_other) "
- "VALUES (@chanserv_name@, @nickserv_display@, CURRENT_DATE, HOUR(NOW()), @letters@, @words@, 1, @actions@, @smileys_happy@, @smileys_sad@, @smileys_other@) "
- "ON DUPLICATE KEY UPDATE letters=letters+VALUES(letters), words=words+VALUES(words), line=line+1, 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);";
- query.setValue("nickserv_display", has_display ? u->Account()->display : "");
- query.setValue("chanserv_name", c->name);
+ 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("actions", action);
+ 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(User *u) anope_override
+ {
+ query = "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = @nick@;";
+ query.setValue("nick", GetDisplay(u));
+ 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 OnChanDrop(ChannelInfo *ci) anope_override
+ {
+ query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
+ query.setValue("channel", ci->name);
+ this->RunQuery(query);
+ }
};
-
-
MODULE_INIT(MChanstats)
diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp
index fef040336..1e5ba79cf 100644
--- a/modules/extra/m_mysql.cpp
+++ b/modules/extra/m_mysql.cpp
@@ -440,7 +440,7 @@ void MySQLService::Connect()
const unsigned int timeout = 1;
mysql_options(this->sql, MYSQL_OPT_CONNECT_TIMEOUT, reinterpret_cast<const char *>(&timeout));
- bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, 0);
+ bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, CLIENT_MULTI_RESULTS);
if (!connect)
throw SQLException("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));