diff --git a/include/znc/Modules.h b/include/znc/Modules.h index 6ffa9485..489c257a 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -567,6 +567,11 @@ public: * @param sMessage The kick message. */ virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage); + /** This module hook is called just before ZNC tries to join an IRC channel. + * @param Chan The channel which is about to get joined. + * @return See CModule::EModRet. + */ + virtual EModRet OnJoining(CChan& Channel); /** Called when a nick joins a channel. * @param Nick The nick who joined. * @param Channel The channel which was joined. @@ -1112,6 +1117,7 @@ public: bool OnQuit(const CNick& Nick, const CString& sMessage, const std::vector& vChans); bool OnNick(const CNick& Nick, const CString& sNewNick, const std::vector& vChans); bool OnKick(const CNick& Nick, const CString& sOpNick, CChan& Channel, const CString& sMessage); + bool OnJoining(CChan& Channel); bool OnJoin(const CNick& Nick, CChan& Channel); bool OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage); bool OnInvite(const CNick& Nick, const CString& sChan); diff --git a/modules/modperl/functions.in b/modules/modperl/functions.in index b0a4304e..64ed0b41 100644 --- a/modules/modperl/functions.in +++ b/modules/modperl/functions.in @@ -28,6 +28,7 @@ void OnModCTCP(const CString& sMessage) void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) void OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) +EModRet OnJoining(CChan& Channel) void OnJoin(const CNick& Nick, CChan& Channel) void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) EModRet OnChanBufferStarting(CChan& Chan, CClient& Client) diff --git a/modules/modperl/module.h b/modules/modperl/module.h index c38f2b83..a881386d 100644 --- a/modules/modperl/module.h +++ b/modules/modperl/module.h @@ -68,6 +68,7 @@ public: virtual void OnQuit(const CNick& Nick, const CString& sMessage, const std::vector& vChans); virtual void OnNick(const CNick& Nick, const CString& sNewNick, const std::vector& vChans); virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage); + virtual EModRet OnJoining(CChan& Channel); virtual void OnJoin(const CNick& Nick, CChan& Channel); virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage); virtual EModRet OnChanBufferStarting(CChan& Chan, CClient& Client); diff --git a/modules/modperl/startup.pl b/modules/modperl/startup.pl index fa7a8109..dd602b10 100644 --- a/modules/modperl/startup.pl +++ b/modules/modperl/startup.pl @@ -337,6 +337,7 @@ sub OnModCTCP {} sub OnQuit {} sub OnNick {} sub OnKick {} +sub OnJoining {} sub OnJoin {} sub OnPart {} sub OnChanBufferStarting {} diff --git a/modules/modpython/functions.in b/modules/modpython/functions.in index 050937d8..4a9e17e3 100644 --- a/modules/modpython/functions.in +++ b/modules/modpython/functions.in @@ -28,6 +28,7 @@ void OnModCTCP(const CString& sMessage) void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) void OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) +EModRet OnJoining(CChan& Channel) void OnJoin(const CNick& Nick, CChan& Channel) void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) EModRet OnChanBufferStarting(CChan& Chan, CClient& Client) diff --git a/modules/modpython/module.h b/modules/modpython/module.h index 10dc07af..2a4e265b 100644 --- a/modules/modpython/module.h +++ b/modules/modpython/module.h @@ -84,6 +84,7 @@ public: virtual void OnQuit(const CNick& Nick, const CString& sMessage, const std::vector& vChans); virtual void OnNick(const CNick& Nick, const CString& sNewNick, const std::vector& vChans); virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage); + virtual EModRet OnJoining(CChan& Channel); virtual void OnJoin(const CNick& Nick, CChan& Channel); virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage); virtual EModRet OnChanBufferStarting(CChan& Chan, CClient& Client); diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index fc4211a5..d0e566de 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -281,6 +281,9 @@ class Module: def OnKick(self, OpNick, sKickedNick, Channel, sMessage): pass + def OnJoining(self, Channel): + pass + def OnJoin(self, Nick, Channel): pass diff --git a/modules/q.cpp b/modules/q.cpp index 648f7e9c..9b6a6acf 100644 --- a/modules/q.cpp +++ b/modules/q.cpp @@ -40,15 +40,17 @@ public: } CString sTmp; - m_bUseCloakedHost = (sTmp = GetNV("UseCloakedHost")).empty() ? true : sTmp.ToBool(); - m_bUseChallenge = (sTmp = GetNV("UseChallenge")).empty() ? true : sTmp.ToBool(); - m_bRequestPerms = GetNV("RequestPerms").ToBool(); - m_bJoinOnInvite = (sTmp = GetNV("JoinOnInvite")).empty() ? true : sTmp.ToBool(); + m_bUseCloakedHost = (sTmp = GetNV("UseCloakedHost")).empty() ? true : sTmp.ToBool(); + m_bUseChallenge = (sTmp = GetNV("UseChallenge")).empty() ? true : sTmp.ToBool(); + m_bRequestPerms = GetNV("RequestPerms").ToBool(); + m_bJoinOnInvite = (sTmp = GetNV("JoinOnInvite")).empty() ? true : sTmp.ToBool(); + m_bJoinAfterCloaked = (sTmp = GetNV("JoinAfterCloaked")).empty() ? true : sTmp.ToBool(); // Make sure NVs are stored in config. Note: SetUseCloakedHost() is called further down. SetUseChallenge(m_bUseChallenge); SetRequestPerms(m_bRequestPerms); SetJoinOnInvite(m_bJoinOnInvite); + SetJoinAfterCloaked(m_bJoinAfterCloaked); OnIRCDisconnected(); // reset module's state @@ -67,6 +69,8 @@ public: "with /msg *q Set UseCloakedHost true/false."); m_bUseCloakedHost = true; SetUseCloakedHost(m_bUseCloakedHost); + m_bJoinAfterCloaked = true; + SetJoinAfterCloaked(m_bJoinAfterCloaked); } else if (m_bUseChallenge) { Cloak(); } @@ -149,6 +153,10 @@ public: Table2.SetCell("Setting", "JoinOnInvite"); Table2.SetCell("Type", "Boolean"); Table2.SetCell("Description", "Whether to join channels when Q invites you."); + Table2.AddRow(); + Table2.SetCell("Setting", "JoinAfterCloaked"); + Table2.SetCell("Type", "Boolean"); + Table2.SetCell("Description", "Whether to delay joining channels until after you are cloaked."); PutModule(Table2); PutModule("This module takes 2 optional parameters: "); @@ -177,6 +185,9 @@ public: } else if (sSetting == "joinoninvite") { SetJoinOnInvite(sValue.ToBool()); PutModule("JoinOnInvite set"); + } else if (sSetting == "joinaftercloaked") { + SetJoinAfterCloaked(sValue.ToBool()); + PutModule("JoinAfterCloaked set"); } else PutModule("Unknown setting: " + sSetting); @@ -202,6 +213,9 @@ public: Table.AddRow(); Table.SetCell("Setting", "JoinOnInvite"); Table.SetCell("Value", CString(m_bJoinOnInvite)); + Table.AddRow(); + Table.SetCell("Setting", "JoinAfterCloaked"); + Table.SetCell("Value", CString(m_bJoinAfterCloaked)); PutModule(Table); } else if (sCommand == "status") { @@ -255,6 +269,13 @@ public: return HandleMessage(Nick, sMessage); } + virtual EModRet OnJoining(CChan& Channel) { + if (m_bJoinAfterCloaked && !m_bCloaked) + return HALT; + + return CONTINUE; + } + virtual void OnJoin(const CNick& Nick, CChan& Channel) { if (m_bRequestPerms && IsSelf(Nick)) HandleNeed(Channel, "ov"); @@ -297,6 +318,7 @@ public: SetUseChallenge(WebSock.GetParam("usechallenge").ToBool()); SetRequestPerms(WebSock.GetParam("requestperms").ToBool()); SetJoinOnInvite(WebSock.GetParam("joinoninvite").ToBool()); + SetJoinAfterCloaked(WebSock.GetParam("joinaftercloaked").ToBool()); } Tmpl["Username"] = m_sUsername; @@ -325,6 +347,12 @@ public: o4["Tooltip"] = "Whether to join channels when Q invites you."; o4["Checked"] = CString(m_bJoinOnInvite); + CTemplate& o5 = Tmpl.AddRow("OptionLoop"); + o5["Name"] = "joinaftercloaked"; + o5["DisplayName"] = "JoinAfterCloaked"; + o5["Tooltip"] = "Whether to delay joining channels until after you are cloaked."; + o5["Checked"] = CString(m_bJoinAfterCloaked); + if (bSubmitted) { WebSock.GetSession()->AddSuccess("Changes have been saved!"); } @@ -558,6 +586,7 @@ private: bool m_bUseChallenge; bool m_bRequestPerms; bool m_bJoinOnInvite; + bool m_bJoinAfterCloaked; void SetUsername(const CString& sUsername) { m_sUsername = sUsername; @@ -591,6 +620,11 @@ private: m_bJoinOnInvite = bJoinOnInvite; SetNV("JoinOnInvite", CString(bJoinOnInvite)); } + + void SetJoinAfterCloaked(const bool bJoinAfterCloaked) { + m_bJoinAfterCloaked = bJoinAfterCloaked; + SetNV("JoinAfterCloaked", CString(bJoinAfterCloaked)); + } }; template<> void TModInfo(CModInfo& Info) { diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index 412c4ddd..fc1bc60d 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -762,6 +762,12 @@ void CIRCNetwork::JoinChans(set& sChans) { } bool CIRCNetwork::JoinChan(CChan* pChan) { + bool bReturn = false; + NETWORKMODULECALL(OnJoining(*pChan), m_pUser, this, NULL, &bReturn); + + if (bReturn) + return false; + if (m_pUser->JoinTries() != 0 && pChan->GetJoinTries() >= m_pUser->JoinTries()) { PutStatus("The channel " + pChan->GetName() + " could not be joined, disabling it."); pChan->Disable(); diff --git a/src/Modules.cpp b/src/Modules.cpp index 4a695368..5e8e39a7 100644 --- a/src/Modules.cpp +++ b/src/Modules.cpp @@ -589,6 +589,7 @@ void CModule::OnUnknownModCommand(const CString& sLine) { void CModule::OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) {} void CModule::OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) {} void CModule::OnKick(const CNick& Nick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) {} +CModule::EModRet CModule::OnJoining(CChan& Channel) { return CONTINUE; } void CModule::OnJoin(const CNick& Nick, CChan& Channel) {} void CModule::OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) {} CModule::EModRet CModule::OnInvite(const CNick& Nick, const CString& sChan) { return CONTINUE; } @@ -775,6 +776,7 @@ bool CModules::OnUserTopicRequest(CString& sChannel) { MODHALTCHK(OnUserTopicReq bool CModules::OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) { MODUNLOADCHK(OnQuit(Nick, sMessage, vChans)); return false; } bool CModules::OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) { MODUNLOADCHK(OnNick(Nick, sNewNick, vChans)); return false; } bool CModules::OnKick(const CNick& Nick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) { MODUNLOADCHK(OnKick(Nick, sKickedNick, Channel, sMessage)); return false; } +bool CModules::OnJoining(CChan& Channel) { MODHALTCHK(OnJoining(Channel)); } bool CModules::OnJoin(const CNick& Nick, CChan& Channel) { MODUNLOADCHK(OnJoin(Nick, Channel)); return false; } bool CModules::OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) { MODUNLOADCHK(OnPart(Nick, Channel, sMessage)); return false; } bool CModules::OnInvite(const CNick& Nick, const CString& sChan) { MODHALTCHK(OnInvite(Nick, sChan)); }