mirror of
https://github.com/anope/anope.git
synced 2026-06-26 03:06:38 +02:00
Add "virtual mode" support
This allows fully tracking extbans and other modes set by a different underlying mode, such as InspIRCd's namedmodes Add two configuration options to cs_ban to configure which mode is set and whether or not to kick banned users. Add default "mute" fantasy command to botserv.example.conf
This commit is contained in:
+123
-37
@@ -21,9 +21,15 @@ struct StackerInfo;
|
||||
static std::map<User *, StackerInfo *> UserStackerObjects;
|
||||
static std::map<Channel *, StackerInfo *> ChannelStackerObjects;
|
||||
|
||||
/* List of all modes Anope knows about */
|
||||
std::vector<ChannelMode *> ModeManager::ChannelModes;
|
||||
std::vector<UserMode *> ModeManager::UserModes;
|
||||
/* Array of all modes Anope knows about.*/
|
||||
static std::vector<ChannelMode *> ChannelModes;
|
||||
static std::vector<UserMode *> UserModes;
|
||||
|
||||
/* Modes are in this array are at position
|
||||
* modechar. Additionally, status modes are in this array (again) at statuschar.
|
||||
*/
|
||||
static std::vector<ChannelMode *> ChannelModesIdx;
|
||||
static std::vector<UserMode *> UserModesIdx;
|
||||
|
||||
static std::map<Anope::string, ChannelMode *> ChannelModesByName;
|
||||
static std::map<Anope::string, UserMode *> UserModesByName;
|
||||
@@ -142,6 +148,28 @@ bool ChannelMode::CanSet(User *u) const
|
||||
return MOD_RESULT != EVENT_STOP;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Wrap(Anope::string ¶m)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Unwrap(Anope::string ¶m)
|
||||
{
|
||||
for (unsigned i = 0; i < listeners.size(); ++i)
|
||||
{
|
||||
ChannelMode *cm = listeners[i]->Unwrap(this, param);
|
||||
if (cm != this)
|
||||
return cm;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Unwrap(ChannelMode *, Anope::string ¶m)
|
||||
{
|
||||
throw CoreException("Unwrap in channel mode");
|
||||
}
|
||||
|
||||
ChannelModeList::ChannelModeList(const Anope::string &cm, char mch) : ChannelMode(cm, mch)
|
||||
{
|
||||
this->type = MODE_LIST;
|
||||
@@ -157,6 +185,42 @@ ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar,
|
||||
this->type = MODE_STATUS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelModeVirtual<T>::ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename) : T(mname, 0)
|
||||
, base(basename)
|
||||
{
|
||||
basech = ModeManager::FindChannelModeByName(base);
|
||||
if (basech)
|
||||
basech->listeners.push_back(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelModeVirtual<T>::~ChannelModeVirtual()
|
||||
{
|
||||
if (basech)
|
||||
{
|
||||
std::vector<ChannelMode *>::iterator it = std::find(basech->listeners.begin(), basech->listeners.end(), this);
|
||||
if (it != basech->listeners.end())
|
||||
basech->listeners.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string ¶m)
|
||||
{
|
||||
if (basech == NULL)
|
||||
{
|
||||
basech = ModeManager::FindChannelModeByName(base);
|
||||
if (basech)
|
||||
basech->listeners.push_back(this);
|
||||
}
|
||||
|
||||
return basech;
|
||||
}
|
||||
|
||||
template class ChannelModeVirtual<ChannelMode>;
|
||||
template class ChannelModeVirtual<ChannelModeList>;
|
||||
|
||||
bool UserModeOperOnly::CanSet(User *u) const
|
||||
{
|
||||
return u && u->HasMode("OPER");
|
||||
@@ -321,6 +385,8 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
{
|
||||
if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
|
||||
return false;
|
||||
if (ModeManager::FindUserModeByName(um->name) != NULL)
|
||||
return false;
|
||||
|
||||
if (um->name.empty())
|
||||
{
|
||||
@@ -329,12 +395,14 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
}
|
||||
|
||||
unsigned want = um->mchar;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
ModeManager::UserModes.resize(want + 1);
|
||||
ModeManager::UserModes[want] = um;
|
||||
if (want >= UserModesIdx.size())
|
||||
UserModesIdx.resize(want + 1);
|
||||
UserModesIdx[want] = um;
|
||||
|
||||
UserModesByName[um->name] = um;
|
||||
|
||||
UserModes.push_back(um);
|
||||
|
||||
FOREACH_MOD(OnUserModeAdd, (um));
|
||||
|
||||
return true;
|
||||
@@ -342,7 +410,9 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
|
||||
bool ModeManager::AddChannelMode(ChannelMode *cm)
|
||||
{
|
||||
if (ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
|
||||
if (cm->mchar && ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
|
||||
return false;
|
||||
if (ModeManager::FindChannelModeByName(cm->name) != NULL)
|
||||
return false;
|
||||
|
||||
if (cm->name.empty())
|
||||
@@ -351,24 +421,29 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
|
||||
Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
|
||||
}
|
||||
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
ModeManager::ChannelModes.resize(want + 1);
|
||||
ModeManager::ChannelModes[want] = cm;
|
||||
if (cm->mchar)
|
||||
{
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
ChannelModesIdx.resize(want + 1);
|
||||
ChannelModesIdx[want] = cm;
|
||||
}
|
||||
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
|
||||
want = cms->symbol;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
ModeManager::ChannelModes.resize(want + 1);
|
||||
ModeManager::ChannelModes[want] = cms;
|
||||
unsigned want = cms->symbol;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
ChannelModesIdx.resize(want + 1);
|
||||
ChannelModesIdx[want] = cms;
|
||||
|
||||
RebuildStatusModes();
|
||||
}
|
||||
|
||||
ChannelModesByName[cm->name] = cm;
|
||||
|
||||
ChannelModes.push_back(cm);
|
||||
|
||||
FOREACH_MOD(OnChannelModeAdd, (cm));
|
||||
|
||||
return true;
|
||||
@@ -378,18 +453,22 @@ void ModeManager::RemoveUserMode(UserMode *um)
|
||||
{
|
||||
if (!um)
|
||||
return;
|
||||
|
||||
|
||||
unsigned want = um->mchar;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
if (want >= UserModesIdx.size())
|
||||
return;
|
||||
|
||||
if (ModeManager::UserModes[want] != um)
|
||||
if (UserModesIdx[want] != um)
|
||||
return;
|
||||
|
||||
ModeManager::UserModes[want] = NULL;
|
||||
UserModesIdx[want] = NULL;
|
||||
|
||||
UserModesByName.erase(um->name);
|
||||
|
||||
std::vector<UserMode *>::iterator it = std::find(UserModes.begin(), UserModes.end(), um);
|
||||
if (it != UserModes.end())
|
||||
UserModes.erase(it);
|
||||
|
||||
StackerDel(um);
|
||||
}
|
||||
|
||||
@@ -397,53 +476,60 @@ void ModeManager::RemoveChannelMode(ChannelMode *cm)
|
||||
{
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
if (cm->mchar)
|
||||
{
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return;
|
||||
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
return;
|
||||
if (ChannelModesIdx[want] != cm)
|
||||
return;
|
||||
|
||||
if (ModeManager::ChannelModes[want] != cm)
|
||||
return;
|
||||
|
||||
ModeManager::ChannelModes[want] = NULL;
|
||||
ChannelModesIdx[want] = NULL;
|
||||
}
|
||||
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
|
||||
want = cms->symbol;
|
||||
unsigned want = cms->symbol;
|
||||
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return;
|
||||
|
||||
if (ModeManager::ChannelModes[want] != cm)
|
||||
if (ChannelModesIdx[want] != cm)
|
||||
return;
|
||||
|
||||
ModeManager::ChannelModes[want] = NULL;
|
||||
ChannelModesIdx[want] = NULL;
|
||||
|
||||
RebuildStatusModes();
|
||||
}
|
||||
|
||||
ChannelModesByName.erase(cm->name);
|
||||
|
||||
std::vector<ChannelMode *>::iterator it = std::find(ChannelModes.begin(), ChannelModes.end(), cm);
|
||||
if (it != ChannelModes.end())
|
||||
ChannelModes.erase(it);
|
||||
|
||||
StackerDel(cm);
|
||||
}
|
||||
|
||||
ChannelMode *ModeManager::FindChannelModeByChar(char mode)
|
||||
{
|
||||
unsigned want = mode;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return NULL;
|
||||
|
||||
return ModeManager::ChannelModes[want];
|
||||
return ChannelModesIdx[want];
|
||||
}
|
||||
|
||||
UserMode *ModeManager::FindUserModeByChar(char mode)
|
||||
{
|
||||
unsigned want = mode;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
if (want >= UserModesIdx.size())
|
||||
return NULL;
|
||||
|
||||
return ModeManager::UserModes[want];
|
||||
return UserModesIdx[want];
|
||||
}
|
||||
|
||||
ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name)
|
||||
@@ -465,10 +551,10 @@ UserMode *ModeManager::FindUserModeByName(const Anope::string &name)
|
||||
char ModeManager::GetStatusChar(char value)
|
||||
{
|
||||
unsigned want = value;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return 0;
|
||||
|
||||
ChannelMode *cm = ModeManager::ChannelModes[want];
|
||||
ChannelMode *cm = ChannelModesIdx[want];
|
||||
if (cm == NULL || cm->type != MODE_STATUS || cm->mchar == value)
|
||||
return 0;
|
||||
|
||||
@@ -505,7 +591,7 @@ void ModeManager::RebuildStatusModes()
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
|
||||
if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
|
||||
if (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);
|
||||
|
||||
Reference in New Issue
Block a user