diff options
author | Adam <Adam@anope.org> | 2013-04-08 00:19:07 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2013-04-08 00:19:07 -0500 |
commit | 1a37e1c0480f8bd11f57dfba514069a4e9c7d8de (patch) | |
tree | 41798df9056ef555f00c4a6c0964f1219c357dc3 | |
parent | fb7fef7a849342ab8463743497e781c5c3e6ae88 (diff) |
Made auto* chanserv privileges not hard coded.
Made cs_statusupdate not remove status on users if they still match other entries.
Move privilege descriptions out of the config
-rw-r--r-- | data/chanserv.example.conf | 36 | ||||
-rw-r--r-- | include/modes.h | 2 | ||||
-rw-r--r-- | modules/commands/cs_access.cpp | 75 | ||||
-rw-r--r-- | modules/commands/cs_mode.cpp | 20 | ||||
-rw-r--r-- | modules/extra/cs_statusupdate.cpp | 41 | ||||
-rw-r--r-- | modules/protocol/inspircd11.cpp | 2 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 2 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 4 | ||||
-rw-r--r-- | src/channels.cpp | 51 | ||||
-rw-r--r-- | src/config.cpp | 9 | ||||
-rw-r--r-- | src/modes.cpp | 33 |
11 files changed, 136 insertions, 139 deletions
diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index aec506c8e..1c0710f7b 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -244,7 +244,6 @@ chanserv privilege { name = "ACCESS_CHANGE" - desc = "Allowed to modify the access list" rank = 0 level = 10 flag = "f" @@ -260,7 +259,6 @@ privilege privilege { name = "ACCESS_LIST" - desc = "Allowed to view the access list" rank = 10 level = 3 flag = "f" @@ -276,7 +274,6 @@ privilege privilege { name = "AKICK" - desc = "Allowed to use the AKICK command" rank = 250 level = 10 flag = "K" @@ -292,7 +289,6 @@ privilege privilege { name = "ASSIGN" - desc = "Allowed to assign/unassign a bot" rank = 270 level = "founder" flag = "s" @@ -308,7 +304,6 @@ privilege privilege { name = "AUTOHALFOP" - desc = "Automatic mode +h" rank = 100 level = 4 flag = "H" @@ -324,7 +319,6 @@ privilege privilege { name = "AUTOOP" - desc = "Automatic channel operator status" rank = 210 level = 5 flag = "O" @@ -340,7 +334,6 @@ privilege privilege { name = "AUTOOWNER" - desc = "Automatic mode +q" rank = 330 level = 9999 flag = "Q" @@ -356,7 +349,6 @@ privilege privilege { name = "AUTOPROTECT" - desc = "Automatic mode +a" rank = 240 level = 10 flag = "A" @@ -372,7 +364,6 @@ privilege privilege { name = "AUTOVOICE" - desc = "Automatic mode +v" rank = 50 level = 3 flag = "V" @@ -388,7 +379,6 @@ privilege privilege { name = "BADWORDS" - desc = "Allowed to modify channel badwords list" rank = 260 level = 10 flag = "K" @@ -404,7 +394,6 @@ privilege privilege { name = "BAN" - desc = "Allowed to ban users" rank = 150 level = 4 flag = "b" @@ -420,7 +409,6 @@ privilege privilege { name = "FANTASIA" - desc = "Allowed to use fantasy commands" rank = 30 level = 3 flag = "c" @@ -439,7 +427,6 @@ privilege privilege { name = "FOUNDER" - desc = "Allowed to issue commands restricted to channel founders" rank = 360 level = "founder" flag = "F" @@ -456,7 +443,6 @@ privilege privilege { name = "GETKEY" - desc = "Allowed to use GETKEY command" rank = 180 level = 5 flag = "G" @@ -472,7 +458,6 @@ privilege privilege { name = "GREET" - desc = "Greet message displayed on join" rank = 40 level = 5 flag = "g" @@ -489,7 +474,6 @@ privilege privilege { name = "HALFOP" - desc = "Allowed to (de)halfop users" rank = 120 level = 5 flag = "h" @@ -506,7 +490,6 @@ privilege privilege { name = "HALFOPME" - desc = "Allowed to (de)halfop him/herself" rank = 110 level = 4 flag = "h" @@ -523,7 +506,6 @@ privilege privilege { name = "INFO" - desc = "Allowed to get full INFO output" rank = 80 level = 9999 flag = "I" @@ -540,7 +522,6 @@ privilege privilege { name = "INVITE" - desc = "Allowed to use the INVITE command" rank = 190 level = 5 flag = "i" @@ -556,7 +537,6 @@ privilege privilege { name = "KICK" - desc = "Allowed to use the KICK command" rank = 130 level = 4 flag = "k" @@ -573,7 +553,6 @@ privilege privilege { name = "MEMO" - desc = "Allowed to read channel memos" rank = 280 level = 10 flag = "m" @@ -590,7 +569,6 @@ privilege privilege { name = "MODE" - desc = "Allowed to use the MODE command" rank = 170 level = 9999 flag = "s" @@ -606,7 +584,6 @@ privilege privilege { name = "NOKICK" - desc = "Prevents users being kicked by Services" rank = 20 level = 1 flag = "N" @@ -623,7 +600,6 @@ privilege privilege { name = "OPDEOP" - desc = "Allowed to (de)op users" rank = 230 level = 5 flag = "o" @@ -640,7 +616,6 @@ privilege privilege { name = "OPDEOPME" - desc = "Allowed to (de)op him/herself" rank = 220 level = 5 flag = "o" @@ -657,7 +632,6 @@ privilege privilege { name = "OWNER" - desc = "Allowed to (de)owner users" rank = 350 level = "founder" flag = "q" @@ -674,7 +648,6 @@ privilege privilege { name = "OWNERME" - desc = "Allowed to (de)owner him/herself" rank = 340 level = 9999 flag = "q" @@ -691,7 +664,6 @@ privilege privilege { name = "PROTECT" - desc = "Allowed to (de)protect users" rank = 310 level = 9999 flag = "a" @@ -708,7 +680,6 @@ privilege privilege { name = "PROTECTME" - desc = "Allowed to (de)protect him/herself" rank = 300 level = 10 flag = "a" @@ -725,7 +696,6 @@ privilege privilege { name = "SAY" - desc = "Allowed to use SAY and ACT commands" rank = 90 level = 5 flag = "B" @@ -744,7 +714,6 @@ privilege privilege { name = "SET" - desc = "Allowed to set channel settings" rank = 320 level = 9999 flag = "s" @@ -761,7 +730,6 @@ privilege privilege { name = "SIGNKICK" - desc = "No signed kick when SIGNKICK LEVEL is used" rank = 140 level = 9999 flag = "K" @@ -777,7 +745,6 @@ privilege privilege { name = "TOPIC" - desc = "Allowed to change channel topics" rank = 160 level = 5 flag = "t" @@ -793,7 +760,6 @@ privilege privilege { name = "UNBAN" - desc = "Allowed to unban users" rank = 200 level = 4 flag = "u" @@ -810,7 +776,6 @@ privilege privilege { name = "VOICE" - desc = "Allowed to (de)voice users" rank = 70 level = 4 flag = "v" @@ -827,7 +792,6 @@ privilege privilege { name = "VOICEME" - desc = "Allowed to (de)voice him/herself" rank = 60 level = 3 flag = "v" diff --git a/include/modes.h b/include/modes.h index 6a39393bb..f5a1296c5 100644 --- a/include/modes.h +++ b/include/modes.h @@ -368,6 +368,8 @@ class CoreExport ModeManager static const std::vector<ChannelMode *> &GetChannelModes(); static const std::vector<UserMode *> &GetUserModes(); + static const std::vector<ChannelModeStatus *> &GetStatusChannelModesByRank(); + static void RebuildStatusModes(); /** Add a mode to the stacker to be set on a channel * @param bi The client to set the modes from diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 3a4bdff54..86ce37a51 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -15,6 +15,49 @@ static std::map<Anope::string, int16_t, ci::less> defaultLevels; +static struct +{ + Anope::string name; + Anope::string desc; +} descriptions[] = { + {"ACCESS_CHANGE", _("Allowed to modify the access list")}, + {"ACCESS_LIST", _("Allowed to view the access list")}, + {"AKICK", _("Allowed to use the AKICK command")}, + {"ASSIGN", _("Allowed to assign/unassign a bot")}, + {"AUTOHALFOP", _("Automatic halfop upon join")}, + {"AUTOOP", _("Automatic channel operator status upon join")}, + {"AUTOOWNER", _("Automatic owner upon join")}, + {"AUTOPROTECT", _("Automatic protect upon join")}, + {"AUTOVOICE", _("Automatic voice on join")}, + {"BADWORDS", _("Allowed to modify channel badwords list")}, + {"BAN", _("Allowed to ban users")}, + {"FANTASIA", _("Allowed to use fantasy commands")}, + {"FOUNDER", _("Allowed to issue commands restricted to channel founders")}, + {"GETKEY", _("Allowed to use GETKEY command")}, + {"GREET", _("Greet message displayed on join")}, + {"HALFOP", _("Allowed to (de)halfop users")}, + {"HALFOPME", _("Allowed to (de)halfop him/herself")}, + {"INFO", _("Allowed to get full INFO output")}, + {"INVITE", _("Allowed to use the INVITE command")}, + {"KICK", _("Allowed to use the KICK command")}, + {"MEMO", _("Allowed to read channel memos")}, + {"MODE", _("Allowed to use the MODE command")}, + {"NOKICK", _("Prevents users being kicked by Services")}, + {"OPDEOP", _("Allowed to (de)op users")}, + {"OPDEOPME", _("Allowed to (de)op him/herself")}, + {"OWNER", _("Allowed to (de)owner users")}, + {"OWNERME", _("Allowed to (de)owner him/herself")}, + {"PROTECT", _("Allowed to (de)protect users")}, + {"PROTECTME", _("Allowed to (de)protect him/herself")}, + {"SAY", _("Allowed to use SAY and ACT commands")}, + {"SET", _("Allowed to set channel settings")}, + {"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")}, + {"TOPIC", _("Allowed to change channel topics")}, + {"UNBAN", _("Allowed to unban users")}, + {"VOICE", _("Allowed to (de)voice users")}, + {"VOICEME", _("Allowed to (de)voice him/herself")} +}; + static inline void reset_levels(ChannelInfo *ci) { ci->ClearLevels(); @@ -552,22 +595,8 @@ class CommandCSAccess : public Command " \n" "The \002ACCESS CLEAR\002 command clears all entries of the\n" "access list.")); - source.Reply(_("\002User access levels\002\n" - " \n" - "By default, the following access levels are defined:\n" - " \n" - " \002Founder\002 Full access to %s functions; automatic\n" - " opping upon entering channel. Note\n" - " that only one person may have founder\n" - " status (it cannot be given using the\n" - " \002ACCESS\002 command).\n" - " \002 10\002 Access to AKICK command; automatic opping.\n" - " \002 5\002 Automatic opping.\n" - " \002 3\002 Automatic voicing.\n" - " \002 0\002 No special privileges; can be opped by other\n" - " ops (unless \002secure-ops\002 is set).\n" - " \n" - "These levels may be changed, or new ones added, using the\n" + source.Reply(" "); + source.Reply(_("\002User access levels\002 can be seen by using the\n" "\002LEVELS\002 command; type \002%s%s HELP LEVELS\002 for\n" "information."), source.service->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; @@ -806,14 +835,7 @@ class CSAccess : public Module Implementation i[] = { I_OnReload, I_OnCreateChan, I_OnGroupCheckPriv }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - try - { - this->OnReload(); - } - catch (const ConfigException &ex) - { - throw ModuleException(ex.GetReason()); - } + this->OnReload(); } void OnReload() anope_override @@ -829,6 +851,11 @@ class CSAccess : public Module if (p == NULL) continue; + if (p->desc.empty()) + for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j) + if (descriptions[j].name == pname) + p->desc = descriptions[j].desc; + const Anope::string &value = config.ReadValue("privilege", "level", "", i); if (value.empty()) continue; diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index 1d0f0985b..f0f7894cf 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -20,25 +20,7 @@ class CommandCSMode : public Command if (!ci || !cm || cm->type != MODE_STATUS) return false; - const Anope::string accesses[] = { "VOICE", "HALFOP", "OPDEOP", "PROTECT", "OWNER", "" }, - accesses_self[] = { "VOICEME", "HALFOPME", "OPDEOPME", "PROTECTME", "OWNERME", "" }; - const Anope::string modes[] = { "VOICE", "HALFOP", "OP", "PROTECT", "OWNER" }; - ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); - AccessGroup access = source.AccessFor(ci); - short u_level = -1; - - for (int i = 0; !accesses[i].empty(); ++i) - if (access.HasPriv(self ? accesses_self[i] : accesses[i])) - { - ChannelMode *cm2 = ModeManager::FindChannelModeByName(modes[i]); - if (cm2 == NULL || cm2->type != MODE_STATUS) - continue; - ChannelModeStatus *cms2 = anope_dynamic_static_cast<ChannelModeStatus *>(cm2); - if (cms2->level > u_level) - u_level = cms2->level; - } - - return u_level >= cms->level; + return source.AccessFor(ci).HasPriv(cm->name + (self ? "ME" : "")); } void DoLock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) diff --git a/modules/extra/cs_statusupdate.cpp b/modules/extra/cs_statusupdate.cpp index 4a53956d7..934b928d1 100644 --- a/modules/extra/cs_statusupdate.cpp +++ b/modules/extra/cs_statusupdate.cpp @@ -7,19 +7,6 @@ #include "module.h" -static struct ModeInfo -{ - Anope::string priv; - Anope::string name; -} modeInfo[] = { - { "AUTOOWNER", "OWNER" }, - { "AUTOPROTECT", "PROTECT" }, - { "AUTOOP", "OP" }, - { "AUTOHALFOP", "HALFOP" }, - { "AUTOVOICE", "VOICE" }, - { "", "" } -}; - class StatusUpdate : public Module { public: @@ -38,11 +25,14 @@ class StatusUpdate : public Module { User *user = it->second->user; - if (access->Matches(user, user->Account())) + if (user->server != Me && access->Matches(user, user->Account())) { - for (int i = 0; !modeInfo[i].priv.empty(); ++i) - if (!access->HasPriv(modeInfo[i].priv)) - ci->c->RemoveMode(NULL, modeInfo[i].name, user->nick); + for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i) + { + ChannelModeStatus *cms = ModeManager::GetStatusChannelModesByRank()[i]; + if (!access->HasPriv("AUTO" + cms->name)) + ci->c->RemoveMode(NULL, cms, user->GetUID()); + } ci->c->SetCorrectModes(user, true, false); } } @@ -55,11 +45,20 @@ class StatusUpdate : public Module { User *user = it->second->user; - if (access->Matches(user, user->Account())) + if (user->server != Me && access->Matches(user, user->Account())) { - for (int i = 0; !modeInfo[i].priv.empty(); ++i) - if (access->HasPriv(modeInfo[i].priv)) - ci->c->RemoveMode(NULL, modeInfo[i].name, user->nick); + /* Get user's current access and remove the entry about to be deleted */ + AccessGroup ag = ci->AccessFor(user); + AccessGroup::iterator iter = std::find(ag.begin(), ag.end(), access); + if (iter != ag.end()) + ag.erase(iter); + + for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i) + { + ChannelModeStatus *cms = ModeManager::GetStatusChannelModesByRank()[i]; + if (!ag.HasPriv("AUTO" + cms->name)) + ci->c->RemoveMode(NULL, cms, user->GetUID()); + } } } } diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index b6cb905c2..34b807983 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -531,6 +531,8 @@ struct IRCDMessageCapab : Message::Capab ModeManager::AddChannelMode(new ChannelModeStatus("", modes[t], chars[t], level--)); } } + + ModeManager::RebuildStatusModes(); } else if (capab.find("MAXMODES=") != Anope::string::npos) { diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index deb7bbbf1..dcabbac7f 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -717,6 +717,8 @@ struct IRCDMessageCapab : Message::Capab ModeManager::AddChannelMode(new ChannelModeStatus("", modes[t], chars[t], level--)); } } + + ModeManager::RebuildStatusModes(); } else if (capab.find("MAXMODES=") != Anope::string::npos) { diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 0af696bf0..ac970ddf9 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -469,7 +469,11 @@ struct IRCDMessageCapab : Message::Capab ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); cms->level = level--; + + Log(LOG_DEBUG) << cms->name << " is now level " << cms->level; } + + ModeManager::RebuildStatusModes(); } } } diff --git a/src/channels.cpp b/src/channels.cpp index f3a061e94..62c6462d6 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -922,13 +922,6 @@ void Channel::Hold() void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop) { - ChannelMode *owner = ModeManager::FindChannelModeByName("OWNER"), - *admin = ModeManager::FindChannelModeByName("PROTECT"), - *op = ModeManager::FindChannelModeByName("OP"), - *halfop = ModeManager::FindChannelModeByName("HALFOP"), - *voice = ModeManager::FindChannelModeByName("VOICE"), - *registered = ModeManager::FindChannelModeByName("REGISTERED"); - if (user == NULL) return; @@ -938,39 +931,33 @@ void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop) Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << this->name << " (" << (give_modes ? "" : "not ") << "giving modes)"; AccessGroup u_access = ci->AccessFor(user); + ChannelMode *registered = ModeManager::FindChannelModeByName("REGISTERED"); - if (give_modes && (!user->Account() || user->Account()->HasExt("AUTOOP")) && (!check_noop || !ci->HasExt("NOAUTOOP"))) - { - if (owner && u_access.HasPriv("AUTOOWNER")) - this->SetMode(NULL, owner, user->GetUID()); - else if (admin && u_access.HasPriv("AUTOPROTECT")) - this->SetMode(NULL, admin, user->GetUID()); - - if (op && u_access.HasPriv("AUTOOP")) - this->SetMode(NULL, op, user->GetUID()); - else if (halfop && u_access.HasPriv("AUTOHALFOP")) - this->SetMode(NULL, halfop, user->GetUID()); - else if (voice && u_access.HasPriv("AUTOVOICE")) - this->SetMode(NULL, voice, user->GetUID()); - } + /* Only give modes if autoop isn't set */ + give_modes &= (!user->Account() || user->Account()->HasExt("AUTOOP")) && (!check_noop || !ci->HasExt("NOAUTOOP")); /* If this channel has secureops, or the registered channel mode exists and the channel does not have +r set (aka the channel * was created just now or while we were off), or the registered channel mode does not exist and channel is syncing (aka just * created *to us*) and the user's server is synced (aka this isn't us doing our initial uplink - without this we would be deopping all * users with no access on a non-secureops channel on startup), and the user's server isn't ulined, then set negative modes. */ - if ((ci->HasExt("SECUREOPS") || (registered && !this->HasMode("REGISTERED")) || (!registered && this->HasExt("SYNCING") && user->server->IsSynced())) && !user->server->IsULined()) - { - if (owner && !u_access.HasPriv("AUTOOWNER") && !u_access.HasPriv("OWNERME")) - this->RemoveMode(NULL, owner, user->GetUID()); + bool take_modes = (ci->HasExt("SECUREOPS") || (registered && !this->HasMode("REGISTERED")) || (!registered && this->HasExt("SYNCING") && user->server->IsSynced())) && !user->server->IsULined(); - if (admin && !u_access.HasPriv("AUTOPROTECT") && !u_access.HasPriv("PROTECTME")) - this->RemoveMode(NULL, admin, user->GetUID()); - - if (op && this->HasUserStatus(user, "OP") && !u_access.HasPriv("AUTOOP") && !u_access.HasPriv("OPDEOPME")) - this->RemoveMode(NULL, op, user->GetUID()); + bool given = false; + for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i) + { + ChannelModeStatus *cm = ModeManager::GetStatusChannelModesByRank()[i]; + bool has_priv = u_access.HasPriv("AUTO" + cm->name); - if (halfop && !u_access.HasPriv("AUTOHALFOP") && !u_access.HasPriv("HALFOPME")) - this->RemoveMode(NULL, halfop, user->GetUID()); + /* If we have already given one mode, don't give more until it has a symbol */ + if (give_modes && has_priv && (!given || cm->symbol)) + { + this->SetMode(NULL, cm, user->GetUID()); + /* Now if this contains a symbol don't give any more modes, to prevent setting +qaohv etc on users */ + give_modes = !cm->symbol; + given = true; + } + else if (take_modes && !has_priv) + this->RemoveMode(NULL, cm, user->GetUID()); } // Check mlock diff --git a/src/config.cpp b/src/config.cpp index 4d1267f23..d49d9e8d9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -812,18 +812,13 @@ static bool InitPrivileges(ServerConfig *config, const Anope::string &) static bool DoPrivileges(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) { Anope::string name = values[0].GetValue(); - Anope::string desc = values[1].GetValue(); - int rank = values[2].GetInteger(); + int rank = values[1].GetInteger(); ValueItem vi(name); if (!ValidateNotEmpty(config, "privilege", "name", vi)) throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); - vi = ValueItem(desc); - if (!ValidateNotEmpty(config, "privilege", "desc", vi)) - throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); - - PrivilegeManager::AddPrivilege(Privilege(name, desc, rank)); + PrivilegeManager::AddPrivilege(Privilege(name, "", rank)); return true; } diff --git a/src/modes.cpp b/src/modes.cpp index a1ecdbfee..6cdeb6565 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -25,6 +25,9 @@ std::vector<UserMode *> ModeManager::UserModes; static std::map<Anope::string, ChannelMode *> ChannelModesByName; static std::map<Anope::string, UserMode *> UserModesByName; +/* Sorted by status */ +static std::vector<ChannelModeStatus *> ChannelModesByStatus; + /* Number of generic modes we support */ unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0; @@ -349,6 +352,8 @@ bool ModeManager::AddChannelMode(ChannelMode *cm) if (want >= ModeManager::ChannelModes.size()) ModeManager::ChannelModes.resize(want + 1); ModeManager::ChannelModes[want] = cms; + + RebuildStatusModes(); } ChannelModesByName[cm->name] = cm; @@ -406,6 +411,8 @@ void ModeManager::RemoveChannelMode(ChannelMode *cm) return; ModeManager::ChannelModes[want] = NULL; + + RebuildStatusModes(); } ChannelModesByName.erase(cm->name); @@ -470,6 +477,32 @@ const std::vector<UserMode *> &ModeManager::GetUserModes() return UserModes; } +const std::vector<ChannelModeStatus *> &ModeManager::GetStatusChannelModesByRank() +{ + return ChannelModesByStatus; +} + +static struct StatusSort +{ + bool operator()(ChannelModeStatus *cm1, ChannelModeStatus *cm2) const + { + return cm1->level > cm2->level; + } +} statuscmp; + +void ModeManager::RebuildStatusModes() +{ + ChannelModesByStatus.clear(); + for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j) + { + ChannelMode *cm = ModeManager::GetChannelModes()[j]; + + if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end()) + ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm)); + } + std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp); +} + void ModeManager::StackerAdd(const BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param) { StackerInfo *s = GetInfo(ChannelStackerObjects, c); |