mirror of
https://github.com/anope/anope.git
synced 2026-07-02 21:23:12 +02:00
Added Chanstats. It uses a new, improved database format and is not compatible with current phpdenora or magirc installations.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Only install example.chk and example.conf from this directory
|
||||
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
|
||||
set(DATA example.chk botserv.example.conf example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf)
|
||||
set(DATA example.chk botserv.example.conf example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf)
|
||||
install(FILES ${DATA}
|
||||
DESTINATION data
|
||||
)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Example configuration file for chanstats
|
||||
* Make sure BotServ, ChanServ and NickServ are running.
|
||||
*/
|
||||
|
||||
module { name = "m_chanstats" }
|
||||
|
||||
chanstats
|
||||
{
|
||||
/*
|
||||
* WARNING: DO NOT USE THE SAME DATABASE AS db_mysql! db_mysql drops ALL tables in the db!
|
||||
* For this, we add a second mysql{ } block after the chanstats{ } configuration block
|
||||
* and give it another engine name, so m_mysql opens a second connection to the mysql server.
|
||||
* /
|
||||
|
||||
/*
|
||||
* The name of this engine.
|
||||
* This must match with the name in the mysql{ } block
|
||||
*/
|
||||
|
||||
engine = "mysql/chanstats"
|
||||
|
||||
|
||||
smileyshappy = ":) :-) ;) :D :-D"
|
||||
smileyssad = ":( :-( ;( ;-("
|
||||
smileysother = ":/"
|
||||
|
||||
/*
|
||||
* Enable Chanstats for new registered nicks / channels
|
||||
* set it to 0 to disable it.
|
||||
*/
|
||||
NSDefChanstats = 1
|
||||
CSDefChanstats = 1
|
||||
}
|
||||
|
||||
mysql
|
||||
{
|
||||
name = "mysql/chanstats"
|
||||
database = "anope"
|
||||
server = "127.0.0.1"
|
||||
username = "anope"
|
||||
password = "anope"
|
||||
port = 3306
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module { name = "cs_set_chanstats" }
|
||||
command { service = "ChanServ"; name = "SET CHANSTATS"; command = "chanserv/set/chanstats"; }
|
||||
|
||||
module { name = "ns_set_chanstats" }
|
||||
command { service = "NickServ"; name = "SET CHANSTATS"; command = "nickserv/set/chanstats"; }
|
||||
|
||||
module { name = "cs_fantasy_stats" }
|
||||
command { service = "ChanServ"; name = "STATS"; command = "chanserv/stats"; }
|
||||
command { service = "ChanServ"; name = "GSTATS"; command = "chanserv/gstats"; }
|
||||
|
||||
module { name = "cs_fantasy_top" }
|
||||
command { service = "ChanServ"; name = "TOP"; command = "chanserv/top"; }
|
||||
command { service = "ChanServ"; name = "TOP10"; command = "chanserv/top10"; }
|
||||
command { service = "ChanServ"; name = "GTOP"; command = "chanserv/gtop"; }
|
||||
command { service = "ChanServ"; name = "GTOP10"; command = "chanserv/gtop10"; }
|
||||
+12
-2
@@ -1172,7 +1172,17 @@ module { name = "enc_md5" }
|
||||
/* Extra (optional) modules */
|
||||
include
|
||||
{
|
||||
type = "file"
|
||||
name = "modules.example.conf"
|
||||
type = "file"
|
||||
name = "modules.example.conf"
|
||||
}
|
||||
|
||||
/*
|
||||
* Chanstats Modules
|
||||
* Requires a MySQL Database
|
||||
*/
|
||||
|
||||
#include
|
||||
#{
|
||||
# type = "file"
|
||||
# name = "chanstats.example.conf"
|
||||
#}
|
||||
|
||||
+3
-1
@@ -97,6 +97,8 @@ enum NickCoreFlag
|
||||
/* If set means the nick core does not have their email addrses confirmed.
|
||||
*/
|
||||
NI_UNCONFIRMED,
|
||||
/* Chanstats are enabled for this user */
|
||||
NI_STATS,
|
||||
|
||||
NI_END
|
||||
};
|
||||
@@ -104,7 +106,7 @@ enum NickCoreFlag
|
||||
const Anope::string NickCoreFlagStrings[] = {
|
||||
"BEGIN", "KILLPROTECT", "SECURE", "MSG", "MEMO_HARDMAX", "MEMO_SIGNON", "MEMO_RECEIVE",
|
||||
"PRIVATE", "HIDE_EMAIL", "HIDE_MASK", "HIDE_QUIT", "KILL_QUICK", "KILL_IMMED",
|
||||
"MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", "UNCONFIRMED", ""
|
||||
"MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", "UNCONFIRMED", "STATS", ""
|
||||
};
|
||||
|
||||
class CoreExport NickAlias : public Base, public Extensible, public Flags<NickNameFlag, NS_END>, public Serializable
|
||||
|
||||
+4
-2
@@ -135,18 +135,20 @@ class CoreExport Channel : public Base, public Extensible, public Flags<ChannelF
|
||||
std::pair<ModeList::iterator, ModeList::iterator> GetModeList(ChannelModeName Name);
|
||||
|
||||
/** Set a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The setter
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param EnforceMLock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetModeInternal(ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true);
|
||||
void SetModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true);
|
||||
|
||||
/** Remove a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The Setter
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param EnforceMLock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true);
|
||||
void RemoveModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true);
|
||||
|
||||
/** Set a mode on a channel
|
||||
* @param bi The client setting the modes
|
||||
|
||||
+6
-3
@@ -439,9 +439,10 @@ class CoreExport Module : public Extensible
|
||||
|
||||
/** Called when a new topic is set
|
||||
* @param c The channel
|
||||
* @param setter The user who set the new topic
|
||||
* @param topic The new topic
|
||||
*/
|
||||
virtual void OnTopicUpdated(Channel *c, const Anope::string &topic) { }
|
||||
virtual void OnTopicUpdated(Channel *c, User *setter, const Anope::string &topic) { }
|
||||
|
||||
/** Called before a channel expires
|
||||
* @param ci The channel
|
||||
@@ -847,19 +848,21 @@ class CoreExport Module : public Extensible
|
||||
|
||||
/** Called when a mode is set on a channel
|
||||
* @param c The channel
|
||||
* @param setter The user who is setting the mode
|
||||
* @param Name The mode name
|
||||
* @param param The mode param, if there is one
|
||||
* @return EVENT_STOP to make mlock/secureops etc checks not happen
|
||||
*/
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; }
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when a mode is unset on a channel
|
||||
* @param c The channel
|
||||
* @param setter the user who is unsetting the mode
|
||||
* @param Name The mode name
|
||||
* @param param The mode param, if there is one
|
||||
* @return EVENT_STOP to make mlock/secureops etc checks not happen
|
||||
*/
|
||||
virtual EventReturn OnChannelModeUnset(Channel *c, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; }
|
||||
virtual EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when a mode is set on a user
|
||||
* @param u The user
|
||||
|
||||
@@ -57,6 +57,8 @@ enum ChannelInfoFlag
|
||||
* is set or not
|
||||
*/
|
||||
CI_PERSIST,
|
||||
/* Chanstats are enabled */
|
||||
CI_STATS,
|
||||
|
||||
CI_END
|
||||
};
|
||||
@@ -64,7 +66,7 @@ enum ChannelInfoFlag
|
||||
const Anope::string ChannelInfoFlagStrings[] = {
|
||||
"BEGIN", "KEEPTOPIC", "SECUREOPS", "PRIVATE", "TOPICLOCK", "RESTRICTED",
|
||||
"PEACE", "SECURE", "NO_EXPIRE", "MEMO_HARDMAX", "SECUREFOUNDER",
|
||||
"SIGNKICK", "SIGNKICK_LEVEL", "SUSPENDED", "PERSIST", ""
|
||||
"SIGNKICK", "SIGNKICK_LEVEL", "SUSPENDED", "PERSIST", "STATS", ""
|
||||
};
|
||||
|
||||
/** Flags for badwords
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/* Chanstats core functions
|
||||
*
|
||||
* (C) 2003-2012 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 "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &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->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays your Channel Stats"));
|
||||
this->SetSyntax(_("\037nick\037"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
class CommandCSGStats : public Command
|
||||
{
|
||||
public:
|
||||
CommandCSGStats(Module *creator) : Command (creator, "chanserv/gstats", 0, 2)
|
||||
{
|
||||
this->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays your Global Stats"));
|
||||
this->SetSyntax(_("\037nick\037"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
|
||||
class CSStats;
|
||||
static CSStats *me;
|
||||
class CSStats : public Module
|
||||
{
|
||||
CommandCSStats commandcsstats;
|
||||
CommandCSGStats commandcsgstats;
|
||||
service_reference<SQLProvider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
public:
|
||||
CSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
|
||||
commandcsstats(this), commandcsgstats(this), sql("", ""), sqlinterface(this)
|
||||
{
|
||||
me = this;
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
this->OnReload();
|
||||
}
|
||||
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = service_reference<SQLProvider>("SQLProvider", engine);
|
||||
}
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query)
|
||||
{
|
||||
if (!this->sql)
|
||||
throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
|
||||
SQLResult res = this->sql->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
throw SQLException(res.GetError());
|
||||
return res;
|
||||
}
|
||||
|
||||
void DoStats(CommandSource &source, const bool is_global, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (!source.u || !source.c)
|
||||
return;
|
||||
|
||||
Anope::string display;
|
||||
if (params.empty())
|
||||
display = source.u->Account()->display;
|
||||
else if (NickAlias *na = findnick(params[0]))
|
||||
display = na->nc->display;
|
||||
else
|
||||
{
|
||||
source.Reply(_("%s not found."), params[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query;
|
||||
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@";
|
||||
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);
|
||||
SQLResult 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(), source.c->name.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 SQLException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void CommandCSStats::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoStats(source, false, params);
|
||||
}
|
||||
|
||||
void CommandCSGStats::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoStats(source, true, params);
|
||||
}
|
||||
|
||||
MODULE_INIT(CSStats)
|
||||
@@ -0,0 +1,213 @@
|
||||
/* Chanstats core functions
|
||||
*
|
||||
* (C) 2003-2012 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 "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &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->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays the top 3 users of a channel"));
|
||||
this->SetSyntax(_("\037channel\037"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
class CommandCSTop10 : public Command
|
||||
{
|
||||
public:
|
||||
CommandCSTop10(Module *creator) : Command (creator, "chanserv/top10", 0, 2)
|
||||
{
|
||||
this->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays the top 10 users of a channel"));
|
||||
this->SetSyntax(_("\037channel\037"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
class CommandCSGTop : public Command
|
||||
{
|
||||
public:
|
||||
CommandCSGTop(Module *creator) : Command (creator, "chanserv/gtop", 0, 1)
|
||||
{
|
||||
this->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays the top 3 users of the network"));
|
||||
this->SetSyntax("");
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
class CommandCSGTop10 : public Command
|
||||
{
|
||||
public:
|
||||
CommandCSGTop10(Module *creator) : Command (creator, "chanserv/gtop10", 0, 1)
|
||||
{
|
||||
this->SetFlag(CFLAG_STRIP_CHANNEL);
|
||||
this->SetDesc(_("Displays the top 10 users of the network"));
|
||||
this->SetSyntax("");
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
|
||||
};
|
||||
|
||||
|
||||
class CSTop;
|
||||
static CSTop *me;
|
||||
class CSTop : public Module
|
||||
{
|
||||
CommandCSTop commandcstop;
|
||||
CommandCSGTop commandcsgtop;
|
||||
CommandCSTop10 commandcstop10;
|
||||
CommandCSGTop10 commandcsgtop10;
|
||||
service_reference<SQLProvider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
|
||||
public:
|
||||
CSTop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
|
||||
commandcstop(this), commandcsgtop(this), commandcstop10(this), commandcsgtop10(this), sql("", ""),
|
||||
sqlinterface(this)
|
||||
{
|
||||
me = this;
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
this->OnReload();
|
||||
}
|
||||
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = service_reference<SQLProvider>("SQLProvider", engine);
|
||||
}
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query)
|
||||
{
|
||||
if (!this->sql)
|
||||
throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
|
||||
SQLResult res = sql->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
throw SQLException(res.GetError());
|
||||
return res;
|
||||
}
|
||||
|
||||
void DoTop(CommandSource &source, const std::vector<Anope::string> ¶ms, bool is_global, int limit = 1)
|
||||
{
|
||||
if (!source.u || !source.c || !source.c->ci)
|
||||
return;
|
||||
|
||||
Anope::string channel;
|
||||
if (is_global || params.empty())
|
||||
channel = source.c->ci->name;
|
||||
else if (!params.empty())
|
||||
channel = params[0];
|
||||
else
|
||||
{
|
||||
source.Reply(_("%s not found."), params[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
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, "nickserv_display").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 SQLException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void CommandCSTop::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoTop(source, params, false, 3);
|
||||
}
|
||||
|
||||
void CommandCSTop10::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoTop(source, params, false, 10);
|
||||
}
|
||||
|
||||
void CommandCSGTop::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoTop(source, params, true, 3);
|
||||
}
|
||||
|
||||
void CommandCSGTop10::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
me->DoTop(source, params, true, 10);
|
||||
}
|
||||
|
||||
|
||||
MODULE_INIT(CSTop)
|
||||
@@ -94,6 +94,7 @@ class CommandCSInfo : public Command
|
||||
CheckOptStr(optbuf, CI_TOPICLOCK, _("Topic Lock"), ci, u->Account());
|
||||
CheckOptStr(optbuf, CI_PERSIST, _("Persistant"), ci, u->Account());
|
||||
CheckOptStr(optbuf, CI_NO_EXPIRE, _("No expire"), ci, u->Account());
|
||||
CheckOptStr(optbuf, CI_STATS, _("Chanstats"), ci, u->Account());
|
||||
|
||||
info["Options"] = optbuf.empty() ? _("None") : optbuf;
|
||||
info["Mode lock"] = ci->GetMLockAsString(true);
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2012 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"
|
||||
|
||||
class CommandCSSetChanstats : public Command
|
||||
{
|
||||
public:
|
||||
CommandCSSetChanstats(Module *creator) : Command(creator, "chanserv/set/chanstats", 2, 2)
|
||||
{
|
||||
this->SetDesc(_("Turn chanstat statistics on or off"));
|
||||
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
User *u = source.u;
|
||||
ChannelInfo *ci = cs_findchan(params[0]);
|
||||
if (!ci)
|
||||
{
|
||||
source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.permission.empty() && !ci->AccessFor(u).HasPriv("SET"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params[1].equals_ci("ON"))
|
||||
{
|
||||
ci->SetFlag(CI_STATS);
|
||||
source.Reply(_("Chanstats statistics are now enabled for this channel"));
|
||||
}
|
||||
else if (params[1].equals_ci("OFF"))
|
||||
{
|
||||
ci->UnsetFlag(CI_STATS);
|
||||
source.Reply(_("Chanstats statistics are now disabled for this channel"));
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
return;
|
||||
}
|
||||
|
||||
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 CSSetChanstats : public Module
|
||||
{
|
||||
CommandCSSetChanstats commandcssetchanstats;
|
||||
bool CSDefChanstats;
|
||||
public:
|
||||
CSSetChanstats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
|
||||
commandcssetchanstats(this)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
Implementation i[] = { I_OnReload, I_OnChanRegistered };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
this->OnReload();
|
||||
}
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
CSDefChanstats = config.ReadFlag("chanstats", "CSDefChanstats", "0", 0);
|
||||
}
|
||||
void OnChanRegistered(ChannelInfo *ci) anope_override
|
||||
{
|
||||
if (CSDefChanstats)
|
||||
ci->SetFlag(CI_STATS);
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(CSSetChanstats)
|
||||
@@ -120,6 +120,7 @@ class CommandNSInfo : public Command
|
||||
CheckOptStr<NickCoreFlag, NI_END>(u, optbuf, NI_MSG, _("Message mode"), na->nc);
|
||||
CheckOptStr<NickCoreFlag, NI_END>(u, optbuf, NI_AUTOOP, _("Auto-op"), na->nc);
|
||||
CheckOptStr<NickCoreFlag, NI_END>(u, optbuf, NI_SUSPENDED, _("Suspended"), na->nc);
|
||||
CheckOptStr<NickCoreFlag, NI_END>(u, optbuf, NI_STATS, _("Chanstats"), na->nc);
|
||||
CheckOptStr<NickNameFlag, NS_END>(u, optbuf, NS_NO_EXPIRE, _("No expire"), na);
|
||||
|
||||
info[_("Options")] = optbuf.empty() ? _("None") : optbuf;
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2012 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"
|
||||
|
||||
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 chanstat statistic on or off"));
|
||||
this->SetSyntax(_("{ON | OFF}"));
|
||||
}
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
NickAlias *na = findnick(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
na->nc->SetFlag(NI_STATS);
|
||||
source.Reply(_("Chanstat statistics are now enabled for your nick"));
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
na->nc->UnsetFlag(NI_STATS);
|
||||
source.Reply(_("Chanstat statistics are now disabled for your nick"));
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "CHANSTATS");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
this->Run(source, source.u->Account()->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> ¶ms) anope_override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
|
||||
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 NSSetChanstats : public Module
|
||||
{
|
||||
CommandNSSetChanstats commandnssetchanstats;
|
||||
CommandNSSASetChanstats commandnssasetchanstats;
|
||||
bool NSDefChanstats;
|
||||
|
||||
public:
|
||||
NSSetChanstats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
|
||||
commandnssetchanstats(this), commandnssasetchanstats(this)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnNickRegister };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
this->OnReload();
|
||||
}
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
NSDefChanstats = config.ReadFlag("chanstats", "NSDefChanstats", "0", 0);
|
||||
}
|
||||
void OnNickRegister(NickAlias *na) anope_override
|
||||
{
|
||||
if (NSDefChanstats)
|
||||
na->nc->SetFlag(NI_STATS);
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSSetChanstats)
|
||||
@@ -438,7 +438,7 @@ class OSDefcon : public Module
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(Name);
|
||||
|
||||
@@ -452,7 +452,7 @@ class OSDefcon : public Module
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeUnset(Channel *c, ChannelModeName Name, const Anope::string &) anope_override
|
||||
EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string &) anope_override
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(Name);
|
||||
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r) anope_override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &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
|
||||
{
|
||||
service_reference<SQLProvider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
SQLQuery query;
|
||||
Anope::string SmileysHappy, SmileysSad, SmileysOther;
|
||||
std::vector<Anope::string> TableList;
|
||||
|
||||
void RunQuery(const SQLQuery &q)
|
||||
{
|
||||
if (sql)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
void GetTables()
|
||||
{
|
||||
TableList.clear();
|
||||
SQLResult r = this->sql->RunQuery(this->sql->GetTables());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void CheckTables()
|
||||
{
|
||||
this->GetTables();
|
||||
if (!this->HasTable("anope_bs_chanstats"))
|
||||
{
|
||||
query = "CREATE TABLE `anope_bs_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,"
|
||||
"`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',"
|
||||
"PRIMARY KEY (`id`),"
|
||||
"UNIQUE KEY `chanserv_name` (`chanserv_name`,`nickserv_display`,`day`,`hour`),"
|
||||
"KEY `nickserv_display` (`nickserv_display`), "
|
||||
"KEY `day` (`day`),"
|
||||
"KEY `hour` (`hour`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable("anope_bs_chanstats_view_sum_all"))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
MChanstats(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, CORE), sql("", ""), sqlinterface(this)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnPrivmsg,
|
||||
I_OnUserKicked,
|
||||
I_OnChannelModeSet,
|
||||
I_OnChannelModeUnset,
|
||||
I_OnTopicUpdated,
|
||||
I_OnReload};
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
this->OnReload();
|
||||
}
|
||||
void OnReload() anope_override
|
||||
{
|
||||
ConfigReader config;
|
||||
SmileysHappy = config.ReadValue("chanstats", "SmileysHappy", ":) :-) ;) :D :-D", 0);
|
||||
SmileysSad = config.ReadValue("chanstats", "SmileysSad", ":( :-( ;( ;-(", 0);
|
||||
SmileysOther = config.ReadValue("chanstats", "SmileysOther", ":/", 0);
|
||||
|
||||
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
|
||||
this->sql = service_reference<SQLProvider>("SQLProvider", engine);
|
||||
this->CheckTables();
|
||||
|
||||
}
|
||||
void OnTopicUpdated(Channel *c, User *u, const Anope::string &topic) anope_override
|
||||
{
|
||||
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);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
{
|
||||
this->OnModeChange(c, setter);
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
{
|
||||
this->OnModeChange(c, setter);
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
void OnModeChange(Channel *c, User *u)
|
||||
{
|
||||
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);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) anope_override
|
||||
{
|
||||
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);
|
||||
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);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
|
||||
{
|
||||
if (!c->ci || !c->ci->HasFlag(CI_STATS) || (msg[0] == Config->BSFantasyCharacter[0]))
|
||||
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;
|
||||
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.setValue("letters", letters);
|
||||
query.setValue("words", words);
|
||||
query.setValue("actions", action);
|
||||
query.setValue("smileys_happy", smileys_happy);
|
||||
query.setValue("smileys_sad", smileys_sad);
|
||||
query.setValue("smileys_other", smileys_other);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
MODULE_INIT(MChanstats)
|
||||
|
||||
@@ -22,7 +22,7 @@ class HelpChannel : public Module
|
||||
OnReload();
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
{
|
||||
if (Name == CMODE_OP && c && c->ci && c->name.equals_ci(this->HelpChan))
|
||||
{
|
||||
|
||||
@@ -475,7 +475,7 @@ class BahamutIRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
|
||||
@@ -468,7 +468,7 @@ class InspircdIRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
|
||||
@@ -718,7 +718,7 @@ class InspircdIRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
|
||||
@@ -408,7 +408,7 @@ class PlexusIRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
@@ -514,11 +514,11 @@ bool event_bmask(const Anope::string &source, const std::vector<Anope::string> &
|
||||
{
|
||||
Anope::string b = myStrGetToken(bans, ' ', i);
|
||||
if (ban && params[2].equals_cs("b"))
|
||||
c->SetModeInternal(ban, b);
|
||||
c->SetModeInternal(NULL, ban, b);
|
||||
else if (except && params[2].equals_cs("e"))
|
||||
c->SetModeInternal(except, b);
|
||||
c->SetModeInternal(NULL, except, b);
|
||||
if (invex && params[2].equals_cs("I"))
|
||||
c->SetModeInternal(invex, b);
|
||||
c->SetModeInternal(NULL, invex, b);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -381,7 +381,7 @@ class RatboxIRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
@@ -505,11 +505,11 @@ bool event_bmask(const Anope::string &source, const std::vector<Anope::string> &
|
||||
{
|
||||
Anope::string b = myStrGetToken(bans, ' ', i);
|
||||
if (ban && params[2].equals_cs("b"))
|
||||
c->SetModeInternal(ban, b);
|
||||
c->SetModeInternal(NULL, ban, b);
|
||||
else if (except && params[2].equals_cs("e"))
|
||||
c->SetModeInternal(except, b);
|
||||
c->SetModeInternal(NULL, except, b);
|
||||
if (invex && params[2].equals_cs("I"))
|
||||
c->SetModeInternal(invex, b);
|
||||
c->SetModeInternal(NULL, invex, b);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -879,19 +879,19 @@ class Unreal32IRCdMessage : public IRCdMessage
|
||||
if (keep_their_modes && ban && buf[0] == '&')
|
||||
{
|
||||
buf.erase(buf.begin());
|
||||
c->SetModeInternal(ban, buf);
|
||||
c->SetModeInternal(NULL, ban, buf);
|
||||
}
|
||||
/* Except */
|
||||
else if (keep_their_modes && except && buf[0] == '"')
|
||||
{
|
||||
buf.erase(buf.begin());
|
||||
c->SetModeInternal(except, buf);
|
||||
c->SetModeInternal(NULL, except, buf);
|
||||
}
|
||||
/* Invex */
|
||||
else if (keep_their_modes && invex && buf[0] == '\'')
|
||||
{
|
||||
buf.erase(buf.begin());
|
||||
c->SetModeInternal(invex, buf);
|
||||
c->SetModeInternal(NULL, invex, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -930,7 +930,7 @@ class Unreal32IRCdMessage : public IRCdMessage
|
||||
* This will enforce secureops etc on the user
|
||||
*/
|
||||
for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
|
||||
c->SetModeInternal(*it, buf);
|
||||
c->SetModeInternal(NULL, *it, buf);
|
||||
|
||||
/* Now set whatever modes this user is allowed to have on the channel */
|
||||
chan_set_correct_modes(u, c, 1);
|
||||
|
||||
@@ -199,7 +199,7 @@ class BotServCore : public Module
|
||||
"name with one of the following characters: %s."), Config->ChanServ.c_str(), Config->BSFantasyCharacter.c_str());
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override
|
||||
{
|
||||
if (Config->BSSmartJoin && Name == CMODE_BAN && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
{
|
||||
|
||||
+15
-13
@@ -332,17 +332,18 @@ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::Get
|
||||
}
|
||||
|
||||
/** Set a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The user who is setting the mode
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param EnforeMLock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock)
|
||||
void Channel::SetModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock)
|
||||
{
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, cm->Name, param));
|
||||
FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, setter, cm->Name, param));
|
||||
|
||||
/* Setting v/h/o/a/q etc */
|
||||
if (cm->Type == MODE_STATUS)
|
||||
@@ -406,17 +407,18 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool
|
||||
}
|
||||
|
||||
/** Remove a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The user who is unsetting the mode
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param EnforceMLock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock)
|
||||
void Channel::RemoveModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock)
|
||||
{
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, cm->Name, param));
|
||||
FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, setter, cm->Name, param));
|
||||
|
||||
/* Setting v/h/o/a/q etc */
|
||||
if (cm->Type == MODE_STATUS)
|
||||
@@ -535,7 +537,7 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m,
|
||||
}
|
||||
|
||||
ModeManager::StackerAdd(bi, this, cm, true, param);
|
||||
SetModeInternal(cm, param, EnforceMLock);
|
||||
SetModeInternal(bi ? finduser(bi->nick) : NULL, cm, param, EnforceMLock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -587,7 +589,7 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶
|
||||
}
|
||||
|
||||
ModeManager::StackerAdd(bi, this, cm, false, realparam);
|
||||
RemoveModeInternal(cm, realparam, EnforceMLock);
|
||||
RemoveModeInternal(bi ? finduser(bi->nick) : NULL, cm, realparam, EnforceMLock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -725,9 +727,9 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf
|
||||
if (cm->Type == MODE_REGULAR)
|
||||
{
|
||||
if (add)
|
||||
this->SetModeInternal(cm, "", EnforceMLock);
|
||||
this->SetModeInternal(setter, cm, "", EnforceMLock);
|
||||
else
|
||||
this->RemoveModeInternal(cm, "", EnforceMLock);
|
||||
this->RemoveModeInternal(setter, cm, "", EnforceMLock);
|
||||
continue;
|
||||
}
|
||||
else if (cm->Type == MODE_PARAM)
|
||||
@@ -736,7 +738,7 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf
|
||||
|
||||
if (!add && cmp->MinusNoArg)
|
||||
{
|
||||
this->RemoveModeInternal(cm, "", EnforceMLock);
|
||||
this->RemoveModeInternal(setter, cm, "", EnforceMLock);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -750,9 +752,9 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf
|
||||
paramstring += " " + token;
|
||||
|
||||
if (add)
|
||||
this->SetModeInternal(cm, token, EnforceMLock);
|
||||
this->SetModeInternal(setter, cm, token, EnforceMLock);
|
||||
else
|
||||
this->RemoveModeInternal(cm, token, EnforceMLock);
|
||||
this->RemoveModeInternal(setter, cm, token, EnforceMLock);
|
||||
}
|
||||
else
|
||||
Log() << "warning: Channel::SetModesInternal() recieved more modes requiring params than params, modes: " << mode;
|
||||
@@ -874,7 +876,7 @@ void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string
|
||||
|
||||
Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << user << " to " << newtopic;
|
||||
|
||||
FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic));
|
||||
FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, u, this->topic));
|
||||
|
||||
if (this->ci)
|
||||
{
|
||||
@@ -891,7 +893,7 @@ void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtop
|
||||
|
||||
ircdproto->SendTopic(this->ci->WhoSends(), this);
|
||||
|
||||
FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic));
|
||||
FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, u, this->topic));
|
||||
|
||||
if (this->ci)
|
||||
{
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ Server::Server(Server *uplink, const Anope::string &name, unsigned hops, const A
|
||||
if (cm == NULL)
|
||||
cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
|
||||
if (cm && cm->Type == MODE_STATUS)
|
||||
c->SetModeInternal(cm, bi->nick);
|
||||
c->SetModeInternal(bi ? finduser(bi->nick) : NULL, cm, bi->nick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user