summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/commands/cs_access.cpp2
-rw-r--r--modules/commands/cs_log.cpp198
-rw-r--r--modules/database/db_plain.cpp20
-rw-r--r--modules/protocol/bahamut.cpp5
-rw-r--r--modules/protocol/inspircd-ts6.h5
-rw-r--r--modules/protocol/inspircd11.cpp5
-rw-r--r--modules/protocol/plexus.cpp5
-rw-r--r--modules/protocol/ratbox.cpp5
-rw-r--r--modules/protocol/unreal.cpp7
9 files changed, 219 insertions, 33 deletions
diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp
index 8c3e1a1ca..c5f8313f0 100644
--- a/modules/commands/cs_access.cpp
+++ b/modules/commands/cs_access.cpp
@@ -319,7 +319,7 @@ class CommandCSAccess : public Command
FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, access));
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level;
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " as level " << level;
source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->mask.c_str(), ci->name.c_str(), level);
return;
diff --git a/modules/commands/cs_log.cpp b/modules/commands/cs_log.cpp
new file mode 100644
index 000000000..dc7fe0999
--- /dev/null
+++ b/modules/commands/cs_log.cpp
@@ -0,0 +1,198 @@
+/* ChanServ core functions
+ *
+ * (C) 2003-2011 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 "memoserv.h"
+
+class CommandCSLog : public Command
+{
+public:
+ CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4)
+ {
+ this->SetDesc(_("Configures channel logging settings"));
+ this->SetSyntax(_("\037channel\037"));
+ this->SetSyntax(_("\037channel\037 \037command\037 [\037method\037]"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params)
+ {
+ const Anope::string &channel = params[0];
+
+ User *u = source.u;
+ ChannelInfo *ci = cs_findchan(channel);
+ if (ci == NULL)
+ source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str());
+ else if (!ci->AccessFor(u).HasPriv("SET"))
+ source.Reply(ACCESS_DENIED);
+ else if (params.size() == 1)
+ {
+ if (ci->log_settings.empty())
+ source.Reply(_("There currently are no logging configurations for %s."), ci->name.c_str());
+ else
+ {
+ source.Reply(_("Log list for %s:"), ci->name.c_str());
+ for (unsigned i = 0; i < ci->log_settings.size(); ++i)
+ {
+ LogSetting &log = ci->log_settings[i];
+
+ source.Reply("%d: %s %s, %s %s", i + 1, log.command_service.c_str(), log.command_name.c_str(), log.method.c_str(), log.extra.c_str());
+ }
+ }
+ }
+ else if (params.size() > 2)
+ {
+ const Anope::string &command = params[1];
+ const Anope::string &method = params[2];
+ const Anope::string &extra = params.size() > 3 ? params[3] : "";
+
+ size_t sl = command.find('/');
+ if (sl == Anope::string::npos)
+ {
+ source.Reply(_("%s is not a valid command."), command.c_str());
+ return;
+ }
+
+ Anope::string service = command.substr(0, sl),
+ command_name = command.substr(sl + 1);
+ BotInfo *bi = findbot(service);
+
+ if (bi == NULL || bi->commands.count(command_name) == 0)
+ {
+ source.Reply(_("%s is not a valid command."), command.c_str());
+ return;
+ }
+
+ service_reference<Command> c_service(bi->commands[command_name].name);
+ if (!c_service)
+ {
+ source.Reply(_("%s is not a valid command."), command.c_str());
+ return;
+ }
+
+ if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO"))
+ {
+ source.Reply(_("%s is not a valid logging method."), method.c_str());
+ return;
+ }
+
+ for (unsigned i = 0; i < extra.length(); ++i)
+ if (ModeManager::GetStatusChar(extra[i]) == 0)
+ {
+ source.Reply(_("%c is an unknown status mode."), extra[i]);
+ return;
+ }
+
+ for (unsigned i = ci->log_settings.size(); i > 0; --i)
+ {
+ LogSetting &log = ci->log_settings[i - 1];
+
+ if (log.service_name == bi->commands[command_name].name && log.method.equals_ci(method))
+ {
+ if (log.extra == extra)
+ {
+ ci->log_settings.erase(ci->log_settings.begin() + i - 1);
+ source.Reply(_("Logging for command %s on %s with method %s%s has been removed."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : extra.c_str());
+ }
+ else
+ {
+ log.extra = extra;
+ source.Reply(_("Logging changed for command %s on %s, using log method %s %s"), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.c_str());
+ }
+ return;
+ }
+ }
+
+ LogSetting log;
+ log.service_name = bi->commands[command_name].name;
+ log.command_service = bi->nick;
+ log.command_name = command_name;
+ log.method = method;
+ log.extra = extra;
+ log.created = Anope::CurTime;
+ log.creator = u->nick;
+
+ ci->log_settings.push_back(log);
+ Log(LOG_COMMAND, u, this, ci) << command << " " << method << " " << extra;
+
+ source.Reply(_("Logging is now active for command %s on %s, using log method %s %s"), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand)
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("The %s command allows users to configure logging settings\n"
+ "for their channel. If no parameters are given this command\n"
+ "lists the current logging methods in place for this channel.\n"
+ " \n"
+ "Otherwise, \037command\037 must be a command name, and \037method\037\n"
+ "is one of the following logging methods:\n"
+ " \n"
+ " MESSAGE [status], NOTICE [status], MEMO\n"
+ " \n"
+ "Which are used to message, notice, and memo the channel respectively.\n"
+ "With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
+ "to your channel. Status may be a channel status such as @ or +.\n"
+ " \n"
+ "To remove a logging method use the same syntax as you would to add it.\n"
+ " \n"
+ "Example:\n"
+ " %s #anope chanserv/access MESSAGE @%\n"
+ " Would message any channel operators whenever someone used the\n"
+ " ACCESS command on ChanServ on the channel."),
+ source.command.c_str(), source.command.c_str());
+ return true;
+ }
+};
+
+class CSLog : public Module
+{
+ CommandCSLog commandcslog;
+
+ public:
+ CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcslog(this)
+ {
+ this->SetAuthor("Anope");
+
+ Implementation i[] = { I_OnLog };
+ ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
+ }
+
+ void OnLog(Log *l)
+ {
+ if (l->Type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced())
+ return;
+
+ for (unsigned i = l->ci->log_settings.size(); i > 0; --i)
+ {
+ LogSetting &log = l->ci->log_settings[i - 1];
+
+ if (log.service_name == l->c->name)
+ {
+ Anope::string buffer = l->u->nick + " used " + log.command_name + " " + l->buf.str();
+
+ if (log.method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
+ ircdproto->SendPrivmsg(l->ci->bi, log.extra + l->ci->c->name, "%s", buffer.c_str());
+ else if (log.method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
+ ircdproto->SendNotice(l->ci->bi, log.extra + l->ci->c->name, "%s", buffer.c_str());
+ else if (log.method.equals_ci("MEMO") && memoserv && l->ci->WhoSends() != NULL)
+ memoserv->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
+ }
+ }
+ }
+};
+
+MODULE_INIT(CSLog)
diff --git a/modules/database/db_plain.cpp b/modules/database/db_plain.cpp
index dfcddfcfe..fffa02c87 100644
--- a/modules/database/db_plain.cpp
+++ b/modules/database/db_plain.cpp
@@ -561,6 +561,20 @@ class DBPlain : public Module
ak->SetFlag(AK_ISNICK);
}
+ else if (key.equals_ci("LOG"))
+ {
+ LogSetting l;
+
+ l.service_name = params[0];
+ l.command_service = params[1];
+ l.command_name = params[2];
+ l.method = params[3];
+ l.creator = params[4];
+ l.created = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
+ l.extra = params.size() > 6 ? params[6] : "";
+
+ ci->log_settings.push_back(l);
+ }
else if (key.equals_ci("MLOCK"))
{
bool set = params[0] == "1" ? true : false;
@@ -785,6 +799,12 @@ class DBPlain : public Module
db_buffer << ci->GetAkick(k)->reason;
db_buffer << endl;
}
+ for (unsigned k = 0, end = ci->log_settings.size(); k < end; ++k)
+ {
+ LogSetting &l = ci->log_settings[k];
+
+ db_buffer << "MD LOG " << l.service_name << " " << l.command_service << " " << l.command_name << " " << l.method << " " << l.creator << " " << l.created << " " << l.extra << endl;
+ }
{
std::vector<Anope::string> mlocks;
if (ci->GetExtRegular("db_mlock", mlocks))
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp
index 9aae47086..008c4dd32 100644
--- a/modules/protocol/bahamut.cpp
+++ b/modules/protocol/bahamut.cpp
@@ -201,11 +201,6 @@ class BahamutIRCdProto : public IRCDProto
send_cmd("", "BURST 0");
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf)
{
if (!buf.empty())
diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h
index bb2c1cc9a..3603555c4 100644
--- a/modules/protocol/inspircd-ts6.h
+++ b/modules/protocol/inspircd-ts6.h
@@ -117,11 +117,6 @@ class InspIRCdTS6Proto : public IRCDProto
send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), user->nick.c_str());
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- send_cmd(Config->Numeric, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
/* SERVER services-dev.chatspike.net password 0 :Description here */
void SendServer(const Server *server)
{
diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp
index 2a1b4e435..8b51c93a6 100644
--- a/modules/protocol/inspircd11.cpp
+++ b/modules/protocol/inspircd11.cpp
@@ -150,11 +150,6 @@ class InspIRCdProto : public IRCDProto
send_cmd(source->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), user->nick.c_str());
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- send_cmd(Config->ServerName, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
/* SERVER services-dev.chatspike.net password 0 :Description here */
void SendServer(const Server *server)
{
diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp
index 8bc3e21b9..f31bfea6a 100644
--- a/modules/protocol/plexus.cpp
+++ b/modules/protocol/plexus.cpp
@@ -216,11 +216,6 @@ class PlexusProto : public IRCDProto
send_cmd(bi->GetUID(), "KICK %s %s", chan->name.c_str(), user->GetUID().c_str());
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
/* INVITE */
void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick)
{
diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp
index d4208760e..957564890 100644
--- a/modules/protocol/ratbox.cpp
+++ b/modules/protocol/ratbox.cpp
@@ -200,11 +200,6 @@ class RatboxProto : public IRCDProto
send_cmd(bi->GetUID(), "KICK %s %s", chan->name.c_str(), user->GetUID().c_str());
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
/* INVITE */
void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick)
{
diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp
index cbb23dcc5..cb6ec2091 100644
--- a/modules/protocol/unreal.cpp
+++ b/modules/protocol/unreal.cpp
@@ -154,13 +154,6 @@ class UnrealIRCdProto : public IRCDProto
send_cmd(source->nick, "H %s %s", chan->name.c_str(), user->nick.c_str());
}
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
- {
- if (buf.empty())
- return;
- send_cmd(source->nick, "B @%s :%s", dest->name.c_str(), buf.c_str());
- }
-
/* SERVER name hop descript */
/* Unreal 3.2 actually sends some info about itself in the descript area */
void SendServer(const Server *server)