void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &target = params[0]; const Anope::string &modes = params[1]; Reference<Channel> c = Channel::Find(target); if (!c) source.Reply(_("Channel \002{0}\002 doesn't exist."), target); else if (c->bouncy_modes) source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); else if (modes.equals_ci("CLEAR")) { bool all = params.size() > 2 && params[2].equals_ci("ALL"); const Channel::ModeList chmodes = c->GetModes(); for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end && c; ++it) c->RemoveMode(c->ci->WhoSends(), it->first, it->second, false); if (!c) { source.Reply(_("Modes cleared on %s and the channel destroyed."), target.c_str()); return; } if (all) { for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) { ChanUserContainer *uc = it->second; if (uc->user->HasMode("OPER")) continue; for (size_t i = uc->status.Modes().length(); i > 0; --i) c->RemoveMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(uc->status.Modes()[i - 1]), uc->user->GetUID(), false); } source.Reply(_("All modes cleared on \002{0}\002."), c->name); } else source.Reply(_("Non-status modes cleared on \002{0}\002."), c->name); } else { spacesepstream sep(modes + (params.size() > 2 ? " " + params[2] : "")); Anope::string mode; int add = 1; Anope::string log_modes, log_params; sep.GetToken(mode); for (unsigned i = 0; i < mode.length() && c; ++i) { char ch = mode[i]; if (ch == '+') { add = 1; log_modes += "+"; continue; } else if (ch == '-') { add = 0; log_modes += "-"; continue; } ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); if (!cm) continue; Anope::string param, param_log; if (cm->type != MODE_REGULAR) { if (cm->type == MODE_PARAM && !add && anope_dynamic_static_cast<ChannelModeParam *>(cm)->minus_no_arg) ; else if (!sep.GetToken(param)) continue; param_log = param; if (cm->type == MODE_STATUS) { User *targ = User::Find(param, true); if (targ == NULL || c->FindUser(targ) == NULL) continue; param = targ->GetUID(); } } log_modes += cm->mchar; if (!param.empty()) log_params += " " + param_log; if (add) c->SetMode(source.service, cm, param, false); else c->RemoveMode(source.service, cm, param, false); } if (!log_modes.replace_all_cs("+", "").replace_all_cs("-", "").empty()) Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << (c ? c->name : target); } }
void DoStats(CommandSource &source, const bool is_global, const std::vector<Anope::string> ¶ms) { Anope::string display, channel; /* * possible parameters are: * stats [channel] [nick] * stats [channel] * stats [nick] * stats */ switch (params.size()) { case 2: channel = params[0]; display = params[1]; break; case 1: if (params[0][0] == '#') channel = params[0]; else { if (NickAlias *na = NickAlias::Find(params[0])) display = na->nc->display; else { source.Reply(_("%s not found."), params[0].c_str()); return; } } break; } if (display.empty()) display = source.nc->display; try { SQL::Query query; query = "SELECT letters, words, line, smileys_happy+smileys_sad+smileys_other as smileys," "actions FROM `" + prefix + "chanstats` " "WHERE `nick` = @nick@ AND `chan` = @channel@ AND `type` = 'total';"; if (is_global || channel.empty()) query.SetValue("channel", ""); else query.SetValue("channel", channel); query.SetValue("nick", display); SQL::Result res = this->RunQuery(query); if (res.Rows() > 0) { if (is_global) source.Reply(_("Network stats for %s:"), display.c_str()); else source.Reply(_("Channel stats for %s on %s:"), display.c_str(), channel.c_str()); source.Reply(_("letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"), res.Get(0, "letters").c_str(), res.Get(0, "words").c_str(), res.Get(0, "line").c_str(), res.Get(0, "smileys").c_str(), res.Get(0, "actions").c_str()); } else source.Reply(_("No stats for %s."), display.c_str()); } catch (const SQL::Exception &ex) { Log(LOG_DEBUG) << ex.GetReason(); } }
void Run(CommandSource &source, const std::vector<Flux::string> ¶ms) { source.Reply("My PID is: \2%i\2", (int)getpid()); Log(source.u, this) << "command to get navn's PID " << getpid(); }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { if (subcommand.empty()) { CommandInfo *help = source.service->FindCommand("generic/help"); if (!help) return false; source.Reply(_("Sets various memo options. \037option\037 can be one of:\n" "\n" " NOTIFY Changes when you will be notified about\n" " new memos (only for nicknames)\n" " LIMIT Sets the maximum number of memos you can\n" " receive\n" "\n" "Type \002{0}{1} {2} {3} \037option\037\002 for more information on a specific option."), Config->StrictPrivmsg, source.service->nick, help->cname, source.command); } else if (subcommand.equals_ci("NOTIFY")) source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" "\n" "Changes when you will be notified about new memos:\n" "\n" " ON You will be notified of memos when you log on,\n" " when you unset /AWAY, and when they are sent\n" " to you.\n" "\n" " LOGON You will only be notified of memos when you log\n" " on or when you unset /AWAY.\n" "\n" " NEW You will only be notified of memos when they\n" " are sent to you.\n" "\n" " MAIL You will be notified of memos by email as well as\n" " any other settings you have.\n" "\n" " NOMAIL You will not be notified of memos by email.\n" "\n" " OFF You will not receive any notification of memos.\n" "\n" "\002ON\002 is essentially \002LOGON\002 and \002NEW\002 combined.")); else if (subcommand.equals_ci("LIMIT")) { int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos"); if (source.IsServicesOper()) source.Reply(_("Syntax: \002LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]\002\n" "\n" "Sets the maximum number of memos a user or channel is allowed to have." " Setting the limit to 0 prevents the user from receiving any memos; setting it to \002NONE\002 allows the user to receive and keep as many memos as they want." " If you do not give a nickname or channel, your own limit is set.\n" "\n" "Adding \002HARD\002 prevents the user from changing the limit." " Not adding \002HARD\002 has the opposite effect, allowing the user to change the limit, even if a previous limit was set.\n" " \n" "This use of the \002{0} LIMIT\002 command is limited to \002Services Operators\002." " Other users may only enter a limit for themselves or a channel on which they have the \002MEMO\002 privilege on, may not remove their limit, may not set a limit above {1}, and may not set a hard limit."), source.command, max_memos); else source.Reply(_("Syntax: \002LIMIT [\037channel\037] \037limit\037\002\n" "\n" "Sets the maximum number of memos you, or the given channel, are allowed to have." " If you set this to 0, no one will be able to send any memos to you." "However, you cannot set this any higher than {0}."), max_memos); } else return false; return true; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &channel = params[0]; ChanServ::Channel *ci = ChanServ::Find(channel); if (ci == NULL) { source.Reply(_("Channel \002{0}\002 isn't registered."), channel); return; } if (!source.AccessFor(ci).HasPriv("SET") && !source.HasOverridePriv("chanserv/administration")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "SET", ci->GetName()); return; } if (params.size() == 1) { std::vector<LogSetting *> ls = ci->GetRefs<LogSetting *>(); if (ls.empty()) { source.Reply(_("There currently are no logging configurations for \002{0}\002."), ci->GetName()); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method")).AddColumn(""); for (unsigned i = 0; i < ls.size(); ++i) { LogSetting *log = ls[i]; ListFormatter::ListEntry entry; entry["Number"] = stringify(i + 1); entry["Service"] = log->GetCommandService(); entry["Command"] = !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(); entry["Method"] = log->GetMethod(); entry[""] = log->GetExtra(); list.AddEntry(entry); } source.Reply(_("Log list for \002{0}\002:"), ci->GetName()); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); } else if (params.size() > 2) { if (Anope::ReadOnly) { source.Reply(_("Services are in read-only mode.")); return; } 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(_("\002{0}\002 is not a valid command."), command); return; } Anope::string service = command.substr(0, sl), command_name = command.substr(sl + 1); ServiceBot *bi = ServiceBot::Find(service, true); Anope::string service_name; /* Allow either a command name or a service name. */ if (bi && bi->commands.count(command_name)) { /* Get service name from command */ service_name = bi->commands[command_name].name; } else if (ServiceReference<Command>(command.lower())) { /* This is the service name, don't use any specific command */ service_name = command; bi = NULL; command_name.clear(); } else { source.Reply(_("\002{0}\002 is not a valid command."), command); return; } if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO")) { source.Reply(_("\002%s\002 is not a valid logging method.")); return; } for (unsigned i = 0; i < extra.length(); ++i) if (ModeManager::GetStatusChar(extra[i]) == 0) { source.Reply(_("\002%c\002 is an unknown status mode."), extra[i]); return; } std::vector<LogSetting *> ls = ci->GetRefs<LogSetting *>(); for (unsigned i = ls.size(); i > 0; --i) { LogSetting *log = ls[i - 1]; if (log->GetServiceName() == service_name && log->GetMethod().equals_ci(method) && command_name.equals_ci(log->GetCommandName())) { if (log->GetExtra() == extra) { logger.Command(source, ci, _("{source} used {command} on {channel} to remove logging for {0} with method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging for command \002{0}\002 on \002{1}\002 with log method \002{2}{3}{4}\002 has been removed."), !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(), !log->GetCommandService().empty() ? log->GetCommandService() : "any service", method, extra.empty() ? "" : " ", extra); log->Delete(); } else { log->SetExtra(extra); logger.Command(source, ci, _("{source} used {command} on {channel} to change logging for {0} to method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging changed for command \002{0}\002 on \002{1}\002, now using log method \002{2}{3}{4]\002."), !log->GetCommandName().empty() ? log->GetCommandName() : log->GetServiceName(), !log->GetCommandService().empty() ? log->GetCommandService() : "any service", method, extra.empty() ? "" : " ", extra); } return; } } LogSetting *log = Serialize::New<LogSetting *>(); log->SetChannel(ci); log->SetServiceName(service_name); if (bi) log->SetCommandService(bi->nick); log->SetCommandName(command_name); log->SetMethod(method); log->SetExtra(extra); log->SetCreated(Anope::CurTime); log->SetCreator(source.GetNick()); logger.Command(source, ci, _("{source} used {command} on {channel} to log {0} to method {1}"), command, method + (extra.empty() ? "" : (" " + extra))); source.Reply(_("Logging is now active for command \002{0}\002 on \002{1}\002, using log method \002{2}{3}{4}\002."), !command_name.empty() ? command_name : service_name, bi ? bi->nick : "any service", method, extra.empty() ? "" : " ", extra); } else { this->OnSyntaxError(source, ""); } }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Deactivates your vhost.")); return true; }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Causes Services to shut down")); return true; }
bool Show(CommandSource &source, const Anope::string &what) const { return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end(); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &chan = params[0]; User *u = source.GetUser(); Channel *c = Channel::Find(chan); if (!c) { source.Reply(_("Channel \002{0}\002 doesn't exist."), chan); return; } ChanServ::Channel *ci = c->ci; if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), c->name); return; } if (!source.AccessFor(ci).HasPriv("INVITE") && !source.HasCommand("chanserv/invite")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "INVITE", ci->GetName()); return; } User *u2; if (params.size() == 1) u2 = u; else u2 = User::Find(params[1], true); if (!u2) { source.Reply(_("\002{0}\002 isn't currently online."), params.size() > 1 ? params[1] : source.GetNick()); return; } if (c->FindUser(u2)) { if (u2 == u) source.Reply(_("You are already in \002{0}\002!"), c->name); else source.Reply(_("\002{0}\002 is already in \002{1}\002!"), u2->nick, c->name); return; } bool override = !source.AccessFor(ci).HasPriv("INVITE"); IRCD->SendInvite(ci->WhoSends(), c, u2); if (u2 != u) { source.Reply(_("\002{0}\002 has been invited to \002{1}\002."), u2->nick, c->name); u2->SendMessage(ci->WhoSends(), _("You have been invited to \002{0}\002 by \002{1}\002."), c->name, source.GetNick()); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; }
void DoAdd(CommandSource &source, NickServ::Account *nc, const Anope::string &chans, const Anope::string &keys) { std::vector<AutoJoin *> channels = nc->GetRefs<AutoJoin *>(); Anope::string addedchans; Anope::string alreadyadded; Anope::string invalidkey; commasepstream ksep(keys, true); commasepstream csep(chans); for (Anope::string chan, key; csep.GetToken(chan);) { ksep.GetToken(key); unsigned i = 0; for (; i < channels.size(); ++i) if (channels[i]->GetChannel().equals_ci(chan)) break; if (channels.size() >= Config->GetModule(this->GetOwner())->Get<unsigned>("ajoinmax")) { source.Reply(_("Sorry, the maximum of \002{0}\002 auto join entries has been reached."), Config->GetModule(this->GetOwner())->Get<unsigned>("ajoinmax")); return; } if (i != channels.size()) alreadyadded += chan + ", "; else if (IRCD->IsChannelValid(chan) == false) source.Reply(_("\002{0}\002 isn't a valid channel."), chan); else { Channel *c = Channel::Find(chan); Anope::string k; if (c && c->GetParam("KEY", k) && key != k) { invalidkey += chan + ", "; continue; } AutoJoin *entry = Serialize::New<AutoJoin *>(); entry->SetOwner(nc); entry->SetChannel(chan); entry->SetKey(key); addedchans += chan + ", "; } } if (!alreadyadded.empty()) { alreadyadded = alreadyadded.substr(0, alreadyadded.length() - 2); source.Reply(_("\002{0}\002 is already on the auto join list of \002{1}\002."), alreadyadded, nc->GetDisplay()); } if (!invalidkey.empty()) { invalidkey = invalidkey.substr(0, invalidkey.length() - 2); source.Reply(_("\002{0}\002 had an invalid key specified, and was ignored."), invalidkey); } if (addedchans.empty()) return; addedchans = addedchans.substr(0, addedchans.length() - 2); Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD channel " << addedchans << " to " << nc->GetDisplay(); source.Reply(_("\002{0}\002 added to the auto join list of \002{1}\002."), addedchans, nc->GetDisplay()); }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Allows Services Operators to change modes for any user. Parameters are the same as for the standard /MODE command.")); return true; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &chdesc = params.size() > 1 ? params[1] : ""; User *u = source.u; Channel *c = findchan(params[0]); ChannelInfo *ci = cs_findchan(params[0]); if (readonly) source.Reply(_("Sorry, channel registration is temporarily disabled.")); else if (u->Account()->HasFlag(NI_UNCONFIRMED)) source.Reply(_("You must confirm your account before you can register a channel.")); else if (chan[0] == '&') source.Reply(_("Local channels cannot be registered.")); else if (chan[0] != '#') source.Reply(CHAN_SYMBOL_REQUIRED); else if (!ircdproto->IsChannelValid(chan)) source.Reply(CHAN_X_INVALID, chan.c_str()); else if (ci) source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str()); else if (c && !c->HasUserStatus(u, CMODE_OP)) source.Reply(_("You must be a channel operator to register the channel.")); else if (Config->CSMaxReg && u->Account()->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) source.Reply(u->Account()->channelcount > Config->CSMaxReg ? CHAN_EXCEEDED_CHANNEL_LIMIT : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); else { ci = new ChannelInfo(chan); ci->SetFounder(u->Account()); if (!chdesc.empty()) ci->desc = chdesc; ci->mode_locks = def_mode_locks; for (ChannelInfo::ModeList::iterator it = ci->mode_locks.begin(), it_end = ci->mode_locks.end(); it != it_end; ++it) { it->second.setter = u->nick; it->second.ci = ci; } if (c && !c->topic.empty()) { ci->last_topic = c->topic; ci->last_topic_setter = c->topic_setter; ci->last_topic_time = c->topic_time; } else ci->last_topic_setter = source.owner->nick; Log(LOG_COMMAND, u, this, ci); source.Reply(_("Channel \002%s\002 registered under your nickname: %s"), chan.c_str(), u->nick.c_str()); /* Implement new mode lock */ if (c) { check_modes(c); ChannelMode *cm; if (u->FindChannel(c) != NULL) { /* On most ircds you do not receive the admin/owner mode till its registered */ if ((cm = ModeManager::FindChannelModeByName(CMODE_OWNER))) c->SetMode(NULL, cm, u->nick); else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) c->RemoveMode(NULL, cm, u->nick); } /* Mark the channel as persistent */ if (c->HasMode(CMODE_PERM)) ci->SetFlag(CI_PERSIST); /* Persist may be in def cflags, set it here */ else if (ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM))) c->SetMode(NULL, CMODE_PERM); } FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(ci)); } return; }
void ProcessList(CommandSource &source, const std::vector<Anope::string> ¶ms, ListFormatter &list) { const Anope::string &mask = params.size() > 1 ? params[1] : ""; if (session_service->GetExceptions().empty()) { source.Reply(_("The session exception list is empty.")); return; } if (!mask.empty() && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { class ExceptionListCallback : public NumberList { ListFormatter &list; public: ExceptionListCallback(ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), list(_list) { } void HandleNumber(unsigned Number) { if (!Number || Number > session_service->GetExceptions().size()) return; Exception *e = session_service->GetExceptions()[Number - 1]; ListFormatter::ListEntry entry; entry["Number"] = stringify(Number); entry["Mask"] = e->mask; entry["By"] = e->who; entry["Created"] = do_strftime(e->time); entry["Limit"] = stringify(e->limit); entry["Reason"] = e->reason; this->list.addEntry(entry); } } nl_list(list, mask); nl_list.Process(); } else { for (unsigned i = 0, end = session_service->GetExceptions().size(); i < end; ++i) { Exception *e = session_service->GetExceptions()[i]; if (mask.empty() || Anope::Match(e->mask, mask)) { ListFormatter::ListEntry entry; entry["Number"] = stringify(i + 1); entry["Mask"] = e->mask; entry["By"] = e->who; entry["Created"] = do_strftime(e->time); entry["Limit"] = stringify(e->limit); entry["Reason"] = e->reason; list.addEntry(entry); } } } if (list.isEmpty()) source.Reply(_("No matching entries on session-limit exception list.")); else { source.Reply(_("Current Session Limit Exception list:")); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); } }
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string mask, expiry, limitstr; unsigned last_param = 3; mask = params.size() > 1 ? params[1] : ""; if (!mask.empty() && mask[0] == '+') { expiry = mask; mask = params.size() > 2 ? params[2] : ""; last_param = 4; } limitstr = params.size() > last_param - 1 ? params[last_param - 1] : ""; if (params.size() <= last_param) { this->OnSyntaxError(source, "ADD"); return; } Anope::string reason = params[last_param]; if (last_param == 3 && params.size() > 4) reason += " " + params[4]; if (reason.empty()) { this->OnSyntaxError(source, "ADD"); return; } time_t expires = !expiry.empty() ? dotime(expiry) : Config->ExceptionExpiry; if (expires < 0) { source.Reply(BAD_EXPIRY_TIME); return; } else if (expires > 0) expires += Anope::CurTime; int limit = -1; try { limit = convertTo<int>(limitstr); } catch (const ConvertException &) { } if (limit < 0 || limit > static_cast<int>(Config->MaxSessionLimit)) { source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), Config->MaxSessionLimit); return; } else { if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) { source.Reply(_("Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames.")); return; } for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it) { Exception *e = *it; if (e->mask.equals_ci(mask)) { if (e->limit != limit) { e->limit = limit; source.Reply(_("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); } else source.Reply(_("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); return; } } Exception *exception = new Exception(); exception->mask = mask; exception->limit = limit; exception->reason = reason; exception->time = Anope::CurTime; exception->who = u->nick; exception->expires = expires; EventReturn MOD_RESULT; FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(exception)); if (MOD_RESULT == EVENT_STOP) delete exception; else { session_service->AddException(exception); source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit); if (readonly) source.Reply(READ_ONLY_MODE); } } return; }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Suspends \037account\037, which prevents it from being used while keeping all the data for it." " If an expiry is given the account will be unsuspended after that period of time, otherwise the default expiry from the configuration is used.")); // XXX return true; }
void Command::OnServHelp(CommandSource &source) { source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str())); }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Unsuspends \037account\037, which allows it to be used again.")); return true; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { if (!this->fs) return; const Anope::string &command = params[0]; const Anope::string &subcommand = params.size() > 1 ? params[1] : ""; ForbidType ftype = FT_SIZE; if (subcommand.equals_ci("NICK")) ftype = FT_NICK; else if (subcommand.equals_ci("CHAN")) ftype = FT_CHAN; else if (subcommand.equals_ci("EMAIL")) ftype = FT_EMAIL; else if (subcommand.equals_ci("REGISTER")) ftype = FT_REGISTER; if (command.equals_ci("ADD") && params.size() > 3 && ftype != FT_SIZE) { const Anope::string &expiry = params[2][0] == '+' ? params[2] : ""; const Anope::string &entry = !expiry.empty() ? params[3] : params[2]; Anope::string reason; if (expiry.empty()) reason = params[3] + " "; if (params.size() > 4) reason += params[4]; reason.trim(); if (entry.replace_all_cs("?*", "").empty()) { source.Reply(_("The mask must contain at least one non wildcard character.")); return; } time_t expiryt = 0; if (!expiry.empty()) { expiryt = Anope::DoTime(expiry); if (expiryt == -1) { source.Reply(_("Invalid expiry time \002{0}\002."), expiry); return; } else if (expiryt) expiryt += Anope::CurTime; } NickServ::Nick *target = NickServ::FindNick(entry); if (target != NULL && Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && target->GetAccount()->IsServicesOper()) { source.Reply(_("Access denied.")); return; } ForbidData *d = this->fs->FindForbid(entry, ftype); bool created = false; if (d == NULL) { d = Serialize::New<ForbidData *>(); created = true; } d->SetMask(entry); d->SetCreator(source.GetNick()); d->SetReason(reason); d->SetCreated(Anope::CurTime); d->SetExpires(expiryt); d->SetType(ftype); if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); Log(LOG_ADMIN, source, this) << "to add a forbid on " << entry << " of type " << subcommand; source.Reply(_("Added a forbid on \002{0}\002 of type \002{1}\002 to expire on \002{2}\002."), entry, subcommand.lower(), expiryt ? Anope::strftime(expiryt, source.GetAccount()) : "never"); /* apply forbid */ switch (ftype) { case FT_NICK: { int na_matches = 0; for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) this->OnUserNickChange(it->second); for (auto it = NickServ::service->GetNickList().begin(); it != NickServ::service->GetNickList().end();) { NickServ::Nick *na = *it; ++it; d = this->fs->FindForbid(na->GetNick(), FT_NICK); if (d == NULL) continue; ++na_matches; delete na; } source.Reply(_("\002{0}\002 nickname(s) dropped."), na_matches); break; } case FT_CHAN: { int chan_matches = 0, ci_matches = 0; for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end;) { Channel *c = it->second; ++it; d = this->fs->FindForbid(c->name, FT_CHAN); if (d == NULL) continue; ServiceBot *OperServ = Config->GetClient("OperServ"); if (IRCD->CanSQLineChannel && OperServ) { time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s"); #warning "xline allocated on stack" #if 0 XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->GetReason()); IRCD->SendSQLine(NULL, &x); #endif } else if (ChanServ::service) { ChanServ::service->Hold(c); } ++chan_matches; for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end;) { User *u = cit->first; ++cit; if (u->server == Me || u->HasMode("OPER")) continue; reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: \002%s\002")), d->GetReason().c_str()); c->Kick(source.service, u, "%s", reason.c_str()); } } for (auto it = ChanServ::service->GetChannels().begin(); it != ChanServ::service->GetChannels().end();) { ChanServ::Channel *ci = it->second; ++it; d = this->fs->FindForbid(ci->GetName(), FT_CHAN); if (d == NULL) continue; ++ci_matches; delete ci; } source.Reply(_("\002{0}\002 channel(s) cleared, and \002{1}\002 channel(s) dropped."), chan_matches, ci_matches); break; } default: break; } } else if (command.equals_ci("DEL") && params.size() > 2 && ftype != FT_SIZE) { const Anope::string &entry = params[2]; ForbidData *d = this->fs->FindForbid(entry, ftype); if (d == nullptr) { source.Reply(_("Forbid on \002{0}\002 was not found."), entry); return; } if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); Log(LOG_ADMIN, source, this) << "to remove forbid on " << d->GetMask() << " of type " << subcommand; source.Reply(_("\002{0}\002 deleted from the \002{1}\002 forbid list."), d->GetMask(), subcommand); d->Delete(); } else if (command.equals_ci("LIST")) { const std::vector<ForbidData *> &forbids = this->fs->GetForbids(); if (forbids.empty()) { source.Reply(_("Forbid list is empty.")); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Mask")).AddColumn(_("Type")).AddColumn(_("Creator")).AddColumn(_("Expires")).AddColumn(_("Reason")); unsigned shown = 0; for (unsigned i = 0; i < forbids.size(); ++i) { ForbidData *d = forbids[i]; if (ftype != FT_SIZE && ftype != d->GetType()) continue; Anope::string stype; if (d->GetType() == FT_NICK) stype = "NICK"; else if (d->GetType() == FT_CHAN) stype = "CHAN"; else if (d->GetType() == FT_EMAIL) stype = "EMAIL"; else if (d->GetType() == FT_REGISTER) stype = "REGISTER"; else continue; ListFormatter::ListEntry entry; entry["Mask"] = d->GetMask(); entry["Type"] = stype; entry["Creator"] = d->GetCreator(); entry["Expires"] = d->GetExpires() ? Anope::strftime(d->GetExpires(), NULL, true).c_str() : Language::Translate(source.GetAccount(), _("Never")); entry["Reason"] = d->GetReason(); list.AddEntry(entry); ++shown; } if (!shown) { source.Reply(_("There are no forbids of type \002{0}\002."), subcommand.upper()); return; } source.Reply(_("Forbid list:")); std::vector<Anope::string> replies; list.Process(replies); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); if (shown >= forbids.size()) source.Reply(_("End of forbid list.")); else source.Reply(_("End of forbid list - \002{0}\002/\002{1}\002 entries shown."), shown, forbids.size()); } else this->OnSyntaxError(source, command); }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &subcommand = params[0]; if (subcommand.equals_ci("ADD") && params.size() > 2) { const Anope::string &oper = params[1]; const Anope::string &otype = params[2]; NickAlias *na = findnick(oper); if (na == NULL) source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); else if (na->nc->o) source.Reply(_("Nick \2%s\2 is already an operator."), na->nick.c_str()); else { OperType *ot = OperType::Find(otype); if (ot == NULL) source.Reply(_("Oper type \2%s\2 has not been configured."), otype.c_str()); else { na->nc->o = new MyOper(na->nc->display, ot); Log(LOG_ADMIN, source.u, this) << "ADD " << na->nick << " as type " << ot->GetName(); source.Reply("%s (%s) added to the \2%s\2 list.", na->nick.c_str(), na->nc->display.c_str(), ot->GetName().c_str()); } } } else if (subcommand.equals_ci("DEL") && params.size() > 1) { const Anope::string &oper = params[1]; NickAlias *na = findnick(oper); if (na == NULL) source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); else if (!na->nc || !na->nc->o) source.Reply(_("Nick \2%s\2 is not a services operator."), oper.c_str()); else { delete na->nc->o; na->nc->o = NULL; Log(LOG_ADMIN, source.u, this) << "DEL " << na->nick; source.Reply(_("Oper privileges removed from %s (%s)."), na->nick.c_str(), na->nc->display.c_str()); } } else if (subcommand.equals_ci("LIST")) { source.Reply(_("Name Type")); for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it) { NickCore *nc = it->second; if (!nc->o) continue; source.Reply(_("%-8s %s"), nc->o->name.c_str(), nc->o->ot->GetName().c_str()); if (nc->o->config) source.Reply(_(" This oper is configured in the configuration file.")); for (std::list<User *>::iterator uit = nc->Users.begin(); uit != nc->Users.end(); ++uit) { User *u = *uit; source.Reply(_(" %s is online using this oper block."), u->nick.c_str()); } } } else if (subcommand.equals_ci("INFO") && params.size() > 1) { Anope::string fulltype = params[1]; if (params.size() > 2) fulltype += " " + params[2]; OperType *ot = OperType::Find(fulltype); if (ot == NULL) source.Reply(_("Oper type \2%s\2 has not been configured."), fulltype.c_str()); else { if (ot->GetCommands().empty()) source.Reply(_("Opertype \2%s\2 has no allowed commands."), ot->GetName().c_str()); else { source.Reply(_("Available commands for \2%s\2:"), ot->GetName().c_str()); Anope::string buf; std::list<Anope::string> cmds = ot->GetCommands(); for (std::list<Anope::string>::const_iterator it = cmds.begin(), it_end = cmds.end(); it != it_end; ++it) { buf += *it + " "; if (buf.length() > 400) { source.Reply("%s", buf.c_str()); buf.clear(); } } if (!buf.empty()) { source.Reply("%s", buf.c_str()); buf.clear(); } } if (ot->GetPrivs().empty()) source.Reply(_("Opertype \2%s\2 has no allowed privileges."), ot->GetName().c_str()); else { source.Reply(_("Available privileges for \2%s\2:"), ot->GetName().c_str()); Anope::string buf; std::list<Anope::string> privs = ot->GetPrivs(); for (std::list<Anope::string>::const_iterator it = privs.begin(), it_end = privs.end(); it != it_end; ++it) { buf += *it + " "; if (buf.length() > 400) { source.Reply("%s", buf.c_str()); buf.clear(); } } if (!buf.empty()) { source.Reply("%s", buf.c_str()); buf.clear(); } } if (!ot->modes.empty()) source.Reply(_("Opertype \2%s\2 receives modes \2%s\2 once identifying."), ot->GetName().c_str(), ot->modes.c_str()); } } else this->OnSyntaxError(source, subcommand); return; }
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) override { if (command->GetName() == "nickserv/info" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_NICK); if (d != NULL) { if (source.IsOper()) source.Reply(_("Nick \002%s\002 is forbidden by %s: %s"), params[0], d->GetCreator(), d->GetReason()); else source.Reply(_("Nick \002%s\002 is forbidden."), params[0]); return EVENT_STOP; } } else if (command->GetName() == "chanserv/info" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_CHAN); if (d != NULL) { if (source.IsOper()) source.Reply(_("Channel \002%s\002 is forbidden by %s: %s"), params[0], d->GetCreator(), d->GetReason()); else source.Reply(_("Channel \002%s\002 is forbidden."), params[0]); return EVENT_STOP; } } else if (source.IsOper()) return EVENT_CONTINUE; else if (command->GetName() == "nickserv/register" && params.size() > 1) { ForbidData *d = this->forbid_service.FindForbid(source.GetNick(), FT_REGISTER); if (d != NULL) { source.Reply(_("\002{0}\002 may not be registered."), source.GetNick()); return EVENT_STOP; } d = this->forbid_service.FindForbid(params[1], FT_EMAIL); if (d != NULL) { source.Reply(_("Your email address is not allowed, choose a different one.")); return EVENT_STOP; } } else if (command->GetName() == "nickserv/set/email" && params.size() > 0) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_EMAIL); if (d != NULL) { source.Reply(_("Your email address is not allowed, choose a different one.")); return EVENT_STOP; } } else if (command->GetName() == "chanserv/register" && !params.empty()) { ForbidData *d = this->forbid_service.FindForbid(params[0], FT_REGISTER); if (d != NULL) { source.Reply(_("Channel \002{0}\002 is currently suspended."), params[0]); return EVENT_STOP; } } return EVENT_CONTINUE; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { Anope::string param = !params.empty() ? params[0] : "", chan; ChanServ::Channel *ci = NULL; MemoServ::MemoInfo *mi; if (!param.empty() && param[0] == '#') { chan = param; param = params.size() > 1 ? params[1] : ""; ci = ChanServ::Find(chan); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), chan); return; } if (!source.AccessFor(ci).HasPriv("MEMO")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); return; } mi = ci->GetMemos(); } else { mi = source.nc->GetMemos(); } if (!param.empty() && !isdigit(param[0]) && !param.equals_ci("NEW")) { this->OnSyntaxError(source); return; } if (!mi) return; auto memos = mi->GetMemos(); if (!memos.size()) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no memos."), chan); else source.Reply(_("You have no memos.")); return; } ListFormatter list(source.GetAccount()); list.AddColumn(_("Number")).AddColumn(_("Sender")).AddColumn(_("Date/Time")); if (!param.empty() && isdigit(param[0])) { NumberList(param, false, [&](unsigned int number) { if (!number || number > memos.size()) return; MemoServ::Memo *m = mi->GetMemo(number - 1); ListFormatter::ListEntry entry; entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(number); entry["Sender"] = m->GetSender(); entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); list.AddEntry(entry); }, []{}); } else { if (!param.empty()) { unsigned i, end; for (i = 0, end = memos.size(); i < end; ++i) if (mi->GetMemo(i)->GetUnread()) break; if (i == end) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no new memos."), chan); else source.Reply(_("You have no new memos.")); return; } } for (unsigned i = 0, end = memos.size(); i < end; ++i) { if (!param.empty() && !mi->GetMemo(i)->GetUnread()) continue; MemoServ::Memo *m = mi->GetMemo(i); ListFormatter::ListEntry entry; entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(i + 1); entry["Sender"] = m->GetSender(); entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); list.AddEntry(entry); } } std::vector<Anope::string> replies; list.Process(replies); source.Reply(_("Memos for \002{0}\002:"), ci ? ci->GetName().c_str() : source.GetNick().c_str()); for (unsigned i = 0; i < replies.size(); ++i) source.Reply(replies[i]); }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Tells services to jupiter a server -- that is, to create a fake \"server\" connected to Services which prevents the real server of that name from connecting." " The jupe may be removed using a standard \002SQUIT\002. If a reason is given, it is placed in the server information field; otherwise, the server information field will contain the text \"Juped by <nick>\", showing the nickname of the person who jupitered the server.")); return true; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { MemoServ::MemoInfo *mi; ChanServ::Channel *ci = NULL; Anope::string numstr = params[0], chan; if (!numstr.empty() && numstr[0] == '#') { chan = numstr; numstr = params.size() > 1 ? params[1] : ""; ci = ChanServ::Find(chan); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), chan); return; } if (!source.AccessFor(ci).HasPriv("MEMO")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); return; } mi = ci->GetMemos(); } else mi = source.nc->GetMemos(); if (numstr.empty() || (!numstr.equals_ci("LAST") && !numstr.equals_ci("NEW") && !numstr.is_number_only())) { this->OnSyntaxError(source, numstr); return; } if (!mi) return; auto memos = mi->GetMemos(); if (memos.empty()) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no memos."), chan); else source.Reply(_("You have no memos.")); return; } int i, end; if (numstr.equals_ci("NEW")) { int readcount = 0; for (i = 0, end = memos.size(); i < end; ++i) if (mi->GetMemo(i)->GetUnread()) { DoRead(source, mi, ci, i); ++readcount; } if (!readcount) { if (!chan.empty()) source.Reply(_("\002{0}\002 has no new memos."), chan); else source.Reply(_("You have no new memos.")); } } else if (numstr.equals_ci("LAST")) { for (i = 0, end = memos.size() - 1; i < end; ++i); DoRead(source, mi, ci, i); } else /* number[s] */ { NumberList(numstr, false, [&](unsigned int number) { if (!number || number > memos.size()) return; DoRead(source, mi, ci, number - 1); }, []{}); } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { #warning "this is completely disabled" #if 0 if (!MemoServ::service) return; if (Anope::ReadOnly && !source.IsOper()) { source.Reply(_("Sorry, memo sending is temporarily disabled.")); return; } const Anope::string &nick = params[0]; const Anope::string &text = params[1]; const NickServ::Nick *na = NULL; /* prevent user from rsend to themselves */ if ((na = NickServ::FindNick(nick)) && na->GetAccount() == source.GetAccount()) { source.Reply(_("You can not request a receipt when sending a memo to yourself.")); return; } if (Config->GetModule(this->GetOwner())->Get<bool>("operonly") && !source.IsServicesOper()) source.Reply(_("Access denied. This command is for operators only.")); else { MemoServ::MemoServService::MemoResult result = MemoServ::service->Send(source.GetNick(), nick, text); if (result == MemoServ::MemoServService::MEMO_INVALID_TARGET) source.Reply(_("\002{0}\002 isn't registered."), nick); else if (result == MemoServ::MemoServService::MEMO_TOO_FAST) source.Reply(_("Please wait \002{0}\002 seconds before using the \002{1}\002 command again."), Config->GetModule("memoserv/main")->Get<time_t>("senddelay"), source.command); else if (result == MemoServ::MemoServService::MEMO_TARGET_FULL) source.Reply(_("Sorry, \002{0}\002 currently has too many memos and cannot receive more."), nick); else { source.Reply(_("Memo sent to \002{0}\002."), nick); bool ischan, isregistered; MemoServ::MemoInfo *mi = MemoServ::service->GetMemoInfo(nick, ischan, isregistered, false); if (mi == NULL) throw CoreException("NULL mi in ms_rsend"); MemoServ::Memo *m = (mi->memos->size() ? mi->GetMemo(mi->memos->size() - 1) : NULL); if (m != NULL) m->receipt = true; } } #endif }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("Causes Services to reload the configuration file.")); return true; }
void DoClear(CommandSource &source, ChannelInfo *ci) { ci->Shrink("cs_entrymsg"); source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str()); }
void DoLimit(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoServ::MemoInfo *mi) { Anope::string p1 = params[1]; Anope::string p2 = params.size() > 2 ? params[2] : ""; Anope::string p3 = params.size() > 3 ? params[3] : ""; Anope::string user, chan; int16_t limit; NickServ::Account *nc = source.nc; ChanServ::Channel *ci = NULL; bool is_servadmin = source.HasPriv("memoserv/set-limit"); if (p1[0] == '#') { chan = p1; p1 = p2; p2 = p3; p3 = params.size() > 4 ? params[4] : ""; ci = ChanServ::Find(chan); if (!ci) { source.Reply(_("Channel \002{0}\002 isn't registered."), chan); return; } if (!is_servadmin && !source.AccessFor(ci).HasPriv("MEMO")) { source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); return; } mi = ci->GetMemos(); } if (is_servadmin) { if (!p2.empty() && !p2.equals_ci("HARD") && chan.empty()) { NickServ::Nick *na; if (!(na = NickServ::FindNick(p1))) { source.Reply(_("\002{0}\002 isn't registered."), p1); return; } user = p1; mi = na->GetAccount()->GetMemos(); nc = na->GetAccount(); p1 = p2; p2 = p3; } else if (p1.empty() || (!p1.is_pos_number_only() && !p1.equals_ci("NONE")) || (!p2.empty() && !p2.equals_ci("HARD"))) { this->OnSyntaxError(source, ""); return; } if (!chan.empty()) { if (!p2.empty()) ci->SetS<bool>("MEMO_HARDMAX", true); else ci->UnsetS<bool>("MEMO_HARDMAX"); } else { if (!p2.empty()) nc->SetS<bool>("MEMO_HARDMAX", true); else nc->UnsetS<bool>("MEMO_HARDMAX"); } limit = -1; try { limit = convertTo<int16_t>(p1); } catch (const ConvertException &) { } } else { if (p1.empty() || !p2.empty() || !isdigit(p1[0])) { this->OnSyntaxError(source, ""); return; } if (!chan.empty() && ci->HasFieldS("MEMO_HARDMAX")) { source.Reply(_("The memo limit for \002{0}\002 may not be changed."), chan); return; } if (chan.empty() && nc->HasFieldS("MEMO_HARDMAX")) { source.Reply(_("You are not permitted to change your memo limit.")); return; } int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos"); limit = -1; try { limit = convertTo<int16_t>(p1); } catch (const ConvertException &) { } /* The first character is a digit, but we could still go negative * from overflow... watch out! */ if (limit < 0 || (max_memos > 0 && limit > max_memos)) { if (!chan.empty()) source.Reply(_("You cannot set the memo limit for \002{0}\002 higher than \002{1}\002."), chan, max_memos); else source.Reply(_("You cannot set your memo limit higher than \002{0}\002."), max_memos); return; } } mi->SetMemoMax(limit); if (limit > 0) { if (chan.empty() && nc == source.nc) source.Reply(_("Your memo limit has been set to \002{0}\002."), limit); else source.Reply(_("Memo limit for \002{0}\002 set to \002{1}\002."), !chan.empty() ? chan : user, limit); } else if (!limit) { if (chan.empty() && nc == source.nc) source.Reply(_("You will no longer be able to receive memos.")); else source.Reply(_("Memo limit for \002{0}\002 set to \0020\002."), !chan.empty() ? chan : user); } else { if (chan.empty() && nc == source.nc) source.Reply(_("Your memo limit has been disabled.")); else source.Reply(_("Memo limit \002disabled\002 for \002{0}\002."), !chan.empty() ? chan : user); } }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override { const Anope::string &nick = params[0]; Anope::string expiry = params[1]; Anope::string reason = params.size() > 2 ? params[2] : ""; time_t expiry_secs = Config->GetModule(this->GetOwner())->Get<time_t>("suspendexpire"); if (Anope::ReadOnly) source.Reply(_("Services are in read-only mode. Any changes made may not persist.")); if (expiry[0] != '+') { reason = expiry + " " + reason; reason.trim(); expiry.clear(); } else { expiry_secs = Anope::DoTime(expiry); if (expiry_secs == -1) { source.Reply(_("Invalid expiry time \002{0}\002."), expiry); return; } } NickServ::Nick *na = NickServ::FindNick(nick); if (!na) { source.Reply(_("\002{0}\002 isn't registered."), nick); return; } if (Config->GetModule("nickserv/main")->Get<bool>("secureadmins", "yes") && na->GetAccount()->GetOper()) { source.Reply(_("You may not suspend other Services Operators' nicknames.")); return; } NSSuspendInfo *si = na->GetAccount()->GetRef<NSSuspendInfo *>(); if (!si) { source.Reply(_("\002%s\002 is already suspended."), na->GetAccount()->GetDisplay().c_str()); return; } NickServ::Account *nc = na->GetAccount(); si = Serialize::New<NSSuspendInfo *>(); si->SetAccount(nc); si->SetBy(source.GetNick()); si->SetReason(reason); si->SetWhen(Anope::CurTime); si->SetExpires(expiry_secs ? expiry_secs + Anope::CurTime : 0); for (NickServ::Nick *na2 : nc->GetRefs<NickServ::Nick *>()) { na2->SetLastQuit(reason); User *u2 = User::Find(na2->GetNick(), true); if (u2) { u2->Logout(); if (NickServ::service) NickServ::service->Collide(u2, na2); } } Log(LOG_ADMIN, source, this) << "for " << nick << " (" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); source.Reply(_("\002{0}\002 is now suspended."), na->GetNick()); EventManager::Get()->Dispatch(&Event::NickSuspend::OnNickSuspend, na); }
void Run(CommandSource &source, const std::vector<Flux::string> ¶ms) { source.Reply("Rehashing Configuration file"); Log(source.u, this) << "to rehash the configuration"; Rehash(); }
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override { source.Reply(_("\002{0} SET\002 kills all operators from the given \002server\002 and prevents operators from opering up on the given server." " \002{0} REVOKE\002 removes this restriction.")); return true; }