00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015 #include "../extra/sql.h"
00016
00017 class MySQLInterface : public SQL::Interface
00018 {
00019 public:
00020 MySQLInterface(Module *o) : SQL::Interface(o) { }
00021
00022 void OnResult(const SQL::Result &r) anope_override
00023 {
00024 }
00025
00026 void OnError(const SQL::Result &r) anope_override
00027 {
00028 if (!r.GetQuery().query.empty())
00029 Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
00030 else
00031 Log(LOG_DEBUG) << "Chanstats: Error executing query: " << r.GetError();
00032 }
00033 };
00034
00035
00036 class CommandCSStats : public Command
00037 {
00038 public:
00039 CommandCSStats(Module *creator) : Command (creator, "chanserv/stats", 0, 2)
00040 {
00041 this->SetDesc(_("Displays your Channel Stats"));
00042 this->SetSyntax(_("\037nick\037"));
00043 }
00044
00045 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
00046 };
00047
00048 class CommandCSGStats : public Command
00049 {
00050 public:
00051 CommandCSGStats(Module *creator) : Command (creator, "chanserv/gstats", 0, 2)
00052 {
00053 this->SetDesc(_("Displays your Global Stats"));
00054 this->SetSyntax(_("\037nick\037"));
00055 }
00056
00057 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms);
00058 };
00059
00060
00061 class CSStats;
00062 static CSStats *me;
00063 class CSStats : public Module
00064 {
00065 CommandCSStats commandcsstats;
00066 CommandCSGStats commandcsgstats;
00067 ServiceReference<SQL::Provider> sql;
00068 MySQLInterface sqlinterface;
00069 Anope::string prefix;
00070 public:
00071 CSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00072 commandcsstats(this), commandcsgstats(this), sql("", ""), sqlinterface(this)
00073 {
00074 me = this;
00075 this->SetAuthor("Anope");
00076
00077 Implementation i[] = { I_OnReload };
00078 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00079 this->OnReload();
00080 }
00081
00082 void OnReload() anope_override
00083 {
00084 ConfigReader config;
00085 prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
00086 Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
00087 this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
00088 }
00089
00090 SQL::Result RunQuery(const SQL::Query &query)
00091 {
00092 if (!this->sql)
00093 throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
00094
00095 SQL::Result res = this->sql->RunQuery(query);
00096 if (!res.GetError().empty())
00097 throw SQL::Exception(res.GetError());
00098 return res;
00099 }
00100
00101 void DoStats(CommandSource &source, const bool is_global, const std::vector<Anope::string> ¶ms)
00102 {
00103 if (!source.c)
00104 return;
00105
00106 Anope::string display;
00107 if (params.empty())
00108 display = source.nc->display;
00109 else if (const NickAlias *na = NickAlias::Find(params[0]))
00110 display = na->nc->display;
00111 else
00112 {
00113 source.Reply(_("%s not found."), params[0].c_str());
00114 return;
00115 }
00116
00117 try
00118 {
00119 SQL::Query query;
00120 query = "SELECT letters, words, line, smileys_happy+smileys_sad+smileys_other as smileys,"
00121 "actions FROM `" + prefix + "chanstats` "
00122 "WHERE `nick` = @nick@ AND `chan` = @channel@ AND `type` = 'total';";
00123 if (is_global)
00124 query.SetValue("channel", "");
00125 else
00126 query.SetValue("channel", source.c->ci->name);
00127 query.SetValue("nick", display);
00128 SQL::Result res = this->RunQuery(query);
00129
00130 if (res.Rows() > 0)
00131 {
00132 if (is_global)
00133 source.Reply(_("Network stats for %s:"), display.c_str());
00134 else
00135 source.Reply(_("Channel stats for %s on %s:"), display.c_str(), source.c->name.c_str());
00136
00137 source.Reply(_("letters: %s, words: %s, lines: %s, smileys %s, actions: %s"),
00138 res.Get(0, "letters").c_str(), res.Get(0, "words").c_str(),
00139 res.Get(0, "line").c_str(), res.Get(0, "smileys").c_str(),
00140 res.Get(0, "actions").c_str());
00141 }
00142 else
00143 source.Reply(_("No stats for %s."), display.c_str());
00144 }
00145 catch (const SQL::Exception &ex)
00146 {
00147 Log(LOG_DEBUG) << ex.GetReason();
00148 }
00149
00150 }
00151 };
00152
00153 void CommandCSStats::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
00154 {
00155 me->DoStats(source, false, params);
00156 }
00157
00158 void CommandCSGStats::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
00159 {
00160 me->DoStats(source, true, params);
00161 }
00162
00163 MODULE_INIT(CSStats)
00164