]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_customprefix.cpp
Sync helpop chmodes s and p with docs
[user/henk/code/inspircd.git] / src / modules / m_customprefix.cpp
index dfc60e082560190d62736bc02c3bcd006d41da24..53b0376b241a353eeb8f5eaeb72df41ef18064a4 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
+ *   Copyright (C) 2013-2014 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2013, 2017-2018 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
  *   Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
 
 #include "inspircd.h"
 
-/* $ModDesc: Allows custom prefix modes to be created. */
-
-class CustomPrefixMode : public ModeHandler
+class CustomPrefixMode : public PrefixMode
 {
  public:
        reference<ConfigTag> tag;
-       int rank;
-       bool depriv;
-       CustomPrefixMode(Module* parent, ConfigTag* Tag)
-               : ModeHandler(parent, Tag->getString("name"), 0, PARAM_ALWAYS, MODETYPE_CHANNEL), tag(Tag)
-       {
-               list = true;
-               m_paramtype = TR_NICK;
-               std::string v = tag->getString("prefix");
-               prefix = v.c_str()[0];
-               v = tag->getString("letter");
-               mode = v.c_str()[0];
-               rank = tag->getInt("rank");
-               levelrequired = tag->getInt("ranktoset", rank);
-               depriv = tag->getBool("depriv", true);
-       }
-
-       unsigned int GetPrefixRank()
-       {
-               return rank;
-       }
-
-       ModResult AccessCheck(User* src, Channel*, std::string& value, bool adding)
-       {
-               if (!adding && src->nick == value && depriv)
-                       return MOD_RES_ALLOW;
-               return MOD_RES_PASSTHRU;
-       }
-
-       void RemoveMode(Channel* channel, irc::modestacker* stack)
-       {
-               const UserMembList* cl = channel->GetUsers();
-               std::vector<std::string> mode_junk;
-               mode_junk.push_back(channel->name);
-               irc::modestacker modestack(false);
-               std::deque<std::string> stackresult;
-
-               for (UserMembCIter i = cl->begin(); i != cl->end(); i++)
-               {
-                       if (i->second->hasMode(mode))
-                       {
-                               if (stack)
-                                       stack->Push(this->GetModeChar(), i->first->nick);
-                               else
-                                       modestack.Push(this->GetModeChar(), i->first->nick);
-                       }
-               }
-
-               if (stack)
-                       return;
 
-               while (modestack.GetStackedLine(stackresult))
-               {
-                       mode_junk.insert(mode_junk.end(), stackresult.begin(), stackresult.end());
-                       ServerInstance->SendMode(mode_junk, ServerInstance->FakeClient);
-                       mode_junk.erase(mode_junk.begin() + 1, mode_junk.end());
-               }
-       }
-
-       void RemoveMode(User* user, irc::modestacker* stack)
+       CustomPrefixMode(Module* parent, const std::string& Name, char Letter, char Prefix, ConfigTag* Tag)
+               : PrefixMode(parent, Name, Letter, 0, Prefix)
+               , tag(Tag)
        {
-       }
-
-       ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
-       {
-               return MODEACTION_ALLOW;
+               unsigned long rank = tag->getUInt("rank", 0, 0, UINT_MAX);
+               unsigned long setrank = tag->getUInt("ranktoset", prefixrank, rank, UINT_MAX);
+               unsigned long unsetrank = tag->getUInt("ranktounset", setrank, setrank, UINT_MAX);
+               bool depriv = tag->getBool("depriv", true);
+               this->Update(rank, setrank, unsetrank, depriv);
+
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Created the %s prefix: letter=%c prefix=%c rank=%u ranktoset=%u ranktounset=%i depriv=%d",
+                       name.c_str(), GetModeChar(), GetPrefix(), GetPrefixRank(), GetLevelRequired(true), GetLevelRequired(false), CanSelfRemove());
        }
 };
 
@@ -97,43 +46,67 @@ class ModuleCustomPrefix : public Module
 {
        std::vector<CustomPrefixMode*> modes;
  public:
-       ModuleCustomPrefix()
-       {
-       }
-
-       void init()
+       void init() CXX11_OVERRIDE
        {
                ConfigTagList tags = ServerInstance->Config->ConfTags("customprefix");
-               while (tags.first != tags.second)
+               for (ConfigIter iter = tags.first; iter != tags.second; ++iter)
                {
-                       ConfigTag* tag = tags.first->second;
-                       tags.first++;
-                       CustomPrefixMode* mh = new CustomPrefixMode(this, tag);
-                       modes.push_back(mh);
-                       if (mh->rank <= 0)
-                               throw ModuleException("Rank must be specified for prefix at " + tag->getTagLocation());
-                       if (!isalpha(mh->GetModeChar()))
-                               throw ModuleException("Mode must be a letter for prefix at " + tag->getTagLocation());
+                       ConfigTag* tag = iter->second;
+
+                       const std::string name = tag->getString("name");
+                       if (name.empty())
+                               throw ModuleException("<customprefix:name> must be specified at " + tag->getTagLocation());
+
+                       if (tag->getBool("change"))
+                       {
+                               ModeHandler* mh = ServerInstance->Modes->FindMode(name, MODETYPE_CHANNEL);
+                               if (!mh)
+                                       throw ModuleException("<customprefix:change> specified for a nonexistent mode at " + tag->getTagLocation());
+
+                               PrefixMode* pm = mh->IsPrefixMode();
+                               if (!pm)
+                                       throw ModuleException("<customprefix:change> specified for a non-prefix mode at " + tag->getTagLocation());
+
+                               unsigned long rank = tag->getUInt("rank", pm->GetPrefixRank(), 0, UINT_MAX);
+                               unsigned long setrank = tag->getUInt("ranktoset", pm->GetLevelRequired(true), rank, UINT_MAX);
+                               unsigned long unsetrank = tag->getUInt("ranktounset", pm->GetLevelRequired(false), setrank, UINT_MAX);
+                               bool depriv = tag->getBool("depriv", pm->CanSelfRemove());
+                               pm->Update(rank, setrank, unsetrank, depriv);
+
+                               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Changed the %s prefix: depriv=%u rank=%u ranktoset=%u ranktounset=%u",
+                                       pm->name.c_str(), pm->CanSelfRemove(), pm->GetPrefixRank(), pm->GetLevelRequired(true), pm->GetLevelRequired(false));
+                               continue;
+                       }
+
+                       const std::string letter = tag->getString("letter");
+                       if (letter.length() != 1)
+                               throw ModuleException("<customprefix:letter> must be set to a mode character at " + tag->getTagLocation());
+
+                       const std::string prefix = tag->getString("prefix");
+                       if (prefix.length() != 1)
+                               throw ModuleException("<customprefix:prefix> must be set to a mode prefix at " + tag->getTagLocation());
+
                        try
                        {
+                               CustomPrefixMode* mh = new CustomPrefixMode(this, name, letter[0], prefix[0], tag);
+                               modes.push_back(mh);
                                ServerInstance->Modules->AddService(*mh);
                        }
                        catch (ModuleException& e)
                        {
-                               throw ModuleException(e.err + " (while creating mode from " + tag->getTagLocation() + ")");
+                               throw ModuleException(e.GetReason() + " (while creating mode from " + tag->getTagLocation() + ")");
                        }
                }
        }
 
        ~ModuleCustomPrefix()
        {
-               for (std::vector<CustomPrefixMode*>::iterator i = modes.begin(); i != modes.end(); i++)
-                       delete *i;
+               stdalgo::delete_all(modes);
        }
 
-       Version GetVersion()
+       Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Provides custom prefix channel modes", VF_VENDOR);
+               return Version("Allows the server administrator to configure custom channel prefix modes.", VF_VENDOR);
        }
 };