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> &params) 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> &params) 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)