anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

ms_set.cpp (9855B)

      1 /* MemoServ 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 CommandMSSet : public Command
     15 {
     16  private:
     17 	void DoNotify(CommandSource &source, const std::vector<Anope::string> &params, MemoInfo *mi)
     18 	{
     19 		const Anope::string &param = params[1];
     20 		NickCore *nc = source.nc;
     21 		BotInfo *MemoServ = Config->GetClient("MemoServ");
     22 
     23 		if (!MemoServ)
     24 			return;
     25 
     26 		if (param.equals_ci("ON"))
     27 		{
     28 			nc->Extend<bool>("MEMO_SIGNON");
     29 			nc->Extend<bool>("MEMO_RECEIVE");
     30 			source.Reply(_("%s will now notify you of memos when you log on and when they are sent to you."), MemoServ->nick.c_str());
     31 		}
     32 		else if (param.equals_ci("LOGON"))
     33 		{
     34 			nc->Extend<bool>("MEMO_SIGNON");
     35 			nc->Shrink<bool>("MEMO_RECEIVE");
     36 			source.Reply(_("%s will now notify you of memos when you log on or unset /AWAY."), MemoServ->nick.c_str());
     37 		}
     38 		else if (param.equals_ci("NEW"))
     39 		{
     40 			nc->Shrink<bool>("MEMO_SIGNON");
     41 			nc->Extend<bool>("MEMO_RECEIVE");
     42 			source.Reply(_("%s will now notify you of memos when they are sent to you."), MemoServ->nick.c_str());
     43 		}
     44 		else if (param.equals_ci("MAIL"))
     45 		{
     46 			if (!nc->email.empty())
     47 			{
     48 				nc->Extend<bool>("MEMO_MAIL");
     49 				source.Reply(_("You will now be informed about new memos via email."));
     50 			}
     51 			else
     52 				source.Reply(_("There's no email address set for your nick."));
     53 		}
     54 		else if (param.equals_ci("NOMAIL"))
     55 		{
     56 			nc->Shrink<bool>("MEMO_MAIL");
     57 			source.Reply(_("You will no longer be informed via email."));
     58 		}
     59 		else if (param.equals_ci("OFF"))
     60 		{
     61 			nc->Shrink<bool>("MEMO_SIGNON");
     62 			nc->Shrink<bool>("MEMO_RECEIVE");
     63 			nc->Shrink<bool>("MEMO_MAIL");
     64 			source.Reply(_("%s will not send you any notification of memos."), MemoServ->nick.c_str());
     65 		}
     66 		else
     67 			this->OnSyntaxError(source, "");
     68 	}
     69 
     70 	void DoLimit(CommandSource &source, const std::vector<Anope::string> &params, MemoInfo *mi)
     71 	{
     72 
     73 		Anope::string p1 = params[1];
     74 		Anope::string p2 = params.size() > 2 ? params[2] : "";
     75 		Anope::string p3 = params.size() > 3 ? params[3] : "";
     76 		Anope::string user, chan;
     77 		int16_t limit;
     78 		NickCore *nc = source.nc;
     79 		ChannelInfo *ci = NULL;
     80 		bool is_servadmin = source.HasPriv("memoserv/set-limit");
     81 
     82 		if (p1[0] == '#')
     83 		{
     84 			chan = p1;
     85 			p1 = p2;
     86 			p2 = p3;
     87 			p3 = params.size() > 4 ? params[4] : "";
     88 
     89 			ci = ChannelInfo::Find(chan);
     90 			if (!ci)
     91 			{
     92 				source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str());
     93 				return;
     94 			}
     95 			else if (!is_servadmin && !source.AccessFor(ci).HasPriv("MEMO"))
     96 			{
     97 				source.Reply(ACCESS_DENIED);
     98 				return;
     99 			}
    100 			mi = &ci->memos;
    101 		}
    102 		if (is_servadmin)
    103 		{
    104 			if (!p2.empty() && !p2.equals_ci("HARD") && chan.empty())
    105 			{
    106 				const NickAlias *na;
    107 				if (!(na = NickAlias::Find(p1)))
    108 				{
    109 					source.Reply(NICK_X_NOT_REGISTERED, p1.c_str());
    110 					return;
    111 				}
    112 				user = p1;
    113 				mi = &na->nc->memos;
    114 				nc = na->nc;
    115 				p1 = p2;
    116 				p2 = p3;
    117 			}
    118 			else if (p1.empty() || (!p1.is_pos_number_only() && !p1.equals_ci("NONE")) || (!p2.empty() && !p2.equals_ci("HARD")))
    119 			{
    120 				this->OnSyntaxError(source, "");
    121 				return;
    122 			}
    123 			if (!chan.empty())
    124 			{
    125 				if (!p2.empty())
    126 					ci->Extend<bool>("MEMO_HARDMAX");
    127 				else
    128 					ci->Shrink<bool>("MEMO_HARDMAX");
    129 			}
    130 			else
    131 			{
    132 				if (!p2.empty())
    133 					nc->Extend<bool>("MEMO_HARDMAX");
    134 				else
    135 					nc->Shrink<bool>("MEMO_HARDMAX");
    136 			}
    137 			limit = -1;
    138 			try
    139 			{
    140 				limit = convertTo<int16_t>(p1);
    141 			}
    142 			catch (const ConvertException &) { }
    143 		}
    144 		else
    145 		{
    146 			if (p1.empty() || !p2.empty() || !isdigit(p1[0]))
    147 			{
    148 				this->OnSyntaxError(source, "");
    149 				return;
    150 			}
    151 			if (!chan.empty() && ci->HasExt("MEMO_HARDMAX"))
    152 			{
    153 				source.Reply(_("The memo limit for %s may not be changed."), chan.c_str());
    154 				return;
    155 			}
    156 			else if (chan.empty() && nc->HasExt("MEMO_HARDMAX"))
    157 			{
    158 				source.Reply(_("You are not permitted to change your memo limit."));
    159 				return;
    160 			}
    161 			int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos");
    162 			limit = -1;
    163 			try
    164 			{
    165 				limit = convertTo<int16_t>(p1);
    166 			}
    167 			catch (const ConvertException &) { }
    168 			/* The first character is a digit, but we could still go negative
    169 			 * from overflow... watch out! */
    170 			if (limit < 0 || (max_memos > 0 && limit > max_memos))
    171 			{
    172 				if (!chan.empty())
    173 					source.Reply(_("You cannot set the memo limit for %s higher than %d."), chan.c_str(), max_memos);
    174 				else
    175 					source.Reply(_("You cannot set your memo limit higher than %d."), max_memos);
    176 				return;
    177 			}
    178 		}
    179 		mi->memomax = limit;
    180 		if (limit > 0)
    181 		{
    182 			if (chan.empty() && nc == source.nc)
    183 				source.Reply(_("Your memo limit has been set to \002%d\002."), limit);
    184 			else
    185 				source.Reply(_("Memo limit for %s set to \002%d\002."), !chan.empty() ? chan.c_str() : user.c_str(), limit);
    186 		}
    187 		else if (!limit)
    188 		{
    189 			if (chan.empty() && nc == source.nc)
    190 				source.Reply(_("You will no longer be able to receive memos."));
    191 			else
    192 				source.Reply(_("Memo limit for %s set to \0020\002."), !chan.empty() ? chan.c_str() : user.c_str());
    193 		}
    194 		else
    195 		{
    196 			if (chan.empty() && nc == source.nc)
    197 				source.Reply(_("Your memo limit has been disabled."));
    198 			else
    199 				source.Reply(_("Memo limit \002disabled\002 for %s."), !chan.empty() ? chan.c_str() : user.c_str());
    200 		}
    201 		return;
    202 	}
    203  public:
    204 	CommandMSSet(Module *creator) : Command(creator, "memoserv/set", 2, 5)
    205 	{
    206 		this->SetDesc(_("Set options related to memos"));
    207 		this->SetSyntax(_("\037option\037 \037parameters\037"));
    208 	}
    209 
    210 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    211 	{
    212 		const Anope::string &cmd = params[0];
    213 		MemoInfo *mi = &source.nc->memos;
    214 
    215 		if (Anope::ReadOnly)
    216 			source.Reply(_("Sorry, memo option setting is temporarily disabled."));
    217 		else if (cmd.equals_ci("NOTIFY"))
    218 			return this->DoNotify(source, params, mi);
    219 		else if (cmd.equals_ci("LIMIT"))
    220 			return this->DoLimit(source, params, mi);
    221 		else
    222 		{
    223 			this->OnSyntaxError(source, "");
    224 		}
    225 
    226 		return;
    227 	}
    228 
    229 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    230 	{
    231 		if (subcommand.empty())
    232 		{
    233 			this->SendSyntax(source);
    234 			source.Reply(" ");
    235 			source.Reply(_("Sets various memo options.  \037option\037 can be one of:\n"
    236 					" \n"
    237 					"    NOTIFY      Changes when you will be notified about\n"
    238 					"                   new memos (only for nicknames)\n"
    239 					"    LIMIT       Sets the maximum number of memos you can\n"
    240 					"                   receive\n"
    241 					" \n"
    242 					"Type \002%s%s HELP %s \037option\037\002 for more information\n"
    243 					"on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
    244 		}
    245 		else if (subcommand.equals_ci("NOTIFY"))
    246 			source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n"
    247 					" \n"
    248 					"Changes when you will be notified about new memos:\n"
    249 					" \n"
    250 					"    ON      You will be notified of memos when you log on,\n"
    251 					"               when you unset /AWAY, and when they are sent\n"
    252 					"               to you.\n"
    253 					"    LOGON   You will only be notified of memos when you log\n"
    254 					"               on or when you unset /AWAY.\n"
    255 					"    NEW     You will only be notified of memos when they\n"
    256 					"               are sent to you.\n"
    257 					"    MAIL    You will be notified of memos by email as well as\n"
    258 					"               any other settings you have.\n"
    259 					"    NOMAIL  You will not be notified of memos by email.\n"
    260 					"    OFF     You will not receive any notification of memos.\n"
    261 					" \n"
    262 					"\002ON\002 is essentially \002LOGON\002 and \002NEW\002 combined."));
    263 		else if (subcommand.equals_ci("LIMIT"))
    264 		{
    265 			int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos");
    266 			if (source.IsServicesOper())
    267 				source.Reply(_("Syntax: \002LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]\002\n"
    268 						" \n"
    269 						"Sets the maximum number of memos a user or channel is\n"
    270 						"allowed to have.  Setting the limit to 0 prevents the user\n"
    271 						"from receiving any memos; setting it to \002NONE\002 allows the\n"
    272 						"user to receive and keep as many memos as they want.  If\n"
    273 						"you do not give a nickname or channel, your own limit is\n"
    274 						"set.\n"
    275 						" \n"
    276 						"Adding \002HARD\002 prevents the user from changing the limit.  Not\n"
    277 						"adding \002HARD\002 has the opposite effect, allowing the user to\n"
    278 						"change the limit (even if a previous limit was set with\n"
    279 						"\002HARD\002).\n"
    280 						" \n"
    281 						"This use of the \002SET LIMIT\002 command is limited to \002Services\002\n"
    282 						"\002Operators\002.  Other users may only enter a limit for themselves\n"
    283 						"or a channel on which they have such privileges, may not\n"
    284 						"remove their limit, may not set a limit above %d, and may\n"
    285 						"not set a hard limit."), max_memos);
    286 			else
    287 				source.Reply(_("Syntax: \002LIMIT [\037channel\037] \037limit\037\002\n"
    288 									" \n"
    289 									"Sets the maximum number of memos you (or the given channel)\n"
    290 									"are allowed to have. If you set this to 0, no one will be\n"
    291 									"able to send any memos to you.  However, you cannot set\n"
    292 									"this any higher than %d."), max_memos);
    293 		}
    294 		else
    295 			return false;
    296 
    297 		return true;
    298 	}
    299 };
    300 
    301 class MSSet : public Module
    302 {
    303 	CommandMSSet commandmsset;
    304 	SerializableExtensibleItem<bool> memo_signon, memo_receive, memo_mail, memo_hardmax;
    305 
    306  public:
    307 	MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    308 		commandmsset(this), memo_signon(this, "MEMO_SIGNON"), memo_receive(this, "MEMO_RECEIVE"), memo_mail(this, "MEMO_MAIL"),
    309 		memo_hardmax(this, "MEMO_HARDMAX")
    310 	{
    311 
    312 	}
    313 };
    314 
    315 MODULE_INIT(MSSet)