anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
cs_kick.cpp (4513B)
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 14 class CommandCSKick : public Command 15 { 16 public: 17 CommandCSKick(Module *creator) : Command(creator, "chanserv/kick", 2, 3) 18 { 19 this->SetDesc(_("Kicks a specified nick from a channel")); 20 this->SetSyntax(_("\037channel\037 \037nick\037 [\037reason\037]")); 21 this->SetSyntax(_("\037channel\037 \037mask\037 [\037reason\037]")); 22 } 23 24 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 25 { 26 const Anope::string &chan = params[0]; 27 const Anope::string &target = params[1]; 28 Anope::string reason = params.size() > 2 ? params[2] : "Requested"; 29 30 User *u = source.GetUser(); 31 ChannelInfo *ci = ChannelInfo::Find(params[0]); 32 Channel *c = Channel::Find(params[0]); 33 User *u2 = User::Find(target, true); 34 35 if (!c) 36 { 37 source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); 38 return; 39 } 40 else if (!ci) 41 { 42 source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); 43 return; 44 } 45 46 unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200"); 47 if (reason.length() > reasonmax) 48 reason = reason.substr(0, reasonmax); 49 50 Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)"); 51 signkickformat = signkickformat.replace_all_cs("%n", source.GetNick()); 52 53 AccessGroup u_access = source.AccessFor(ci); 54 55 if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick")) 56 source.Reply(ACCESS_DENIED); 57 else if (u2) 58 { 59 AccessGroup u2_access = ci->AccessFor(u2); 60 if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick")) 61 source.Reply(ACCESS_DENIED); 62 else if (u2->IsProtected()) 63 source.Reply(ACCESS_DENIED); 64 else if (!c->FindUser(u2)) 65 source.Reply(NICK_X_NOT_ON_CHAN, u2->nick.c_str(), c->name.c_str()); 66 else 67 { 68 bool override = !u_access.HasPriv("KICK") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access); 69 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; 70 71 if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK"))) 72 { 73 signkickformat = signkickformat.replace_all_cs("%m", reason); 74 c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str()); 75 } 76 else 77 c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); 78 } 79 } 80 else if (u_access.HasPriv("FOUNDER")) 81 { 82 Anope::string mask = IRCD->NormalizeMask(target); 83 84 Log(LOG_COMMAND, source, this, ci) << "for " << mask; 85 86 int matched = 0, kicked = 0; 87 for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;) 88 { 89 ChanUserContainer *uc = it->second; 90 ++it; 91 92 Entry e("", mask); 93 if (e.Matches(uc->user)) 94 { 95 ++matched; 96 97 AccessGroup u2_access = ci->AccessFor(uc->user); 98 if (u != uc->user && ci->HasExt("PEACE") && u2_access >= u_access) 99 continue; 100 else if (uc->user->IsProtected()) 101 continue; 102 103 ++kicked; 104 if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK"))) 105 { 106 reason += " (Matches " + mask + ")"; 107 signkickformat = signkickformat.replace_all_cs("%m", reason); 108 c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str()); 109 } 110 else 111 c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str()); 112 } 113 } 114 115 if (matched) 116 source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str()); 117 else 118 source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str()); 119 } 120 else 121 source.Reply(NICK_X_NOT_IN_USE, target.c_str()); 122 } 123 124 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 125 { 126 this->SendSyntax(source); 127 source.Reply(" "); 128 source.Reply(_("Kicks a specified nick from a channel.\n" 129 " \n" 130 "By default, limited to AOPs or those with level 5 access\n" 131 "and above on the channel. Channel founders can also specify masks.")); 132 return true; 133 } 134 }; 135 136 class CSKick : public Module 137 { 138 CommandCSKick commandcskick; 139 140 public: 141 CSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcskick(this) 142 { 143 144 } 145 }; 146 147 MODULE_INIT(CSKick)