anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
cs_list.cpp (8292B)
1 /* ChanServ core functions 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 #include "modules/cs_mode.h" 14 15 class CommandCSList : public Command 16 { 17 public: 18 CommandCSList(Module *creator) : Command(creator, "chanserv/list", 1, 2) 19 { 20 this->SetDesc(_("Lists all registered channels matching the given pattern")); 21 this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE]")); 22 } 23 24 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 25 { 26 Anope::string pattern = params[0]; 27 unsigned nchans; 28 bool is_servadmin = source.HasCommand("chanserv/list"); 29 int count = 0, from = 0, to = 0; 30 bool suspended = false, channoexpire = false; 31 32 if (pattern[0] == '#') 33 { 34 Anope::string n1, n2; 35 sepstream(pattern.substr(1), '-').GetToken(n1, 0); 36 sepstream(pattern, '-').GetToken(n2, 1); 37 38 try 39 { 40 from = convertTo<int>(n1); 41 to = convertTo<int>(n2); 42 } 43 catch (const ConvertException &) 44 { 45 source.Reply(LIST_INCORRECT_RANGE); 46 source.Reply(_("To search for channels starting with #, search for the channel\n" 47 "name without the #-sign prepended (\002anope\002 instead of \002#anope\002).")); 48 return; 49 } 50 51 pattern = "*"; 52 } 53 54 nchans = 0; 55 56 if (is_servadmin && params.size() > 1) 57 { 58 Anope::string keyword; 59 spacesepstream keywords(params[1]); 60 while (keywords.GetToken(keyword)) 61 { 62 if (keyword.equals_ci("SUSPENDED")) 63 suspended = true; 64 if (keyword.equals_ci("NOEXPIRE")) 65 channoexpire = true; 66 } 67 } 68 69 Anope::string spattern = "#" + pattern; 70 unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50"); 71 72 source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str()); 73 74 ListFormatter list(source.GetAccount()); 75 list.AddColumn(_("Name")).AddColumn(_("Description")); 76 77 Anope::map<ChannelInfo *> ordered_map; 78 for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) 79 ordered_map[it->first] = it->second; 80 81 for (Anope::map<ChannelInfo *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it) 82 { 83 const ChannelInfo *ci = it->second; 84 85 if (!is_servadmin) 86 { 87 if (ci->HasExt("CS_PRIVATE") || ci->HasExt("CS_SUSPENDED")) 88 continue; 89 if (ci->c && ci->c->HasMode("SECRET")) 90 continue; 91 92 ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks"); 93 const ModeLock *secret = ml ? ml->GetMLock("SECRET") : NULL; 94 if (secret && secret->set) 95 continue; 96 } 97 98 if (suspended && !ci->HasExt("CS_SUSPENDED")) 99 continue; 100 101 if (channoexpire && !ci->HasExt("CS_NO_EXPIRE")) 102 continue; 103 104 if (pattern.equals_ci(ci->name) || ci->name.equals_ci(spattern) || Anope::Match(ci->name, pattern, false, true) || Anope::Match(ci->name, spattern, false, true) || Anope::Match(ci->desc, pattern, false, true) || Anope::Match(ci->last_topic, pattern, false, true)) 105 { 106 if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nchans <= listmax) 107 { 108 bool isnoexpire = false; 109 if (is_servadmin && (ci->HasExt("CS_NO_EXPIRE"))) 110 isnoexpire = true; 111 112 ListFormatter::ListEntry entry; 113 entry["Name"] = (isnoexpire ? "!" : "") + ci->name; 114 if (ci->HasExt("CS_SUSPENDED")) 115 entry["Description"] = Language::Translate(source.GetAccount(), _("[Suspended]")); 116 else 117 entry["Description"] = ci->desc; 118 list.AddEntry(entry); 119 } 120 ++count; 121 } 122 } 123 124 std::vector<Anope::string> replies; 125 list.Process(replies); 126 127 for (unsigned i = 0; i < replies.size(); ++i) 128 source.Reply(replies[i]); 129 130 source.Reply(_("End of list - %d/%d matches shown."), nchans > listmax ? listmax : nchans, nchans); 131 } 132 133 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 134 { 135 this->SendSyntax(source); 136 source.Reply(" "); 137 source.Reply(_("Lists all registered channels matching the given pattern.\n" 138 "Channels with the \002PRIVATE\002 option set will only be\n" 139 "displayed to Services Operators with the proper access.\n" 140 "Channels with the \002NOEXPIRE\002 option set will have\n" 141 "a \002!\002 prefixed to the channel for Services Operators to see.\n" 142 " \n" 143 "Note that a preceding '#' specifies a range, channel names\n" 144 "are to be written without '#'.\n" 145 " \n" 146 "If the SUSPENDED or NOEXPIRE options are given, only channels\n" 147 "which, respectively, are SUSPENDED or have the NOEXPIRE\n" 148 "flag set will be displayed. If multiple options are given,\n" 149 "all channels matching at least one option will be displayed.\n" 150 "Note that these options are limited to \037Services Operators\037.\n" 151 " \n" 152 "Examples:\n" 153 " \n" 154 " \002LIST *anope*\002\n" 155 " Lists all registered channels with \002anope\002 in their\n" 156 " names (case insensitive).\n" 157 " \n" 158 " \002LIST * NOEXPIRE\002\n" 159 " Lists all registered channels which have been set to not expire.\n" 160 " \n" 161 " \002LIST #51-100\002\n" 162 " Lists all registered channels within the given range (51-100).")); 163 164 if (!Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty()) 165 { 166 source.Reply(" "); 167 source.Reply(_("Regex matches are also supported using the %s engine.\n" 168 "Enclose your pattern in // if this is desired."), Config->GetBlock("options")->Get<const Anope::string>("regexengine").c_str()); 169 } 170 171 return true; 172 } 173 }; 174 175 class CommandCSSetPrivate : public Command 176 { 177 public: 178 CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2) 179 { 180 this->SetDesc(_("Hide channel from the LIST command")); 181 this->SetSyntax(_("\037channel\037 {ON | OFF}")); 182 } 183 184 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 185 { 186 if (Anope::ReadOnly) 187 { 188 source.Reply(READ_ONLY_MODE); 189 return; 190 } 191 192 ChannelInfo *ci = ChannelInfo::Find(params[0]); 193 if (ci == NULL) 194 { 195 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); 196 return; 197 } 198 199 EventReturn MOD_RESULT; 200 FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); 201 if (MOD_RESULT == EVENT_STOP) 202 return; 203 204 if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) 205 { 206 source.Reply(ACCESS_DENIED); 207 return; 208 } 209 210 if (params[1].equals_ci("ON")) 211 { 212 Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable private"; 213 ci->Extend<bool>("CS_PRIVATE"); 214 source.Reply(_("Private option for %s is now \002on\002."), ci->name.c_str()); 215 } 216 else if (params[1].equals_ci("OFF")) 217 { 218 Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable private"; 219 ci->Shrink<bool>("CS_PRIVATE"); 220 source.Reply(_("Private option for %s is now \002off\002."), ci->name.c_str()); 221 } 222 else 223 this->OnSyntaxError(source, "PRIVATE"); 224 225 return; 226 } 227 228 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 229 { 230 this->SendSyntax(source); 231 source.Reply(" "); 232 source.Reply(_("Enables or disables the \002private\002 option for a channel.")); 233 234 BotInfo *bi; 235 Anope::string cmd; 236 if (Command::FindCommandFromService("chanserv/list", bi, cmd)) 237 source.Reply(_("When \002private\002 is set, the channel will not appear in\n" 238 "%s's %s command."), bi->nick.c_str(), cmd.c_str()); 239 return true; 240 } 241 }; 242 243 class CSList : public Module 244 { 245 CommandCSList commandcslist; 246 CommandCSSetPrivate commandcssetprivate; 247 248 SerializableExtensibleItem<bool> priv; 249 250 public: 251 CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), 252 commandcslist(this), commandcssetprivate(this), priv(this, "CS_PRIVATE") 253 { 254 } 255 256 void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override 257 { 258 if (!show_all) 259 return; 260 261 if (priv.HasExt(ci)) 262 info.AddOption(_("Private")); 263 } 264 }; 265 266 MODULE_INIT(CSList)