#include "inspircd.h"
+#include "modules/exemption.h"
+#include "modules/names.h"
+#include "modules/who.h"
class AuditoriumMode : public SimpleChannelModeHandler
{
public:
AuditoriumMode(Module* Creator) : SimpleChannelModeHandler(Creator, "auditorium", 'u')
{
- levelrequired = OP_VALUE;
+ ranktoset = ranktounset = OP_VALUE;
}
};
-class ModuleAuditorium : public Module
+class ModuleAuditorium;
+
+namespace
+{
+
+/** Hook handler for join client protocol events.
+ * This allows us to block join protocol events completely, including all associated messages (e.g. MODE, away-notify AWAY).
+ * This is not the same as OnUserJoin() because that runs only when a real join happens but this runs also when a module
+ * such as delayjoin or hostcycle generates a join.
+ */
+class JoinHook : public ClientProtocol::EventHook
{
+ ModuleAuditorium* const parentmod;
+ bool active;
+
+ public:
+ JoinHook(ModuleAuditorium* mod);
+ void OnEventInit(const ClientProtocol::Event& ev) CXX11_OVERRIDE;
+ ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE;
+};
+
+}
+
+class ModuleAuditorium
+ : public Module
+ , public Names::EventListener
+ , public Who::EventListener
+{
+ CheckExemption::EventProvider exemptionprov;
AuditoriumMode aum;
bool OpsVisible;
bool OpsCanSee;
bool OperCanSee;
+ JoinHook joinhook;
public:
- ModuleAuditorium() : aum(this)
+ ModuleAuditorium()
+ : Names::EventListener(this)
+ , Who::EventListener(this)
+ , exemptionprov(this)
+ , aum(this)
+ , joinhook(this)
{
}
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list", VF_VENDOR);
+ return Version("Provides channel mode +u, auditorium channels where nobody can see others joining and parting or the nick list", VF_VENDOR);
}
/* Can they be seen by everyone? */
if (!memb->chan->IsModeSet(&aum))
return true;
- ModResult res = ServerInstance->OnCheckExemption(memb->user, memb->chan, "auditorium-vis");
+ ModResult res = CheckExemption::Call(exemptionprov, memb->user, memb->chan, "auditorium-vis");
return res.check(OpsVisible && memb->getRank() >= OP_VALUE);
}
return true;
// Can you see the list by permission?
- ModResult res = ServerInstance->OnCheckExemption(issuer,memb->chan,"auditorium-see");
+ ModResult res = CheckExemption::Call(exemptionprov, issuer, memb->chan, "auditorium-see");
if (res.check(OpsCanSee && memb->chan->GetPrefixValue(issuer) >= OP_VALUE))
return true;
return false;
}
- ModResult OnNamesListItem(User* issuer, Membership* memb, std::string& prefixes, std::string& nick) CXX11_OVERRIDE
+ ModResult OnNamesListItem(LocalUser* issuer, Membership* memb, std::string& prefixes, std::string& nick) CXX11_OVERRIDE
{
if (IsVisible(memb))
return MOD_RES_PASSTHRU;
}
}
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
- {
- BuildExcept(memb, excepts);
- }
-
void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE
{
BuildExcept(memb, excepts);
}
}
- ModResult OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, Membership* memb, Numeric::Numeric& numeric) CXX11_OVERRIDE
+ ModResult OnWhoLine(const Who::Request& request, LocalUser* source, User* user, Membership* memb, Numeric::Numeric& numeric) CXX11_OVERRIDE
{
if (!memb)
return MOD_RES_PASSTHRU;
}
};
+JoinHook::JoinHook(ModuleAuditorium* mod)
+ : ClientProtocol::EventHook(mod, "JOIN", 10)
+ , parentmod(mod)
+{
+}
+
+void JoinHook::OnEventInit(const ClientProtocol::Event& ev)
+{
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+ active = !parentmod->IsVisible(join.GetMember());
+}
+
+ModResult JoinHook::OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist)
+{
+ if (!active)
+ return MOD_RES_PASSTHRU;
+
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+ return ((parentmod->CanSee(user, join.GetMember())) ? MOD_RES_PASSTHRU : MOD_RES_DENY);
+}
+
MODULE_INIT(ModuleAuditorium)