diff options
-rw-r--r-- | data/modules.example.conf | 21 | ||||
-rw-r--r-- | modules/extra/m_rewrite.cpp | 127 |
2 files changed, 148 insertions, 0 deletions
diff --git a/data/modules.example.conf b/data/modules.example.conf index e03761fb2..715be1898 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -311,6 +311,27 @@ sqlite } /* + * m_rewrite + * + * Allows rewriting commands sent to clients. + */ +#module { name = "m_rewrite" } +rewrite +{ + /* The client to apply this rewrite to. */ + client = "ChanServ" + + /* Source message to match. A $ can be used to match anything. */ + source_message = "CLEAR $ USERS" + + /* + * Message to rewrite the source message to. A $ followed by a number, eg $0, gets + * replaced by the number-th word from the source_message, starting from 0. + */ + target_message = "CLEARUSERS $1" +} + +/* * m_ssl * * This module uses SSL to connect to the uplink server(s) diff --git a/modules/extra/m_rewrite.cpp b/modules/extra/m_rewrite.cpp new file mode 100644 index 000000000..f40e828b0 --- /dev/null +++ b/modules/extra/m_rewrite.cpp @@ -0,0 +1,127 @@ +/* + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + */ + +#include "module.h" + +struct Rewrite +{ + Anope::string client, source_message, target_message; + + bool Matches(const std::vector<Anope::string> &message) + { + std::vector<Anope::string> sm = BuildStringVector(this->source_message); + + for (unsigned i = 0; i < sm.size(); ++i) + if (sm[i] != "$" && !sm[i].equals_ci(message[i])) + return false; + + return true; + } + + Anope::string Process(const std::vector<Anope::string> ¶ms) + { + spacesepstream sep(this->target_message); + Anope::string token, message; + + while (sep.GetToken(token)) + { + if (token[0] != '$') + message += " " + token; + else + { + int num = -1, end = -1; + try + { + Anope::string num_str = token.substr(1); + size_t hy = num_str.find('-'); + if (hy == Anope::string::npos) + { + num = convertTo<int>(num_str); + end = num + 1; + } + else + { + num = convertTo<int>(num_str.substr(0, hy)); + if (hy == num_str.length() - 1) + end = params.size(); + else + end = convertTo<int>(num_str.substr(hy + 1)) + 1; + } + } + catch (const ConvertException &) + { + continue; + } + + for (int i = num; i < end && static_cast<unsigned>(i) < params.size(); ++i) + message += " " + params[i]; + } + } + + message.trim(); + return message; + } +}; + +class ModuleRewrite : public Module +{ + std::vector<Rewrite> rewrites; + + public: + ModuleRewrite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) + { + this->SetAuthor("Anope"); + + Implementation i[] = { I_OnReload, I_OnBotPrivmsg }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + ModuleManager::SetPriority(this, PRIORITY_FIRST); + + this->OnReload(); + } + + void OnReload() + { + ConfigReader config; + + this->rewrites.clear(); + + for (int i = 0; i < config.Enumerate("rewrite"); ++i) + { + Rewrite rw; + + rw.client = config.ReadValue("rewrite", "client", "", i); + rw.source_message = config.ReadValue("rewrite", "source_message", "", i), + rw.target_message = config.ReadValue("rewrite", "target_message", "", i); + + if (rw.client.empty() || rw.source_message.empty() || rw.target_message.empty()) + continue; + + this->rewrites.push_back(rw); + } + } + + EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) + { + std::vector<Anope::string> tokens = BuildStringVector(message); + for (unsigned i = 0; i < this->rewrites.size(); ++i) + { + Rewrite &rw = this->rewrites[i]; + + if (rw.client == bi->nick && rw.Matches(tokens)) + { + Anope::string new_message = rw.Process(tokens); + Log(LOG_DEBUG) << "m_rewrite: Rewrote '" << message << "' to '" << new_message << "'"; + message = new_message; + break; + } + } + + return EVENT_CONTINUE; + } +}; + +MODULE_INIT(ModuleRewrite) |