anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
cs_suspend.cpp (7810B)
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/suspend.h" 14 15 struct CSSuspendInfo : SuspendInfo, Serializable 16 { 17 CSSuspendInfo(Extensible *) : Serializable("CSSuspendInfo") { } 18 19 void Serialize(Serialize::Data &data) const anope_override 20 { 21 data["chan"] << what; 22 data["by"] << by; 23 data["reason"] << reason; 24 data["time"] << when; 25 data["expires"] << expires; 26 } 27 28 static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) 29 { 30 Anope::string schan; 31 data["chan"] >> schan; 32 33 CSSuspendInfo *si; 34 if (obj) 35 si = anope_dynamic_static_cast<CSSuspendInfo *>(obj); 36 else 37 { 38 ChannelInfo *ci = ChannelInfo::Find(schan); 39 if (!ci) 40 return NULL; 41 si = ci->Extend<CSSuspendInfo>("CS_SUSPENDED"); 42 data["chan"] >> si->what; 43 } 44 45 data["by"] >> si->by; 46 data["reason"] >> si->reason; 47 data["time"] >> si->when; 48 data["expires"] >> si->expires; 49 return si; 50 } 51 }; 52 53 class CommandCSSuspend : public Command 54 { 55 public: 56 CommandCSSuspend(Module *creator) : Command(creator, "chanserv/suspend", 2, 3) 57 { 58 this->SetDesc(_("Prevent a channel from being used preserving channel data and settings")); 59 this->SetSyntax(_("\037channel\037 [+\037expiry\037] [\037reason\037]")); 60 } 61 62 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 63 { 64 const Anope::string &chan = params[0]; 65 Anope::string expiry = params[1]; 66 Anope::string reason = params.size() > 2 ? params[2] : ""; 67 time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("expire"); 68 69 if (!expiry.empty() && expiry[0] != '+') 70 { 71 reason = expiry + " " + reason; 72 reason.trim(); 73 expiry.clear(); 74 } 75 else 76 { 77 expiry_secs = Anope::DoTime(expiry); 78 if (expiry_secs < 0) 79 { 80 source.Reply(BAD_EXPIRY_TIME); 81 return; 82 } 83 } 84 85 if (Anope::ReadOnly) 86 source.Reply(READ_ONLY_MODE); 87 88 ChannelInfo *ci = ChannelInfo::Find(chan); 89 if (ci == NULL) 90 { 91 source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); 92 return; 93 } 94 95 if (ci->HasExt("CS_SUSPENDED")) 96 { 97 source.Reply(_("\002%s\002 is already suspended."), ci->name.c_str()); 98 return; 99 } 100 101 CSSuspendInfo *si = ci->Extend<CSSuspendInfo>("CS_SUSPENDED"); 102 si->what = ci->name; 103 si->by = source.GetNick(); 104 si->reason = reason; 105 si->when = Anope::CurTime; 106 si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0; 107 108 if (ci->c) 109 { 110 std::vector<User *> users; 111 112 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) 113 { 114 ChanUserContainer *uc = it->second; 115 User *user = uc->user; 116 if (!user->HasMode("OPER") && user->server != Me) 117 users.push_back(user); 118 } 119 120 for (unsigned i = 0; i < users.size(); ++i) 121 ci->c->Kick(NULL, users[i], "%s", !reason.empty() ? reason.c_str() : Language::Translate(users[i], _("This channel has been suspended."))); 122 } 123 124 Log(LOG_ADMIN, source, this, ci) << "(" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); 125 source.Reply(_("Channel \002%s\002 is now suspended."), ci->name.c_str()); 126 127 FOREACH_MOD(OnChanSuspend, (ci)); 128 } 129 130 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 131 { 132 this->SendSyntax(source); 133 source.Reply(" "); 134 source.Reply(_("Disallows anyone from using the given channel.\n" 135 "May be cancelled by using the \002UNSUSPEND\002\n" 136 "command to preserve all previous channel data/settings.\n" 137 "If an expiry is given the channel will be unsuspended after\n" 138 "that period of time, else the default expiry from the\n" 139 "configuration is used.\n" 140 " \n" 141 "Reason may be required on certain networks.")); 142 return true; 143 } 144 }; 145 146 class CommandCSUnSuspend : public Command 147 { 148 public: 149 CommandCSUnSuspend(Module *creator) : Command(creator, "chanserv/unsuspend", 1, 1) 150 { 151 this->SetDesc(_("Releases a suspended channel")); 152 this->SetSyntax(_("\037channel\037")); 153 } 154 155 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 156 { 157 158 if (Anope::ReadOnly) 159 source.Reply(READ_ONLY_MODE); 160 161 ChannelInfo *ci = ChannelInfo::Find(params[0]); 162 if (ci == NULL) 163 { 164 source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); 165 return; 166 } 167 168 /* Only UNSUSPEND already suspended channels */ 169 CSSuspendInfo *si = ci->GetExt<CSSuspendInfo>("CS_SUSPENDED"); 170 if (!si) 171 { 172 source.Reply(_("Channel \002%s\002 isn't suspended."), ci->name.c_str()); 173 return; 174 } 175 176 Log(LOG_ADMIN, source, this, ci) << "which was suspended by " << si->by << " for: " << (!si->reason.empty() ? si->reason : "No reason"); 177 178 ci->Shrink<CSSuspendInfo>("CS_SUSPENDED"); 179 180 source.Reply(_("Channel \002%s\002 is now released."), ci->name.c_str()); 181 182 FOREACH_MOD(OnChanUnsuspend, (ci)); 183 184 return; 185 } 186 187 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 188 { 189 this->SendSyntax(source); 190 source.Reply(" "); 191 source.Reply(_("Releases a suspended channel. All data and settings\n" 192 "are preserved from before the suspension.")); 193 return true; 194 } 195 }; 196 197 class CSSuspend : public Module 198 { 199 CommandCSSuspend commandcssuspend; 200 CommandCSUnSuspend commandcsunsuspend; 201 ExtensibleItem<CSSuspendInfo> suspend; 202 Serialize::Type suspend_type; 203 std::vector<Anope::string> show; 204 205 struct trim 206 { 207 Anope::string operator()(Anope::string s) const 208 { 209 return s.trim(); 210 } 211 }; 212 213 bool Show(CommandSource &source, const Anope::string &what) const 214 { 215 return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end(); 216 } 217 218 public: 219 CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), 220 commandcssuspend(this), commandcsunsuspend(this), suspend(this, "CS_SUSPENDED"), 221 suspend_type("CSSuspendInfo", CSSuspendInfo::Unserialize) 222 { 223 } 224 225 void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override 226 { 227 CSSuspendInfo *si = suspend.Get(ci); 228 if (!si) 229 return; 230 231 if (show_hidden || Show(source, "suspended")) 232 info[_("Suspended")] = _("This channel is \002suspended\002."); 233 if (!si->by.empty() && (show_hidden || Show(source, "by"))) 234 info[_("Suspended by")] = si->by; 235 if (!si->reason.empty() && (show_hidden || Show(source, "reason"))) 236 info[_("Suspend reason")] = si->reason; 237 if (si->when && (show_hidden || Show(source, "on"))) 238 info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount()); 239 if (si->expires && (show_hidden || Show(source, "expires"))) 240 info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount()); 241 } 242 243 void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override 244 { 245 CSSuspendInfo *si = suspend.Get(ci); 246 if (!si) 247 return; 248 249 expire = false; 250 251 if (!si->expires) 252 return; 253 254 if (si->expires < Anope::CurTime) 255 { 256 ci->last_used = Anope::CurTime; 257 suspend.Unset(ci); 258 259 Log(this) << "Expiring suspend for " << ci->name; 260 } 261 } 262 263 EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override 264 { 265 if (u->HasMode("OPER") || !c->ci || !suspend.HasExt(c->ci)) 266 return EVENT_CONTINUE; 267 268 reason = Language::Translate(u, _("This channel may not be used.")); 269 return EVENT_STOP; 270 } 271 272 EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) anope_override 273 { 274 CSSuspendInfo *si = suspend.Get(ci); 275 if (si && !source.HasCommand("chanserv/drop")) 276 { 277 source.Reply(CHAN_X_SUSPENDED, ci->name.c_str()); 278 return EVENT_STOP; 279 } 280 281 return EVENT_CONTINUE; 282 } 283 }; 284 285 MODULE_INIT(CSSuspend)