00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "module.h"
00013
00014 class CommandCSSet : public Command
00015 {
00016 public:
00017 CommandCSSet(Module *creator) : Command(creator, "chanserv/set", 2, 3)
00018 {
00019 this->SetDesc(_("Set channel options and information"));
00020 this->SetSyntax(_("\037option\037 \037channel\037 \037parameters\037"));
00021 }
00022
00023 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00024 {
00025 this->OnSyntaxError(source, "");
00026 return;
00027 }
00028
00029 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00030 {
00031 this->SendSyntax(source);
00032 source.Reply(" ");
00033 source.Reply(_("Allows the channel founder to set various channel options\n"
00034 "and other information.\n"
00035 " \n"
00036 "Available options:"));
00037 Anope::string this_name = source.command;
00038 for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
00039 {
00040 const Anope::string &c_name = it->first;
00041 const CommandInfo &info = it->second;
00042 if (c_name.find_ci(this_name + " ") == 0)
00043 {
00044 ServiceReference<Command> command("Command", info.name);
00045 if (command)
00046 {
00047 source.command = it->first;
00048 command->OnServHelp(source);
00049 }
00050 }
00051 }
00052 source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n"
00053 "particular option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00054 return true;
00055 }
00056 };
00057
00058 class CommandCSSASet : public Command
00059 {
00060 public:
00061 CommandCSSASet(Module *creator) : Command(creator, "chanserv/saset", 2, 3)
00062 {
00063 this->SetDesc(_("Forcefully set channel options and information"));
00064 this->SetSyntax(_("\037option\037 \037channel\037 \037parameters\037"));
00065 }
00066
00067 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00068 {
00069 this->OnSyntaxError(source, "");
00070 return;
00071 }
00072
00073 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00074 {
00075 this->SendSyntax(source);
00076 source.Reply(" ");
00077 source.Reply(_("Allows Services Operators to forcefully change settings\n"
00078 "on channels.\n"
00079 " \n"
00080 "Available options:"));
00081 Anope::string this_name = source.command;
00082 for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
00083 {
00084 const Anope::string &c_name = it->first;
00085 const CommandInfo &info = it->second;
00086 if (c_name.find_ci(this_name + " ") == 0)
00087 {
00088 ServiceReference<Command> command("Command", info.name);
00089 if (command)
00090 {
00091 source.command = it->first;
00092 command->OnServHelp(source);
00093 }
00094 }
00095 }
00096 source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information on a\n"
00097 "particular option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00098 return true;
00099 }
00100 };
00101
00102 class CommandCSSetAutoOp : public Command
00103 {
00104 public:
00105 CommandCSSetAutoOp(Module *creator, const Anope::string &cname = "chanserv/set/autoop") : Command(creator, cname, 2, 2)
00106 {
00107 this->SetDesc(_("Should services automatically give status to users"));
00108 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00109 }
00110
00111 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00112 {
00113 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00114 if (ci == NULL)
00115 {
00116 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00117 return;
00118 }
00119
00120 EventReturn MOD_RESULT;
00121 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00122 if (MOD_RESULT == EVENT_STOP)
00123 return;
00124
00125 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00126 {
00127 source.Reply(ACCESS_DENIED);
00128 return;
00129 }
00130
00131 if (params[1].equals_ci("ON"))
00132 {
00133 ci->Shrink("NOAUTOOP");
00134 source.Reply(_("Services will now automatically give modes to users in \002%s\002."), ci->name.c_str());
00135 }
00136 else if (params[1].equals_ci("OFF"))
00137 {
00138 ci->ExtendMetadata("NOAUTOOP");
00139 source.Reply(_("Services will no longer automatically give modes to users in \002%s\002."), ci->name.c_str());
00140 }
00141 else
00142 this->OnSyntaxError(source, "AUTOOP");
00143 }
00144
00145 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00146 {
00147 this->SendSyntax(source);
00148 source.Reply(" ");
00149 source.Reply(_("Enables or disables %s's autoop feature for a\n"
00150 "channel. When disabled, users who join the channel will\n"
00151 "not automatically gain any status from %s."), Config->ChanServ.c_str(),
00152 Config->ChanServ.c_str(), this->name.c_str());
00153 return true;
00154 }
00155 };
00156
00157 class CommandCSSetBanType : public Command
00158 {
00159 public:
00160 CommandCSSetBanType(Module *creator, const Anope::string &cname = "chanserv/set/bantype") : Command(creator, cname, 2, 2)
00161 {
00162 this->SetDesc(_("Set how Services make bans on the channel"));
00163 this->SetSyntax(_("\037channel\037 \037bantype\037"));
00164 }
00165
00166 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00167 {
00168 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00169 if (ci == NULL)
00170 {
00171 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00172 return;
00173 }
00174
00175 EventReturn MOD_RESULT;
00176 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00177 if (MOD_RESULT == EVENT_STOP)
00178 return;
00179
00180 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00181 {
00182 source.Reply(ACCESS_DENIED);
00183 return;
00184 }
00185
00186 try
00187 {
00188 int16_t new_type = convertTo<int16_t>(params[1]);
00189 if (new_type < 0 || new_type > 3)
00190 throw ConvertException("Invalid range");
00191 ci->bantype = new_type;
00192 source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype);
00193 }
00194 catch (const ConvertException &)
00195 {
00196 source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str());
00197 }
00198
00199 return;
00200 }
00201
00202 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00203 {
00204 this->SendSyntax(source);
00205 source.Reply(" ");
00206 source.Reply(_("Sets the ban type that will be used by services whenever\n"
00207 "they need to ban someone from your channel.\n"
00208 " \n"
00209 "Bantype is a number between 0 and 3 that means:\n"
00210 " \n"
00211 "0: ban in the form *!user@host\n"
00212 "1: ban in the form *!*user@host\n"
00213 "2: ban in the form *!*@host\n"
00214 "3: ban in the form *!*user@*.domain"), this->name.c_str());
00215 return true;
00216 }
00217 };
00218
00219 class CommandCSSetChanstats : public Command
00220 {
00221 public:
00222 CommandCSSetChanstats(Module *creator) : Command(creator, "chanserv/set/chanstats", 2, 2)
00223 {
00224 this->SetDesc(_("Turn chanstat statistics on or off"));
00225 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00226 }
00227
00228 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00229 {
00230 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00231 if (!ci)
00232 {
00233 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00234 return;
00235 }
00236
00237 EventReturn MOD_RESULT;
00238 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00239 if (MOD_RESULT == EVENT_STOP)
00240 return;
00241
00242 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00243 {
00244 source.Reply(ACCESS_DENIED);
00245 return;
00246 }
00247
00248 if (params[1].equals_ci("ON"))
00249 {
00250 ci->ExtendMetadata("STATS");
00251 source.Reply(_("Chanstats statistics are now enabled for this channel."));
00252 }
00253 else if (params[1].equals_ci("OFF"))
00254 {
00255 ci->Shrink("STATS");
00256 source.Reply(_("Chanstats statistics are now disabled for this channel."));
00257 }
00258 else
00259 this->OnSyntaxError(source, "");
00260 return;
00261 }
00262
00263 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00264 {
00265 this->SendSyntax(source);
00266 source.Reply(" ");
00267 source.Reply("Turn Chanstats channel statistics ON or OFF.");
00268 return true;
00269 }
00270 };
00271
00272 class CommandCSSetDescription : public Command
00273 {
00274 public:
00275 CommandCSSetDescription(Module *creator, const Anope::string &cname = "chanserv/set/description") : Command(creator, cname, 1, 2)
00276 {
00277 this->SetDesc(_("Set the channel description"));
00278 this->SetSyntax(_("\037channel\037 [\037description\037]"));
00279 }
00280
00281 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00282 {
00283 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00284 if (ci == NULL)
00285 {
00286 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00287 return;
00288 }
00289
00290 EventReturn MOD_RESULT;
00291 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00292 if (MOD_RESULT == EVENT_STOP)
00293 return;
00294
00295 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00296 {
00297 source.Reply(ACCESS_DENIED);
00298 return;
00299 }
00300
00301 if (params.size() > 1)
00302 {
00303 ci->desc = params[1];
00304 source.Reply(_("Description of %s changed to \002%s\002."), ci->name.c_str(), ci->desc.c_str());
00305 }
00306 else
00307 {
00308 ci->desc.clear();
00309 source.Reply(_("Description of %s unset."), ci->name.c_str());
00310 }
00311
00312 return;
00313 }
00314
00315 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00316 {
00317 this->SendSyntax(source);
00318 source.Reply(" ");
00319 source.Reply(_("Sets the description for the channel, which shows up with\n"
00320 "the \002LIST\002 and \002INFO\002 commands."), this->name.c_str());
00321 return true;
00322 }
00323 };
00324
00325 class CommandCSSetFounder : public Command
00326 {
00327 public:
00328 CommandCSSetFounder(Module *creator, const Anope::string &cname = "chanserv/set/founder") : Command(creator, cname, 2, 2)
00329 {
00330 this->SetDesc(_("Set the founder of a channel"));
00331 this->SetSyntax(_("\037channel\037 \037nick\037"));
00332 }
00333
00334 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00335 {
00336 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00337 if (ci == NULL)
00338 {
00339 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00340 return;
00341 }
00342
00343 EventReturn MOD_RESULT;
00344 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00345 if (MOD_RESULT == EVENT_STOP)
00346 return;
00347
00348 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00349 {
00350 source.Reply(ACCESS_DENIED);
00351 return;
00352 }
00353
00354 if (source.permission.empty() && (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")))
00355 {
00356 source.Reply(ACCESS_DENIED);
00357 return;
00358 }
00359
00360 const NickAlias *na = NickAlias::Find(params[1]);
00361 if (!na)
00362 {
00363 source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str());
00364 return;
00365 }
00366
00367 NickCore *nc = na->nc;
00368 if (Config->CSMaxReg && nc->channelcount >= Config->CSMaxReg && !source.HasPriv("chanserv/no-register-limit"))
00369 {
00370 source.Reply(_("\002%s\002 has too many channels registered."), na->nick.c_str());
00371 return;
00372 }
00373
00374 Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the founder from " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << " to " << nc->display;
00375
00376 ci->SetFounder(nc);
00377
00378 source.Reply(_("Founder of \002%s\002 changed to \002%s\002."), ci->name.c_str(), na->nick.c_str());
00379
00380 return;
00381 }
00382
00383 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00384 {
00385 this->SendSyntax(source);
00386 source.Reply(" ");
00387 source.Reply(_("Changes the founder of a channel. The new nickname must\n"
00388 "be a registered one."), this->name.c_str());
00389 return true;
00390 }
00391 };
00392
00393 class CommandCSSetKeepTopic : public Command
00394 {
00395 public:
00396 CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic") : Command(creator, cname, 2, 2)
00397 {
00398 this->SetDesc(_("Retain topic when channel is not in use"));
00399 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00400 }
00401
00402 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00403 {
00404 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00405 if (ci == NULL)
00406 {
00407 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00408 return;
00409 }
00410
00411 EventReturn MOD_RESULT;
00412 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00413 if (MOD_RESULT == EVENT_STOP)
00414 return;
00415
00416 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00417 {
00418 source.Reply(ACCESS_DENIED);
00419 return;
00420 }
00421
00422 if (params[1].equals_ci("ON"))
00423 {
00424 ci->ExtendMetadata("KEEPTOPIC");
00425 source.Reply(_("Topic retention option for %s is now \002on\002."), ci->name.c_str());
00426 }
00427 else if (params[1].equals_ci("OFF"))
00428 {
00429 ci->Shrink("KEEPTOPIC");
00430 source.Reply(_("Topic retention option for %s is now \002off\002."), ci->name.c_str());
00431 }
00432 else
00433 this->OnSyntaxError(source, "KEEPTOPIC");
00434
00435 return;
00436 }
00437
00438 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00439 {
00440 this->SendSyntax(source);
00441 source.Reply(" ");
00442 source.Reply(_("Enables or disables the \002topic retention\002 option for a\n"
00443 "channel. When \002%s\002 is set, the topic for the\n"
00444 "channel will be remembered by %s even after the\n"
00445 "last user leaves the channel, and will be restored the\n"
00446 "next time the channel is created."), this->name.c_str(), source.service->nick.c_str());
00447 return true;
00448 }
00449 };
00450
00451 class CommandCSSetPeace : public Command
00452 {
00453 public:
00454 CommandCSSetPeace(Module *creator, const Anope::string &cname = "chanserv/set/peace") : Command(creator, cname, 2, 2)
00455 {
00456 this->SetDesc(_("Regulate the use of critical commands"));
00457 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00458 }
00459
00460 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00461 {
00462 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00463 if (ci == NULL)
00464 {
00465 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00466 return;
00467 }
00468 EventReturn MOD_RESULT;
00469 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00470 if (MOD_RESULT == EVENT_STOP)
00471 return;
00472
00473 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00474 {
00475 source.Reply(ACCESS_DENIED);
00476 return;
00477 }
00478
00479 if (params[1].equals_ci("ON"))
00480 {
00481 ci->ExtendMetadata("PEACE");
00482 source.Reply(_("Peace option for %s is now \002on\002."), ci->name.c_str());
00483 }
00484 else if (params[1].equals_ci("OFF"))
00485 {
00486 ci->Shrink("PEACE");
00487 source.Reply(_("Peace option for %s is now \002off\002."), ci->name.c_str());
00488 }
00489 else
00490 this->OnSyntaxError(source, "PEACE");
00491
00492 return;
00493 }
00494
00495 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00496 {
00497 this->SendSyntax(source);
00498 source.Reply(" ");
00499 source.Reply(_("Enables or disables the \002peace\002 option for a channel.\n"
00500 "When \002peace\002 is set, a user won't be able to kick,\n"
00501 "ban or remove a channel status of a user that has\n"
00502 "a level superior or equal to his via %s commands."), source.service->nick.c_str());
00503 return true;
00504 }
00505 };
00506
00507 class CommandCSSetPersist : public Command
00508 {
00509 public:
00510 CommandCSSetPersist(Module *creator, const Anope::string &cname = "chanserv/set/persist") : Command(creator, cname, 2, 2)
00511 {
00512 this->SetDesc(_("Set the channel as permanent"));
00513 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00514 }
00515
00516 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00517 {
00518 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00519 if (ci == NULL)
00520 {
00521 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00522 return;
00523 }
00524
00525 EventReturn MOD_RESULT;
00526 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00527 if (MOD_RESULT == EVENT_STOP)
00528 return;
00529
00530 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00531 {
00532 source.Reply(ACCESS_DENIED);
00533 return;
00534 }
00535
00536 ChannelMode *cm = ModeManager::FindChannelModeByName("PERM");
00537
00538 if (params[1].equals_ci("ON"))
00539 {
00540 if (!ci->HasExt("PERSIST"))
00541 {
00542 ci->ExtendMetadata("PERSIST");
00543 if (ci->c)
00544 ci->c->Extend("PERSIST");
00545
00546
00547 if (!ci->c)
00548 {
00549 Channel *c = new Channel(ci->name);
00550 if (ci->bi)
00551 ci->bi->Join(c);
00552 }
00553
00554
00555
00556
00557 if (!ci->bi && !cm)
00558 {
00559 if (!ChanServ)
00560 {
00561 source.Reply(_("ChanServ is required to enable persist on this network."));
00562 return;
00563 }
00564 ChanServ->Assign(NULL, ci);
00565 if (!ci->c->FindUser(ChanServ))
00566 ChanServ->Join(ci->c);
00567 }
00568
00569
00570 if (cm)
00571 {
00572 if (ci->c && !ci->c->HasMode("PERM"))
00573 ci->c->SetMode(NULL, cm);
00574
00575 ci->SetMLock(cm, true);
00576 }
00577 }
00578
00579 source.Reply(_("Channel \002%s\002 is now persistent."), ci->name.c_str());
00580 }
00581 else if (params[1].equals_ci("OFF"))
00582 {
00583 if (ci->HasExt("PERSIST"))
00584 {
00585 ci->Shrink("PERSIST");
00586 if (ci->c)
00587 ci->c->Shrink("PERSIST");
00588
00589
00590 if (cm)
00591 {
00592 if (ci->c && ci->c->HasMode("PERM"))
00593 ci->c->RemoveMode(NULL, cm);
00594
00595 ci->RemoveMLock(cm, true);
00596 }
00597
00598
00599
00600
00601 if (!cm && Config->BotServ.empty() && ci->bi)
00602 {
00603 if (!ChanServ)
00604 {
00605 source.Reply(_("ChanServ is required to enable persist on this network."));
00606 return;
00607 }
00608
00609 ChanServ->UnAssign(NULL, ci);
00610 }
00611 }
00612
00613 source.Reply(_("Channel \002%s\002 is no longer persistent."), ci->name.c_str());
00614 }
00615 else
00616 this->OnSyntaxError(source, "PERSIST");
00617
00618 return;
00619 }
00620
00621 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00622 {
00623 this->SendSyntax(source);
00624 source.Reply(" ");
00625 source.Reply(_("Enables or disables the persistent channel setting.\n"
00626 "When persistent is set, the service bot will remain\n"
00627 "in the channel when it has emptied of users.\n"
00628 " \n"
00629 "If your IRCd does not have a permanent (persistent) channel\n"
00630 "mode you must have a service bot in your channel to\n"
00631 "set persist on, and it can not be unassigned while persist\n"
00632 "is on.\n"
00633 " \n"
00634 "If this network does not have BotServ enabled and does\n"
00635 "not have a permanent channel mode, ChanServ will\n"
00636 "join your channel when you set persist on (and leave when\n"
00637 "it has been set off).\n"
00638 " \n"
00639 "If your IRCd has a permanent (persistent) channel mode\n"
00640 "and it is set or unset (for any reason, including MODE LOCK),\n"
00641 "persist is automatically set and unset for the channel aswell.\n"
00642 "Additionally, services will set or unset this mode when you\n"
00643 "set persist on or off."));
00644 return true;
00645 }
00646 };
00647
00648 class CommandCSSetPrivate : public Command
00649 {
00650 public:
00651 CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2)
00652 {
00653 this->SetDesc(_("Hide channel from the LIST command"));
00654 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00655 }
00656
00657 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00658 {
00659 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00660 if (ci == NULL)
00661 {
00662 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00663 return;
00664 }
00665
00666 EventReturn MOD_RESULT;
00667 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00668 if (MOD_RESULT == EVENT_STOP)
00669 return;
00670
00671 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00672 {
00673 source.Reply(ACCESS_DENIED);
00674 return;
00675 }
00676
00677 if (params[1].equals_ci("ON"))
00678 {
00679 ci->ExtendMetadata("PRIVATE");
00680 source.Reply(_("Private option for %s is now \002on\002."), ci->name.c_str());
00681 }
00682 else if (params[1].equals_ci("OFF"))
00683 {
00684 ci->Shrink("PRIVATE");
00685 source.Reply(_("Private option for %s is now \002off\002."), ci->name.c_str());
00686 }
00687 else
00688 this->OnSyntaxError(source, "PRIVATE");
00689
00690 return;
00691 }
00692
00693 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00694 {
00695 this->SendSyntax(source);
00696 source.Reply(" ");
00697 source.Reply(_("Enables or disables the \002private\002 option for a channel.\n"
00698 "When \002private\002 is set, a \002%s%s LIST\002 will not\n"
00699 "include the channel in any lists."),
00700 Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00701 return true;
00702 }
00703 };
00704
00705 class CommandCSSetRestricted : public Command
00706 {
00707 public:
00708 CommandCSSetRestricted(Module *creator, const Anope::string &cname = "chanserv/set/restricted") : Command(creator, cname, 2, 2)
00709 {
00710 this->SetDesc(_("Restrict access to the channel"));
00711 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00712 }
00713
00714 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00715 {
00716 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00717 if (ci == NULL)
00718 {
00719 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00720 return;
00721 }
00722
00723 EventReturn MOD_RESULT;
00724 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00725 if (MOD_RESULT == EVENT_STOP)
00726 return;
00727
00728 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00729 {
00730 source.Reply(ACCESS_DENIED);
00731 return;
00732 }
00733
00734 if (params[1].equals_ci("ON"))
00735 {
00736 ci->ExtendMetadata("RESTRICTED");
00737 source.Reply(_("Restricted access option for %s is now \002on\002."), ci->name.c_str());
00738 }
00739 else if (params[1].equals_ci("OFF"))
00740 {
00741 ci->Shrink("RESTRICTED");
00742 source.Reply(_("Restricted access option for %s is now \002off\002."), ci->name.c_str());
00743 }
00744 else
00745 this->OnSyntaxError(source, "RESTRICTED");
00746
00747 return;
00748 }
00749
00750 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00751 {
00752 this->SendSyntax(source);
00753 source.Reply(" ");
00754 source.Reply(_("Enables or disables the \002restricted access\002 option for a\n"
00755 "channel. When \002restricted access\002 is set, users not on the access list will\n"
00756 "instead be kicked and banned from the channel."));
00757 return true;
00758 }
00759 };
00760
00761 class CommandCSSetSecure : public Command
00762 {
00763 public:
00764 CommandCSSetSecure(Module *creator, const Anope::string &cname = "chanserv/set/secure") : Command(creator, cname, 2, 2)
00765 {
00766 this->SetDesc(_("Activate security features"));
00767 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00768 }
00769
00770 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00771 {
00772 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00773 if (ci == NULL)
00774 {
00775 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00776 return;
00777 }
00778
00779 EventReturn MOD_RESULT;
00780 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00781 if (MOD_RESULT == EVENT_STOP)
00782 return;
00783
00784 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00785 {
00786 source.Reply(ACCESS_DENIED);
00787 return;
00788 }
00789
00790 if (params[1].equals_ci("ON"))
00791 {
00792 ci->ExtendMetadata("SECURE");
00793 source.Reply(_("Secure option for %s is now \002on\002."), ci->name.c_str());
00794 }
00795 else if (params[1].equals_ci("OFF"))
00796 {
00797 ci->Shrink("SECURE");
00798 source.Reply(_("Secure option for %s is now \002off\002."), ci->name.c_str());
00799 }
00800 else
00801 this->OnSyntaxError(source, "SECURE");
00802
00803 return;
00804 }
00805
00806 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00807 {
00808 this->SendSyntax(source);
00809 source.Reply(" ");
00810 source.Reply(_("Enables or disables security features for a\n"
00811 "channel. When \002%s\002 is set, only users who have\n"
00812 "registered their nicknames and IDENTIFY'd\n"
00813 "with their password will be given access to the channel\n"
00814 "as controlled by the access list."), this->name.c_str());
00815 return true;
00816 }
00817 };
00818
00819 class CommandCSSetSecureFounder : public Command
00820 {
00821 public:
00822 CommandCSSetSecureFounder(Module *creator, const Anope::string &cname = "chanserv/set/securefounder") : Command(creator, cname, 2, 2)
00823 {
00824 this->SetDesc(_("Stricter control of channel founder status"));
00825 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00826 }
00827
00828 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00829 {
00830 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00831 if (ci == NULL)
00832 {
00833 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00834 return;
00835 }
00836
00837 EventReturn MOD_RESULT;
00838 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00839 if (MOD_RESULT == EVENT_STOP)
00840 return;
00841
00842 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00843 {
00844 source.Reply(ACCESS_DENIED);
00845 return;
00846 }
00847
00848 if (params[1].equals_ci("ON"))
00849 {
00850 ci->ExtendMetadata("SECUREFOUNDER");
00851 source.Reply(_("Secure founder option for %s is now \002on\002."), ci->name.c_str());
00852 }
00853 else if (params[1].equals_ci("OFF"))
00854 {
00855 ci->Shrink("SECUREFOUNDER");
00856 source.Reply(_("Secure founder option for %s is now \002off\002."), ci->name.c_str());
00857 }
00858 else
00859 this->OnSyntaxError(source, "SECUREFOUNDER");
00860
00861 return;
00862 }
00863
00864 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00865 {
00866 this->SendSyntax(source);
00867 source.Reply(" ");
00868 source.Reply(_("Enables or disables the \002secure founder\002 option for a channel.\n"
00869 "When \002secure founder\002 is set, only the real founder will be\n"
00870 "able to drop the channel, change its founder and its successor,\n"
00871 "and not those who have founder level access through\n"
00872 "the access/qop command."));
00873 return true;
00874 }
00875 };
00876
00877 class CommandCSSetSecureOps : public Command
00878 {
00879 public:
00880 CommandCSSetSecureOps(Module *creator, const Anope::string &cname = "chanserv/set/secureops") : Command(creator, cname, 2, 2)
00881 {
00882 this->SetDesc(_("Stricter control of chanop status"));
00883 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
00884 }
00885
00886 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00887 {
00888 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00889 if (ci == NULL)
00890 {
00891 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00892 return;
00893 }
00894
00895 EventReturn MOD_RESULT;
00896 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00897 if (MOD_RESULT == EVENT_STOP)
00898 return;
00899
00900 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00901 {
00902 source.Reply(ACCESS_DENIED);
00903 return;
00904 }
00905
00906 if (params[1].equals_ci("ON"))
00907 {
00908 ci->ExtendMetadata("SECUREOPS");
00909 source.Reply(_("Secure ops option for %s is now \002on\002."), ci->name.c_str());
00910 }
00911 else if (params[1].equals_ci("OFF"))
00912 {
00913 ci->Shrink("SECUREOPS");
00914 source.Reply(_("Secure ops option for %s is now \002off\002."), ci->name.c_str());
00915 }
00916 else
00917 this->OnSyntaxError(source, "SECUREOPS");
00918
00919 return;
00920 }
00921
00922 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00923 {
00924 this->SendSyntax(source);
00925 source.Reply(" ");
00926 source.Reply(_("Enables or disables the \002secure ops\002 option for a channel.\n"
00927 "When \002secure ops\002 is set, users who are not on the userlist\n"
00928 "will not be allowed chanop status."));
00929 return true;
00930 }
00931 };
00932
00933 class CommandCSSetSignKick : public Command
00934 {
00935 public:
00936 CommandCSSetSignKick(Module *creator, const Anope::string &cname = "chanserv/set/signkick") : Command(creator, cname, 2, 2)
00937 {
00938 this->SetDesc(_("Sign kicks that are done with the KICK command"));
00939 this->SetSyntax(_("\037channel\037 SIGNKICK {ON | LEVEL | OFF}"));
00940 }
00941
00942 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00943 {
00944 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00945 if (ci == NULL)
00946 {
00947 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00948 return;
00949 }
00950
00951 EventReturn MOD_RESULT;
00952 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
00953 if (MOD_RESULT == EVENT_STOP)
00954 return;
00955
00956 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
00957 {
00958 source.Reply(ACCESS_DENIED);
00959 return;
00960 }
00961
00962 if (params[1].equals_ci("ON"))
00963 {
00964 ci->ExtendMetadata("SIGNKICK");
00965 ci->Shrink("SIGNKICK_LEVEL");
00966 source.Reply(_("Signed kick option for %s is now \002on\002."), ci->name.c_str());
00967 }
00968 else if (params[1].equals_ci("LEVEL"))
00969 {
00970 ci->ExtendMetadata("SIGNKICK_LEVEL");
00971 ci->Shrink("SIGNKICK");
00972 source.Reply(_("Signed kick option for %s is now \002on\002, but depends of the\n"
00973 "level of the user that is using the command."), ci->name.c_str());
00974 }
00975 else if (params[1].equals_ci("OFF"))
00976 {
00977 ci->Shrink("SIGNKICK");
00978 ci->Shrink("SIGNKICK_LEVEL");
00979 source.Reply(_("Signed kick option for %s is now \002off\002."), ci->name.c_str());
00980 }
00981 else
00982 this->OnSyntaxError(source, "SIGNKICK");
00983 }
00984
00985 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
00986 {
00987 this->SendSyntax(source);
00988 source.Reply(" ");
00989 source.Reply(_("Enables or disables signed kicks for a\n"
00990 "channel. When \002SIGNKICK\002 is set, kicks issued with\n"
00991 "the \002KICK\002 command will have the nick that used the\n"
00992 "command in their reason.\n"
00993 " \n"
00994 "If you use \002LEVEL\002, those who have a level that is superior\n"
00995 "or equal to the SIGNKICK level on the channel won't have their\n"
00996 "kicks signed."));
00997 return true;
00998 }
00999 };
01000
01001 class CommandCSSetSuccessor : public Command
01002 {
01003 public:
01004 CommandCSSetSuccessor(Module *creator, const Anope::string &cname = "chanserv/set/successor") : Command(creator, cname, 1, 2)
01005 {
01006 this->SetDesc(_("Set the successor for a channel"));
01007 this->SetSyntax(_("\037channel\037 \037nick\037"));
01008 }
01009
01010 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
01011 {
01012 ChannelInfo *ci = ChannelInfo::Find(params[0]);
01013 if (ci == NULL)
01014 {
01015 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
01016 return;
01017 }
01018
01019 EventReturn MOD_RESULT;
01020 FOREACH_RESULT(I_OnSetChannelOption, OnSetChannelOption(source, this, ci, params[1]));
01021 if (MOD_RESULT == EVENT_STOP)
01022 return;
01023
01024 if (MOD_RESULT != EVENT_ALLOW && source.permission.empty())
01025 {
01026 if (!source.AccessFor(ci).HasPriv("SET"))
01027 {
01028 source.Reply(ACCESS_DENIED);
01029 return;
01030 }
01031
01032 if (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER"))
01033 {
01034 source.Reply(ACCESS_DENIED);
01035 return;
01036 }
01037 }
01038
01039 NickCore *nc;
01040
01041 if (params.size() > 1)
01042 {
01043 const NickAlias *na = NickAlias::Find(params[1]);
01044
01045 if (!na)
01046 {
01047 source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str());
01048 return;
01049 }
01050 if (na->nc == ci->GetFounder())
01051 {
01052 source.Reply(_("%s cannot be the successor on channel %s as they are the founder."), na->nick.c_str(), ci->name.c_str());
01053 return;
01054 }
01055 nc = na->nc;
01056 }
01057 else
01058 nc = NULL;
01059
01060 Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)");
01061
01062 ci->SetSuccessor(nc);
01063
01064 if (nc)
01065 source.Reply(_("Successor for \002%s\002 changed to \002%s\002."), ci->name.c_str(), nc->display.c_str());
01066 else
01067 source.Reply(_("Successor for \002%s\002 unset."), ci->name.c_str());
01068
01069 return;
01070 }
01071
01072 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
01073 {
01074 this->SendSyntax(source);
01075 source.Reply(" ");
01076 source.Reply(_("Changes the successor of a channel. If the founder's\n"
01077 "nickname expires or is dropped while the channel is still\n"
01078 "registered, the successor will become the new founder of the\n"
01079 "channel. However, if the successor already has too many\n"
01080 "channels registered (%d), the channel will be dropped\n"
01081 "instead, just as if no successor had been set. The new\n"
01082 "nickname must be a registered one."), Config->CSMaxReg);
01083 return true;
01084 }
01085 };
01086
01087 class CommandCSSASetNoexpire : public Command
01088 {
01089 public:
01090 CommandCSSASetNoexpire(Module *creator) : Command(creator, "chanserv/saset/noexpire", 2, 2)
01091 {
01092 this->SetDesc(_("Prevent the channel from expiring"));
01093 this->SetSyntax(_("\037channel\037 {ON | OFF}"));
01094 }
01095
01096 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
01097 {
01098 ChannelInfo *ci = ChannelInfo::Find(params[0]);
01099 if (ci == NULL)
01100 {
01101 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
01102 return;
01103 }
01104
01105 if (source.permission.empty() && !source.AccessFor(ci).HasPriv("SET"))
01106 {
01107 source.Reply(ACCESS_DENIED);
01108 return;
01109 }
01110
01111 if (params[1].equals_ci("ON"))
01112 {
01113 ci->ExtendMetadata("NO_EXPIRE");
01114 source.Reply(_("Channel %s \002will not\002 expire."), ci->name.c_str());
01115 }
01116 else if (params[1].equals_ci("OFF"))
01117 {
01118 ci->Shrink("NO_EXPIRE");
01119 source.Reply(_("Channel %s \002will\002 expire."), ci->name.c_str());
01120 }
01121 else
01122 this->OnSyntaxError(source, "NOEXPIRE");
01123
01124 return;
01125 }
01126
01127 bool OnHelp(CommandSource &source, const Anope::string &) anope_override
01128 {
01129 this->SendSyntax(source);
01130 source.Reply(" ");
01131 source.Reply(_("Sets whether the given channel will expire. Setting this\n"
01132 "to ON prevents the channel from expiring."));
01133 return true;
01134 }
01135 };
01136
01137 class CSSet : public Module
01138 {
01139 CommandCSSet commandcsset;
01140 CommandCSSASet commandcssaset;
01141 CommandCSSetAutoOp commandcssetautoop;
01142 CommandCSSetBanType commandcssetbantype;
01143 CommandCSSetChanstats commandcssetchanstats;
01144 bool CSDefChanstats;
01145 CommandCSSetDescription commandcssetdescription;
01146 CommandCSSetFounder commandcssetfounder;
01147 CommandCSSetKeepTopic commandcssetkeeptopic;
01148 CommandCSSetPeace commandcssetpeace;
01149 CommandCSSetPersist commandcssetpersist;
01150 CommandCSSetPrivate commandcssetprivate;
01151 CommandCSSetRestricted commandcssetrestricted;
01152 CommandCSSetSecure commandcssetsecure;
01153 CommandCSSetSecureFounder commandcssetsecurefounder;
01154 CommandCSSetSecureOps commandcssetsecureops;
01155 CommandCSSetSignKick commandcssetsignkick;
01156 CommandCSSetSuccessor commandcssetsuccessor;
01157 CommandCSSASetNoexpire commandcssasetnoexpire;
01158
01159 public:
01160 CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
01161 commandcsset(this), commandcssaset(this), commandcssetautoop(this), commandcssetbantype(this), commandcssetchanstats(this),
01162 CSDefChanstats(false), commandcssetdescription(this), commandcssetfounder(this), commandcssetkeeptopic(this),
01163 commandcssetpeace(this), commandcssetpersist(this), commandcssetprivate(this), commandcssetrestricted(this),
01164 commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
01165 commandcssetsuccessor(this), commandcssasetnoexpire(this)
01166 {
01167 this->SetAuthor("Anope");
01168
01169 Implementation i[] = { I_OnReload, I_OnChanRegistered, I_OnCheckKick };
01170 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
01171
01172 this->OnReload();
01173 }
01174
01175 void OnReload() anope_override
01176 {
01177 ConfigReader config;
01178 CSDefChanstats = config.ReadFlag("chanstats", "CSDefChanstats", "0", 0);
01179 }
01180
01181 void OnChanRegistered(ChannelInfo *ci) anope_override
01182 {
01183 if (CSDefChanstats)
01184 ci->ExtendMetadata("STATS");
01185 }
01186
01187 EventReturn OnCheckKick(User *u, ChannelInfo *ci, Anope::string &mask, Anope::string &reason) anope_override
01188 {
01189 if (!ci->HasExt("RESTRICTED") || ci->c->MatchesList(u, "EXCEPT"))
01190 return EVENT_CONTINUE;
01191
01192 if (ci->AccessFor(u).empty() && (!ci->GetFounder() || u->Account() != ci->GetFounder()))
01193 return EVENT_STOP;
01194
01195 return EVENT_CONTINUE;
01196 }
01197 };
01198
01199 MODULE_INIT(CSSet)