1
0
mirror of https://github.com/anope/anope.git synced 2026-06-27 22:56:38 +02:00

Move modules/stats under extras because it depends on m_mysql, update its config a bit to look similar to all of the other config files

This commit is contained in:
Adam
2014-01-03 19:54:14 -05:00
parent 2781b6946d
commit e1ce6174ce
9 changed files with 56 additions and 57 deletions
-2
View File
@@ -1,2 +0,0 @@
build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
-285
View File
@@ -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)
-77
View File
@@ -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;
};
-382
View File
@@ -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);
}
-61
View File
@@ -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;
}