mirror of
https://github.com/anope/anope.git
synced 2026-06-12 19:14:47 +02:00
Store the setter and ts for all modes and try to restore them.
This is mostly for preserving channel list mode info.
This commit is contained in:
+1
-1
@@ -151,7 +151,7 @@ public:
|
||||
/* The time this account was registered */
|
||||
time_t registered = Anope::CurTime;
|
||||
MemoInfo memos;
|
||||
std::map<Anope::string, Anope::string> last_modes;
|
||||
std::map<Anope::string, ModeData> last_modes;
|
||||
|
||||
/* Nicknames registered that are grouped to this account.
|
||||
* for n in aliases, n->nc == this.
|
||||
|
||||
+7
-7
@@ -36,7 +36,7 @@ class CoreExport Channel final
|
||||
static std::vector<Channel *> deleting;
|
||||
|
||||
public:
|
||||
typedef std::multimap<Anope::string, Anope::string> ModeList;
|
||||
typedef std::multimap<Anope::string, ModeData> ModeList;
|
||||
private:
|
||||
/** A map of channel modes with their parameters set on this channel
|
||||
*/
|
||||
@@ -148,10 +148,10 @@ public:
|
||||
/** Set a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The setter
|
||||
* @param cm The mode
|
||||
* @param param The param
|
||||
* @param data Data about the mode.
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetModeInternal(MessageSource &source, ChannelMode *cm, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/** Remove a mode internally on a channel, this is not sent out to the IRCd
|
||||
* @param setter The Setter
|
||||
@@ -164,19 +164,19 @@ public:
|
||||
/** Set a mode on a channel
|
||||
* @param bi The client setting the modes
|
||||
* @param cm The mode
|
||||
* @param param Optional param arg for the mode
|
||||
* @param data Data about the mode
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetMode(BotInfo *bi, ChannelMode *cm, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/**
|
||||
* Set a mode on a channel
|
||||
* @param bi The client setting the modes
|
||||
* @param name The mode name
|
||||
* @param param Optional param arg for the mode
|
||||
* @param data Data about the mode
|
||||
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
|
||||
*/
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m = "", bool enforce_mlock = true);
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const ModeData &data = {}, bool enforce_mlock = true);
|
||||
|
||||
/** Remove a mode from a channel
|
||||
* @param bi The client setting the modes
|
||||
|
||||
@@ -19,6 +19,7 @@ class ChanAccess;
|
||||
class Channel;
|
||||
class ChannelInfo;
|
||||
class ChannelStatus;
|
||||
struct ModeData;
|
||||
struct ChanUserContainer;
|
||||
class ClientSocket;
|
||||
class Command;
|
||||
|
||||
+19
-4
@@ -33,6 +33,20 @@ enum ModeClass
|
||||
MC_USER
|
||||
};
|
||||
|
||||
struct ModeData final
|
||||
{
|
||||
Anope::string value;
|
||||
Anope::string set_by;
|
||||
time_t set_at;
|
||||
|
||||
ModeData(const Anope::string &v = "", const Anope::string &s = "", time_t t = 0)
|
||||
: value(v)
|
||||
, set_by(s)
|
||||
, set_at(t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** This class is the basis of all modes in Anope
|
||||
*/
|
||||
class CoreExport Mode
|
||||
@@ -311,6 +325,7 @@ public:
|
||||
class CoreExport ModeManager final
|
||||
{
|
||||
public:
|
||||
using Change = std::multimap<Mode *, std::pair<bool, ModeData>>;
|
||||
|
||||
/* Number of generic channel and user modes we are tracking */
|
||||
static unsigned GenericChannelModes;
|
||||
@@ -378,18 +393,18 @@ public:
|
||||
* @param c The channel
|
||||
* @param cm The channel mode
|
||||
* @param set true for setting, false for removing
|
||||
* @param param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const Anope::string ¶m = "");
|
||||
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const ModeData &data = {});
|
||||
|
||||
/** Add a mode to the stacker to be set on a user
|
||||
* @param bi The client to set the modes from
|
||||
* @param u The user
|
||||
* @param um The user mode
|
||||
* @param set true for setting, false for removing
|
||||
* @param param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
static void StackerAdd(BotInfo *bi, User *u, UserMode *um, bool set, const Anope::string ¶m = "");
|
||||
static void StackerAdd(BotInfo *bi, User *u, UserMode *um, bool set, const ModeData &data = {});
|
||||
|
||||
/** Process all of the modes in the stacker and send them to the IRCd to be set on channels/users
|
||||
*/
|
||||
|
||||
+2
-2
@@ -871,10 +871,10 @@ public:
|
||||
* @param c The channel
|
||||
* @param setter The user or server that is setting the mode
|
||||
* @param mode The mode
|
||||
* @param param The mode param, if there is one
|
||||
* @param data Data about the mode.
|
||||
* @return EVENT_STOP to make mlock/secureops etc checks not happen
|
||||
*/
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
|
||||
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
|
||||
|
||||
/** Called when a mode is unset on a channel
|
||||
* @param c The channel
|
||||
|
||||
@@ -195,8 +195,10 @@ public:
|
||||
*/
|
||||
virtual void SendSVSKill(const MessageSource &source, User *user, const Anope::string &msg);
|
||||
|
||||
virtual void SendMode(const MessageSource &source, Channel *chan, const ModeManager::Change &change);
|
||||
virtual void SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values);
|
||||
|
||||
virtual void SendMode(const MessageSource &source, User *u, const ModeManager::Change &change);
|
||||
virtual void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values);
|
||||
|
||||
/** Introduces a client to the rest of the network
|
||||
|
||||
+7
-7
@@ -39,7 +39,7 @@ class CoreExport User
|
||||
static std::list<User *> quitting_users;
|
||||
|
||||
public:
|
||||
typedef std::map<Anope::string, Anope::string> ModeList;
|
||||
typedef std::map<Anope::string, ModeData> ModeList;
|
||||
protected:
|
||||
Anope::string vident;
|
||||
Anope::string ident;
|
||||
@@ -261,9 +261,9 @@ public:
|
||||
/** Set a mode internally on the user, the IRCd is not informed
|
||||
* @param setter who/what is setting the mode
|
||||
* @param um The user mode
|
||||
* @param Param The param, if there is one
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
void SetModeInternal(const MessageSource &setter, UserMode *um, const Anope::string ¶m = "");
|
||||
void SetModeInternal(const MessageSource &setter, UserMode *um, const ModeData &data = {});
|
||||
|
||||
/** Remove a mode internally on the user, the IRCd is not informed
|
||||
* @param setter who/what is setting the mode
|
||||
@@ -274,16 +274,16 @@ public:
|
||||
/** Set a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
* @param um The user mode
|
||||
* @param Param Optional param for the mode
|
||||
* @param data Data about the mode
|
||||
*/
|
||||
void SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m = "");
|
||||
void SetMode(BotInfo *bi, UserMode *um, const ModeData &data = {});
|
||||
|
||||
/** Set a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
* @param name The mode name
|
||||
* @param Param Optional param for the mode
|
||||
* @param data Data about the mode
|
||||
*/
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m = "");
|
||||
void SetMode(BotInfo *bi, const Anope::string &name, const ModeData &data = {});
|
||||
|
||||
/** Remove a mode on the user
|
||||
* @param bi The client setting the mode
|
||||
|
||||
@@ -196,15 +196,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this).Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
{
|
||||
BotInfo *bi = c->ci->bi;
|
||||
|
||||
Entry ban("BAN", param);
|
||||
Entry ban("BAN", data.value);
|
||||
if (ban.Matches(bi))
|
||||
c->RemoveMode(bi, "BAN", param);
|
||||
c->RemoveMode(bi, "BAN", data.value);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
@@ -309,7 +309,7 @@ public:
|
||||
return;
|
||||
|
||||
if (c->ci)
|
||||
c->SetMode(c->ci->WhoSends(), "REGISTERED", "", false);
|
||||
c->SetMode(c->ci->WhoSends(), "REGISTERED", {}, false);
|
||||
else
|
||||
c->RemoveMode(c->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
@@ -461,7 +461,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (!always_lower && Anope::CurTime == c->created && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
|
||||
{
|
||||
@@ -470,7 +470,7 @@ public:
|
||||
if (cu && cm && !cu->status.HasMode(cm->mchar))
|
||||
{
|
||||
/* Our -o and their mode change crossing, bounce their mode */
|
||||
c->RemoveMode(c->ci->WhoSends(), mode, param);
|
||||
c->RemoveMode(c->ci->WhoSends(), mode, data.value);
|
||||
/* We don't set mlocks until after the join has finished processing, it will stack with this change,
|
||||
* so there isn't much for the user to remove except -nt etc which is likely locked anyway.
|
||||
*/
|
||||
|
||||
@@ -1008,7 +1008,7 @@ public:
|
||||
if (cm->type == MODE_REGULAR)
|
||||
{
|
||||
if (!c->HasMode(cm->name) && ml->set)
|
||||
c->SetMode(NULL, cm, "", false);
|
||||
c->SetMode(NULL, cm, {}, false);
|
||||
else if (c->HasMode(cm->name) && !ml->set)
|
||||
c->RemoveMode(NULL, cm, "", false);
|
||||
}
|
||||
|
||||
+37
-10
@@ -1121,13 +1121,19 @@ class CSSet final
|
||||
|
||||
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(s);
|
||||
Anope::string modes;
|
||||
for (const auto &[last_mode, last_value] : ci->last_modes)
|
||||
for (const auto &[last_mode, last_data] : ci->last_modes)
|
||||
{
|
||||
if (!modes.empty())
|
||||
modes += " ";
|
||||
|
||||
modes += '+';
|
||||
modes += last_mode;
|
||||
if (!last_value.empty())
|
||||
modes += "," + last_value;
|
||||
if (!last_data.value.empty())
|
||||
{
|
||||
modes += "," + Anope::ToString(last_data.set_at);
|
||||
modes += "," + last_data.set_by;
|
||||
modes += "," + last_data.value;
|
||||
}
|
||||
}
|
||||
data.Store("last_modes", modes);
|
||||
}
|
||||
@@ -1145,11 +1151,32 @@ class CSSet final
|
||||
ci->last_modes.clear();
|
||||
for (spacesepstream sep(modes); sep.GetToken(modes);)
|
||||
{
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
ci->last_modes.emplace(modes, "");
|
||||
if (modes[0] == '+')
|
||||
{
|
||||
commasepstream mode(modes, true);
|
||||
mode.GetToken(modes);
|
||||
modes.erase(0, 1);
|
||||
|
||||
ModeData info;
|
||||
Anope::string set_at;
|
||||
mode.GetToken(set_at);
|
||||
info.set_at = Anope::Convert(set_at, 0);
|
||||
mode.GetToken(info.set_by);
|
||||
info.value = mode.GetRemaining();
|
||||
|
||||
ci->last_modes.emplace(modes, info);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
ci->last_modes.emplace(modes.substr(0, c), modes.substr(c + 1));
|
||||
{
|
||||
// Begin 2.0 compatibility
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
ci->last_modes.emplace(modes, ModeData());
|
||||
else
|
||||
ci->last_modes.emplace(modes.substr(0, c), ModeData(modes.substr(c + 1)));
|
||||
// End 2.0 compatibility.
|
||||
}
|
||||
}
|
||||
}
|
||||
} keep_modes;
|
||||
@@ -1207,8 +1234,8 @@ public:
|
||||
if (c->ci && keep_modes.HasExt(c->ci))
|
||||
{
|
||||
Channel::ModeList ml = c->ci->last_modes;
|
||||
for (const auto &[last_mode, last_value] : ml)
|
||||
c->SetMode(c->ci->WhoSends(), last_mode, last_value);
|
||||
for (const auto &[last_mode, last_data] : ml)
|
||||
c->SetMode(c->ci->WhoSends(), last_mode, last_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,7 +1257,7 @@ public:
|
||||
persist.Unset(ci);
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (c->ci)
|
||||
{
|
||||
|
||||
@@ -540,7 +540,7 @@ public:
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
this->OnModeChange(c, setter.GetUser());
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
@@ -84,14 +84,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ModeData final
|
||||
struct ModeLockData final
|
||||
{
|
||||
char letter;
|
||||
Anope::string name;
|
||||
Anope::string value;
|
||||
bool set;
|
||||
|
||||
ModeData(const Anope::string &n, bool s, const Anope::string &v = "")
|
||||
ModeLockData(const Anope::string &n, bool s, const Anope::string &v = "")
|
||||
: letter(0)
|
||||
, name(n)
|
||||
, value(v)
|
||||
@@ -99,7 +99,7 @@ struct ModeData final
|
||||
{
|
||||
}
|
||||
|
||||
ModeData(char l, const Anope::string &v = "")
|
||||
ModeLockData(char l, const Anope::string &v = "")
|
||||
: letter(l)
|
||||
, value(v)
|
||||
, set(true)
|
||||
@@ -123,7 +123,7 @@ struct ChannelData final
|
||||
Anope::string info_adder;
|
||||
Anope::string info_message;
|
||||
time_t info_ts = 0;
|
||||
std::vector<ModeData> mlocks;
|
||||
std::vector<ModeLockData> mlocks;
|
||||
Anope::string suspend_by;
|
||||
Anope::string suspend_reason;
|
||||
time_t suspend_ts = 0;
|
||||
|
||||
@@ -16,11 +16,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (mode->name == "OP" && c && c->ci && c->name.equals_ci(Config->GetModule(this).Get<const Anope::string>("helpchannel")))
|
||||
{
|
||||
User *u = User::Find(param);
|
||||
User *u = User::Find(data.value);
|
||||
|
||||
if (u && c->ci->AccessFor(u).HasPriv("OPME"))
|
||||
u->SetMode(Config->GetClient("OperServ"), "HELPOP");
|
||||
|
||||
@@ -232,11 +232,11 @@ void IRC2SQL::OnJoinChannel(User *u, Channel *c)
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
EventReturn IRC2SQL::OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m)
|
||||
EventReturn IRC2SQL::OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data)
|
||||
{
|
||||
if (mode->type == MODE_STATUS)
|
||||
{
|
||||
User *u = User::Find(param);
|
||||
User *u = User::Find(data.value);
|
||||
if (u == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
void OnChannelDelete(Channel *c) override;
|
||||
void OnLeaveChannel(User *u, Channel *c) override;
|
||||
void OnJoinChannel(User *u, Channel *c) override;
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override;
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override;
|
||||
EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override;
|
||||
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override;
|
||||
|
||||
@@ -128,13 +128,19 @@ private:
|
||||
|
||||
const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(s);
|
||||
Anope::string modes;
|
||||
for (const auto &[last_mode, last_value] : nc->last_modes)
|
||||
for (const auto &[last_mode, last_data] : nc->last_modes)
|
||||
{
|
||||
if (!modes.empty())
|
||||
modes += " ";
|
||||
|
||||
modes += '+';
|
||||
modes += last_mode;
|
||||
if (!last_value.empty())
|
||||
modes += "," + last_value;
|
||||
if (!last_data.value.empty())
|
||||
{
|
||||
modes += "," + Anope::ToString(last_data.set_at);
|
||||
modes += "," + last_data.set_by;
|
||||
modes += "," + last_data.value;
|
||||
}
|
||||
}
|
||||
data.Store("last_modes", modes);
|
||||
}
|
||||
@@ -152,11 +158,32 @@ private:
|
||||
nc->last_modes.clear();
|
||||
for (spacesepstream sep(modes); sep.GetToken(modes);)
|
||||
{
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
nc->last_modes.emplace(modes, "");
|
||||
if (modes[0] == '+')
|
||||
{
|
||||
commasepstream mode(modes, true);
|
||||
mode.GetToken(modes);
|
||||
modes.erase(0, 1);
|
||||
|
||||
ModeData info;
|
||||
Anope::string set_at;
|
||||
mode.GetToken(set_at);
|
||||
info.set_at = Anope::Convert(set_at, 0);
|
||||
mode.GetToken(info.set_by);
|
||||
info.value = mode.GetRemaining();
|
||||
|
||||
nc->last_modes.emplace(modes, info);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
nc->last_modes.emplace(modes.substr(0, c), modes.substr(c + 1));
|
||||
{
|
||||
// Begin 2.0 compatibility
|
||||
size_t c = modes.find(',');
|
||||
if (c == Anope::string::npos)
|
||||
nc->last_modes.emplace(modes, ModeData());
|
||||
else
|
||||
nc->last_modes.emplace(modes.substr(0, c), ModeData(modes.substr(c + 1)));
|
||||
// End 2.0 compatibility.
|
||||
}
|
||||
}
|
||||
}
|
||||
} keep_modes;
|
||||
@@ -197,11 +224,11 @@ public:
|
||||
{
|
||||
const auto norestore = Config->GetModule(this).Get<const Anope::string>("norestore");
|
||||
User::ModeList modes = u->Account()->last_modes;
|
||||
for (const auto &[last_mode, last_value] : modes)
|
||||
for (const auto &[last_mode, last_data] : modes)
|
||||
{
|
||||
auto *um = ModeManager::FindUserModeByName(last_mode);
|
||||
if (um && um->CanSet(nullptr) && norestore.find(um->mchar) == Anope::string::npos)
|
||||
u->SetMode(nullptr, last_mode, last_value);
|
||||
u->SetMode(nullptr, last_mode, last_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,11 +407,11 @@ public:
|
||||
this->ParseModeString();
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) override
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const ModeData &data) override
|
||||
{
|
||||
if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOff.count(mode->name) && source.GetUser() && !source.GetBot())
|
||||
{
|
||||
c->RemoveMode(Config->GetClient("OperServ"), mode, param);
|
||||
c->RemoveMode(Config->GetClient("OperServ"), mode, data.value);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ public:
|
||||
{
|
||||
bool all = params.size() > 2 && params[2].equals_ci("ALL");
|
||||
|
||||
for (const auto &[mode, value] : c->GetModes())
|
||||
c->RemoveMode(c->WhoSends(), mode, value, false);
|
||||
for (const auto &[mode, data] : c->GetModes())
|
||||
c->RemoveMode(c->WhoSends(), mode, data.value, false);
|
||||
|
||||
if (!c)
|
||||
{
|
||||
|
||||
@@ -434,6 +434,41 @@ public:
|
||||
Uplink::SendInternal({}, Me, "NUM", newparams);
|
||||
}
|
||||
|
||||
void SendMode(const MessageSource &source, Channel *chan, const ModeManager::Change &change)
|
||||
{
|
||||
std::map<char, std::vector<Anope::string>> listchanges;
|
||||
ModeManager::Change otherchanges;
|
||||
|
||||
for (const auto &[mode, info] : change)
|
||||
{
|
||||
if (spanningtree_proto_ver >= 1206 && mode->type == MODE_LIST && info.first)
|
||||
{
|
||||
// Adding to a list mode.
|
||||
const auto &data = info.second;
|
||||
|
||||
auto &listchange = listchanges[mode->mchar];
|
||||
listchange.push_back(data.value);
|
||||
listchange.push_back(data.set_by);
|
||||
listchange.push_back(Anope::ToString(data.set_at));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular mode change or mode removal.
|
||||
otherchanges.emplace(mode, info);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &[mode, params] : listchanges)
|
||||
{
|
||||
// :<sid> LMODE <chan> <chants> <modechr> [<mask> <setter> <setts>]+
|
||||
params.insert(params.begin(), { chan->name, Anope::ToString(chan->created), Anope::ToString(mode) });
|
||||
Uplink::SendInternal({}, source, "LMODE", params);
|
||||
}
|
||||
|
||||
if (!otherchanges.empty())
|
||||
IRCDProto::SendMode(source, chan, otherchanges);
|
||||
}
|
||||
|
||||
void SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values) override
|
||||
{
|
||||
auto params = values;
|
||||
@@ -2310,7 +2345,7 @@ struct IRCDMessageLMode final
|
||||
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
// :<sid> LMODE <chan> <chants> <modechr> [<mask> <setts> <setter>]+
|
||||
// :<sid> LMODE <chan> <chants> <modechr> [<mask> <setter> <setts>]+
|
||||
auto *chan = Channel::Find(params[0]);
|
||||
if (!chan)
|
||||
return; // Channel doesn't exist.
|
||||
@@ -2327,10 +2362,14 @@ struct IRCDMessageLMode final
|
||||
if (params.size() % 3)
|
||||
return; // Invalid parameter count.
|
||||
|
||||
for (auto it = params.begin() + 3; it != params.end(); it += 3)
|
||||
for (auto it = params.begin() + 3; it != params.end(); )
|
||||
{
|
||||
// TODO: Anope doesn't store set time and setter for list modes yet.
|
||||
chan->SetModeInternal(source, cm, *it);
|
||||
ModeData data;
|
||||
data.value = *it++;
|
||||
data.set_by = *it++;
|
||||
data.set_at = Anope::Convert(*it++, 0);
|
||||
|
||||
chan->SetModeInternal(source, cm, data, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,15 +220,15 @@ public:
|
||||
}
|
||||
|
||||
std::vector<Anope::string> modelist = { "+" };
|
||||
for (const auto &[mname, mvalue] : c->GetModes())
|
||||
for (const auto &[mname, mdata] : c->GetModes())
|
||||
{
|
||||
auto *cm = ModeManager::FindChannelModeByName(mname);
|
||||
if (!cm || cm->type == MODE_LIST)
|
||||
continue;
|
||||
|
||||
modelist.front().push_back(cm->mchar);
|
||||
if (!mvalue.empty())
|
||||
modelist.push_back(mvalue);
|
||||
if (!mdata.value.empty())
|
||||
modelist.push_back(mdata.value);
|
||||
}
|
||||
auto &modes = root.ReplyArray("modes");
|
||||
for (const auto &modeparam : modelist)
|
||||
@@ -522,15 +522,15 @@ public:
|
||||
root.Reply("fingerprint", u->fingerprint);
|
||||
|
||||
std::vector<Anope::string> modelist = { "+" };
|
||||
for (const auto &[mname, mvalue] : u->GetModeList())
|
||||
for (const auto &[mname, mdata] : u->GetModeList())
|
||||
{
|
||||
auto *um = ModeManager::FindUserModeByName(mname);
|
||||
if (!um || um->type == MODE_LIST)
|
||||
continue;
|
||||
|
||||
modelist.front().push_back(um->mchar);
|
||||
if (!mvalue.empty())
|
||||
modelist.push_back(mvalue);
|
||||
if (!mdata.value.empty())
|
||||
modelist.push_back(mdata.value);
|
||||
}
|
||||
auto &modes = root.ReplyArray("modes");
|
||||
for (const auto &modeparam : modelist)
|
||||
|
||||
+53
-44
@@ -209,7 +209,7 @@ Anope::string Channel::GetModes(bool complete, bool plus)
|
||||
{
|
||||
Anope::string res, params;
|
||||
|
||||
for (const auto &[mode, value] : this->modes)
|
||||
for (const auto &[mode, data] : this->modes)
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
|
||||
if (!cm || cm->type == MODE_LIST)
|
||||
@@ -217,14 +217,14 @@ Anope::string Channel::GetModes(bool complete, bool plus)
|
||||
|
||||
res += cm->mchar;
|
||||
|
||||
if (complete && !value.empty())
|
||||
if (complete && !data.value.empty())
|
||||
{
|
||||
ChannelModeParam *cmp = NULL;
|
||||
if (cm->type == MODE_PARAM)
|
||||
cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
|
||||
|
||||
if (plus || !cmp || !cmp->minus_no_arg)
|
||||
params += " " + value;
|
||||
params += " " + data.value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,46 +236,42 @@ const Channel::ModeList &Channel::GetModes() const
|
||||
return this->modes;
|
||||
}
|
||||
|
||||
template<typename F, typename S>
|
||||
struct second final
|
||||
{
|
||||
S operator()(const std::pair<F, S> &p)
|
||||
{
|
||||
return p.second;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Anope::string> Channel::GetModeList(const Anope::string &mname)
|
||||
{
|
||||
std::vector<Anope::string> r;
|
||||
std::transform(modes.lower_bound(mname), modes.upper_bound(mname), std::back_inserter(r), second<Anope::string, Anope::string>());
|
||||
std::transform(modes.lower_bound(mname), modes.upper_bound(mname), std::back_inserter(r), [](const auto &mode) {
|
||||
return mode.second.value;
|
||||
});
|
||||
return r;
|
||||
}
|
||||
|
||||
void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
|
||||
void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const ModeData &data, bool enforce_mlock)
|
||||
{
|
||||
if (!ocm)
|
||||
return;
|
||||
|
||||
Anope::string param = oparam;
|
||||
ChannelMode *cm = ocm->Unwrap(param);
|
||||
// We build a mode data which has more than what the caller gives us.
|
||||
ModeData mdata;
|
||||
mdata.set_at = data.set_at ? data.set_at : Anope::CurTime;
|
||||
mdata.set_by = data.set_by.empty() ? setter.GetName() : data.set_by;
|
||||
mdata.value = data.value;
|
||||
auto *cm = ocm->Unwrap(mdata.value);
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
|
||||
/* Setting v/h/o/a/q etc */
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
if (param.empty())
|
||||
if (mdata.value.empty())
|
||||
{
|
||||
Log() << "Channel::SetModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name;
|
||||
return;
|
||||
}
|
||||
|
||||
User *u = User::Find(param);
|
||||
|
||||
auto *u = User::Find(mdata.value);
|
||||
if (!u)
|
||||
{
|
||||
Log(LOG_DEBUG) << "MODE " << this->name << " +" << cm->mchar << " for nonexistent user " << param;
|
||||
Log(LOG_DEBUG) << "MODE " << this->name << " +" << cm->mchar << " for nonexistent user " << mdata.value;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -286,7 +282,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
|
||||
if (cc)
|
||||
cc->status.AddMode(cm->mchar);
|
||||
|
||||
FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
|
||||
FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, data));
|
||||
|
||||
/* Enforce secureops, etc */
|
||||
if (enforce_mlock && MOD_RESULT != EVENT_STOP)
|
||||
@@ -296,12 +292,12 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
|
||||
|
||||
if (cm->type != MODE_LIST)
|
||||
this->modes.erase(cm->name);
|
||||
else if (this->HasMode(cm->name, param))
|
||||
else if (this->HasMode(cm->name, mdata.value))
|
||||
return;
|
||||
|
||||
this->modes.emplace(cm->name, param);
|
||||
this->modes.emplace(cm->name, mdata);
|
||||
|
||||
if (param.empty() && cm->type != MODE_REGULAR)
|
||||
if (mdata.value.empty() && cm->type != MODE_REGULAR)
|
||||
{
|
||||
Log() << "Channel::SetModeInternal() mode " << cm->mchar << " for " << this->name << " with no parameter, but is a param mode";
|
||||
return;
|
||||
@@ -310,10 +306,10 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
|
||||
if (cm->type == MODE_LIST)
|
||||
{
|
||||
ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
|
||||
cml->OnAdd(this, param);
|
||||
cml->OnAdd(this, mdata.value);
|
||||
}
|
||||
|
||||
FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
|
||||
FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, data));
|
||||
|
||||
/* Check if we should enforce mlock */
|
||||
if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
|
||||
@@ -368,7 +364,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
|
||||
if (cm->type == MODE_LIST)
|
||||
{
|
||||
for (Channel::ModeList::iterator it = modes.lower_bound(cm->name), it_end = modes.upper_bound(cm->name); it != it_end; ++it)
|
||||
if (param.equals_ci(it->second))
|
||||
if (param.equals_ci(it->second.value))
|
||||
{
|
||||
this->modes.erase(it);
|
||||
break;
|
||||
@@ -401,27 +397,33 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
|
||||
this->CheckModes();
|
||||
}
|
||||
|
||||
void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
|
||||
void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const ModeData &data, bool enforce_mlock)
|
||||
{
|
||||
Anope::string wparam = param;
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
// We build a mode data which has more than what the caller gives us.
|
||||
ModeData mdata;
|
||||
mdata.set_at = data.set_at ? data.set_at : Anope::CurTime;
|
||||
mdata.set_by = data.set_by.empty() && bi ? bi->nick : data.set_by;
|
||||
mdata.value = data.value;
|
||||
|
||||
/* Don't set modes already set */
|
||||
if (cm->type == MODE_REGULAR && HasMode(cm->name))
|
||||
return;
|
||||
else if (cm->type == MODE_PARAM)
|
||||
{
|
||||
ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
|
||||
if (!cmp->IsValid(wparam))
|
||||
if (!cmp->IsValid(mdata.value))
|
||||
return;
|
||||
|
||||
Anope::string cparam;
|
||||
if (GetParam(cm->name, cparam) && cparam.equals_cs(wparam))
|
||||
if (GetParam(cm->name, cparam) && cparam.equals_cs(mdata.value))
|
||||
return;
|
||||
}
|
||||
else if (cm->type == MODE_STATUS)
|
||||
{
|
||||
User *u = User::Find(param);
|
||||
User *u = User::Find(mdata.value);
|
||||
if (!u || HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
|
||||
return;
|
||||
}
|
||||
@@ -429,10 +431,10 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m,
|
||||
{
|
||||
ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
|
||||
|
||||
if (!cml->IsValid(wparam))
|
||||
if (!cml->IsValid(mdata.value))
|
||||
return;
|
||||
|
||||
if (this->HasMode(cm->name, wparam))
|
||||
if (this->HasMode(cm->name, mdata.value))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -447,16 +449,16 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m,
|
||||
this->chanserv_modecount++;
|
||||
}
|
||||
|
||||
ChannelMode *wcm = cm->Wrap(wparam);
|
||||
ChannelMode *wcm = cm->Wrap(mdata.value);
|
||||
|
||||
ModeManager::StackerAdd(bi, this, wcm, true, wparam);
|
||||
ModeManager::StackerAdd(bi, this, wcm, true, mdata);
|
||||
MessageSource ms(bi);
|
||||
SetModeInternal(ms, wcm, wparam, enforce_mlock);
|
||||
SetModeInternal(ms, wcm, mdata, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
|
||||
void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const ModeData &data, bool enforce_mlock)
|
||||
{
|
||||
SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
|
||||
SetMode(bi, ModeManager::FindChannelModeByName(mname), data, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &wparam, bool enforce_mlock)
|
||||
@@ -520,13 +522,13 @@ void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::s
|
||||
|
||||
bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const
|
||||
{
|
||||
std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.find(mname);
|
||||
const auto it = this->modes.find(mname);
|
||||
|
||||
target.clear();
|
||||
|
||||
if (it != this->modes.end())
|
||||
{
|
||||
target = it->second;
|
||||
target = it->second.value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -586,7 +588,7 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const Anope::string &cmo
|
||||
this->SetMode(bi, cm, sbuf, enforce_mlock);
|
||||
}
|
||||
else
|
||||
this->SetMode(bi, cm, "", enforce_mlock);
|
||||
this->SetMode(bi, cm, {}, enforce_mlock);
|
||||
}
|
||||
else if (!add)
|
||||
{
|
||||
@@ -659,12 +661,16 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &modes
|
||||
modestring += cm->mchar;
|
||||
}
|
||||
|
||||
ModeData data;
|
||||
data.set_by = source.GetName();
|
||||
data.set_at = ts ? ts : Anope::CurTime;
|
||||
|
||||
if (cm->type == MODE_REGULAR)
|
||||
{
|
||||
/* something changed if we are adding a mode we don't have, or removing one we have */
|
||||
changed |= !!add != this->HasMode(cm->name);
|
||||
if (add)
|
||||
this->SetModeInternal(source, cm, "", false);
|
||||
this->SetModeInternal(source, cm, data, false);
|
||||
else
|
||||
this->RemoveModeInternal(source, cm, "", false);
|
||||
continue;
|
||||
@@ -691,7 +697,10 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &modes
|
||||
changed |= !!add != this->HasMode(cm->name, token);
|
||||
/* CheckModes below doesn't check secureops (+ the module event) */
|
||||
if (add)
|
||||
this->SetModeInternal(source, cm, token, enforce_mlock);
|
||||
{
|
||||
data.value = token;
|
||||
this->SetModeInternal(source, cm, data, enforce_mlock);
|
||||
}
|
||||
else
|
||||
this->RemoveModeInternal(source, cm, token, enforce_mlock);
|
||||
}
|
||||
|
||||
+33
-91
@@ -41,19 +41,20 @@ unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0
|
||||
|
||||
struct StackerInfo final
|
||||
{
|
||||
using ModeList = std::list<std::pair<Mode *, ModeData>>;
|
||||
/* Modes to be added */
|
||||
std::list<std::pair<Mode *, Anope::string> > AddModes;
|
||||
ModeList AddModes;
|
||||
/* Modes to be deleted */
|
||||
std::list<std::pair<Mode *, Anope::string> > DelModes;
|
||||
ModeList DelModes;
|
||||
/* Bot this is sent from */
|
||||
BotInfo *bi = nullptr;
|
||||
|
||||
/** Add a mode to this object
|
||||
* @param mode The mode
|
||||
* @param set true if setting, false if unsetting
|
||||
* @param param The param for the mode
|
||||
* @param data Data about the mode.
|
||||
*/
|
||||
void AddMode(Mode *mode, bool set, const Anope::string ¶m);
|
||||
void AddMode(Mode *mode, bool set, const ModeData &data);
|
||||
};
|
||||
|
||||
ChannelStatus::ChannelStatus(const Anope::string &m) : modes(m)
|
||||
@@ -246,11 +247,11 @@ bool ChannelModeNoone::CanSet(User *u) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m)
|
||||
void StackerInfo::AddMode(Mode *mode, bool set, const ModeData &data)
|
||||
{
|
||||
bool is_param = mode->type == MODE_PARAM;
|
||||
|
||||
std::list<std::pair<Mode *, Anope::string> > *list, *otherlist;
|
||||
ModeList *list, *otherlist;
|
||||
if (set)
|
||||
{
|
||||
list = &AddModes;
|
||||
@@ -263,13 +264,13 @@ void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m)
|
||||
}
|
||||
|
||||
/* Loop through the list and find if this mode is already on here */
|
||||
std::list<std::pair<Mode *, Anope::string > >::iterator it, it_end;
|
||||
StackerInfo::ModeList::iterator it, it_end;
|
||||
for (it = list->begin(), it_end = list->end(); it != it_end; ++it)
|
||||
{
|
||||
/* The param must match too (can have multiple status or list modes), but
|
||||
* if it is a param mode it can match no matter what the param is
|
||||
*/
|
||||
if (it->first == mode && (is_param || param.equals_cs(it->second)))
|
||||
if (it->first == mode && (is_param || data.value.equals_cs(it->second.value)))
|
||||
{
|
||||
list->erase(it);
|
||||
/* It can only be on this list once */
|
||||
@@ -282,7 +283,7 @@ void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m)
|
||||
/* The param must match too (can have multiple status or list modes), but
|
||||
* if it is a param mode it can match no matter what the param is
|
||||
*/
|
||||
if (it->first == mode && (is_param || param.equals_cs(it->second)))
|
||||
if (it->first == mode && (is_param || data.value.equals_cs(it->second.value)))
|
||||
{
|
||||
otherlist->erase(it);
|
||||
return;
|
||||
@@ -294,7 +295,7 @@ void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m)
|
||||
}
|
||||
|
||||
/* Add this mode and its param to our list */
|
||||
list->emplace_back(mode, param);
|
||||
list->emplace_back(mode, data);
|
||||
}
|
||||
|
||||
static class ModePipe final
|
||||
@@ -323,72 +324,6 @@ static StackerInfo *GetInfo(List &l, Object *o)
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Build a list of mode strings to send to the IRCd from the mode stacker
|
||||
* @param info The stacker info for a channel or user
|
||||
* @return a list of strings
|
||||
*/
|
||||
static auto BuildModeStrings(StackerInfo *info)
|
||||
{
|
||||
std::list<std::pair<Anope::string, std::vector<Anope::string>>> ret;
|
||||
std::list<std::pair<Mode *, Anope::string> >::iterator it, it_end;
|
||||
Anope::string buf = "+";
|
||||
std::vector<Anope::string> parambuf;
|
||||
unsigned NModes = 0;
|
||||
size_t paramlen = 0;
|
||||
|
||||
for (it = info->AddModes.begin(), it_end = info->AddModes.end(); it != it_end; ++it)
|
||||
{
|
||||
if ((IRCD->MaxModes && ++NModes > IRCD->MaxModes) || (IRCD->MaxLine && buf.length() + paramlen > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
|
||||
{
|
||||
ret.push_back({buf, parambuf});
|
||||
buf = "+";
|
||||
parambuf.clear();
|
||||
paramlen = 0;
|
||||
NModes = 1;
|
||||
}
|
||||
|
||||
buf += it->first->mchar;
|
||||
|
||||
if (!it->second.empty())
|
||||
{
|
||||
parambuf.push_back(it->second);
|
||||
paramlen += it->second.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf[buf.length() - 1] == '+')
|
||||
buf.erase(buf.length() - 1);
|
||||
|
||||
buf += "-";
|
||||
for (it = info->DelModes.begin(), it_end = info->DelModes.end(); it != it_end; ++it)
|
||||
{
|
||||
if ((IRCD->MaxModes && ++NModes > IRCD->MaxModes) || (IRCD->MaxLine && buf.length() + paramlen > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
|
||||
{
|
||||
ret.push_back({buf, parambuf});
|
||||
buf = "-";
|
||||
parambuf.clear();
|
||||
paramlen = 0;
|
||||
NModes = 1;
|
||||
}
|
||||
|
||||
buf += it->first->mchar;
|
||||
|
||||
if (!it->second.empty())
|
||||
{
|
||||
parambuf.push_back(it->second);
|
||||
paramlen += it->second.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf[buf.length() - 1] == '-')
|
||||
buf.erase(buf.length() - 1);
|
||||
|
||||
if (!buf.empty())
|
||||
ret.push_back({buf, parambuf});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ModeManager::AddUserMode(UserMode *um)
|
||||
{
|
||||
if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
|
||||
@@ -606,10 +541,10 @@ void ModeManager::RebuildStatusModes()
|
||||
std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp);
|
||||
}
|
||||
|
||||
void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param)
|
||||
void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const ModeData &data)
|
||||
{
|
||||
StackerInfo *s = GetInfo(ChannelStackerObjects, c);
|
||||
s->AddMode(cm, Set, Param);
|
||||
s->AddMode(cm, Set, data);
|
||||
if (bi)
|
||||
s->bi = bi;
|
||||
else
|
||||
@@ -620,10 +555,10 @@ void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set,
|
||||
modePipe->Notify();
|
||||
}
|
||||
|
||||
void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const Anope::string &Param)
|
||||
void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const ModeData &data)
|
||||
{
|
||||
StackerInfo *s = GetInfo(UserStackerObjects, u);
|
||||
s->AddMode(um, Set, Param);
|
||||
s->AddMode(um, Set, data);
|
||||
if (bi)
|
||||
s->bi = bi;
|
||||
|
||||
@@ -632,14 +567,24 @@ void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const
|
||||
modePipe->Notify();
|
||||
}
|
||||
|
||||
static auto BuildModeMap(StackerInfo *info)
|
||||
{
|
||||
// TODO: make the stacker store this so we don't need to build it.
|
||||
ModeManager::Change change;
|
||||
for (const auto &[mode, data] : info->AddModes)
|
||||
change.emplace(mode, std::make_pair(true, data));
|
||||
for (const auto &[mode, data] : info->DelModes)
|
||||
change.emplace(mode, std::make_pair(false, data));
|
||||
return change;
|
||||
}
|
||||
|
||||
void ModeManager::ProcessModes()
|
||||
{
|
||||
if (!UserStackerObjects.empty())
|
||||
{
|
||||
for (const auto &[u, s] : UserStackerObjects)
|
||||
{
|
||||
for (const auto &modestr : BuildModeStrings(s))
|
||||
IRCD->SendModeInternal(s->bi, u, modestr.first, modestr.second);
|
||||
IRCD->SendMode(s->bi, u, BuildModeMap(s));
|
||||
delete s;
|
||||
}
|
||||
UserStackerObjects.clear();
|
||||
@@ -649,8 +594,7 @@ void ModeManager::ProcessModes()
|
||||
{
|
||||
for (const auto &[c, s] : ChannelStackerObjects)
|
||||
{
|
||||
for (const auto &modestr : BuildModeStrings(s))
|
||||
IRCD->SendModeInternal(s->bi, c, modestr.first, modestr.second);
|
||||
IRCD->SendMode(s->bi, c, BuildModeMap(s));
|
||||
delete s;
|
||||
}
|
||||
ChannelStackerObjects.clear();
|
||||
@@ -664,9 +608,7 @@ static void StackerDel(std::map<T *, StackerInfo *> &map, T *obj)
|
||||
if (it != map.end())
|
||||
{
|
||||
StackerInfo *si = it->second;
|
||||
for (const auto &modestr : BuildModeStrings(si))
|
||||
IRCD->SendModeInternal(si->bi, obj, modestr.first, modestr.second);
|
||||
|
||||
IRCD->SendMode(si->bi, obj, BuildModeMap(si));
|
||||
delete si;
|
||||
map.erase(it);
|
||||
}
|
||||
@@ -689,7 +631,7 @@ void ModeManager::StackerDel(Mode *m)
|
||||
StackerInfo *si = it->second;
|
||||
++it;
|
||||
|
||||
for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
|
||||
for (StackerInfo::ModeList::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
|
||||
{
|
||||
if (it2->first == m)
|
||||
it2 = si->AddModes.erase(it2);
|
||||
@@ -697,7 +639,7 @@ void ModeManager::StackerDel(Mode *m)
|
||||
++it2;
|
||||
}
|
||||
|
||||
for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
|
||||
for (StackerInfo::ModeList::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
|
||||
{
|
||||
if (it2->first == m)
|
||||
it2 = si->DelModes.erase(it2);
|
||||
@@ -711,7 +653,7 @@ void ModeManager::StackerDel(Mode *m)
|
||||
StackerInfo *si = it->second;
|
||||
++it;
|
||||
|
||||
for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
|
||||
for (StackerInfo::ModeList::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
|
||||
{
|
||||
if (it2->first == m)
|
||||
it2 = si->AddModes.erase(it2);
|
||||
@@ -719,7 +661,7 @@ void ModeManager::StackerDel(Mode *m)
|
||||
++it2;
|
||||
}
|
||||
|
||||
for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
|
||||
for (StackerInfo::ModeList::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
|
||||
{
|
||||
if (it2->first == m)
|
||||
it2 = si->DelModes.erase(it2);
|
||||
|
||||
@@ -113,6 +113,61 @@ void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const Anope
|
||||
Uplink::Send(source, "KILL", user->GetUID(), buf);
|
||||
}
|
||||
|
||||
static auto BuildModeChange(const ModeManager::Change &change)
|
||||
{
|
||||
std::list<std::pair<Anope::string, std::vector<Anope::string>>> modes;
|
||||
|
||||
Anope::string modebuf;
|
||||
size_t modecount = 0;
|
||||
std::vector<Anope::string> parambuf;
|
||||
size_t paramlen;
|
||||
|
||||
auto adding = true;
|
||||
for (const auto &[mode, info] : change)
|
||||
{
|
||||
const auto reached_max_line = IRCD->MaxLine && modebuf.length() + paramlen > IRCD->MaxLine - 100; // Leave room for command, channel, etc
|
||||
const auto reached_max_modes = IRCD->MaxModes && ++modecount > IRCD->MaxModes;
|
||||
if (reached_max_modes || reached_max_line)
|
||||
{
|
||||
modes.push_back({modebuf, parambuf});
|
||||
|
||||
modebuf.clear();
|
||||
modecount = 0;
|
||||
|
||||
parambuf.clear();
|
||||
paramlen = 0;
|
||||
}
|
||||
|
||||
// Push the mode.
|
||||
const auto direction = info.first;
|
||||
if (modebuf.empty() || adding != direction)
|
||||
{
|
||||
adding = direction;
|
||||
modebuf += (adding ? '+' : '-');
|
||||
}
|
||||
modebuf += mode->mchar;
|
||||
|
||||
// If it has a value push that too.
|
||||
const auto &data = info.second;
|
||||
if (!data.value.empty())
|
||||
{
|
||||
parambuf.push_back(data.value);
|
||||
paramlen += data.value.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modebuf.empty())
|
||||
modes.push_back({modebuf, parambuf});
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
void IRCDProto::SendMode(const MessageSource &source, Channel *chan, const ModeManager::Change &change)
|
||||
{
|
||||
for (const auto &[modes, params] : BuildModeChange(change))
|
||||
IRCD->SendModeInternal(source, chan, modes, params);
|
||||
}
|
||||
|
||||
void IRCDProto::SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values)
|
||||
{
|
||||
auto params = values;
|
||||
@@ -120,6 +175,12 @@ void IRCDProto::SendModeInternal(const MessageSource &source, Channel *chan, con
|
||||
Uplink::SendInternal({}, source, "MODE", params);
|
||||
}
|
||||
|
||||
void IRCDProto::SendMode(const MessageSource &source, User *dest, const ModeManager::Change &change)
|
||||
{
|
||||
for (const auto &[modes, params] : BuildModeChange(change))
|
||||
IRCD->SendModeInternal(source, dest, modes, params);
|
||||
}
|
||||
|
||||
void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &modes, const std::vector<Anope::string> &values)
|
||||
{
|
||||
auto params = values;
|
||||
|
||||
+2
-2
@@ -117,12 +117,12 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
|
||||
IRCD->SendJoin(uc->user, c, &uc->status);
|
||||
}
|
||||
|
||||
for (const auto &[mode, value] : c->GetModes())
|
||||
for (const auto &[mode, data] : c->GetModes())
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
|
||||
if (!cm || cm->type != MODE_LIST)
|
||||
continue;
|
||||
ModeManager::StackerAdd(c->WhoSends(), c, cm, true, value);
|
||||
ModeManager::StackerAdd(c->WhoSends(), c, cm, true, data);
|
||||
}
|
||||
|
||||
if (!c->topic.empty() && !c->topic_setter.empty())
|
||||
|
||||
+10
-10
@@ -548,12 +548,12 @@ bool User::HasMode(const Anope::string &mname) const
|
||||
return this->modes.count(mname);
|
||||
}
|
||||
|
||||
void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anope::string ¶m)
|
||||
void User::SetModeInternal(const MessageSource &source, UserMode *um, const ModeData &data)
|
||||
{
|
||||
if (!um)
|
||||
return;
|
||||
|
||||
this->modes[um->name] = param;
|
||||
this->modes[um->name] = data;
|
||||
|
||||
if (um->name == "OPER")
|
||||
{
|
||||
@@ -609,18 +609,18 @@ void User::RemoveModeInternal(const MessageSource &source, UserMode *um)
|
||||
FOREACH_MOD(OnUserModeUnset, (source, this, um->name));
|
||||
}
|
||||
|
||||
void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m)
|
||||
void User::SetMode(BotInfo *bi, UserMode *um, const ModeData &data)
|
||||
{
|
||||
if (!um || HasMode(um->name))
|
||||
return;
|
||||
|
||||
ModeManager::StackerAdd(bi, this, um, true, param);
|
||||
SetModeInternal(bi, um, param);
|
||||
ModeManager::StackerAdd(bi, this, um, true, data);
|
||||
SetModeInternal(bi, um, data);
|
||||
}
|
||||
|
||||
void User::SetMode(BotInfo *bi, const Anope::string &uname, const Anope::string ¶m)
|
||||
void User::SetMode(BotInfo *bi, const Anope::string &uname, const ModeData &data)
|
||||
{
|
||||
SetMode(bi, ModeManager::FindUserModeByName(uname), param);
|
||||
SetMode(bi, ModeManager::FindUserModeByName(uname), data);
|
||||
}
|
||||
|
||||
void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string ¶m)
|
||||
@@ -730,7 +730,7 @@ Anope::string User::GetModes() const
|
||||
{
|
||||
Anope::string m, params;
|
||||
|
||||
for (const auto &[mode, value] : this->modes)
|
||||
for (const auto &[mode, data] : this->modes)
|
||||
{
|
||||
UserMode *um = ModeManager::FindUserModeByName(mode);
|
||||
if (um == NULL)
|
||||
@@ -738,8 +738,8 @@ Anope::string User::GetModes() const
|
||||
|
||||
m += um->mchar;
|
||||
|
||||
if (!value.empty())
|
||||
params += " " + value;
|
||||
if (!data.value.empty())
|
||||
params += " " + data.value;
|
||||
}
|
||||
|
||||
return m + params;
|
||||
|
||||
Reference in New Issue
Block a user