diff --git a/include/znc/Modules.h b/include/znc/Modules.h index 50ef5df9..8b9faae6 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -784,6 +784,20 @@ public: */ virtual EModRet OnDeleteNetwork(CIRCNetwork& Network); + /** Called when ZNC sends a raw traffic line to a client. + * @param sLine The raw traffic line sent. + * @param Client The client this line is sent to. + * @warning Calling PutUser() from within this hook leads to infinite recursion. + * @return See CModule::EModRet. + */ + virtual EModRet OnSendToClient(CString& sLine, CClient& Client); + /** Called when ZNC sends a raw traffic line to the IRC server. + * @param sLine The raw traffic line sent. + * @warning Calling PutIRC() from within this hook leads to infinite recursion. + * @return See CModule::EModRet. + */ + virtual EModRet OnSendToIRC(CString& sLine); + ModHandle GetDLL() { return m_pDLL; } static double GetCoreVersion() { return VERSION; } @@ -1135,6 +1149,9 @@ public: bool OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); bool OnDeleteNetwork(CIRCNetwork& Network); + bool OnSendToClient(CString& sLine, CClient& Client); + bool OnSendToIRC(CString& sLine); + bool OnServerCapAvailable(const CString& sCap); bool OnServerCapResult(const CString& sCap, bool bSuccess); diff --git a/modules/modperl/functions.in b/modules/modperl/functions.in index 56d98fe5..8573e71e 100644 --- a/modules/modperl/functions.in +++ b/modules/modperl/functions.in @@ -62,4 +62,6 @@ EModRet OnTimerAutoJoin(CChan& Channel) bool OnEmbeddedWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl)=false EModRet OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) EModRet OnDeleteNetwork(CIRCNetwork& Network) +EModRet OnSendToClient(CString& sLine, CClient& Client) +EModRet OnSendToIRC(CString& sLine) diff --git a/modules/modperl/module.h b/modules/modperl/module.h index c66cebe2..765804c2 100644 --- a/modules/modperl/module.h +++ b/modules/modperl/module.h @@ -102,6 +102,8 @@ public: virtual bool OnEmbeddedWebRequest(CWebSock&, const CString&, CTemplate&); virtual EModRet OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); virtual EModRet OnDeleteNetwork(CIRCNetwork& Network); + virtual EModRet OnSendToClient(CString& sLine, CClient& Client); + virtual EModRet OnSendToIRC(CString& sLine); }; static inline CPerlModule* AsPerlModule(CModule* p) { diff --git a/modules/modperl/startup.pl b/modules/modperl/startup.pl index b5382d54..14be159e 100644 --- a/modules/modperl/startup.pl +++ b/modules/modperl/startup.pl @@ -371,6 +371,8 @@ sub OnTimerAutoJoin {} sub OnEmbeddedWebRequest {} sub OnAddNetwork {} sub OnDeleteNetwork {} +sub OnSendToClient {} +sub OnSendToIRC {} # Functions of CModule will be usable from perl modules. diff --git a/modules/modpython/functions.in b/modules/modpython/functions.in index d3b1f4e7..5fdf3586 100644 --- a/modules/modpython/functions.in +++ b/modules/modpython/functions.in @@ -62,6 +62,8 @@ EModRet OnTimerAutoJoin(CChan& Channel) bool OnEmbeddedWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl)=false EModRet OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) EModRet OnDeleteNetwork(CIRCNetwork& Network) +EModRet OnSendToClient(CString& sLine, CClient& Client) +EModRet OnSendToIRC(CString& sLine) EModRet OnAddUser(CUser& User, CString& sErrorRet) EModRet OnDeleteUser(CUser& User) diff --git a/modules/modpython/module.h b/modules/modpython/module.h index 51867bf7..d246512e 100644 --- a/modules/modpython/module.h +++ b/modules/modpython/module.h @@ -118,6 +118,8 @@ public: virtual bool OnEmbeddedWebRequest(CWebSock&, const CString&, CTemplate&); virtual EModRet OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); virtual EModRet OnDeleteNetwork(CIRCNetwork& Network); + virtual EModRet OnSendToClient(CString& sLine, CClient& Client); + virtual EModRet OnSendToIRC(CString& sLine); // Global Modules virtual EModRet OnAddUser(CUser& User, CString& sErrorRet); diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index f277b9bb..b92a9c0d 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -383,6 +383,12 @@ class Module: def OnDeleteNetwork(self, Network): pass + def OnSendToClient(self, sLine, Client): + pass + + def OnSendToIRC(self, sLine): + pass + # Global modules def OnAddUser(self, User, sErrorRet): pass diff --git a/src/Client.cpp b/src/Client.cpp index 7a84d1de..a6ea8b67 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -19,6 +19,7 @@ #include #include +using std::map; using std::vector; #define CALLMOD(MOD, CLIENT, USER, NETWORK, FUNC) { \ @@ -753,8 +754,12 @@ CString CClient::GetFullName() { } void CClient::PutClient(const CString& sLine) { - DEBUG("(" << GetFullName() << ") ZNC -> CLI [" << sLine << "]"); - Write(sLine + "\r\n"); + bool bReturn = false; + CString sCopy = sLine; + ALLMODULECALL(OnSendToClient(sCopy, *this), &bReturn); + if (bReturn) return; + DEBUG("(" << GetFullName() << ") ZNC -> CLI [" << sCopy << "]"); + Write(sCopy + "\r\n"); } void CClient::PutStatusNotice(const CString& sLine) { diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index ed4eb587..2ef12f64 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -1040,8 +1040,13 @@ void CIRCSock::TrySend() { // This condition must be the same as in PutIRC() and PutIRCQuick()! while (!m_vsSendQueue.empty() && (!m_bFloodProtection || m_iSendsAllowed > 0)) { m_iSendsAllowed--; - DEBUG("(" << m_pNetwork->GetUser()->GetUserName() << "/" << m_pNetwork->GetName() << ") ZNC -> IRC [" << m_vsSendQueue.front() << "]"); - Write(m_vsSendQueue.front() + "\r\n"); + bool bSkip = false; + CString& sLine = m_vsSendQueue.front(); + ALLMODULECALL(OnSendToIRC(sLine), &bSkip); + if (!bSkip) {; + DEBUG("(" << m_pNetwork->GetUser()->GetUserName() << "/" << m_pNetwork->GetName() << ") ZNC -> IRC [" << sLine << "]"); + Write(sLine + "\r\n"); + } m_vsSendQueue.pop_front(); } } diff --git a/src/Modules.cpp b/src/Modules.cpp index 3e118d20..053e763b 100644 --- a/src/Modules.cpp +++ b/src/Modules.cpp @@ -625,6 +625,9 @@ CModule::EModRet CModule::OnTimerAutoJoin(CChan& Channel) { return CONTINUE; } CModule::EModRet CModule::OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) { return CONTINUE; } CModule::EModRet CModule::OnDeleteNetwork(CIRCNetwork& Network) { return CONTINUE; } +CModule::EModRet CModule::OnSendToClient(CString& sLine, CClient& Client) { return CONTINUE; } +CModule::EModRet CModule::OnSendToIRC(CString& sLine) { return CONTINUE; } + bool CModule::OnServerCapAvailable(const CString& sCap) { return false; } void CModule::OnServerCapResult(const CString& sCap, bool bSuccess) {} @@ -792,6 +795,8 @@ bool CModules::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) { MODHALTCH bool CModules::OnTimerAutoJoin(CChan& Channel) { MODHALTCHK(OnTimerAutoJoin(Channel)); } bool CModules::OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) { MODHALTCHK(OnAddNetwork(Network, sErrorRet)); } bool CModules::OnDeleteNetwork(CIRCNetwork& Network) { MODHALTCHK(OnDeleteNetwork(Network)); } +bool CModules::OnSendToClient(CString& sLine, CClient& Client) { MODHALTCHK(OnSendToClient(sLine, Client)); } +bool CModules::OnSendToIRC(CString& sLine) { MODHALTCHK(OnSendToIRC(sLine)); } bool CModules::OnStatusCommand(CString& sCommand) { MODHALTCHK(OnStatusCommand(sCommand)); } bool CModules::OnModCommand(const CString& sCommand) { MODUNLOADCHK(OnModCommand(sCommand)); return false; } bool CModules::OnModNotice(const CString& sMessage) { MODUNLOADCHK(OnModNotice(sMessage)); return false; }