aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_permchannels.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2023-08-13 19:13:22 +0100
committerGravatar Sadie Powell2023-08-13 19:13:22 +0100
commit16b85a93e9e01ba0100ec3df03b0ac2d170c4dd6 (patch)
tree3fe5b039e7a7c8e4e0b34538ed496eb50b6f295d /src/modules/m_permchannels.cpp
parentFix big list limits and expose the limit to TellListTooLong. (diff)
Allow permchannels to save the set time and setter of list mode entries.
Diffstat (limited to 'src/modules/m_permchannels.cpp')
-rw-r--r--src/modules/m_permchannels.cpp70
1 files changed, 48 insertions, 22 deletions
diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp
index 5e404ab9c..9dc1c829f 100644
--- a/src/modules/m_permchannels.cpp
+++ b/src/modules/m_permchannels.cpp
@@ -63,7 +63,7 @@ public:
// Not in a class due to circular dependency hell.
static std::string permchannelsconf;
-static bool WriteDatabase(PermChannel& permchanmode, bool save_listmodes)
+static bool WriteDatabase(PermChannel& permchanmode, bool save_listmodes, unsigned char writeversion)
{
/*
* We need to perform an atomic write so as not to fuck things up.
@@ -95,7 +95,7 @@ static bool WriteDatabase(PermChannel& permchanmode, bool save_listmodes)
continue;
std::string chanmodes = chan->ChanModes(true);
- if (save_listmodes)
+ if (save_listmodes && writeversion == 1)
{
std::string modes;
std::string params;
@@ -138,6 +138,7 @@ static bool WriteDatabase(PermChannel& permchanmode, bool save_listmodes)
stream << "<permchannels channel=\"" << ServerConfig::Escape(chan->name)
<< "\" ts=\"" << chan->age;
+
if (!chan->topic.empty())
{
// Only store the topic if one is set.
@@ -145,6 +146,25 @@ static bool WriteDatabase(PermChannel& permchanmode, bool save_listmodes)
<< "\" topicts=\"" << chan->topicset
<< "\" topicsetby=\"" << ServerConfig::Escape(chan->setby);
}
+
+ if (save_listmodes && writeversion >= 2)
+ {
+ for (auto* lm : ServerInstance->Modes.GetListModes())
+ {
+ ListModeBase::ModeList* list = lm->GetList(chan);
+ if (!list || list->empty())
+ continue;
+
+ stream << "\" " << lm->name << "list=\"";
+ for (auto entry = list->begin(); entry != list->end(); ++entry)
+ {
+ if (entry != list->begin())
+ stream << ' ';
+ stream << entry->mask << ' ' << entry->setter << ' ' << entry->time;
+ }
+ }
+ }
+
stream << "\" modes=\"" << ServerConfig::Escape(chanmodes)
<< "\">" << std::endl;
}
@@ -184,6 +204,7 @@ private:
unsigned long saveperiod;
unsigned long maxbackoff;
unsigned char backoff;
+ unsigned char writeversion;
public:
@@ -203,6 +224,7 @@ public:
saveperiod = tag->getDuration("saveperiod", 5);
backoff = tag->getNum<uint8_t>("backoff", 0);
maxbackoff = tag->getDuration("maxbackoff", saveperiod * 120, saveperiod);
+ writeversion = tag->getNum<unsigned char>("writeversion", 2, 1, 2);
SetInterval(saveperiod);
if (!permchannelsconf.empty())
@@ -246,35 +268,39 @@ public:
ServerInstance->Logs.Debug(MODNAME, "Added {} with topic {}", channel, c->topic);
- std::string modes = tag->getString("modes");
- if (modes.empty())
- continue;
-
- irc::spacesepstream list(modes);
- std::string modeseq;
- std::string par;
-
- list.GetToken(modeseq);
-
- // XXX bleh, should we pass this to the mode parser instead? ugly. --w00t
- for (const auto modechr : modeseq)
+ irc::spacesepstream modes(tag->getString("modes"));
+ std::string modechars;
+ modes.GetToken(modechars);
+ for (const auto modechr : modechars)
{
- ModeHandler* mode = ServerInstance->Modes.FindMode(modechr, MODETYPE_CHANNEL);
+ auto* mode = ServerInstance->Modes.FindMode(modechr, MODETYPE_CHANNEL);
if (mode)
{
+ std::string param;
if (mode->NeedsParam(true))
- list.GetToken(par);
- else
- par.clear();
+ modes.GetToken(param);
- Modes::Change modechange(mode, true, par);
+ Modes::Change modechange(mode, true, param);
mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, modechange);
}
}
+ for (auto* lm : ServerInstance->Modes.GetListModes())
+ {
+ irc::spacesepstream listmodes(tag->getString(lm->name + "list"));
+
+ std::string mask;
+ std::string set_by;
+ time_t set_at;
+ while (listmodes.GetToken(mask) && listmodes.GetToken(set_by) && listmodes.GetNumericToken(set_at))
+ {
+ Modes::Change modechange(lm, true, mask, set_by, set_at);
+ lm->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, modechange);
+ }
+ }
+
// We always apply the permchannels mode to permanent channels.
- par.clear();
- Modes::Change modechange(&p, true, par);
+ Modes::Change modechange(&p, true);
p.OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, modechange);
}
}
@@ -298,7 +324,7 @@ public:
{
if (dirty)
{
- if (WriteDatabase(p, save_listmodes))
+ if (WriteDatabase(p, save_listmodes, writeversion))
{
// If we were previously unable to write but now can then reset the time interval.
if (GetInterval() != saveperiod)