anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
ns_suspend.cpp (7678B)
1 /* NickServ 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/suspend.h" 14 15 static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); 16 17 struct NSSuspendInfo : SuspendInfo, Serializable 18 { 19 NSSuspendInfo(Extensible *) : Serializable("NSSuspendInfo") { } 20 21 void Serialize(Serialize::Data &data) const anope_override 22 { 23 data["nick"] << what; 24 data["by"] << by; 25 data["reason"] << reason; 26 data["time"] << when; 27 data["expires"] << expires; 28 } 29 30 static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) 31 { 32 Anope::string snick; 33 data["nick"] >> snick; 34 35 NSSuspendInfo *si; 36 if (obj) 37 si = anope_dynamic_static_cast<NSSuspendInfo *>(obj); 38 else 39 { 40 NickAlias *na = NickAlias::Find(snick); 41 if (!na) 42 return NULL; 43 si = na->nc->Extend<NSSuspendInfo>("NS_SUSPENDED"); 44 data["nick"] >> si->what; 45 } 46 47 data["by"] >> si->by; 48 data["reason"] >> si->reason; 49 data["time"] >> si->when; 50 data["expires"] >> si->expires; 51 return si; 52 } 53 }; 54 55 class CommandNSSuspend : public Command 56 { 57 public: 58 CommandNSSuspend(Module *creator) : Command(creator, "nickserv/suspend", 2, 3) 59 { 60 this->SetDesc(_("Suspend a given nick")); 61 this->SetSyntax(_("\037nickname\037 [+\037expiry\037] [\037reason\037]")); 62 } 63 64 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 65 { 66 67 const Anope::string &nick = params[0]; 68 Anope::string expiry = params[1]; 69 Anope::string reason = params.size() > 2 ? params[2] : ""; 70 time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("suspendexpire"); 71 72 if (Anope::ReadOnly) 73 source.Reply(READ_ONLY_MODE); 74 75 if (expiry[0] != '+') 76 { 77 reason = expiry + " " + reason; 78 reason.trim(); 79 expiry.clear(); 80 } 81 else 82 { 83 expiry_secs = Anope::DoTime(expiry); 84 if (expiry_secs < 0) 85 { 86 source.Reply(BAD_EXPIRY_TIME); 87 return; 88 } 89 } 90 91 NickAlias *na = NickAlias::Find(nick); 92 if (!na) 93 { 94 source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); 95 return; 96 } 97 98 if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && na->nc->IsServicesOper()) 99 { 100 source.Reply(_("You may not suspend other Services Operators' nicknames.")); 101 return; 102 } 103 104 if (na->nc->HasExt("NS_SUSPENDED")) 105 { 106 source.Reply(_("\002%s\002 is already suspended."), na->nc->display.c_str()); 107 return; 108 } 109 110 NickCore *nc = na->nc; 111 112 NSSuspendInfo *si = nc->Extend<NSSuspendInfo>("NS_SUSPENDED"); 113 si->what = nc->display; 114 si->by = source.GetNick(); 115 si->reason = reason; 116 si->when = Anope::CurTime; 117 si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0; 118 119 for (unsigned i = 0; i < nc->aliases->size(); ++i) 120 { 121 NickAlias *na2 = nc->aliases->at(i); 122 123 if (na2 && *na2->nc == *na->nc) 124 { 125 na2->last_quit = reason; 126 127 User *u2 = User::Find(na2->nick, true); 128 if (u2) 129 { 130 u2->Logout(); 131 if (nickserv) 132 nickserv->Collide(u2, na2); 133 } 134 } 135 } 136 137 Log(LOG_ADMIN, source, this) << "for " << nick << " (" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); 138 source.Reply(_("Nick %s is now suspended."), nick.c_str()); 139 140 FOREACH_MOD(OnNickSuspend, (na)); 141 } 142 143 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 144 { 145 this->SendSyntax(source); 146 source.Reply(" "); 147 source.Reply(_("Suspends a registered nickname, which prevents it from being used\n" 148 "while keeping all the data for that nick. If an expiry is given\n" 149 "the nick will be unsuspended after that period of time, else the\n" 150 "default expiry from the configuration is used.")); 151 return true; 152 } 153 }; 154 155 class CommandNSUnSuspend : public Command 156 { 157 public: 158 CommandNSUnSuspend(Module *creator) : Command(creator, "nickserv/unsuspend", 1, 1) 159 { 160 this->SetDesc(_("Unsuspend a given nick")); 161 this->SetSyntax(_("\037nickname\037")); 162 } 163 164 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 165 { 166 const Anope::string &nick = params[0]; 167 168 if (Anope::ReadOnly) 169 source.Reply(READ_ONLY_MODE); 170 171 NickAlias *na = NickAlias::Find(nick); 172 if (!na) 173 { 174 source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); 175 return; 176 } 177 178 if (!na->nc->HasExt("NS_SUSPENDED")) 179 { 180 source.Reply(_("Nick %s is not suspended."), na->nick.c_str()); 181 return; 182 } 183 184 NSSuspendInfo *si = na->nc->GetExt<NSSuspendInfo>("NS_SUSPENDED"); 185 186 Log(LOG_ADMIN, source, this) << "for " << na->nick << " which was suspended by " << (!si->by.empty() ? si->by : "(none)") << " for: " << (!si->reason.empty() ? si->reason : "No reason"); 187 188 na->nc->Shrink<NSSuspendInfo>("NS_SUSPENDED"); 189 190 source.Reply(_("Nick %s is now released."), nick.c_str()); 191 192 FOREACH_MOD(OnNickUnsuspended, (na)); 193 } 194 195 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 196 { 197 this->SendSyntax(source); 198 source.Reply(" "); 199 source.Reply(_("Unsuspends a nickname which allows it to be used again.")); 200 return true; 201 } 202 }; 203 204 class NSSuspend : public Module 205 { 206 CommandNSSuspend commandnssuspend; 207 CommandNSUnSuspend commandnsunsuspend; 208 ExtensibleItem<NSSuspendInfo> suspend; 209 Serialize::Type suspend_type; 210 std::vector<Anope::string> show; 211 212 struct trim 213 { 214 Anope::string operator()(Anope::string s) const 215 { 216 return s.trim(); 217 } 218 }; 219 220 bool Show(CommandSource &source, const Anope::string &what) const 221 { 222 return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end(); 223 } 224 225 public: 226 NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), 227 commandnssuspend(this), commandnsunsuspend(this), suspend(this, "NS_SUSPENDED"), 228 suspend_type("NSSuspendInfo", NSSuspendInfo::Unserialize) 229 { 230 } 231 232 void OnReload(Configuration::Conf *conf) anope_override 233 { 234 Anope::string s = conf->GetModule(this)->Get<Anope::string>("show"); 235 commasepstream(s).GetTokens(show); 236 std::transform(show.begin(), show.end(), show.begin(), trim()); 237 } 238 239 void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override 240 { 241 NSSuspendInfo *s = suspend.Get(na->nc); 242 if (!s) 243 return; 244 245 if (show_hidden || Show(source, "suspended")) 246 info[_("Suspended")] = _("This nickname is \002suspended\002."); 247 if (!s->by.empty() && (show_hidden || Show(source, "by"))) 248 info[_("Suspended by")] = s->by; 249 if (!s->reason.empty() && (show_hidden || Show(source, "reason"))) 250 info[_("Suspend reason")] = s->reason; 251 if (s->when && (show_hidden || Show(source, "on"))) 252 info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount()); 253 if (s->expires && (show_hidden || Show(source, "expires"))) 254 info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount()); 255 } 256 257 void OnPreNickExpire(NickAlias *na, bool &expire) anope_override 258 { 259 NSSuspendInfo *s = suspend.Get(na->nc); 260 if (!s) 261 return; 262 263 expire = false; 264 265 if (!s->expires) 266 return; 267 268 if (s->expires < Anope::CurTime) 269 { 270 na->last_seen = Anope::CurTime; 271 suspend.Unset(na->nc); 272 273 Log(LOG_NORMAL, "nickserv/expire", Config->GetClient("NickServ")) << "Expiring suspend for " << na->nick; 274 } 275 } 276 277 EventReturn OnNickValidate(User *u, NickAlias *na) anope_override 278 { 279 NSSuspendInfo *s = suspend.Get(na->nc); 280 if (!s) 281 return EVENT_CONTINUE; 282 283 u->SendMessage(Config->GetClient("NickServ"), NICK_X_SUSPENDED, u->nick.c_str()); 284 return EVENT_STOP; 285 } 286 }; 287 288 MODULE_INIT(NSSuspend)