00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015 #include "memoserv.h"
00016
00017 class CommandCSLog : public Command
00018 {
00019 public:
00020 CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4)
00021 {
00022 this->SetDesc(_("Configures channel logging settings"));
00023 this->SetSyntax(_("\037channel\037"));
00024 this->SetSyntax(_("\037channel\037 \037command\037 \037method\037 [\037status\037]"));
00025 }
00026
00027 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00028 {
00029 const Anope::string &channel = params[0];
00030
00031 ChannelInfo *ci = ChannelInfo::Find(channel);
00032 if (ci == NULL)
00033 source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str());
00034 else if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/set"))
00035 source.Reply(ACCESS_DENIED);
00036 else if (params.size() == 1)
00037 {
00038 if (ci->log_settings->empty())
00039 source.Reply(_("There currently are no logging configurations for %s."), ci->name.c_str());
00040 else
00041 {
00042 ListFormatter list;
00043 list.AddColumn("Number").AddColumn("Service").AddColumn("Command").AddColumn("Method").AddColumn("");
00044
00045 for (unsigned i = 0; i < ci->log_settings->size(); ++i)
00046 {
00047 const LogSetting *log = ci->log_settings->at(i);
00048
00049 ListFormatter::ListEntry entry;
00050 entry["Number"] = stringify(i + 1);
00051 entry["Service"] = log->command_service;
00052 entry["Command"] = log->command_name;
00053 entry["Method"] = log->method;
00054 entry[""] = log->extra;
00055 list.AddEntry(entry);
00056 }
00057
00058 source.Reply(_("Log list for %s:"), ci->name.c_str());
00059
00060 std::vector<Anope::string> replies;
00061 list.Process(replies);
00062
00063 for (unsigned i = 0; i < replies.size(); ++i)
00064 source.Reply(replies[i]);
00065 }
00066 }
00067 else if (params.size() > 2)
00068 {
00069 const Anope::string &command = params[1];
00070 const Anope::string &method = params[2];
00071 const Anope::string &extra = params.size() > 3 ? params[3] : "";
00072
00073 size_t sl = command.find('/');
00074 if (sl == Anope::string::npos)
00075 {
00076 source.Reply(_("%s is not a valid command."), command.c_str());
00077 return;
00078 }
00079
00080 Anope::string service = command.substr(0, sl),
00081 command_name = command.substr(sl + 1);
00082 BotInfo *bi = BotInfo::Find(service, true);
00083
00084 if (bi == NULL || bi->commands.count(command_name) == 0)
00085 {
00086 source.Reply(_("%s is not a valid command."), command.c_str());
00087 return;
00088 }
00089
00090 ServiceReference<Command> c_service("Command", bi->commands[command_name].name);
00091 if (!c_service)
00092 {
00093 source.Reply(_("%s is not a valid command."), command.c_str());
00094 return;
00095 }
00096
00097 if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO"))
00098 {
00099 source.Reply(_("%s is not a valid logging method."), method.c_str());
00100 return;
00101 }
00102
00103 for (unsigned i = 0; i < extra.length(); ++i)
00104 if (ModeManager::GetStatusChar(extra[i]) == 0)
00105 {
00106 source.Reply(_("%c is an unknown status mode."), extra[i]);
00107 return;
00108 }
00109
00110 bool override = !source.AccessFor(ci).HasPriv("SET");
00111
00112 for (unsigned i = ci->log_settings->size(); i > 0; --i)
00113 {
00114 LogSetting *log = ci->log_settings->at(i - 1);
00115
00116 if (log->service_name == bi->commands[command_name].name && log->method.equals_ci(method))
00117 {
00118 if (log->extra == extra)
00119 {
00120 delete log;
00121 ci->log_settings->erase(ci->log_settings->begin() + i - 1);
00122 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to remove logging for " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
00123 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());
00124 }
00125 else
00126 {
00127 log->extra = extra;
00128 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to change logging for " << command << " to method " << method << (extra == "" ? "" : " ") << extra;
00129 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());
00130 }
00131 return;
00132 }
00133 }
00134
00135 LogSetting *log = new LogSetting();
00136 log->ci = ci;
00137 log->service_name = bi->commands[command_name].name;
00138 log->command_service = bi->nick;
00139 log->command_name = command_name;
00140 log->method = method;
00141 log->extra = extra;
00142 log->created = Anope::CurTime;
00143 log->creator = source.GetNick();
00144
00145 ci->log_settings->push_back(log);
00146 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to log " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
00147
00148 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());
00149 }
00150 else
00151 this->OnSyntaxError(source, "");
00152 }
00153
00154 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00155 {
00156 this->SendSyntax(source);
00157 source.Reply(" ");
00158 source.Reply(_("The %s command allows users to configure logging settings\n"
00159 "for their channel. If no parameters are given this command\n"
00160 "lists the current logging methods in place for this channel.\n"
00161 " \n"
00162 "Otherwise, \037command\037 must be a command name, and \037method\037\n"
00163 "is one of the following logging methods:\n"
00164 " \n"
00165 " MESSAGE [status], NOTICE [status], MEMO\n"
00166 " \n"
00167 "Which are used to message, notice, and memo the channel respectively.\n"
00168 "With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
00169 "to your channel. Status may be a channel status such as @ or +.\n"
00170 " \n"
00171 "To remove a logging method use the same syntax as you would to add it.\n"
00172 " \n"
00173 "Example:\n"
00174 " %s #anope chanserv/access MESSAGE @%\n"
00175 " Would message any channel operators whenever someone used the\n"
00176 " ACCESS command on ChanServ on the channel."),
00177 source.command.c_str(), source.command.c_str());
00178 return true;
00179 }
00180 };
00181
00182 class CSLog : public Module
00183 {
00184 ServiceReference<MemoServService> MSService;
00185 CommandCSLog commandcslog;
00186
00187 public:
00188 CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00189 MSService("MemoServService", "MemoServ"), commandcslog(this)
00190 {
00191 this->SetAuthor("Anope");
00192
00193 Implementation i[] = { I_OnLog };
00194 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00195 }
00196
00197 void OnLog(Log *l) anope_override
00198 {
00199 if (l->type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced())
00200 return;
00201
00202 for (unsigned i = l->ci->log_settings->size(); i > 0; --i)
00203 {
00204 const LogSetting *log = l->ci->log_settings->at(i - 1);
00205
00206 if (log->service_name == l->c->name)
00207 {
00208 Anope::string buffer = l->u->nick + " used " + log->command_name + " " + l->buf.str();
00209
00210 if (log->method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
00211 {
00212 IRCD->SendPrivmsg(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
00213 l->ci->bi->lastmsg = Anope::CurTime;
00214 }
00215 else if (log->method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
00216 IRCD->SendNotice(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
00217 else if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL)
00218 MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
00219 }
00220 }
00221 }
00222 };
00223
00224 MODULE_INIT(CSLog)