anope

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

fantasy.cpp (6119B)

      1 /* Fantasy functionality
      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 CommandBSSetFantasy : public Command
     15 {
     16  public:
     17 	CommandBSSetFantasy(Module *creator, const Anope::string &sname = "botserv/set/fantasy") : Command(creator, sname, 2, 2)
     18 	{
     19 		this->SetDesc(_("Enable fantaisist commands"));
     20 		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
     21 	}
     22 
     23 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
     24 	{
     25 		ChannelInfo *ci = ChannelInfo::Find(params[0]);
     26 		const Anope::string &value = params[1];
     27 
     28 		if (ci == NULL)
     29 		{
     30 			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
     31 			return;
     32 		}
     33 
     34 		if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
     35 		{
     36 			source.Reply(ACCESS_DENIED);
     37 			return;
     38 		}
     39 
     40 		if (Anope::ReadOnly)
     41 		{
     42 			source.Reply(_("Sorry, bot option setting is temporarily disabled."));
     43 			return;
     44 		}
     45 
     46 		if (value.equals_ci("ON"))
     47 		{
     48 			bool override = !source.AccessFor(ci).HasPriv("SET");
     49 			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable fantasy";
     50 
     51 			ci->Extend<bool>("BS_FANTASY");
     52 			source.Reply(_("Fantasy mode is now \002on\002 on channel %s."), ci->name.c_str());
     53 		}
     54 		else if (value.equals_ci("OFF"))
     55 		{
     56 			bool override = !source.AccessFor(ci).HasPriv("SET");
     57 			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable fantasy";
     58 
     59 			ci->Shrink<bool>("BS_FANTASY");
     60 			source.Reply(_("Fantasy mode is now \002off\002 on channel %s."), ci->name.c_str());
     61 		}
     62 		else
     63 			this->OnSyntaxError(source, source.command);
     64 	}
     65 
     66 	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
     67 	{
     68 		this->SendSyntax(source);
     69 		source.Reply(_(" \n"
     70 				"Enables or disables \002fantasy\002 mode on a channel.\n"
     71 				"When it is enabled, users will be able to use\n"
     72 				"fantasy commands on a channel when prefixed\n"
     73 				"with one of the following fantasy characters: \002%s\002\n"
     74 				" \n"
     75 				"Note that users wanting to use fantaisist\n"
     76 				"commands MUST have enough access for both\n"
     77 				"the FANTASIA and the command they are executing."),
     78 				Config->GetModule(this->owner)->Get<const Anope::string>("fantasycharacter", "!").c_str());
     79 		return true;
     80 	}
     81 };
     82 
     83 class Fantasy : public Module
     84 {
     85 	SerializableExtensibleItem<bool> fantasy;
     86 
     87 	CommandBSSetFantasy commandbssetfantasy;
     88 
     89  public:
     90 	Fantasy(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
     91 		fantasy(this, "BS_FANTASY"), commandbssetfantasy(this)
     92 	{
     93 	}
     94 
     95 	void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
     96 	{
     97 		if (!u || !c || !c->ci || !c->ci->bi || msg.empty() || msg[0] == '\1')
     98 			return;
     99 
    100 		if (Config->GetClient("BotServ") && !fantasy.HasExt(c->ci))
    101 			return;
    102 
    103 		std::vector<Anope::string> params;
    104 		spacesepstream(msg).GetTokens(params);
    105 
    106 		if (params.empty())
    107 			return;
    108 
    109 		Anope::string normalized_param0 = Anope::NormalizeBuffer(params[0]);
    110 		Anope::string fantasy_chars = Config->GetModule(this)->Get<Anope::string>("fantasycharacter", "!");
    111 
    112 		if (!normalized_param0.find(c->ci->bi->nick))
    113 		{
    114 			params.erase(params.begin());
    115 		}
    116 		else if (!normalized_param0.find_first_of(fantasy_chars))
    117 		{
    118 			size_t sz = params[0].find_first_of(fantasy_chars);
    119 			if (sz == Anope::string::npos)
    120 				return; /* normalized_param0 is a subset of params[0] so this can't happen */
    121 
    122 			params[0].erase(0, sz + 1);
    123 		}
    124 		else
    125 		{
    126 			return;
    127 		}
    128 
    129 		if (params.empty())
    130 			return;
    131 
    132 		CommandInfo::map::const_iterator it = Config->Fantasy.end();
    133 		unsigned count = 0;
    134 		for (unsigned max = params.size(); it == Config->Fantasy.end() && max > 0; --max)
    135 		{
    136 			Anope::string full_command;
    137 			for (unsigned i = 0; i < max; ++i)
    138 				full_command += " " + params[i];
    139 			full_command.erase(full_command.begin());
    140 
    141 			++count;
    142 			it = Config->Fantasy.find(Anope::NormalizeBuffer(full_command));
    143 		}
    144 
    145 		if (it == Config->Fantasy.end())
    146 			return;
    147 
    148 		const CommandInfo &info = it->second;
    149 		ServiceReference<Command> cmd("Command", info.name);
    150 		if (!cmd)
    151 		{
    152 			Log(LOG_DEBUG) << "Fantasy command " << it->first << " exists for nonexistent service " << info.name << "!";
    153 			return;
    154 		}
    155 
    156 		for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
    157 			params.erase(params.begin());
    158 
    159 		/* Some commands take the channel as a first parameter */
    160 		if (info.prepend_channel)
    161 			params.insert(params.begin(), c->name);
    162 
    163 		while (cmd->max_params > 0 && params.size() > cmd->max_params)
    164 		{
    165 			params[cmd->max_params - 1] += " " + params[cmd->max_params];
    166 			params.erase(params.begin() + cmd->max_params);
    167 		}
    168 
    169 		// Command requires registered users only
    170 		if (!cmd->AllowUnregistered() && !u->Account())
    171 			return;
    172 
    173 		if (params.size() < cmd->min_params)
    174 			return;
    175 
    176 		CommandSource source(u->nick, u, u->Account(), u, c->ci->bi);
    177 		source.c = c;
    178 		source.command = it->first;
    179 		source.permission = info.permission;
    180 
    181 		AccessGroup ag = c->ci->AccessFor(u);
    182 		bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("botserv/fantasy");
    183 
    184 		EventReturn MOD_RESULT;
    185 		if (has_fantasia)
    186 		{
    187 			FOREACH_RESULT(OnBotFantasy, MOD_RESULT, (source, cmd, c->ci, params));
    188 		}
    189 		else
    190 		{
    191 			FOREACH_RESULT(OnBotNoFantasyAccess, MOD_RESULT, (source, cmd, c->ci, params));
    192 		}
    193 
    194 		if (MOD_RESULT == EVENT_STOP || !has_fantasia)
    195 			return;
    196 
    197 		if (MOD_RESULT != EVENT_ALLOW && !info.permission.empty() && !source.HasCommand(info.permission))
    198 			return;
    199 
    200 		FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, cmd, params));
    201 		if (MOD_RESULT == EVENT_STOP)
    202 			return;
    203 
    204 		Reference<NickCore> nc_reference(u->Account());
    205 		cmd->Execute(source, params);
    206 		if (!nc_reference)
    207 			source.nc = NULL;
    208 		FOREACH_MOD(OnPostCommand, (source, cmd, params));
    209 	}
    210 
    211 	void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
    212 	{
    213 		if (fantasy.HasExt(ci))
    214 			info.AddOption(_("Fantasy"));
    215 	}
    216 };
    217 
    218 MODULE_INIT(Fantasy)