summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/commands/cs_log.cpp155
-rw-r--r--modules/commands/cs_mode.cpp137
2 files changed, 261 insertions, 31 deletions
diff --git a/modules/commands/cs_log.cpp b/modules/commands/cs_log.cpp
index 4de7e31ee..96d959e2c 100644
--- a/modules/commands/cs_log.cpp
+++ b/modules/commands/cs_log.cpp
@@ -23,10 +23,13 @@ struct LogSettingImpl : LogSetting, Serializable
ChannelInfo *ci = ChannelInfo::Find(chan);
if (ci)
{
- LogSettings *ls = ci->Require<LogSettings>("logsettings");
- LogSettings::iterator it = std::find((*ls)->begin(), (*ls)->end(), this);
- if (it != (*ls)->end())
- (*ls)->erase(it);
+ LogSettings *ls = ci->GetExt<LogSettings>("logsettings");
+ if (ls)
+ {
+ LogSettings::iterator it = std::find((*ls)->begin(), (*ls)->end(), this);
+ if (it != (*ls)->end())
+ (*ls)->erase(it);
+ }
}
}
@@ -78,6 +81,16 @@ struct LogSettingsImpl : LogSettings
{
LogSettingsImpl(Extensible *) { }
+ ~LogSettingsImpl()
+ {
+ for (iterator it = (*this)->begin(); it != (*this)->end();)
+ {
+ LogSetting *ls = *it;
+ ++it;
+ delete ls;
+ }
+ }
+
LogSetting *Create() anope_override
{
return new LogSettingImpl();
@@ -120,7 +133,7 @@ public:
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Service"] = log->command_service;
- entry["Command"] = log->command_name;
+ entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name;
entry["Method"] = log->method;
entry[""] = log->extra;
list.AddEntry(entry);
@@ -153,14 +166,22 @@ public:
command_name = command.substr(sl + 1);
BotInfo *bi = BotInfo::Find(service, true);
- if (bi == NULL || bi->commands.count(command_name) == 0)
+ Anope::string service_name;
+
+ /* Allow either a command name or a service name. */
+ if (bi && bi->commands.count(command_name))
{
- source.Reply(_("%s is not a valid command."), command.c_str());
- return;
+ /* Get service name from command */
+ service_name = bi->commands[command_name].name;
}
-
- ServiceReference<Command> c_service("Command", bi->commands[command_name].name);
- if (!c_service)
+ else if (ServiceReference<Command>("Command", command))
+ {
+ /* This is the service name, don't use any specific command */
+ service_name = command;
+ bi = NULL;
+ command_name.clear();
+ }
+ else
{
source.Reply(_("%s is not a valid command."), command.c_str());
return;
@@ -185,19 +206,19 @@ public:
{
LogSetting *log = (*ls)->at(i - 1);
- if (log->service_name == bi->commands[command_name].name && log->method.equals_ci(method))
+ if (log->service_name == service_name && log->method.equals_ci(method))
{
if (log->extra == extra)
{
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to remove logging for " << (!log->command_name.empty() ? log->command_name : log->service_name) << " with method " << method << (extra == "" ? "" : " ") << extra;
+ source.Reply(_("Logging for command %s on %s with log method %s%s%s has been removed."), !log->command_name.empty() ? log->command_name.c_str() : log->service_name.c_str(), !log->command_service.empty() ? log->command_service.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
delete log;
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to remove logging for " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
- source.Reply(_("Logging for command %s on %s with log method %s%s%s has been removed."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
}
else
{
log->extra = extra;
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to change logging for " << command << " to method " << method << (extra == "" ? "" : " ") << extra;
- source.Reply(_("Logging changed for command %s on %s, now using log method %s%s%s."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to change logging for " << (!log->command_name.empty() ? log->command_name : log->service_name) << " to method " << method << (extra == "" ? "" : " ") << extra;
+ source.Reply(_("Logging changed for command %s on %s, now using log method %s%s%s has been removed."), !log->command_name.empty() ? log->command_name.c_str() : log->service_name.c_str(), !log->command_service.empty() ? log->command_service.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
}
return;
}
@@ -205,8 +226,9 @@ public:
LogSetting *log = new LogSettingImpl();
log->chan = ci->name;
- log->service_name = bi->commands[command_name].name;
- log->command_service = bi->nick;
+ log->service_name = service_name;
+ if (bi)
+ log->command_service = bi->nick;
log->command_name = command_name;
log->method = method;
log->extra = extra;
@@ -217,7 +239,7 @@ public:
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to log " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
- source.Reply(_("Logging is now active for command %s on %s, using log method %s%s%s."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
+ source.Reply(_("Logging is now active for command %s on %s, using log method %s%s%s."), !command_name.empty() ? command_name.c_str() : service_name.c_str(), bi ? bi->nick.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
}
else
this->OnSyntaxError(source, "");
@@ -258,6 +280,13 @@ class CSLog : public Module
ExtensibleItem<LogSettingsImpl> logsettings;
Serialize::Type logsetting_type;
+ struct LogDefault
+ {
+ Anope::string service, command, method;
+ };
+
+ std::vector<LogDefault> defaults;
+
public:
CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
MSService("MemoServService", "MemoServ"), commandcslog(this), logsettings(this, "logsettings"),
@@ -266,6 +295,58 @@ class CSLog : public Module
}
+ void OnReload(Configuration::Conf *conf) anope_override
+ {
+ Configuration::Block *block = conf->GetModule(this);
+ defaults.clear();
+
+ for (int i = 0; i < block->CountBlock("default"); ++i)
+ {
+ Configuration::Block *def = block->GetBlock("default", i);
+
+ LogDefault ld;
+
+ ld.service = def->Get<const Anope::string>("service");
+ ld.command = def->Get<const Anope::string>("command");
+ ld.method = def->Get<const Anope::string>("method");
+
+ defaults.push_back(ld);
+ }
+ }
+
+ void OnChanRegistered(ChannelInfo *ci) anope_override
+ {
+ if (defaults.empty())
+ return;
+
+ LogSettings *ls = logsettings.Require(ci);
+ for (unsigned i = 0; i < defaults.size(); ++i)
+ {
+ LogDefault &d = defaults[i];
+
+ LogSetting *log = new LogSettingImpl();
+ log->chan = ci->name;
+
+ if (!d.service.empty())
+ {
+ log->service_name = d.service.lower() + "/" + d.command.lower();
+ log->command_service = d.service;
+ log->command_name = d.command;
+ }
+ else
+ log->service_name = d.command;
+
+ spacesepstream sep(d.method);
+ sep.GetToken(log->method);
+ log->extra = sep.GetRemaining();
+
+ log->created = Anope::CurTime;
+ log->creator = ci->GetFounder() ? ci->GetFounder()->display : "(default)";
+
+ (*ls)->push_back(log);
+ }
+ }
+
void OnLog(Log *l) anope_override
{
if (l->type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced())
@@ -277,20 +358,34 @@ class CSLog : public Module
{
const LogSetting *log = (*ls)->at(i);
- if (log->service_name == l->c->name)
+ /* wrong command */
+ if (log->service_name != l->c->name)
+ continue;
+
+ /* if a command name is given check the service and the command */
+ if (!log->command_name.empty())
{
- Anope::string buffer = l->u->nick + " used " + log->command_name + " " + l->buf.str();
+ /* wrong service (only check if not a fantasy command, though) */
+ if (!l->source->c && log->command_service != l->source->service->nick)
+ continue;
- if (log->method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
- {
- IRCD->SendPrivmsg(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
- l->ci->bi->lastmsg = Anope::CurTime;
- }
- else if (log->method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
- IRCD->SendNotice(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
- else if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL)
- MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
+ if (!log->command_name.equals_ci(l->source->command))
+ continue;
+ }
+
+ Anope::string buffer = l->u->nick + " used " + l->source->command.upper() + " " + l->buf.str();
+
+ if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL)
+ MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
+ else if (l->source->c)
+ /* Sending a channel message or notice in response to a fantasy command */;
+ else if (log->method.equals_ci("MESSAGE") && l->ci->c)
+ {
+ IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
+ l->ci->WhoSends()->lastmsg = Anope::CurTime;
}
+ else if (log->method.equals_ci("NOTICE") && l->ci->c)
+ IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
}
}
};
diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp
index 1299bc543..f5c98d487 100644
--- a/modules/commands/cs_mode.cpp
+++ b/modules/commands/cs_mode.cpp
@@ -705,17 +705,152 @@ class CommandCSMode : public Command
}
};
+static Anope::map<std::pair<bool, Anope::string> > modes;
+
+class CommandCSModes : public Command
+{
+ public:
+ CommandCSModes(Module *creator) : Command(creator, "chanserv/modes", 1, 2)
+ {
+ this->SetSyntax(_("\037channel\037 [\037user\037]"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ User *u = source.GetUser(),
+ *targ = params.size() > 1 ? User::Find(params[1], true) : u;
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+
+ if (!targ)
+ {
+ if (params.size() > 1)
+ source.Reply(NICK_X_NOT_IN_USE, params[1].c_str());
+ return;
+ }
+
+ if (!ci)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+ else if (!ci->c)
+ {
+ source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
+ return;
+ }
+
+ AccessGroup u_access = source.AccessFor(ci), targ_access = ci->AccessFor(targ);
+ const std::pair<bool, Anope::string> &m = modes[source.command];
+
+ if (m.second.empty())
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (!source.HasPriv("chanserv/administration"))
+ {
+ if (u == targ ? !u_access.HasPriv(m.second + "ME") : !u_access.HasPriv(m.second))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (!m.first && u != targ && (targ->IsProtected() || (ci->HasExt("PEACE") && targ_access >= u_access)))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+ }
+
+ if (!ci->c->FindUser(targ))
+ {
+ source.Reply(NICK_X_NOT_ON_CHAN, targ->nick.c_str(), ci->name.c_str());
+ return;
+ }
+
+ if (m.first)
+ ci->c->SetMode(NULL, m.second, targ->GetUID());
+ else
+ ci->c->RemoveMode(NULL, m.second, targ->GetUID());
+
+ Log(LOG_COMMAND, source, this, ci) << "on " << targ->nick;
+ }
+
+ const Anope::string GetDesc(CommandSource &source) const anope_override
+ {
+ const std::pair<bool, Anope::string> &m = modes[source.command];
+ if (!m.second.empty())
+ {
+ if (m.first)
+ return Anope::printf(_("Gives you or the specific nick %s status on a channel"), m.second.c_str());
+ else
+ return Anope::printf(_("Removes %s status from you or the specific on a channel"), m.second.c_str());
+ }
+ else
+ return "";
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ {
+ const std::pair<bool, Anope::string> &m = modes[source.command];
+ if (m.second.empty())
+ return false;
+
+ this->SendSyntax(source);
+ source.Reply(" ");
+ if (m.first)
+ source.Reply(_("Gives %s status to the selected nick on a channel. If \037nick\037 is\n"
+ "not given, it will %s you."),
+ m.second.upper().c_str(), m.second.lower().c_str());
+ else
+ source.Reply(_("Removes %s status from the selected nick on a channel. If \037nick\037 is\n"
+ "not given, it will de%s you."),
+ m.second.upper().c_str(), m.second.lower().c_str());
+ source.Reply(" ");
+ source.Reply(_("You must have the %s(ME) privilege on the channel to use this command."), m.second.upper().c_str());
+
+ return true;
+ }
+};
+
class CSMode : public Module
{
CommandCSMode commandcsmode;
+ CommandCSModes commandcsmodes;
ExtensibleItem<ModeLocksImpl> modelocks;
Serialize::Type modelocks_type;
public:
CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcsmode(this), modelocks(this, "modelocks"), modelocks_type("ModeLock", ModeLockImpl::Unserialize)
+ commandcsmode(this), commandcsmodes(this),
+ modelocks(this, "modelocks"), modelocks_type("ModeLock", ModeLockImpl::Unserialize)
+ {
+
+ }
+
+ void OnReload(Configuration::Conf *conf) anope_override
{
+ modes.clear();
+ for (int i = 0; i < conf->CountBlock("command"); ++i)
+ {
+ Configuration::Block *block = conf->GetBlock("command", i);
+
+ const Anope::string &cname = block->Get<const Anope::string>("name"),
+ &cmd = block->Get<const Anope::string>("command");
+
+ if (cname.empty() || cmd != "chanserv/modes")
+ continue;
+
+ const Anope::string &set = block->Get<const Anope::string>("set"),
+ &unset = block->Get<const Anope::string>("unset");
+
+ if (set.empty() && unset.empty())
+ continue;
+
+ modes[cname] = std::make_pair(!set.empty(), !set.empty() ? set : unset);
+ }
}
EventReturn OnCheckModes(Channel *c) anope_override