summaryrefslogtreecommitdiff
path: root/modules/pseudoclients
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-05-28 12:07:29 -0400
committerAdam <Adam@anope.org>2014-05-28 12:07:54 -0400
commitf29e1cf383529a1a29f02b0669d973f5ee0b7a66 (patch)
tree3c33db276dc9328235bbd572641521ed44458176 /modules/pseudoclients
parent1253c70e0682fa1490c99c3d2869049a0e3fa2e0 (diff)
Move most of the core pseudoclient logic to modules
Diffstat (limited to 'modules/pseudoclients')
-rw-r--r--modules/pseudoclients/botserv/CMakeLists.txt1
-rw-r--r--modules/pseudoclients/botserv/botserv.cpp (renamed from modules/pseudoclients/botserv.cpp)12
-rw-r--r--modules/pseudoclients/chanserv/CMakeLists.txt1
-rw-r--r--modules/pseudoclients/chanserv/channel.cpp605
-rw-r--r--modules/pseudoclients/chanserv/channel.h41
-rw-r--r--modules/pseudoclients/chanserv/chanserv.cpp (renamed from modules/pseudoclients/chanserv.cpp)261
-rw-r--r--modules/pseudoclients/global.cpp2
-rw-r--r--modules/pseudoclients/hostserv.cpp18
-rw-r--r--modules/pseudoclients/memoserv/CMakeLists.txt1
-rw-r--r--modules/pseudoclients/memoserv/memo.cpp58
-rw-r--r--modules/pseudoclients/memoserv/memo.h11
-rw-r--r--modules/pseudoclients/memoserv/memoinfo.cpp33
-rw-r--r--modules/pseudoclients/memoserv/memoinfo.h10
-rw-r--r--modules/pseudoclients/memoserv/memoserv.cpp (renamed from modules/pseudoclients/memoserv.cpp)99
-rw-r--r--modules/pseudoclients/nickserv/CMakeLists.txt1
-rw-r--r--modules/pseudoclients/nickserv/account.cpp264
-rw-r--r--modules/pseudoclients/nickserv/account.h22
-rw-r--r--modules/pseudoclients/nickserv/identifyrequest.cpp51
-rw-r--r--modules/pseudoclients/nickserv/identifyrequest.h13
-rw-r--r--modules/pseudoclients/nickserv/nick.cpp198
-rw-r--r--modules/pseudoclients/nickserv/nick.h18
-rw-r--r--modules/pseudoclients/nickserv/nickserv.cpp (renamed from modules/pseudoclients/nickserv.cpp)142
-rw-r--r--modules/pseudoclients/operserv.cpp2
23 files changed, 1761 insertions, 103 deletions
diff --git a/modules/pseudoclients/botserv/CMakeLists.txt b/modules/pseudoclients/botserv/CMakeLists.txt
new file mode 100644
index 000000000..781f0ef1f
--- /dev/null
+++ b/modules/pseudoclients/botserv/CMakeLists.txt
@@ -0,0 +1 @@
+build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv/botserv.cpp
index 2f4511f32..cbb76599a 100644
--- a/modules/pseudoclients/botserv.cpp
+++ b/modules/pseudoclients/botserv/botserv.cpp
@@ -10,9 +10,10 @@
*/
#include "module.h"
+#include "modules/botserv.h"
#include "modules/help.h"
-class BotServCore : public Module
+class BotServCore : public Module, public BotServ::BotServService
, public EventHook<Event::SetCorrectModes>
, public EventHook<Event::BotAssign>
, public EventHook<Event::JoinChannel>
@@ -28,6 +29,7 @@ class BotServCore : public Module
public:
BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ , BotServ::BotServService(this)
, EventHook<Event::SetCorrectModes>("OnSetCorrectModes")
, EventHook<Event::BotAssign>("OnBotAssign")
, EventHook<Event::JoinChannel>("OnJoinChannel")
@@ -48,7 +50,7 @@ class BotServCore : public Module
BotServ = BotInfo::Find(bsnick, true);
}
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
+ void OnSetCorrectModes(User *user, Channel *chan, ChanServ::AccessGroup &access, bool &give_modes, bool &take_modes) override
{
/* Do not allow removing bot modes on our service bots */
if (chan->ci && chan->ci->bi == user)
@@ -59,7 +61,7 @@ class BotServCore : public Module
}
}
- void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) override
+ void OnBotAssign(User *sender, ChanServ::Channel *ci, BotInfo *bi) override
{
if (ci->c && ci->c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers"))
{
@@ -128,7 +130,7 @@ class BotServCore : public Module
/* Channel is persistent, it shouldn't be deleted and the service bot should stay */
if (c->ci && persist && persist->HasExt(c->ci))
return;
-
+
/* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly
* We also don't part the bot here either, if necessary we will part it after the sync
*/
@@ -208,7 +210,7 @@ class BotServCore : public Module
return EVENT_CONTINUE;
}
- void OnCreateChan(ChannelInfo *ci) override
+ void OnCreateChan(ChanServ::Channel *ci) override
{
/* Set default bot flags */
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
diff --git a/modules/pseudoclients/chanserv/CMakeLists.txt b/modules/pseudoclients/chanserv/CMakeLists.txt
new file mode 100644
index 000000000..781f0ef1f
--- /dev/null
+++ b/modules/pseudoclients/chanserv/CMakeLists.txt
@@ -0,0 +1 @@
+build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/modules/pseudoclients/chanserv/channel.cpp b/modules/pseudoclients/chanserv/channel.cpp
new file mode 100644
index 000000000..5364075ae
--- /dev/null
+++ b/modules/pseudoclients/chanserv/channel.cpp
@@ -0,0 +1,605 @@
+/* Registered channel functions
+ *
+ * (C) 2003-2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ */
+
+#include "module.h"
+#include "channel.h"
+#include "modules/cs_akick.h"
+
+ChannelImpl::ChannelImpl(const Anope::string &chname)
+{
+ if (chname.empty())
+ throw CoreException("Empty channel passed to ChanServ::Channel constructor");
+
+ this->founder = NULL;
+ this->successor = NULL;
+ this->c = ::Channel::Find(chname);
+ if (this->c)
+ this->c->ci = this;
+ this->banexpire = 0;
+ this->bi = NULL;
+ this->last_topic_time = 0;
+
+ this->name = chname;
+
+ this->bantype = 2;
+ this->last_used = this->time_registered = Anope::CurTime;
+
+ ChanServ::registered_channel_map& map = ChanServ::service->GetChannels();
+ Channel* &ci = map[chname];
+ if (ci)
+ Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?";
+ ci = this;
+
+ Event::OnCreateChan(&Event::CreateChan::OnCreateChan, this);
+}
+
+ChannelImpl::ChannelImpl(const ChanServ::Channel &ci)
+{
+ *this = ci;
+
+ if (this->founder)
+ --this->founder->channelcount;
+
+ this->access->clear();
+ this->akick->clear();
+
+ for (unsigned i = 0; i < ci.GetAccessCount(); ++i)
+ {
+ const ChanServ::ChanAccess *taccess = ci.GetAccess(i);
+ ChanServ::AccessProvider *provider = taccess->provider;
+
+ ChanServ::ChanAccess *newaccess = provider->Create();
+ newaccess->ci = this;
+ newaccess->mask = taccess->mask;
+ newaccess->creator = taccess->creator;
+ newaccess->last_seen = taccess->last_seen;
+ newaccess->created = taccess->created;
+ newaccess->AccessUnserialize(taccess->AccessSerialize());
+
+ this->AddAccess(newaccess);
+ }
+
+ for (unsigned i = 0; i < ci.GetAkickCount(); ++i)
+ {
+ const AutoKick *takick = ci.GetAkick(i);
+ if (takick->nc)
+ this->AddAkick(takick->creator, takick->nc, takick->reason, takick->addtime, takick->last_used);
+ else
+ this->AddAkick(takick->creator, takick->mask, takick->reason, takick->addtime, takick->last_used);
+ }
+
+ Event::OnCreateChan(&Event::CreateChan::OnCreateChan, this);
+}
+
+ChannelImpl::~ChannelImpl()
+{
+ Event::OnDelChan(&Event::DelChan::OnDelChan, this);
+
+ Log(LOG_DEBUG) << "Deleting channel " << this->name;
+
+ if (this->c)
+ {
+ if (this->bi && this->c->FindUser(this->bi))
+ this->bi->Part(this->c);
+
+ /* Parting the service bot can cause the channel to go away */
+
+ if (this->c)
+ {
+ if (this->c && this->c->CheckDelete())
+ delete this->c;
+
+ this->c = NULL;
+ }
+ }
+
+ ChanServ::registered_channel_map& map = ChanServ::service->GetChannels();
+ map.erase(this->name);
+
+ this->SetFounder(NULL);
+ this->SetSuccessor(NULL);
+
+ this->ClearAccess();
+ this->ClearAkick();
+
+ if (this->memos)
+ {
+ for (unsigned i = 0, end = this->memos->memos->size(); i < end; ++i)
+ delete this->memos->GetMemo(i);
+ this->memos->memos->clear();
+ delete memos;
+ }
+
+ if (this->founder)
+ --this->founder->channelcount;
+}
+
+void ChannelImpl::Serialize(Serialize::Data &data) const
+{
+ data["name"] << this->name;
+ if (this->founder)
+ data["founder"] << this->founder->display;
+ if (this->successor)
+ data["successor"] << this->successor->display;
+ data["description"] << this->desc;
+ data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
+ data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
+ data["last_topic"] << this->last_topic;
+ data["last_topic_setter"] << this->last_topic_setter;
+ data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
+ data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
+ {
+ Anope::string levels_buffer;
+ for (Anope::map<int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
+ levels_buffer += it->first + " " + stringify(it->second) + " ";
+ data["levels"] << levels_buffer;
+ }
+ if (this->bi)
+ data["bi"] << this->bi->nick;
+ data.SetType("banexpire", Serialize::Data::DT_INT); data["banexpire"] << this->banexpire;
+ if (memos)
+ {
+ data["memomax"] << this->memos->memomax;
+ for (unsigned i = 0; i < this->memos->ignores.size(); ++i)
+ data["memoignores"] << this->memos->ignores[i] << " ";
+ }
+
+ Extensible::ExtensibleSerialize(this, this, data);
+}
+
+Serializable* ChannelImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+{
+ Anope::string sname, sfounder, ssuccessor, slevels, sbi;
+
+ data["name"] >> sname;
+ data["founder"] >> sfounder;
+ data["successor"] >> ssuccessor;
+ data["levels"] >> slevels;
+ data["bi"] >> sbi;
+
+ ChannelImpl *ci;
+ if (obj)
+ ci = anope_dynamic_static_cast<ChannelImpl *>(obj);
+ else
+ ci = new ChannelImpl(sname);
+
+ ci->SetFounder(NickServ::FindAccount(sfounder));
+ ci->SetSuccessor(NickServ::FindAccount(ssuccessor));
+
+ data["description"] >> ci->desc;
+ data["time_registered"] >> ci->time_registered;
+ data["last_used"] >> ci->last_used;
+ data["last_topic"] >> ci->last_topic;
+ data["last_topic_setter"] >> ci->last_topic_setter;
+ data["last_topic_time"] >> ci->last_topic_time;
+ data["bantype"] >> ci->bantype;
+ {
+ std::vector<Anope::string> v;
+ spacesepstream(slevels).GetTokens(v);
+ for (unsigned i = 0; i + 1 < v.size(); i += 2)
+ try
+ {
+ ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]);
+ }
+ catch (const ConvertException &) { }
+ }
+ BotInfo *bi = BotInfo::Find(sbi);
+ if (*ci->bi != bi)
+ {
+ if (bi)
+ bi->Assign(NULL, ci);
+ else if (ci->bi)
+ ci->bi->UnAssign(NULL, ci);
+ }
+ data["banexpire"] >> ci->banexpire;
+ if (ci->memos)
+ {
+ data["memomax"] >> ci->memos->memomax;
+ {
+ Anope::string buf;
+ data["memoignores"] >> buf;
+ spacesepstream sep(buf);
+ ci->memos->ignores.clear();
+ while (sep.GetToken(buf))
+ ci->memos->ignores.push_back(buf);
+ }
+ }
+
+ Extensible::ExtensibleUnserialize(ci, ci, data);
+
+ /* compat */
+ bool b;
+ b = false;
+ data["extensible:SECURE"] >> b;
+ if (b)
+ ci->Extend<bool>("CS_SECURE");
+ b = false;
+ data["extensible:PRIVATE"] >> b;
+ if (b)
+ ci->Extend<bool>("CS_PRIVATE");
+ b = false;
+ data["extensible:NO_EXPIRE"] >> b;
+ if (b)
+ ci->Extend<bool>("CS_NO_EXPIRE");
+ b = false;
+ data["extensible:FANTASY"] >> b;
+ if (b)
+ ci->Extend<bool>("BS_FANTASY");
+ b = false;
+ data["extensible:GREET"] >> b;
+ if (b)
+ ci->Extend<bool>("BS_GREET");
+ b = false;
+ data["extensible:PEACE"] >> b;
+ if (b)
+ ci->Extend<bool>("PEACE");
+ b = false;
+ data["extensible:SECUREFOUNDER"] >> b;
+ if (b)
+ ci->Extend<bool>("SECUREFOUNDER");
+ b = false;
+ data["extensible:RESTRICTED"] >> b;
+ if (b)
+ ci->Extend<bool>("RESTRICTED");
+ b = false;
+ data["extensible:KEEPTOPIC"] >> b;
+ if (b)
+ ci->Extend<bool>("KEEPTOPIC");
+ b = false;
+ data["extensible:SIGNKICK"] >> b;
+ if (b)
+ ci->Extend<bool>("SIGNKICK");
+ b = false;
+ data["extensible:SIGNKICK_LEVEL"] >> b;
+ if (b)
+ ci->Extend<bool>("SIGNKICK_LEVEL");
+ /* end compat */
+
+ return ci;
+}
+
+
+void ChannelImpl::SetFounder(NickServ::Account *nc)
+{
+ if (this->founder)
+ {
+ --this->founder->channelcount;
+ this->founder->RemoveChannelReference(this);
+ }
+
+ this->founder = nc;
+
+ if (this->founder)
+ {
+ ++this->founder->channelcount;
+ this->founder->AddChannelReference(this);
+ }
+}
+
+NickServ::Account *ChannelImpl::GetFounder() const
+{
+ return this->founder;
+}
+
+void ChannelImpl::SetSuccessor(NickServ::Account *nc)
+{
+ if (this->successor)
+ this->successor->RemoveChannelReference(this);
+ this->successor = nc;
+ if (this->successor)
+ this->successor->AddChannelReference(this);
+}
+
+NickServ::Account *ChannelImpl::GetSuccessor() const
+{
+ return this->successor;
+}
+
+BotInfo *ChannelImpl::WhoSends() const
+{
+ if (this && this->bi)
+ return this->bi;
+
+ BotInfo *ChanServ = Config->GetClient("ChanServ");
+ if (ChanServ)
+ return ChanServ;
+
+ if (!BotListByNick->empty())
+ return BotListByNick->begin()->second;
+
+ return NULL;
+}
+
+void ChannelImpl::AddAccess(ChanServ::ChanAccess *taccess)
+{
+ this->access->push_back(taccess);
+
+ const NickServ::Nick *na = NickServ::FindNick(taccess->mask);
+ if (na != NULL)
+ {
+ na->nc->AddChannelReference(this);
+ taccess->nc = na->nc;
+ }
+ else
+ {
+ ChanServ::Channel *ci = ChanServ::Find(taccess->mask);
+ if (ci != NULL)
+ ci->AddChannelReference(this->name);
+ }
+}
+
+ChanServ::ChanAccess *ChannelImpl::GetAccess(unsigned index) const
+{
+ if (this->access->empty() || index >= this->access->size())
+ return NULL;
+
+ ChanServ::ChanAccess *acc = (*this->access)[index];
+ acc->QueueUpdate();
+ return acc;
+}
+
+ChanServ::AccessGroup ChannelImpl::AccessFor(const User *u)
+{
+ ChanServ::AccessGroup group;
+
+ if (u == NULL)
+ return group;
+
+ const NickServ::Account *nc = u->Account();
+ if (nc == NULL && !this->HasExt("NS_SECURE") && u->IsRecognized())
+ {
+ const NickServ::Nick *na = NickServ::FindNick(u->nick);
+ if (na != NULL)
+ nc = na->nc;
+ }
+
+ group.super_admin = u->super_admin;
+ group.founder = IsFounder(u);
+ group.ci = this;
+ group.nc = nc;
+
+ for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
+ {
+ ChanServ::ChanAccess *a = this->GetAccess(i);
+ if (a->Matches(u, u->Account(), group.path))
+ group.push_back(a);
+ }
+
+ if (group.founder || !group.empty())
+ {
+ this->last_used = Anope::CurTime;
+
+ for (unsigned i = 0; i < group.size(); ++i)
+ group[i]->last_seen = Anope::CurTime;
+ }
+
+ return group;
+}
+
+ChanServ::AccessGroup ChannelImpl::AccessFor(const NickServ::Account *nc)
+{
+ ChanServ::AccessGroup group;
+
+ group.founder = (this->founder && this->founder == nc);
+ group.ci = this;
+ group.nc = nc;
+
+ for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
+ {
+ ChanServ::ChanAccess *a = this->GetAccess(i);
+ if (a->Matches(NULL, nc, group.path))
+ group.push_back(a);
+ }
+
+ if (group.founder || !group.empty())
+ this->last_used = Anope::CurTime;
+
+ /* don't update access last seen here, this isn't the user requesting access */
+
+ return group;
+}
+
+unsigned ChannelImpl::GetAccessCount() const
+{
+ return this->access->size();
+}
+
+unsigned ChannelImpl::GetDeepAccessCount() const
+{
+ ChanServ::ChanAccess::Path path;
+ for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
+ {
+ ChanServ::ChanAccess *a = this->GetAccess(i);
+ a->Matches(NULL, NULL, path);
+ }
+
+ unsigned count = this->GetAccessCount();
+ std::set<const ChanServ::Channel *> channels;
+ channels.insert(this);
+ for (ChanServ::ChanAccess::Set::iterator it = path.first.begin(); it != path.first.end(); ++it)
+ {
+ const ChanServ::Channel *ci = it->first->ci;
+ if (!channels.count(ci))
+ {
+ channels.count(ci);
+ count += ci->GetAccessCount();
+ }
+ }
+ return count;
+}
+
+ChanServ::ChanAccess *ChannelImpl::EraseAccess(unsigned index)
+{
+ if (this->access->empty() || index >= this->access->size())
+ return NULL;
+
+ ChanServ::ChanAccess *ca = this->access->at(index);
+ this->access->erase(this->access->begin() + index);
+ return ca;
+}
+
+void ChannelImpl::ClearAccess()
+{
+ for (unsigned i = this->access->size(); i > 0; --i)
+ delete this->GetAccess(i - 1);
+}
+
+AutoKick *ChannelImpl::AddAkick(const Anope::string &user, NickServ::Account *akicknc, const Anope::string &reason, time_t t, time_t lu)
+{
+ if (!::akick)
+ return nullptr;
+
+ AutoKick *autokick = ::akick->Create();
+ autokick->ci = this;
+ autokick->nc = akicknc;
+ autokick->reason = reason;
+ autokick->creator = user;
+ autokick->addtime = t;
+ autokick->last_used = lu;
+
+ this->akick->push_back(autokick);
+
+ akicknc->AddChannelReference(this);
+
+ return autokick;
+}
+
+AutoKick *ChannelImpl::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu)
+{
+ if (!::akick)
+ return nullptr;
+
+ AutoKick *autokick = ::akick->Create();
+ autokick->ci = this;
+ autokick->mask = mask;
+ autokick->nc = NULL;
+ autokick->reason = reason;
+ autokick->creator = user;
+ autokick->addtime = t;
+ autokick->last_used = lu;
+
+ this->akick->push_back(autokick);
+
+ return autokick;
+}
+
+AutoKick *ChannelImpl::GetAkick(unsigned index) const
+{
+ if (this->akick->empty() || index >= this->akick->size())
+ return NULL;
+
+ AutoKick *ak = (*this->akick)[index];
+ ak->QueueUpdate();
+ return ak;
+}
+
+unsigned ChannelImpl::GetAkickCount() const
+{
+ return this->akick->size();
+}
+
+void ChannelImpl::EraseAkick(unsigned index)
+{
+ if (this->akick->empty() || index >= this->akick->size())
+ return;
+
+ delete this->GetAkick(index);
+}
+
+void ChannelImpl::ClearAkick()
+{
+ while (!this->akick->empty())
+ delete this->akick->back();
+}
+
+int16_t ChannelImpl::GetLevel(const Anope::string &priv) const
+{
+ if (!ChanServ::service || !ChanServ::service->FindPrivilege(priv))
+ {
+ Log(LOG_DEBUG) << "Unknown privilege " + priv;
+ return ChanServ::ACCESS_INVALID;
+ }
+
+ Anope::map<int16_t>::const_iterator it = this->levels.find(priv);
+ if (it == this->levels.end())
+ return 0;
+ return it->second;
+}
+
+void ChannelImpl::SetLevel(const Anope::string &priv, int16_t level)
+{
+ this->levels[priv] = level;
+}
+
+void ChannelImpl::RemoveLevel(const Anope::string &priv)
+{
+ this->levels.erase(priv);
+}
+
+void ChannelImpl::ClearLevels()
+{
+ this->levels.clear();
+}
+
+Anope::string ChannelImpl::GetIdealBan(User *u) const
+{
+ int bt = this ? this->bantype : -1;
+ switch (bt)
+ {
+ case 0:
+ return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
+ case 1:
+ if (u->GetVIdent()[0] == '~')
+ return "*!*" + u->GetVIdent() + "@" + u->GetDisplayedHost();
+ else
+ return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
+ case 3:
+ return "*!" + u->Mask();
+ case 2:
+ default:
+ return "*!*@" + u->GetDisplayedHost();
+ }
+}
+
+bool ChannelImpl::IsFounder(const User *user)
+{
+ if (!user)
+ return false;
+
+ if (user->super_admin)
+ return true;
+
+ if (user->Account() && user->Account() == this->GetFounder())
+ return true;
+
+ return false;
+}
+
+
+void ChannelImpl::AddChannelReference(const Anope::string &what)
+{
+ ++references[what];
+}
+
+void ChannelImpl::RemoveChannelReference(const Anope::string &what)
+{
+ int &i = references[what];
+ if (--i <= 0)
+ references.erase(what);
+}
+
+void ChannelImpl::GetChannelReferences(std::deque<Anope::string> &chans)
+{
+ chans.clear();
+ for (Anope::map<int>::iterator it = references.begin(); it != references.end(); ++it)
+ chans.push_back(it->first);
+}
diff --git a/modules/pseudoclients/chanserv/channel.h b/modules/pseudoclients/chanserv/channel.h
new file mode 100644
index 000000000..c9a85dba6
--- /dev/null
+++ b/modules/pseudoclients/chanserv/channel.h
@@ -0,0 +1,41 @@
+
+
+class ChannelImpl : public ChanServ::Channel
+{
+ public:
+ ChannelImpl(const Anope::string &chname);
+ ChannelImpl(const ChanServ::Channel &ci);
+ ~ChannelImpl();
+
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+
+ bool IsFounder(const User *user) override;
+ void SetFounder(NickServ::Account *nc) override;
+ NickServ::Account *GetFounder() const override;
+ void SetSuccessor(NickServ::Account *nc) override;
+ NickServ::Account *GetSuccessor() const override;
+ BotInfo *WhoSends() const override;
+ void AddAccess(ChanServ::ChanAccess *access) override;
+ ChanServ::ChanAccess *GetAccess(unsigned index) const override;
+ ChanServ::AccessGroup AccessFor(const User *u) override;
+ ChanServ::AccessGroup AccessFor(const NickServ::Account *nc) override;
+ unsigned GetAccessCount() const override;
+ unsigned GetDeepAccessCount() const override;
+ ChanServ::ChanAccess *EraseAccess(unsigned index) override;
+ void ClearAccess() override;
+ AutoKick* AddAkick(const Anope::string &user, NickServ::Account *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) override;
+ AutoKick* AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) override;
+ AutoKick* GetAkick(unsigned index) const override;
+ unsigned GetAkickCount() const override;
+ void EraseAkick(unsigned index) override;
+ void ClearAkick() override;
+ int16_t GetLevel(const Anope::string &priv) const override;
+ void SetLevel(const Anope::string &priv, int16_t level) override;
+ void RemoveLevel(const Anope::string &priv) override;
+ void ClearLevels() override;
+ Anope::string GetIdealBan(User *u) const override;
+ void AddChannelReference(const Anope::string &what) override;
+ void RemoveChannelReference(const Anope::string &what) override;
+ void GetChannelReferences(std::deque<Anope::string> &chans) override;
+};
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv/chanserv.cpp
index 419f25fc3..d4f3aa1c7 100644
--- a/modules/pseudoclients/chanserv.cpp
+++ b/modules/pseudoclients/chanserv/chanserv.cpp
@@ -10,14 +10,17 @@
*/
#include "module.h"
+#include "channel.h"
#include "modules/cs_mode.h"
#include "modules/help.h"
#include "modules/bs_bot.h"
#include "modules/chanserv.h"
#include "modules/cs_info.h"
+#include "modules/cs_akick.h"
class ChanServCore : public Module
, public ChanServ::ChanServService
+ , public EventHook<Event::ChannelCreate>
, public EventHook<Event::BotDelete>
, public EventHook<Event::BotPrivmsg>
, public EventHook<Event::DelCore>
@@ -44,10 +47,15 @@ class ChanServCore : public Module
bool always_lower;
EventHandlers<ChanServ::Event::PreChanExpire> OnPreChanExpire;
EventHandlers<ChanServ::Event::ChanExpire> OnChanExpire;
+ std::vector<ChanServ::Privilege> Privileges;
+ std::vector<ChanServ::AccessProvider *> Providers;
+ Serialize::Checker<ChanServ::registered_channel_map> registered_channels;
+ Serialize::Type channel_type, access_type;
public:
ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
, ChanServService(this)
+ , EventHook<Event::ChannelCreate>("OnChannelCreate")
, EventHook<Event::BotDelete>("OnBotDelete")
, EventHook<Event::BotPrivmsg>("OnBotPrivmsg")
, EventHook<Event::DelCore>("OnDelCore")
@@ -71,9 +79,33 @@ class ChanServCore : public Module
, always_lower(false)
, OnPreChanExpire(this, "OnPreChanExpire")
, OnChanExpire(this, "OnChanExpire")
+ , registered_channels("ChannelInfo")
+ , channel_type("ChannelInfo", ChannelImpl::Unserialize)
+ , access_type("ChanAccess", Unserialize)
{
}
+ ChanServ::Channel *Create(const Anope::string &name) override
+ {
+ return new ChannelImpl(name);
+ }
+
+ ChanServ::Channel *Create(const ChanServ::Channel &ci) override
+ {
+ return new ChannelImpl(ci);
+ }
+
+ ChanServ::Channel *Find(const Anope::string &name) override
+ {
+ auto it = registered_channels->find(name);
+ return it != registered_channels->end() ? it->second : nullptr;
+ }
+
+ ChanServ::registered_channel_map& GetChannels() override
+ {
+ return registered_channels;
+ }
+
void Hold(Channel *c) override
{
/** A timer used to keep the BotServ bot/ChanServ in the channel
@@ -86,7 +118,7 @@ class ChanServCore : public Module
Reference<Channel> c;
public:
- /** Constructor
+ /** Constructor
* @param chan The channel
*/
ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), inhabit(i), c(chan)
@@ -137,6 +169,166 @@ class ChanServCore : public Module
new ChanServTimer(ChanServ, inhabit, this->owner, c);
}
+ void AddPrivilege(ChanServ::Privilege p) override
+ {
+ unsigned i;
+ for (i = 0; i < Privileges.size(); ++i)
+ {
+ ChanServ::Privilege &priv = Privileges[i];
+
+ if (priv.rank > p.rank)
+ break;
+ }
+
+ Privileges.insert(Privileges.begin() + i, p);
+ }
+
+ void RemovePrivilege(ChanServ::Privilege &p) override
+ {
+ std::vector<ChanServ::Privilege>::iterator it = std::find(Privileges.begin(), Privileges.end(), p);
+ if (it != Privileges.end())
+ Privileges.erase(it);
+
+ for (auto& cit : GetChannels())
+ {
+ ChanServ::Channel *ci = cit.second;
+ ci->QueueUpdate();
+ ci->RemoveLevel(p.name);
+ }
+ }
+
+ ChanServ::Privilege *FindPrivilege(const Anope::string &name) override
+ {
+ for (unsigned i = Privileges.size(); i > 0; --i)
+ if (Privileges[i - 1].name.equals_ci(name))
+ return &Privileges[i - 1];
+ return NULL;
+ }
+
+ std::vector<ChanServ::Privilege> &GetPrivileges() override
+ {
+ return Privileges;
+ }
+
+ void ClearPrivileges() override
+ {
+ Privileges.clear();
+ }
+
+ std::vector<ChanServ::AccessProvider *>& GetProviders() override
+ {
+ return Providers;
+ }
+
+ void Destruct(ChanServ::ChanAccess *access) override
+ {
+ if (access->ci)
+ {
+ std::vector<ChanServ::ChanAccess *>::iterator it = std::find(access->ci->access->begin(), access->ci->access->end(), access);
+ if (it != access->ci->access->end())
+ access->ci->access->erase(it);
+
+ const NickServ::Nick *na = NickServ::FindNick(access->mask);
+ if (na != NULL)
+ na->nc->RemoveChannelReference(access->ci);
+ else
+ {
+ ChanServ::Channel *c = this->Find(access->mask);
+ if (c)
+ c->RemoveChannelReference(access->ci->name);
+ }
+ }
+ }
+
+ void Serialize(const ChanServ::ChanAccess *, Serialize::Data &data) override
+ {
+ }
+
+ bool Matches(const ChanServ::ChanAccess *access, const User *u, const NickServ::Account *acc, ChanServ::ChanAccess::Path &p) override
+ {
+ if (access->nc)
+ return access->nc == acc;
+
+ if (u)
+ {
+ bool is_mask = access->mask.find_first_of("!@?*") != Anope::string::npos;
+ if (is_mask && Anope::Match(u->nick, access->mask))
+ return true;
+ else if (Anope::Match(u->GetDisplayedMask(), access->mask))
+ return true;
+ }
+
+ if (acc)
+ {
+ for (unsigned i = 0; i < acc->aliases->size(); ++i)
+ {
+ const NickServ::Nick *na = acc->aliases->at(i);
+ if (Anope::Match(na->nick, access->mask))
+ return true;
+ }
+ }
+
+ if (IRCD->IsChannelValid(access->mask))
+ {
+ ChanServ::Channel *tci = Find(access->mask);
+ if (tci)
+ {
+ for (unsigned i = 0; i < tci->GetAccessCount(); ++i)
+ {
+ ChanServ::Cha