00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 enum XOPType
00017 {
00018 XOP_QOP,
00019 XOP_SOP,
00020 XOP_AOP,
00021 XOP_HOP,
00022 XOP_VOP,
00023 XOP_UNKNOWN
00024 };
00025
00026 static struct XOPAccess
00027 {
00028 XOPType type;
00029 Anope::string name;
00030 Anope::string access[10];
00031 } xopAccess[] = {
00032 { XOP_QOP, "QOP",
00033 {
00034 "SIGNKICK",
00035 "SET",
00036 "MODE",
00037 "AUTOOWNER",
00038 "OWNERME",
00039 "PROTECT",
00040 "INFO",
00041 "ASSIGN",
00042 ""
00043 }
00044 },
00045 { XOP_SOP, "SOP",
00046 {
00047 "AUTOPROTECT",
00048 "AKICK",
00049 "BADWORDS",
00050 "MEMO",
00051 "ACCESS_CHANGE",
00052 "PROTECTME",
00053 "OPDEOP",
00054 ""
00055 }
00056 },
00057 { XOP_AOP, "AOP",
00058 {
00059 "TOPIC",
00060 "GETKEY",
00061 "INVITE",
00062 "AUTOOP",
00063 "OPDEOPME",
00064 "HALFOP",
00065 "SAY",
00066 "GREET",
00067 ""
00068 }
00069 },
00070 { XOP_HOP, "HOP",
00071 {
00072 "AUTOHALFOP",
00073 "HALFOPME",
00074 "VOICE",
00075 "KICK",
00076 "BAN",
00077 "UNBAN",
00078 ""
00079 }
00080 },
00081 { XOP_VOP, "VOP",
00082 {
00083 "AUTOVOICE",
00084 "VOICEME",
00085 "ACCESS_LIST",
00086 "FANTASIA",
00087 "NOKICK",
00088 ""
00089 }
00090 },
00091 { XOP_UNKNOWN, "", { }
00092 }
00093 };
00094
00095 class XOPChanAccess : public ChanAccess
00096 {
00097 public:
00098 XOPType type;
00099
00100 XOPChanAccess(AccessProvider *p) : ChanAccess(p)
00101 {
00102 }
00103
00104 bool HasPriv(const Anope::string &priv) const anope_override
00105 {
00106 for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i)
00107 {
00108 XOPAccess &x = xopAccess[i];
00109
00110 if (this->type > x.type)
00111 continue;
00112
00113 for (int j = 0; !x.access[j].empty(); ++j)
00114 if (x.access[j] == priv)
00115 return true;
00116 }
00117
00118 return false;
00119 }
00120
00121 Anope::string AccessSerialize() const
00122 {
00123 for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i)
00124 {
00125 XOPAccess &x = xopAccess[i];
00126
00127 if (this->type == x.type)
00128 return x.name;
00129 }
00130
00131 return "";
00132 }
00133
00134 void AccessUnserialize(const Anope::string &data) anope_override
00135 {
00136 for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i)
00137 {
00138 XOPAccess &x = xopAccess[i];
00139
00140 if (data == x.name)
00141 {
00142 this->type = x.type;
00143 return;
00144 }
00145 }
00146
00147 this->type = XOP_UNKNOWN;
00148 }
00149
00150 static XOPType DetermineLevel(const ChanAccess *access)
00151 {
00152 if (access->provider->name == "access/xop")
00153 {
00154 const XOPChanAccess *xaccess = anope_dynamic_static_cast<const XOPChanAccess *>(access);
00155 return xaccess->type;
00156 }
00157 else
00158 {
00159 int count[XOP_UNKNOWN];
00160 for (int i = 0; i < XOP_UNKNOWN; ++i)
00161 count[i] = 0;
00162
00163 for (int i = 0; xopAccess[i].type != XOP_UNKNOWN; ++i)
00164 {
00165 XOPAccess &x = xopAccess[i];
00166
00167 for (int j = 0; !x.access[j].empty(); ++j)
00168 if (access->HasPriv(x.access[j]))
00169 ++count[x.type];
00170 }
00171
00172 XOPType max = XOP_UNKNOWN;
00173 int maxn = 0;
00174 for (int i = 0; i < XOP_UNKNOWN; ++i)
00175 if (count[i] > maxn)
00176 {
00177 max = static_cast<XOPType>(i);
00178 maxn = count[i];
00179 }
00180
00181 return max;
00182 }
00183 }
00184 };
00185
00186 class XOPAccessProvider : public AccessProvider
00187 {
00188 public:
00189 XOPAccessProvider(Module *o) : AccessProvider(o, "access/xop")
00190 {
00191 }
00192
00193 ChanAccess *Create() anope_override
00194 {
00195 return new XOPChanAccess(this);
00196 }
00197 };
00198
00199 class XOPBase : public Command
00200 {
00201 private:
00202 void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level)
00203 {
00204
00205 Anope::string mask = params.size() > 2 ? params[2] : "";
00206
00207 if (mask.empty())
00208 {
00209 this->OnSyntaxError(source, "ADD");
00210 return;
00211 }
00212
00213 if (Anope::ReadOnly)
00214 {
00215 source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
00216 return;
00217 }
00218
00219 XOPChanAccess tmp_access(NULL);
00220 tmp_access.ci = ci;
00221 tmp_access.type = level;
00222
00223 AccessGroup access = source.AccessFor(ci);
00224 const ChanAccess *highest = access.Highest();
00225 bool override = false;
00226
00227 if ((!access.founder && !access.HasPriv("ACCESS_CHANGE")) || ((!highest || *highest <= tmp_access) && !access.founder))
00228 {
00229 if (source.HasPriv("chanserv/access/modify"))
00230 override = true;
00231 else
00232 {
00233 source.Reply(ACCESS_DENIED);
00234 return;
00235 }
00236 }
00237
00238 if (mask.find_first_of("!*@") == Anope::string::npos && !NickAlias::Find(mask))
00239 {
00240 User *targ = User::Find(mask, true);
00241 if (targ != NULL)
00242 mask = "*!*@" + targ->GetDisplayedHost();
00243 else
00244 {
00245 source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
00246 return;
00247 }
00248 }
00249
00250 for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
00251 {
00252 const ChanAccess *a = ci->GetAccess(i);
00253
00254 if (a->mask.equals_ci(mask))
00255 {
00256 if ((!highest || *a >= *highest) && !access.founder && !source.HasPriv("chanserv/access/modify"))
00257 {
00258 source.Reply(ACCESS_DENIED);
00259 return;
00260 }
00261
00262 ci->EraseAccess(i);
00263 break;
00264 }
00265 }
00266
00267 if (ci->GetAccessCount() >= Config->CSAccessMax)
00268 {
00269 source.Reply(_("Sorry, you can only have %d %s entries on a channel."), Config->CSAccessMax, source.command.c_str());
00270 return;
00271 }
00272
00273 ServiceReference<AccessProvider> provider("AccessProvider", "access/xop");
00274 if (!provider)
00275 return;
00276 XOPChanAccess *acc = anope_dynamic_static_cast<XOPChanAccess *>(provider->Create());
00277 acc->ci = ci;
00278 acc->mask = mask;
00279 acc->creator = source.GetNick();
00280 acc->type = level;
00281 acc->last_seen = 0;
00282 acc->created = Anope::CurTime;
00283 ci->AddAccess(acc);
00284
00285 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to add " << mask;
00286
00287 FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, source, acc));
00288 source.Reply(_("\002%s\002 added to %s %s list."), acc->mask.c_str(), ci->name.c_str(), source.command.c_str());
00289 }
00290
00291 void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level)
00292 {
00293 NickCore *nc = source.nc;
00294 Anope::string mask = params.size() > 2 ? params[2] : "";
00295
00296 if (mask.empty())
00297 {
00298 this->OnSyntaxError(source, "DEL");
00299 return;
00300 }
00301
00302 if (Anope::ReadOnly)
00303 {
00304 source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
00305 return;
00306 }
00307
00308 if (!ci->GetAccessCount())
00309 {
00310 source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str());
00311 return;
00312 }
00313
00314 XOPChanAccess tmp_access(NULL);
00315 tmp_access.ci = ci;
00316 tmp_access.type = level;
00317
00318 AccessGroup access = source.AccessFor(ci);
00319 const ChanAccess *highest = access.Highest();
00320 bool override = false;
00321
00322 if (!isdigit(mask[0]) && mask.find_first_of("!*@") == Anope::string::npos && !NickAlias::Find(mask))
00323 {
00324 User *targ = User::Find(mask, true);
00325 if (targ != NULL)
00326 mask = "*!*@" + targ->GetDisplayedHost();
00327 else
00328 {
00329 source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
00330 return;
00331 }
00332 }
00333
00334 if ((!mask.equals_ci(nc->display) && !access.HasPriv("ACCESS_CHANGE") && !access.founder) || ((!highest || tmp_access >= *highest) && !access.founder))
00335 {
00336 if (source.HasPriv("chanserv/access/modify"))
00337 override = true;
00338 else
00339 {
00340 source.Reply(ACCESS_DENIED);
00341 return;
00342 }
00343 }
00344
00345
00346 if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
00347 {
00348 class XOPDelCallback : public NumberList
00349 {
00350 CommandSource &source;
00351 ChannelInfo *ci;
00352 Command *c;
00353 unsigned deleted;
00354 Anope::string nicks;
00355 bool override;
00356 XOPType type;
00357 public:
00358 XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, XOPType _type, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), override(_override), type(_type)
00359 {
00360 }
00361
00362 ~XOPDelCallback()
00363 {
00364 if (!deleted)
00365 source.Reply(_("No matching entries on %s %s list."), ci->name.c_str(), source.command.c_str());
00366 else
00367 {
00368 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << nicks;
00369
00370 if (deleted == 1)
00371 source.Reply(_("Deleted one entry from %s %s list."), ci->name.c_str(), source.command.c_str());
00372 else
00373 source.Reply(_("Deleted %d entries from %s %s list."), deleted, ci->name.c_str(), source.command.c_str());
00374 }
00375 }
00376
00377 void HandleNumber(unsigned number) anope_override
00378 {
00379 if (!number || number > ci->GetAccessCount())
00380 return;
00381
00382 ChanAccess *caccess = ci->GetAccess(number - 1);
00383
00384 if (this->type != XOPChanAccess::DetermineLevel(caccess))
00385 return;
00386
00387 ++deleted;
00388 if (!nicks.empty())
00389 nicks += ", " + caccess->mask;
00390 else
00391 nicks = caccess->mask;
00392
00393 FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, source, caccess));
00394
00395 ci->EraseAccess(number - 1);
00396 }
00397 }
00398 delcallback(source, ci, this, override, level, mask);
00399 delcallback.Process();
00400 }
00401 else
00402 {
00403 for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
00404 {
00405 ChanAccess *a = ci->GetAccess(i);
00406
00407 if (a->mask.equals_ci(mask) && XOPChanAccess::DetermineLevel(a) == level)
00408 {
00409 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << a->mask;
00410
00411 source.Reply(_("\002%s\002 deleted from %s %s list."), a->mask.c_str(), ci->name.c_str(), source.command.c_str());
00412
00413 FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, source, a));
00414 delete a;
00415
00416 return;
00417 }
00418 }
00419
00420 source.Reply(_("\002%s\002 not found on %s %s list."), mask.c_str(), ci->name.c_str(), source.command.c_str());
00421 }
00422 }
00423
00424 void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, XOPType level)
00425 {
00426
00427 const Anope::string &nick = params.size() > 2 ? params[2] : "";
00428
00429 AccessGroup access = source.AccessFor(ci);
00430
00431 if (!access.HasPriv("ACCESS_LIST") && !source.HasCommand("chanserv/access/list"))
00432 {
00433 source.Reply(ACCESS_DENIED);
00434 return;
00435 }
00436
00437 if (!ci->GetAccessCount())
00438 {
00439 source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str());
00440 return;
00441 }
00442
00443 ListFormatter list;
00444 list.AddColumn("Number").AddColumn("Mask");
00445
00446 if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
00447 {
00448 class XOPListCallback : public NumberList
00449 {
00450 ListFormatter &list;
00451 ChannelInfo *ci;
00452 XOPType type;
00453 public:
00454 XOPListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist, XOPType _type) : NumberList(numlist, false), list(_list), ci(_ci), type(_type)
00455 {
00456 }
00457
00458 void HandleNumber(unsigned Number) anope_override
00459 {
00460 if (!Number || Number > ci->GetAccessCount())
00461 return;
00462
00463 const ChanAccess *a = ci->GetAccess(Number - 1);
00464
00465 if (this->type != XOPChanAccess::DetermineLevel(a))
00466 return;
00467
00468 ListFormatter::ListEntry entry;
00469 entry["Number"] = stringify(Number);
00470 entry["Mask"] = a->mask;
00471 this->list.AddEntry(entry);
00472 }
00473 } nl_list(list, ci, nick, level);
00474 nl_list.Process();
00475 }
00476 else
00477 {
00478 for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i)
00479 {
00480 const ChanAccess *a = ci->GetAccess(i);
00481
00482 if (XOPChanAccess::DetermineLevel(a) != level)
00483 continue;
00484 else if (!nick.empty() && !Anope::Match(a->mask, nick))
00485 continue;
00486
00487 ListFormatter::ListEntry entry;
00488 entry["Number"] = stringify(i + 1);
00489 entry["Mask"] = a->mask;
00490 list.AddEntry(entry);
00491 }
00492 }
00493
00494 if (list.IsEmpty())
00495 source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
00496 else
00497 {
00498 std::vector<Anope::string> replies;
00499 list.Process(replies);
00500
00501 source.Reply(_("%s list for %s"), source.command.c_str(), ci->name.c_str());
00502 for (unsigned i = 0; i < replies.size(); ++i)
00503 source.Reply(replies[i]);
00504 }
00505 }
00506
00507 void DoClear(CommandSource &source, ChannelInfo *ci, XOPType level)
00508 {
00509
00510 if (Anope::ReadOnly)
00511 {
00512 source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
00513 return;
00514 }
00515
00516 if (!ci->GetAccessCount())
00517 {
00518 source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str());
00519 return;
00520 }
00521
00522 if (!source.AccessFor(ci).HasPriv("FOUNDER") && !source.HasPriv("chanserv/access/modify"))
00523 {
00524 source.Reply(ACCESS_DENIED);
00525 return;
00526 }
00527
00528 bool override = !source.AccessFor(ci).HasPriv("FOUNDER");
00529 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list";
00530
00531 for (unsigned i = ci->GetAccessCount(); i > 0; --i)
00532 {
00533 const ChanAccess *access = ci->GetAccess(i - 1);
00534 if (XOPChanAccess::DetermineLevel(access) == level)
00535 ci->EraseAccess(i - 1);
00536 }
00537
00538 FOREACH_MOD(I_OnAccessClear, OnAccessClear(ci, source));
00539
00540 source.Reply(_("Channel %s %s list has been cleared."), ci->name.c_str(), source.command.c_str());
00541
00542 return;
00543 }
00544
00545 protected:
00546 void DoXop(CommandSource &source, const std::vector<Anope::string> ¶ms, XOPType level)
00547 {
00548 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00549 if (ci == NULL)
00550 {
00551 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00552 return;
00553 }
00554
00555 const Anope::string &cmd = params[1];
00556
00557 if (cmd.equals_ci("ADD"))
00558 return this->DoAdd(source, ci, params, level);
00559 else if (cmd.equals_ci("DEL"))
00560 return this->DoDel(source, ci, params, level);
00561 else if (cmd.equals_ci("LIST"))
00562 return this->DoList(source, ci, params, level);
00563 else if (cmd.equals_ci("CLEAR"))
00564 return this->DoClear(source, ci, level);
00565 else
00566 this->OnSyntaxError(source, "");
00567
00568 return;
00569 }
00570 public:
00571 XOPBase(Module *modname, const Anope::string &command) : Command(modname, command, 2, 4)
00572 {
00573 this->SetSyntax("\037channel\037 ADD \037mask\037");
00574 this->SetSyntax("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}");
00575 this->SetSyntax("\037channel\037 LIST [\037mask\037 | \037list\037]");
00576 this->SetSyntax("\037channel\037 CLEAR");
00577 }
00578
00579 virtual ~XOPBase()
00580 {
00581 }
00582
00583 virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0;
00584
00585 virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0;
00586 };
00587
00588 class CommandCSQOP : public XOPBase
00589 {
00590 public:
00591 CommandCSQOP(Module *creator) : XOPBase(creator, "chanserv/qop")
00592 {
00593 this->SetDesc(_("Modify the list of QOP users"));
00594 }
00595
00596 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00597 {
00598 return this->DoXop(source, params, XOP_QOP);
00599 }
00600
00601 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00602 {
00603 this->SendSyntax(source);
00604 source.Reply(" ");
00605 source.Reply(_("Maintains the \002QOP\002 (AutoOwner) \002list\002 for a channel. The QOP\n"
00606 "list gives users the right to be auto-owner on your channel,\n"
00607 "which gives them almost (or potentially, total) access.\n"
00608 " \n"
00609 "The \002QOP ADD\002 command adds the given nickname to the\n"
00610 "QOP list.\n"
00611 " \n"
00612 "The \002QOP DEL\002 command removes the given nick from the\n"
00613 "QOP list. If a list of entry numbers is given, those\n"
00614 "entries are deleted. (See the example for LIST below.)\n"
00615 " \n"
00616 "The \002QOP LIST\002 command displays the QOP list. If\n"
00617 "a wildcard mask is given, only those entries matching the\n"
00618 "mask are displayed. If a list of entry numbers is given,\n"
00619 "only those entries are shown; for example:\n"
00620 " \002QOP #channel LIST 2-5,7-9\002\n"
00621 " Lists QOP entries numbered 2 through 5 and\n"
00622 " 7 through 9.\n"
00623 " \n"
00624 "The \002QOP CLEAR\002 command clears all entries of the\n"
00625 "QOP list."));
00626 source.Reply(_(" \n"
00627 "The \002QOP\002 commands are limited to founders\n"
00628 "(unless SECUREOPS is off). However, any user on the\n"
00629 "VOP list or above may use the \002QOP LIST\002 command.\n"
00630 " \n"));
00631 source.Reply(_("Alternative methods of modifying channel access lists are\n"
00632 "available. See \002%s%s HELP ACCESS\002 for information\n"
00633 "about the access list, and \002%s%s HELP FLAGS\002 for\n"
00634 "information about the flags based system."),
00635 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(),
00636 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00637 return true;
00638 }
00639 };
00640
00641 class CommandCSAOP : public XOPBase
00642 {
00643 public:
00644 CommandCSAOP(Module *creator) : XOPBase(creator, "chanserv/aop")
00645 {
00646 this->SetDesc(_("Modify the list of AOP users"));
00647 }
00648
00649 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00650 {
00651 return this->DoXop(source, params, XOP_AOP);
00652 }
00653
00654 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00655 {
00656 this->SendSyntax(source);
00657 source.Reply(" ");
00658 source.Reply(_("Maintains the \002AOP\002 (AutoOP) \002list\002 for a channel. The AOP\n"
00659 "list gives users the right to be auto-opped on your channel,\n"
00660 "to unban or invite themselves if needed, to have their\n"
00661 "greet message showed on join, and so on.\n"
00662 " \n"
00663 "The \002AOP ADD\002 command adds the given nickname to the\n"
00664 "AOP list.\n"
00665 " \n"
00666 "The \002AOP DEL\002 command removes the given nick from the\n"
00667 "AOP list. If a list of entry numbers is given, those\n"
00668 "entries are deleted. (See the example for LIST below.)\n"
00669 " \n"
00670 "The \002AOP LIST\002 command displays the AOP list. If\n"
00671 "a wildcard mask is given, only those entries matching the\n"
00672 "mask are displayed. If a list of entry numbers is given,\n"
00673 "only those entries are shown; for example:\n"
00674 " \002AOP #channel LIST 2-5,7-9\002\n"
00675 " Lists AOP entries numbered 2 through 5 and\n"
00676 " 7 through 9.\n"
00677 " \n"
00678 "The \002AOP CLEAR\002 command clears all entries of the\n"
00679 "AOP list."));
00680 source.Reply(_(" \n"
00681 "The \002AOP ADD\002 and \002AOP DEL\002 commands are limited to\n"
00682 "SOPs or above, while the \002AOP CLEAR\002 command can only\n"
00683 "be used by the channel founder. However, any user on the\n"
00684 "VOP list or above may use the \002AOP LIST\002 command.\n"
00685 " \n"));
00686 source.Reply(_("Alternative methods of modifying channel access lists are\n"
00687 "available. See \002%s%s HELP ACCESS\002 for information\n"
00688 "about the access list, and \002%s%s HELP FLAGS\002 for\n"
00689 "information about the flags based system."),
00690 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(),
00691 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00692 return true;
00693 }
00694 };
00695
00696 class CommandCSHOP : public XOPBase
00697 {
00698 public:
00699 CommandCSHOP(Module *creator) : XOPBase(creator, "chanserv/hop")
00700 {
00701 this->SetDesc(_("Maintains the HOP (HalfOP) list for a channel"));
00702 }
00703
00704 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00705 {
00706 return this->DoXop(source, params, XOP_HOP);
00707 }
00708
00709 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00710 {
00711 this->SendSyntax(source);
00712 source.Reply(" ");
00713 source.Reply(_("Maintains the \002HOP\002 (HalfOP) \002list\002 for a channel. The HOP\n"
00714 "list gives users the right to be auto-halfopped on your\n"
00715 "channel.\n"
00716 " \n"
00717 "The \002HOP ADD\002 command adds the given nickname to the\n"
00718 "HOP list.\n"
00719 " \n"
00720 "The \002HOP DEL\002 command removes the given nick from the\n"
00721 "HOP list. If a list of entry numbers is given, those\n"
00722 "entries are deleted. (See the example for LIST below.)\n"
00723 " \n"
00724 "The \002HOP LIST\002 command displays the HOP list. If\n"
00725 "a wildcard mask is given, only those entries matching the\n"
00726 "mask are displayed. If a list of entry numbers is given,\n"
00727 "only those entries are shown; for example:\n"
00728 " \002HOP #channel LIST 2-5,7-9\002\n"
00729 " Lists HOP entries numbered 2 through 5 and\n"
00730 " 7 through 9.\n"
00731 " \n"
00732 "The \002HOP CLEAR\002 command clears all entries of the\n"
00733 "HOP list."));
00734 source.Reply(_(" \n"
00735 "The \002HOP ADD\002 and \002HOP DEL\002 commands are limited\n"
00736 "to SOPs or above, while \002HOP LIST\002 is available to VOPs\n"
00737 "and above. The \002HOP CLEAR\002 command can only be used by the\n"
00738 "channel founder.\n"
00739 " \n"));
00740 source.Reply(_("Alternative methods of modifying channel access lists are\n"
00741 "available. See \002%s%s HELP ACCESS\002 for information\n"
00742 "about the access list, and \002%s%s HELP FLAGS\002 for\n"
00743 "information about the flags based system."),
00744 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(),
00745 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00746 return true;
00747 }
00748 };
00749
00750 class CommandCSSOP : public XOPBase
00751 {
00752 public:
00753 CommandCSSOP(Module *creator) : XOPBase(creator, "chanserv/sop")
00754 {
00755 this->SetDesc(_("Modify the list of SOP users"));
00756 }
00757
00758 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00759 {
00760 return this->DoXop(source, params, XOP_SOP);
00761 }
00762
00763 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00764 {
00765 this->SendSyntax(source);
00766 source.Reply(" ");
00767 source.Reply(_("Maintains the \002SOP\002 (SuperOP) \002list\002 for a channel. The SOP\n"
00768 "list gives users all rights given by the AOP list, and adds\n"
00769 "those needed to use the AutoKick and the BadWords lists,\n"
00770 "to send and read channel memos, and so on.\n"
00771 " \n"
00772 "The \002SOP ADD\002 command adds the given nickname to the\n"
00773 "SOP list.\n"
00774 " \n"
00775 "The \002SOP DEL\002 command removes the given nick from the\n"
00776 "SOP list. If a list of entry numbers is given, those\n"
00777 "entries are deleted. (See the example for LIST below.)\n"
00778 " \n"
00779 "The \002SOP LIST\002 command displays the SOP list. If\n"
00780 "a wildcard mask is given, only those entries matching the\n"
00781 "mask are displayed. If a list of entry numbers is given,\n"
00782 "only those entries are shown; for example:\n"
00783 " \002SOP #channel LIST 2-5,7-9\002\n"
00784 " Lists SOP entries numbered 2 through 5 and\n"
00785 " 7 through 9.\n"
00786 " \n"
00787 "The \002SOP CLEAR\002 command clears all entries of the\n"
00788 "SOP list."));
00789 source.Reply(_(" \n"
00790 "The \002SOP ADD\002, \002SOP DEL\002 and \002SOP CLEAR\002 commands are\n"
00791 "limited to the channel founder. However, any user on the\n"
00792 "VOP list or above may use the \002SOP LIST\002 command.\n"
00793 " \n"));
00794 source.Reply(_("Alternative methods of modifying channel access lists are\n"
00795 "available. See \002%s%s HELP ACCESS\002 for information\n"
00796 "about the access list, and \002%s%s HELP FLAGS\002 for\n"
00797 "information about the flags based system."),
00798 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(),
00799 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00800 return true;
00801 }
00802 };
00803
00804 class CommandCSVOP : public XOPBase
00805 {
00806 public:
00807 CommandCSVOP(Module *creator) : XOPBase(creator, "chanserv/vop")
00808 {
00809 this->SetDesc(_("Maintains the VOP (VOicePeople) list for a channel"));
00810 }
00811
00812 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00813 {
00814 return this->DoXop(source, params, XOP_VOP);
00815 }
00816
00817 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00818 {
00819 this->SendSyntax(source);
00820 source.Reply(" ");
00821 source.Reply(_("Maintains the \002VOP\002 (VOicePeople) \002list\002 for a channel.\n"
00822 "The VOP list allows users to be auto-voiced and to voice\n"
00823 "themselves if they aren't.\n"
00824 " \n"
00825 "The \002VOP ADD\002 command adds the given nickname to the\n"
00826 "VOP list.\n"
00827 " \n"
00828 "The \002VOP DEL\002 command removes the given nick from the\n"
00829 "VOP list. If a list of entry numbers is given, those\n"
00830 "entries are deleted. (See the example for LIST below.)\n"
00831 " \n"
00832 "The \002VOP LIST\002 command displays the VOP list. If\n"
00833 "a wildcard mask is given, only those entries matching the\n"
00834 "mask are displayed. If a list of entry numbers is given,\n"
00835 "only those entries are shown; for example:\n"
00836 " \002VOP #channel LIST 2-5,7-9\002\n"
00837 " Lists VOP entries numbered 2 through 5 and\n"
00838 " 7 through 9.\n"
00839 " \n"
00840 "The \002VOP CLEAR\002 command clears all entries of the\n"
00841 "VOP list."));
00842 source.Reply(_(" \n"
00843 "The \002VOP ADD\002 and \002VOP DEL\002 commands are limited\n"
00844 "to SOPs or above, while \002VOP LIST\002 is available to VOPs\n"
00845 "and above. The \002VOP CLEAR\002 command can only be used by the\n"
00846 "channel founder.\n"
00847 " \n"));
00848 source.Reply(_("Alternative methods of modifying channel access lists are\n"
00849 "available. See \002%s%s HELP ACCESS\002 for information\n"
00850 "about the access list, and \002%s%s HELP FLAGS\002 for\n"
00851 "information about the flags based system."),
00852 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(),
00853 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00854 return true;
00855 }
00856 };
00857
00858 class CSXOP : public Module
00859 {
00860 XOPAccessProvider accessprovider;
00861 CommandCSQOP commandcsqop;
00862 CommandCSSOP commandcssop;
00863 CommandCSAOP commandcsaop;
00864 CommandCSHOP commandcshop;
00865 CommandCSVOP commandcsvop;
00866
00867 public:
00868 CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00869 accessprovider(this), commandcsqop(this), commandcssop(this), commandcsaop(this), commandcshop(this), commandcsvop(this)
00870 {
00871 this->SetAuthor("Anope");
00872 this->SetPermanent(true);
00873 }
00874 };
00875
00876 MODULE_INIT(CSXOP)