anope

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

m_rewrite.cpp (4887B)

      1 /*
      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 
      9 #include "module.h"
     10 
     11 struct Rewrite
     12 {
     13 	Anope::string client, source_message, target_message, desc;
     14 
     15 	bool Matches(const std::vector<Anope::string> &message)
     16 	{
     17 		std::vector<Anope::string> sm;
     18 		spacesepstream(this->source_message).GetTokens(sm);
     19 
     20 		for (unsigned i = 0; i < sm.size(); ++i)
     21 			if (i >= message.size() || (sm[i] != "$" && !sm[i].equals_ci(message[i])))
     22 				return false;
     23 
     24 		return true;
     25 	}
     26 
     27 	Anope::string Process(CommandSource &source, const std::vector<Anope::string> &params)
     28 	{
     29 		spacesepstream sep(this->target_message);
     30 		Anope::string token, message;
     31 
     32 		while (sep.GetToken(token))
     33 		{
     34 			if (token[0] != '$')
     35 				message += " " + token;
     36 			else if (token == "$me")
     37 				message += " " + source.GetNick();
     38 			else
     39 			{
     40 				int num = -1, end = -1;
     41 				try
     42 				{
     43 					Anope::string num_str = token.substr(1);
     44 					size_t hy = num_str.find('-');
     45 					if (hy == Anope::string::npos)
     46 					{
     47 						num = convertTo<int>(num_str);
     48 						end = num + 1;
     49 					}
     50 					else
     51 					{
     52 						num = convertTo<int>(num_str.substr(0, hy));
     53 						if (hy == num_str.length() - 1)
     54 							end = params.size();
     55 						else
     56 							end = convertTo<int>(num_str.substr(hy + 1)) + 1;
     57 					}
     58 				}
     59 				catch (const ConvertException &)
     60 				{
     61 					continue;
     62 				}
     63 
     64 				for (int i = num; i < end && static_cast<unsigned>(i) < params.size(); ++i)
     65 					message += " " +  params[i];
     66 			}
     67 		}
     68 
     69 		message.trim();
     70 		return message;
     71 	}
     72 
     73 	static std::vector<Rewrite> rewrites;
     74 
     75 	static Rewrite *Find(const Anope::string &client, const Anope::string &cmd)
     76 	{
     77 		for (unsigned i = 0; i < rewrites.size(); ++i)
     78 		{
     79 			Rewrite &r = rewrites[i];
     80 
     81 			if ((client.empty() || r.client.equals_ci(client)) && (r.source_message.equals_ci(cmd) || r.source_message.find_ci(cmd + " ") == 0))
     82 				return &r;
     83 		}
     84 
     85 		return NULL;
     86 	}
     87 
     88 	static Rewrite *Match(const Anope::string &client, const std::vector<Anope::string> &params)
     89 	{
     90 		for (unsigned i = 0; i < rewrites.size(); ++i)
     91 		{
     92 			Rewrite &r = rewrites[i];
     93 
     94 			if ((client.empty() || r.client.equals_ci(client)) && r.Matches(params))
     95 				return &r;
     96 		}
     97 
     98 		return NULL;
     99 	}
    100 };
    101 
    102 std::vector<Rewrite> Rewrite::rewrites;
    103 
    104 class RewriteCommand : public Command
    105 {
    106  public:
    107 	RewriteCommand(Module *creator) : Command(creator, "rewrite", 0, 0) { }
    108 
    109 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    110 	{
    111 		std::vector<Anope::string> full_params = params;
    112 		full_params.insert(full_params.begin(), source.command);
    113 
    114 		Rewrite *r = Rewrite::Match(!source.c ? source.service->nick : "", full_params);
    115 		if (r != NULL)
    116 		{
    117 			Anope::string new_message = r->Process(source, full_params);
    118 			Log(LOG_DEBUG) << "m_rewrite: Rewrote '" << source.command << (!params.empty() ? " " + params[0] : "") << "' to '" << new_message << "' using '" << r->source_message << "'";
    119 			source.service = BotInfo::Find(r->client, true);
    120 			if (!source.service)
    121 				return;
    122 			Command::Run(source, new_message);
    123 		}
    124 		else
    125 			Log() << "m_rewrite: Unable to rewrite '" << source.command << (!params.empty() ? " " + params[0] : "") << "'";
    126 	}
    127 
    128 	void OnServHelp(CommandSource &source) anope_override
    129 	{
    130 		Rewrite *r = Rewrite::Find(!source.c ? source.service->nick : "", source.command);
    131 		if (r != NULL && !r->desc.empty())
    132 		{
    133 			this->SetDesc(r->desc);
    134 			Command::OnServHelp(source);
    135 		}
    136 	}
    137 
    138 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    139 	{
    140 		Rewrite *r = Rewrite::Find(!source.c ? source.service->nick : "", source.command);
    141 		if (r != NULL && !r->desc.empty())
    142 		{
    143 			source.Reply(r->desc);
    144 			size_t sz = r->target_message.find(' ');
    145 			source.Reply(_("This command is an alias to the command %s."), sz != Anope::string::npos ? r->target_message.substr(0, sz).c_str() : r->target_message.c_str());
    146 			return true;
    147 		}
    148 		return false;
    149 	}
    150 };
    151 
    152 class ModuleRewrite : public Module
    153 {
    154 	RewriteCommand cmdrewrite;
    155 
    156  public:
    157 	ModuleRewrite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA), cmdrewrite(this)
    158 	{
    159 	}
    160 
    161 	void OnReload(Configuration::Conf *conf) anope_override
    162 	{
    163 		Rewrite::rewrites.clear();
    164 
    165 		for (int i = 0; i < conf->CountBlock("command"); ++i)
    166 		{
    167 			Configuration::Block *block = conf->GetBlock("command", i);
    168 
    169 			if (!block->Get<bool>("rewrite"))
    170 				continue;
    171 
    172 			Rewrite rw;
    173 
    174 			rw.client = block->Get<const Anope::string>("service");
    175 			rw.source_message = block->Get<const Anope::string>("rewrite_source");
    176 			rw.target_message = block->Get<const Anope::string>("rewrite_target");
    177 			rw.desc = block->Get<const Anope::string>("rewrite_description");
    178 
    179 			if (rw.client.empty() || rw.source_message.empty() || rw.target_message.empty())
    180 				continue;
    181 
    182 			Rewrite::rewrites.push_back(rw);
    183 		}
    184 	}
    185 };
    186 
    187 MODULE_INIT(ModuleRewrite)