diff options
-rw-r--r-- | data/botserv.example.conf | 26 | ||||
-rw-r--r-- | data/chanserv.example.conf | 180 | ||||
-rw-r--r-- | data/modules.example.conf | 2 | ||||
-rw-r--r-- | include/logger.h | 4 | ||||
-rw-r--r-- | include/modules/cs_log.h | 2 | ||||
-rw-r--r-- | modules/commands/cs_log.cpp | 155 | ||||
-rw-r--r-- | modules/commands/cs_mode.cpp | 137 | ||||
-rw-r--r-- | src/logger.cpp | 18 |
8 files changed, 341 insertions, 183 deletions
diff --git a/data/botserv.example.conf b/data/botserv.example.conf index 299289416..e93810c81 100644 --- a/data/botserv.example.conf +++ b/data/botserv.example.conf @@ -352,10 +352,16 @@ fantasy { name = "AKICK"; command = "chanserv/akick"; } fantasy { name = "AOP"; command = "chanserv/xop"; } fantasy { name = "BAN"; command = "chanserv/ban"; } fantasy { name = "CLONE"; command = "chanserv/clone"; } +fantasy { name = "DEHALFOP"; command = "chanserv/modes"; } +fantasy { name = "DEOP"; command = "chanserv/modes"; } +fantasy { name = "DEOWNER"; command = "chanserv/modes"; } +fantasy { name = "DEPROTECT"; command = "chanserv/modes"; } +fantasy { name = "DEVOICE"; command = "chanserv/modes"; } fantasy { name = "DOWN"; command = "chanserv/down"; } fantasy { name = "ENFORCE"; command = "chanserv/enforce"; } fantasy { name = "ENTRYMSG"; command = "chanserv/entrymsg"; } fantasy { name = "FLAGS"; command = "chanserv/flags"; } +fantasy { name = "HALFOP"; command = "chanserv/modes"; } fantasy { name = "HELP"; command = "generic/help"; prepend_channel = false; } fantasy { name = "HOP"; command = "chanserv/xop"; } fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = false; } @@ -367,6 +373,9 @@ fantasy { name = "LEVELS"; command = "chanserv/levels"; } fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = false; } fantasy { name = "LOG"; command = "chanserv/log"; } fantasy { name = "MODE"; command = "chanserv/mode"; } +fantasy { name = "OP"; command = "chanserv/modes"; } +fantasy { name = "OWNER"; command = "chanserv/modes"; } +fantasy { name = "PROTECT"; command = "chanserv/modes"; } fantasy { name = "QOP"; command = "chanserv/xop"; } fantasy { name = "SEEN"; command = "chanserv/seen"; prepend_channel = false; } fantasy { name = "SOP"; command = "chanserv/xop"; } @@ -377,20 +386,5 @@ fantasy { name = "TOPIC"; command = "chanserv/topic"; } fantasy { name = "UNBAN"; command = "chanserv/unban"; } fantasy { name = "UNSUSPEND"; command = "chanserv/unsuspend"; permission = "chanserv/suspend"; } fantasy { name = "UP"; command = "chanserv/up"; } +fantasy { name = "VOICE"; command = "chanserv/modes"; } fantasy { name = "VOP"; command = "chanserv/xop"; } - -/* Use m_rewrite to rewrite the op, deop, etc. fantasy commands (see chanserv.conf). */ -fantasy { name = "OWNER"; command = "rewrite"; } -fantasy { name = "DEOWNER"; command = "rewrite"; } - -fantasy { name = "PROTECT"; command = "rewrite"; } -fantasy { name = "DEPROTECT"; command = "rewrite"; } - -fantasy { name = "OP"; command = "rewrite"; } -fantasy { name = "DEOP"; command = "rewrite"; } - -fantasy { name = "HALFOP"; command = "rewrite"; } -fantasy { name = "DEHALFOP"; command = "rewrite"; } - -fantasy { name = "VOICE"; command = "rewrite"; } -fantasy { name = "DEVOICE"; command = "rewrite"; } diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index fb7daf26a..1f7cd0bea 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -558,7 +558,7 @@ privilege /* * OP privilege. * - * Used by chanserv/mode, chanserv/op and chanserv/deop. + * Used by chanserv/mode, chanserv/modes. * * Users with this permission can use ChanServ to op and deop * others in the channel. @@ -575,7 +575,7 @@ privilege /* * OPME privilege. * - * Used by chanserv/mode, chanserv/op and chanserv/deop. + * Used by chanserv/mode, chanserv/modes. * * Users with this permission can use ChanServ to op and deop * themselves in the channel. @@ -592,7 +592,7 @@ privilege /* * OWNER privilege. * - * Used by chanserv/mode, chanserv/owner and chanserv/deowner. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to owner and deowner * others in the channel. @@ -609,7 +609,7 @@ privilege /* * OWNERME privilege. * - * Used by chanserv/mode, chanserv/owner and chanserv/deowner. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to owner and deowner * themselves in the channel. @@ -626,7 +626,7 @@ privilege /* * PROTECT privilege. * - * Used by chanserv/mode, chanserv/protect and chanserv/deprotect. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to protect and deprotect * others in the channel. @@ -643,7 +643,7 @@ privilege /* * PROTECTME privilege. * - * Used by chanserv/mode, chanserv/protect and chanserv/deprotect. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to protect and deprotect * themselves in the channel. @@ -745,7 +745,7 @@ privilege /* * VOICE privilege. * - * Used by chanserv/mode, chanserv/voice and chanserv/devoice. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to voice and devoice * others in the channel. @@ -762,7 +762,7 @@ privilege /* * VOICEME privilege. * - * Used by chanserv/mode, chanserv/voice and chanserv/devoice. + * Used by chanserv/mode and chanserv/modes. * * Users with this permission can use ChanServ to voice and devoice * themselves in the channel. @@ -989,19 +989,65 @@ command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/pr * * Use for configuring what actions on channels are logged and where. */ -module { name = "cs_log" } +module +{ + name = "cs_log" + + /* Default log settings for newly registered channels */ + + #default + { + command = "chanserv/modes" + method = "MESSAGE @" + } + + #default + { + service = "ChanServ" + command = "ACCESS" + method = "MESSAGE @" + } + + #default + { + command = "chanserv/xop" + method = "MESSAGE @" + } + + #default + { + service = "ChanServ" + command = "FLAGS" + method = "MESSAGE @" + } +} command { service = "ChanServ"; name = "LOG"; command = "chanserv/log"; group = "chanserv/management"; } /* * cs_mode * - * Provides the command chanserv/mode. + * Provides the command chanserv/mode and chanserv/modes. * * Used for changing mode locks and changing modes. */ module { name = "cs_mode" } command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; } +command { service = "ChanServ"; name = "OWNER"; command = "chanserv/modes"; group = "chanserv/status"; set = "OWNER" } +command { service = "ChanServ"; name = "DEOWNER"; command = "chanserv/modes"; group = "chanserv/status"; unset = "OWNER" } + +command { service = "ChanServ"; name = "PROTECT"; command = "chanserv/modes"; group = "chanserv/status"; set = "PROTECT" } +command { service = "ChanServ"; name = "DEPROTECT"; command = "chanserv/modes"; group = "chanserv/status"; unset = "PROTECT" } + +command { service = "ChanServ"; name = "OP"; command = "chanserv/modes"; group = "chanserv/status"; set = "OP" } +command { service = "ChanServ"; name = "DEOP"; command = "chanserv/modes"; group = "chanserv/status"; unset = "OP" } + +command { service = "ChanServ"; name = "HALFOP"; command = "chanserv/modes"; group = "chanserv/status"; set = "HALFOP" } +command { service = "ChanServ"; name = "DEHALFOP"; command = "chanserv/modes"; group = "chanserv/status"; unset = "HALFOP" } + +command { service = "ChanServ"; name = "VOICE"; command = "chanserv/modes"; group = "chanserv/status"; set = "VOICE" } +command { service = "ChanServ"; name = "DEVOICE"; command = "chanserv/modes"; group = "chanserv/status"; unset = "VOICE" } + /* * cs_register * @@ -1192,120 +1238,6 @@ command { service = "ChanServ"; name = "HOP"; command = "chanserv/xop"; group = command { service = "ChanServ"; name = "VOP"; command = "chanserv/xop"; group = "chanserv/access"; } -/* Use m_rewrite to rewrite the op, deop, etc. commands (see modules.conf). */ - -/* OWNER and DEOWNER commands */ -command -{ - service = "ChanServ"; name = "OWNER"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "OWNER $" - rewrite_target = "MODE $1 SET +q $2" - - rewrite_description = _("Gives you or a specified nick owner status on a channel") -} -command -{ - service = "ChanServ"; name = "DEOWNER"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "DEOWNER $" - rewrite_target = "MODE $1 SET -q $2" - - rewrite_description = _("Removes owner status from you or a specified nick on a channel") -} - -/* PROTECT and DEPROTECT commands */ -command -{ - service = "ChanServ"; name = "PROTECT"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "PROTECT $" - rewrite_target = "MODE $1 SET +a $2" - - rewrite_description = _("Protects you or a specified nick on a channel") -} -command -{ - service = "ChanServ"; name = "DEPROTECT"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "DEPROTECT $" - rewrite_target = "MODE $1 SET -a $2" - - rewrite_description = _("Deprotects you or a specified nick on a channel") -} - -/* OP and DEOP commands */ -command -{ - service = "ChanServ"; name = "OP"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "OP $" - rewrite_target = "MODE $1 SET +o $2" - - rewrite_description = _("Gives operator status to you or a specified nick on a channel") -} -command -{ - service = "ChanServ"; name = "DEOP"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "DEOP $" - rewrite_target = "MODE $1 SET -o $2"; - - rewrite_description = _("Deops you or a specified nick on a channel") -} - -/* HALFOP and DEHALFOP commands */ -command -{ - service = "ChanServ"; name = "HALFOP"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "HALFOP $" - rewrite_target = "MODE $1 SET +h $2" - - rewrite_description = _("Halfops you or a specified nick on a channel") - -} -command -{ - service = "ChanServ"; name = "DEHALFOP"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "DEHALFOP $" - rewrite_target = "MODE $1 SET -h $2" - - rewrite_description = _("Dehalfops you or a specified nick on a channel") -} - -/* VOICE and DEVOICE commands */ -command -{ - service = "ChanServ"; name = "VOICE"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "VOICE $" - rewrite_target = "MODE $1 SET +v $2" - - rewrite_description = _("Voices you or a specified nick on a channel") -} -command -{ - service = "ChanServ"; name = "DEVOICE"; command = "rewrite"; group = "chanserv/status" - - rewrite = true - rewrite_source = "DEVOICE $" - rewrite_target = "MODE $1 SET -v $2" - - rewrite_description = _("Devoices you or a specified nick on a channel") -} - - /* * Extra ChanServ related modules. */ diff --git a/data/modules.example.conf b/data/modules.example.conf index 2c01245a4..28bef2850 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -555,7 +555,7 @@ module { name = "help" } * * Allows rewriting commands sent to/from clients. */ -module { name = "m_rewrite" } +#module { name = "m_rewrite" } #command { service = "ChanServ"; name = "CLEAR"; command = "rewrite" diff --git a/include/logger.h b/include/logger.h index b97839732..b24d7bbd6 100644 --- a/include/logger.h +++ b/include/logger.h @@ -55,14 +55,14 @@ class CoreExport Log public: /* Bot that should log this message */ const BotInfo *bi; - /* For commands, the user executing the command */ - Anope::string nick; /* For commands, the user executing the command, but might not always exist */ const User *u; /* For commands, the account executing teh command, but will not always exist */ const NickCore *nc; /* For commands, the command being executed */ Command *c; + /* For commands, the command source */ + CommandSource *source; /* Used for LOG_CHANNEL */ Channel *chan; /* For commands, the channel the command was executed on, will not always exist */ diff --git a/include/modules/cs_log.h b/include/modules/cs_log.h index 555a44e50..de3a75aa8 100644 --- a/include/modules/cs_log.h +++ b/include/modules/cs_log.h @@ -22,6 +22,7 @@ struct LogSetting Anope::string creator; time_t created; + virtual ~LogSetting() { } protected: LogSetting() { } }; @@ -36,6 +37,7 @@ struct LogSettings : Serialize::Checker<std::vector<LogSetting *> > } public: + virtual ~LogSettings() { } virtual LogSetting *Create() = 0; }; 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> ¶ms) 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 diff --git a/src/logger.cpp b/src/logger.cpp index f5b7ff55c..cd2dbd504 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -75,11 +75,11 @@ const Anope::string &LogFile::GetName() const return this->filename; } -Log::Log(LogType t, const Anope::string &cat, const BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), type(t), category(cat) +Log::Log(LogType t, const Anope::string &cat, const BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), type(t), category(cat) { } -Log::Log(LogType t, CommandSource &source, Command *_c, const ChannelInfo *_ci) : nick(source.GetNick()), u(source.GetUser()), nc(source.nc), c(_c), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t) +Log::Log(LogType t, CommandSource &src, Command *_c, const ChannelInfo *_ci) : u(src.GetUser()), nc(src.nc), c(_c), source(&src), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t) { if (!c) throw CoreException("Invalid pointers passed to Log::Log"); @@ -94,29 +94,29 @@ Log::Log(LogType t, CommandSource &source, Command *_c, const ChannelInfo *_ci) this->category = c->name; } -Log::Log(const User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(NULL), c(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), m(NULL), type(LOG_CHANNEL), category(cat) +Log::Log(const User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(NULL), c(NULL), source(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), m(NULL), type(LOG_CHANNEL), category(cat) { if (!chan) throw CoreException("Invalid pointers passed to Log::Log"); } -Log::Log(const User *_u, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat) +Log::Log(const User *_u, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat) { if (!u) throw CoreException("Invalid pointers passed to Log::Log"); } -Log::Log(Server *serv, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat) +Log::Log(Server *serv, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat) { if (!s) throw CoreException("Invalid pointer passed to Log::Log"); } -Log::Log(const BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat) +Log::Log(const BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat) { } -Log::Log(Module *mod, const Anope::string &cat) : bi(NULL), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat) +Log::Log(Module *mod, const Anope::string &cat) : bi(NULL), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat) { } @@ -182,10 +182,10 @@ Anope::string Log::BuildPrefix() const Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name; if (this->u) buffer += this->u->GetMask() + " used " + cname + " "; + else if (this->source) + buffer += this->source->GetNick() + " used " + cname + " "; else if (this->nc) buffer += this->nc->display + " used " + cname + " "; - else - buffer += this->nick + " used " + cname + " "; if (this->ci) buffer += "on " + this->ci->name + " "; break; |