summaryrefslogtreecommitdiff
path: root/modules/nickserv/ns_maxemail.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/nickserv/ns_maxemail.cpp')
-rw-r--r--modules/nickserv/ns_maxemail.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/modules/nickserv/ns_maxemail.cpp b/modules/nickserv/ns_maxemail.cpp
new file mode 100644
index 000000000..342ba3c3d
--- /dev/null
+++ b/modules/nickserv/ns_maxemail.cpp
@@ -0,0 +1,112 @@
+/* ns_maxemail.cpp - Limit the amount of times an email address
+ * can be used for a NickServ account.
+ *
+ * (C) 2003-2024 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: GeniusDex <geniusdex@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+
+class NSMaxEmail final
+ : public Module
+{
+ bool clean = false;
+
+ /* strip dots from username, and remove anything after the first + */
+ static Anope::string CleanMail(const Anope::string &email)
+ {
+ size_t host = email.find('@');
+ if (host == Anope::string::npos)
+ return email;
+
+ Anope::string username = email.substr(0, host);
+ username = username.replace_all_cs(".", "");
+
+ size_t sz = username.find('+');
+ if (sz != Anope::string::npos)
+ username = username.substr(0, sz);
+
+ Anope::string cleaned = username + email.substr(host);
+ Log(LOG_DEBUG) << "cleaned " << email << " to " << cleaned;
+ return cleaned;
+ }
+
+ bool CheckLimitReached(CommandSource &source, const Anope::string &email)
+ {
+ int NSEmailMax = Config->GetModule(this)->Get<int>("maxemails");
+
+ if (NSEmailMax < 1 || email.empty())
+ return false;
+
+ if (this->CountEmail(email, source.nc) < NSEmailMax)
+ return false;
+
+ if (NSEmailMax == 1)
+ source.Reply(_("The email address \002%s\002 has reached its usage limit of 1 user."), email.c_str());
+ else
+ source.Reply(_("The email address \002%s\002 has reached its usage limit of %d users."), email.c_str(), NSEmailMax);
+
+ return true;
+ }
+
+ int CountEmail(const Anope::string &email, NickCore *unc)
+ {
+ int count = 0;
+
+ if (email.empty())
+ return 0;
+
+ Anope::string cleanemail = clean ? CleanMail(email) : email;
+
+ for (const auto &[_, nc] : *NickCoreList)
+ {
+ Anope::string cleannc = clean ? CleanMail(nc->email) : nc->email;
+
+ if (unc != nc && cleanemail.equals_ci(cleannc))
+ ++count;
+ }
+
+ return count;
+ }
+
+public:
+ NSMaxEmail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
+ {
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ clean = conf->GetModule(this)->Get<bool>("remove_aliases", "true");
+ }
+
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
+ {
+ if (source.IsOper())
+ return EVENT_CONTINUE;
+
+ if (command->name == "nickserv/register")
+ {
+ if (this->CheckLimitReached(source, params.size() > 1 ? params[1] : ""))
+ return EVENT_STOP;
+ }
+ else if (command->name == "nickserv/set/email")
+ {
+ if (this->CheckLimitReached(source, params.size() > 0 ? params[0] : ""))
+ return EVENT_STOP;
+ }
+ else if (command->name == "nickserv/ungroup" && source.GetAccount())
+ {
+ if (this->CheckLimitReached(source, source.GetAccount()->email))
+ return EVENT_STOP;
+ }
+
+ return EVENT_CONTINUE;
+ }
+};
+
+MODULE_INIT(NSMaxEmail)