mirror of
https://github.com/anope/anope.git
synced 2026-07-08 10:03:14 +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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user