diff --git a/include/znc/IRCSock.h b/include/znc/IRCSock.h index a6949529..cf1fc0e9 100644 --- a/include/znc/IRCSock.h +++ b/include/znc/IRCSock.h @@ -28,6 +28,7 @@ class CChan; class CUser; class CIRCNetwork; class CClient; +class CMessage; // !Forward Declarations // TODO: This class needs new name @@ -49,13 +50,13 @@ public: // Message Handlers bool OnCTCPReply(CNick& Nick, CString& sMessage); - bool OnPrivCTCP(CNick& Nick, CString& sMessage); - bool OnChanCTCP(CNick& Nick, const CString& sChan, CString& sMessage); - bool OnGeneralCTCP(CNick& Nick, CString& sMessage); - bool OnPrivMsg(CNick& Nick, CString& sMessage); - bool OnChanMsg(CNick& Nick, const CString& sChan, CString& sMessage); - bool OnPrivNotice(CNick& Nick, CString& sMessage); - bool OnChanNotice(CNick& Nick, const CString& sChan, CString& sMessage); + bool OnPrivCTCP(CMessage& Message); + bool OnChanCTCP(CMessage& Message); + bool OnGeneralCTCP(CMessage& Message); + bool OnPrivMsg(CMessage& Message); + bool OnChanMsg(CMessage& Message); + bool OnPrivNotice(CMessage& Message); + bool OnChanNotice(CMessage& Message); bool OnServerCapAvailable(const CString& sCap); // !Message Handlers diff --git a/include/znc/Message.h b/include/znc/Message.h index b31a1c02..40a64d68 100644 --- a/include/znc/Message.h +++ b/include/znc/Message.h @@ -87,4 +87,107 @@ private: CChan* m_pChan = nullptr; }; +class CChanAction : public CMessage { +public: + CString GetText() const { return GetParam(1).TrimLeft_n("\001ACTION ").TrimRight_n("\001"); } + void SetText(const CString& sText) { SetParam(1, "\001ACTION " + sText + "\001"); } +}; + +class CChanCTCP : public CMessage { +public: + CString GetText() const { return GetParam(1).TrimLeft_n("\001").TrimRight_n("\001"); } + void SetText(const CString& sText) { SetParam(1, "\001" + sText + "\001"); } +}; + +class CChanMessage : public CMessage { +public: + CString GetText() const { return GetParam(1); } + void SetText(const CString& sText) { SetParam(1, sText); } +}; + +class CChanNotice : public CMessage { +public: + CString GetText() const { return GetParam(1); } + void SetText(const CString& sText) { SetParam(1, sText); } +}; + +class CJoinMessage : public CMessage { +public: +}; + +class CNickMessage : public CMessage { +public: + CString GetOldNick() const { return GetNick().GetNick(); } + CString GetNewNick() const { return GetParam(0); } + void SetNewNick(const CString& sNick) { SetParam(0, sNick); } +}; + +class CKickMessage : public CMessage { +public: + CString GetKickedNick() const { return GetParam(1); } + void SetKickedNick(const CString& sNick) { SetParam(1, sNick); } + CString GetReason() const { return GetParam(2); } + void SetReason(const CString& sReason) { SetParam(2, sReason); } +}; + +class CPartMessage : public CMessage { +public: + CString GetReason() const { return GetParam(1); } + void SetReason(const CString& sReason) { SetParam(1, sReason); } +}; + +class CPrivAction : public CMessage { +public: + CString GetText() const { return GetParam(1).TrimLeft_n("\001ACTION ").TrimRight_n("\001"); } + void SetText(const CString& sText) { SetParam(1, "\001ACTION " + sText + "\001"); } +}; + +class CPrivCTCP : public CMessage { +public: + CString GetText() const { return GetParam(1).TrimLeft_n("\001").TrimRight_n("\001"); } + void SetText(const CString& sText) { SetParam(1, "\001" + sText + "\001"); } +}; + +class CPrivMessage : public CMessage { +public: + CString GetText() const { return GetParam(1); } + void SetText(const CString& sText) { SetParam(1, sText); } +}; + +class CPrivNotice : public CMessage { +public: + CString GetText() const { return GetParam(1); } + void SetText(const CString& sText) { SetParam(1, sText); } +}; + +class CQuitMessage : public CMessage { +public: + CString GetReason() const { return GetParam(0); } + void SetReason(const CString& sReason) { SetParam(0, sReason); } +}; + +class CTopicMessage : public CMessage { +public: + CString GetTopic() const { return GetParam(1); } + void SetTopic(const CString& sTopic) { SetParam(1, sTopic); } +}; + +// The various CMessage subclasses are "mutable views" to the data held by CMessage. +// They provide convenient access to message type speficic attributes, but are not +// allowed to hold extra data of their own. +static_assert(sizeof(CChanAction) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CChanCTCP) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CChanMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CChanNotice) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CJoinMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CPartMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CPrivAction) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CPrivCTCP) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CPrivMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CPrivNotice) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CNickMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CKickMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CQuitMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); +static_assert(sizeof(CTopicMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); + #endif // !_MESSAGE_H diff --git a/include/znc/Modules.h b/include/znc/Modules.h index 5771c80d..fe5a2c75 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -593,6 +594,7 @@ public: * @param vChans List of channels which you and nick share. */ virtual void OnQuit(const CNick& Nick, const CString& sMessage, const std::vector& vChans); + virtual void OnQuitMessage(CQuitMessage& Message, const std::vector& vChans); /** Called when a nickname change occurs. If we are changing our nick, * sNewNick will equal m_pIRCSock->GetNick(). * @param Nick The nick which changed its nickname @@ -600,6 +602,7 @@ public: * @param vChans Channels which we and nick share. */ virtual void OnNick(const CNick& Nick, const CString& sNewNick, const std::vector& vChans); + virtual void OnNickMessage(CNickMessage& Message, const std::vector& vChans); /** Called when a nick is kicked from a channel. * @param OpNick The nick which generated the kick. * @param sKickedNick The nick which was kicked. @@ -607,6 +610,7 @@ public: * @param sMessage The kick message. */ virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage); + virtual void OnKickMessage(CKickMessage& Message); /** 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. @@ -617,12 +621,14 @@ public: * @param Channel The channel which was joined. */ virtual void OnJoin(const CNick& Nick, CChan& Channel); + virtual void OnJoinMessage(CJoinMessage& Message); /** Called when a nick parts a channel. * @param Nick The nick who parted. * @param Channel The channel which was parted. * @param sMessage The part message. */ virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage); + virtual void OnPartMessage(CPartMessage& Message); /** Called when user is invited into a channel * @param Nick The nick who invited you. * @param sChan The channel the user got invited into @@ -749,6 +755,7 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnPrivCTCP(CNick& Nick, CString& sMessage); + virtual EModRet OnPrivCTCPMessage(CPrivCTCP& Message); /** Called when we receive a channel CTCP request from IRC. * @param Nick The nick the CTCP request is from. * @param Channel The channel to which the request was sent. @@ -756,6 +763,7 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnChanCTCP(CNick& Nick, CChan& Channel, CString& sMessage); + virtual EModRet OnChanCTCPMessage(CChanCTCP& Message); /** Called when we receive a private CTCP ACTION ("/me" in query) from IRC. * This is called after CModule::OnPrivCTCP(). * @param Nick The nick the action came from. @@ -763,6 +771,7 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnPrivAction(CNick& Nick, CString& sMessage); + virtual EModRet OnPrivActionMessage(CPrivAction& Message); /** Called when we receive a channel CTCP ACTION ("/me" in a channel) from IRC. * This is called after CModule::OnChanCTCP(). * @param Nick The nick the action came from. @@ -771,12 +780,14 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage); + virtual EModRet OnChanActionMessage(CChanAction& Message); /** Called when we receive a private message from IRC. * @param Nick The nick which sent the message. * @param sMessage The message. * @return See CModule::EModRet. */ virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage); + virtual EModRet OnPrivMessage(CPrivMessage& Message); /** Called when we receive a channel message from IRC. * @param Nick The nick which sent the message. * @param Channel The channel to which the message was sent. @@ -784,12 +795,14 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage); + virtual EModRet OnChanMessage(CChanMessage& Message); /** Called when we receive a private notice. * @param Nick The nick which sent the notice. * @param sMessage The notice message. * @return See CModule::EModRet. */ virtual EModRet OnPrivNotice(CNick& Nick, CString& sMessage); + virtual EModRet OnPrivNoticeMessage(CPrivNotice& Message); /** Called when we receive a channel notice. * @param Nick The nick which sent the notice. * @param Channel The channel to which the notice was sent. @@ -797,6 +810,7 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage); + virtual EModRet OnChanNoticeMessage(CChanNotice& Message); /** Called when we receive a channel topic change from IRC. * @param Nick The nick which changed the topic. * @param Channel The channel whose topic was changed. @@ -804,6 +818,7 @@ public: * @return See CModule::EModRet. */ virtual EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sTopic); + virtual EModRet OnTopicMessage(CTopicMessage& Message); /** Called for every CAP received via CAP LS from server. * @param sCap capability supported by server. @@ -1186,11 +1201,16 @@ public: bool OnModCTCP(const CString& sMessage); bool OnQuit(const CNick& Nick, const CString& sMessage, const std::vector& vChans); + bool OnQuitMessage(CQuitMessage& Message, const std::vector& vChans); bool OnNick(const CNick& Nick, const CString& sNewNick, const std::vector& vChans); + bool OnNickMessage(CNickMessage& Message, const std::vector& vChans); bool OnKick(const CNick& Nick, const CString& sOpNick, CChan& Channel, const CString& sMessage); + bool OnKickMessage(CKickMessage& Message); bool OnJoining(CChan& Channel); bool OnJoin(const CNick& Nick, CChan& Channel); + bool OnJoinMessage(CJoinMessage& Message); bool OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage); + bool OnPartMessage(CPartMessage& Message); bool OnInvite(const CNick& Nick, const CString& sChan); bool OnChanBufferStarting(CChan& Chan, CClient& Client); @@ -1216,14 +1236,23 @@ public: bool OnCTCPReply(CNick& Nick, CString& sMessage); bool OnPrivCTCP(CNick& Nick, CString& sMessage); + bool OnPrivCTCPMessage(CPrivCTCP& Message); bool OnChanCTCP(CNick& Nick, CChan& Channel, CString& sMessage); + bool OnChanCTCPMessage(CChanCTCP& Message); bool OnPrivAction(CNick& Nick, CString& sMessage); + bool OnPrivActionMessage(CPrivAction& Message); bool OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage); + bool OnChanActionMessage(CChanAction& Message); bool OnPrivMsg(CNick& Nick, CString& sMessage); + bool OnPrivMessage(CPrivMessage& Message); bool OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage); + bool OnChanMessage(CChanMessage& Message); bool OnPrivNotice(CNick& Nick, CString& sMessage); + bool OnPrivNoticeMessage(CPrivNotice& Message); bool OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage); + bool OnChanNoticeMessage(CChanNotice& Message); bool OnTopic(CNick& Nick, CChan& Channel, CString& sTopic); + bool OnTopicMessage(CTopicMessage& Message); bool OnTimerAutoJoin(CChan& Channel); bool OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index c2a31914..5e650143 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -507,7 +507,8 @@ void CIRCSock::ReadLine(const CString& sData) { CNick Nick = Message.GetNick(); if (sCmd.Equals("NICK")) { - CString sNewNick = Message.GetParam(0); + CNickMessage& NickMsg = static_cast(Message); + CString sNewNick = NickMsg.GetNewNick(); bool bIsVisible = false; vector vFoundChans; @@ -530,19 +531,19 @@ void CIRCSock::ReadLine(const CString& sData) { m_pNetwork->PutUser(sLine); } - IRCSOCKMODULECALL(OnNick(Nick, sNewNick, vFoundChans), NOTHING); + IRCSOCKMODULECALL(OnNickMessage(NickMsg, vFoundChans), NOTHING); if (!bIsVisible) { return; } } else if (sCmd.Equals("QUIT")) { - CString sMessage = Message.GetParam(0); + CQuitMessage& QuitMsg = static_cast(Message); bool bIsVisible = false; // :nick!ident@host.com QUIT :message if (Nick.NickEquals(GetNick())) { - m_pNetwork->PutStatus("You quit [" + sMessage + "]"); + m_pNetwork->PutStatus("You quit [" + QuitMsg.GetReason() + "]"); // We don't call module hooks and we don't // forward this quit to clients (Some clients // disconnect if they receive such a QUIT) @@ -562,14 +563,15 @@ void CIRCSock::ReadLine(const CString& sData) { } } - IRCSOCKMODULECALL(OnQuit(Nick, sMessage, vFoundChans), NOTHING); + IRCSOCKMODULECALL(OnQuitMessage(QuitMsg, vFoundChans), NOTHING); if (!bIsVisible) { return; } } else if (sCmd.Equals("JOIN")) { - CString sChan = Message.GetParam(0); - CChan* pChan; + CJoinMessage& JoinMsg = static_cast(Message); + CString sChan = JoinMsg.GetParam(0); + CChan* pChan = nullptr; if (Nick.NickEquals(GetNick())) { m_pNetwork->AddChan(sChan, false); @@ -585,7 +587,8 @@ void CIRCSock::ReadLine(const CString& sData) { if (pChan) { pChan->AddNick(Nick.GetNickMask()); - IRCSOCKMODULECALL(OnJoin(Nick.GetNickMask(), *pChan), NOTHING); + JoinMsg.SetChan(pChan); + IRCSOCKMODULECALL(OnJoinMessage(JoinMsg), NOTHING); if (pChan->IsDetached()) { return; @@ -607,14 +610,15 @@ void CIRCSock::ReadLine(const CString& sData) { } } } else if (sCmd.Equals("PART")) { - CString sChan = Message.GetParam(0); - CString sMsg = Message.GetParam(1); + CPartMessage& PartMsg = static_cast(Message); + CString sChan = PartMsg.GetParam(0); CChan* pChan = m_pNetwork->FindChan(sChan); bool bDetached = false; if (pChan) { pChan->RemNick(Nick.GetNick()); - IRCSOCKMODULECALL(OnPart(Nick.GetNickMask(), *pChan, sMsg), NOTHING); + PartMsg.SetChan(pChan); + IRCSOCKMODULECALL(OnPartMessage(PartMsg), NOTHING); if (pChan->IsDetached()) bDetached = true; @@ -667,15 +671,16 @@ void CIRCSock::ReadLine(const CString& sData) { } } } else if (sCmd.Equals("KICK")) { + CKickMessage& KickMsg = static_cast(Message); // :opnick!ident@host.com KICK #chan nick :msg - CString sChan = Message.GetParam(0); - CString sKickedNick = Message.GetParam(1); - CString sMsg = Message.GetParam(2); + CString sChan = KickMsg.GetParam(0); + CString sKickedNick = KickMsg.GetKickedNick(); CChan* pChan = m_pNetwork->FindChan(sChan); if (pChan) { - IRCSOCKMODULECALL(OnKick(Nick, sKickedNick, *pChan, sMsg), NOTHING); + KickMsg.SetChan(pChan); + IRCSOCKMODULECALL(OnKickMessage(KickMsg), NOTHING); // do not remove the nick till after the OnKick call, so modules // can do Chan.FindNick or something to get more info. pChan->RemNick(sKickedNick); @@ -710,11 +715,11 @@ void CIRCSock::ReadLine(const CString& sData) { return; } else { if (sTarget.Equals(GetNick())) { - if (OnPrivNotice(Nick, sMsg)) { + if (OnPrivNotice(Message)) { return; } } else { - if (OnChanNotice(Nick, sTarget, sMsg)) { + if (OnChanNotice(Message)) { return; } } @@ -728,24 +733,24 @@ void CIRCSock::ReadLine(const CString& sData) { return; } else if (sCmd.Equals("TOPIC")) { + CTopicMessage& TopicMsg = static_cast(Message); // :nick!ident@host.com TOPIC #chan :This is a topic - CChan* pChan = m_pNetwork->FindChan(Message.GetParam(0)); + CChan* pChan = m_pNetwork->FindChan(TopicMsg.GetParam(0)); if (pChan) { - CString sTopic = Message.GetParam(1); - - IRCSOCKMODULECALL(OnTopic(Nick, *pChan, sTopic), &bReturn); + TopicMsg.SetChan(pChan); + IRCSOCKMODULECALL(OnTopicMessage(TopicMsg), &bReturn); if (bReturn) return; pChan->SetTopicOwner(Nick.GetNick()); pChan->SetTopicDate((unsigned long) time(nullptr)); - pChan->SetTopic(sTopic); + pChan->SetTopic(TopicMsg.GetTopic()); if (pChan->IsDetached()) { return; // Don't forward this } - sLine = ":" + Nick.GetNickMask() + " TOPIC " + pChan->GetName() + " :" + sTopic; + sLine = ":" + Nick.GetNickMask() + " TOPIC " + pChan->GetName() + " :" + pChan->GetTopic(); } } else if (sCmd.Equals("PRIVMSG")) { // :nick!ident@host.com PRIVMSG #chan :Message @@ -757,11 +762,11 @@ void CIRCSock::ReadLine(const CString& sData) { sMsg.RightChomp(); if (sTarget.Equals(GetNick())) { - if (OnPrivCTCP(Nick, sMsg)) { + if (OnPrivCTCP(Message)) { return; } } else { - if (OnChanCTCP(Nick, sTarget, sMsg)) { + if (OnChanCTCP(Message)) { return; } } @@ -770,11 +775,11 @@ void CIRCSock::ReadLine(const CString& sData) { return; } else { if (sTarget.Equals(GetNick())) { - if (OnPrivMsg(Nick, sMsg)) { + if (OnPrivMsg(Message)) { return; } } else { - if (OnChanMsg(Nick, sTarget, sMsg)) { + if (OnChanMsg(Message)) { return; } } @@ -911,31 +916,34 @@ bool CIRCSock::OnCTCPReply(CNick& Nick, CString& sMessage) { return bResult; } -bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) { +bool CIRCSock::OnPrivCTCP(CMessage& Message) { + CPrivCTCP& PrivCTCP = static_cast(Message); bool bResult = false; - IRCSOCKMODULECALL(OnPrivCTCP(Nick, sMessage), &bResult); + IRCSOCKMODULECALL(OnPrivCTCPMessage(PrivCTCP), &bResult); if (bResult) return true; - if (sMessage.TrimPrefix("ACTION ")) { + if (PrivCTCP.GetText().StartsWith("ACTION ")) { bResult = false; - IRCSOCKMODULECALL(OnPrivAction(Nick, sMessage), &bResult); + CPrivAction& PrivAction = static_cast(Message); + IRCSOCKMODULECALL(OnPrivActionMessage(PrivAction), &bResult); if (bResult) return true; if (!m_pNetwork->IsUserOnline() || !m_pNetwork->GetUser()->AutoClearQueryBuffer()) { + const CNick& Nick = PrivAction.GetNick(); CQuery* pQuery = m_pNetwork->AddQuery(Nick.GetNick()); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION {text}\001", sMessage); + pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION {text}\001", PrivAction.GetText()); } } - - sMessage = "ACTION " + sMessage; } // This handles everything which wasn't handled yet - return OnGeneralCTCP(Nick, sMessage); + return OnGeneralCTCP(Message); } -bool CIRCSock::OnGeneralCTCP(CNick& Nick, CString& sMessage) { +bool CIRCSock::OnGeneralCTCP(CMessage& Message) { + const CNick& Nick = Message.GetNick(); + const CString& sMessage = Message.GetParam(1); const MCString& mssCTCPReplies = m_pNetwork->GetUser()->GetCTCPReplies(); CString sQuery = sMessage.Token(0).AsUpper(); MCString::const_iterator it = mssCTCPReplies.find(sQuery); @@ -979,83 +987,92 @@ bool CIRCSock::OnGeneralCTCP(CNick& Nick, CString& sMessage) { return false; } -bool CIRCSock::OnPrivNotice(CNick& Nick, CString& sMessage) { +bool CIRCSock::OnPrivNotice(CMessage& Message) { + CPrivNotice& PrivNotice = static_cast(Message); bool bResult = false; - IRCSOCKMODULECALL(OnPrivNotice(Nick, sMessage), &bResult); + IRCSOCKMODULECALL(OnPrivNoticeMessage(PrivNotice), &bResult); if (bResult) return true; if (!m_pNetwork->IsUserOnline()) { // If the user is detached, add to the buffer - m_pNetwork->AddNoticeBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE {target} :{text}", sMessage); + m_pNetwork->AddNoticeBuffer(":" + _NAMEDFMT(PrivNotice.GetNick().GetNickMask()) + " NOTICE {target} :{text}", PrivNotice.GetText()); } return false; } -bool CIRCSock::OnPrivMsg(CNick& Nick, CString& sMessage) { +bool CIRCSock::OnPrivMsg(CMessage& Message) { + CPrivMessage& PrivMsg = static_cast(Message); bool bResult = false; - IRCSOCKMODULECALL(OnPrivMsg(Nick, sMessage), &bResult); + IRCSOCKMODULECALL(OnPrivMessage(PrivMsg), &bResult); if (bResult) return true; if (!m_pNetwork->IsUserOnline() || !m_pNetwork->GetUser()->AutoClearQueryBuffer()) { + const CNick& Nick = PrivMsg.GetNick(); CQuery* pQuery = m_pNetwork->AddQuery(Nick.GetNick()); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :{text}", sMessage); + pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :{text}", PrivMsg.GetText()); } } return false; } -bool CIRCSock::OnChanCTCP(CNick& Nick, const CString& sChan, CString& sMessage) { - CChan* pChan = m_pNetwork->FindChan(sChan); +bool CIRCSock::OnChanCTCP(CMessage& Message) { + CChanCTCP& ChanCTCP = static_cast(Message); + CChan* pChan = m_pNetwork->FindChan(ChanCTCP.GetParam(0)); if (pChan) { bool bResult = false; - IRCSOCKMODULECALL(OnChanCTCP(Nick, *pChan, sMessage), &bResult); + ChanCTCP.SetChan(pChan); + IRCSOCKMODULECALL(OnChanCTCPMessage(ChanCTCP), &bResult); if (bResult) return true; // Record a /me - if (sMessage.TrimPrefix("ACTION ")) { + if (ChanCTCP.GetText().StartsWith("ACTION ")) { bResult = false; - IRCSOCKMODULECALL(OnChanAction(Nick, *pChan, sMessage), &bResult); + CChanAction& ChanAction = static_cast(Message); + IRCSOCKMODULECALL(OnChanActionMessage(ChanAction), &bResult); if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :\001ACTION {text}\001", sMessage); + pChan->AddBuffer(":" + _NAMEDFMT(Message.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :\001ACTION {text}\001", ChanAction.GetText()); } - sMessage = "ACTION " + sMessage; } } - if (OnGeneralCTCP(Nick, sMessage)) + if (OnGeneralCTCP(Message)) return true; return (pChan && pChan->IsDetached()); } -bool CIRCSock::OnChanNotice(CNick& Nick, const CString& sChan, CString& sMessage) { - CChan* pChan = m_pNetwork->FindChan(sChan); +bool CIRCSock::OnChanNotice(CMessage& Message) { + CChanNotice& ChanNotice = static_cast(Message); + CChan* pChan = m_pNetwork->FindChan(ChanNotice.GetParam(0)); if (pChan) { bool bResult = false; - IRCSOCKMODULECALL(OnChanNotice(Nick, *pChan, sMessage), &bResult); + ChanNotice.SetChan(pChan); + IRCSOCKMODULECALL(OnChanNoticeMessage(ChanNotice), &bResult); if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE " + _NAMEDFMT(sChan) + " :{text}", sMessage); + pChan->AddBuffer(":" + _NAMEDFMT(ChanNotice.GetNick().GetNickMask()) + " NOTICE " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanNotice.GetText()); } } return ((pChan) && (pChan->IsDetached())); } -bool CIRCSock::OnChanMsg(CNick& Nick, const CString& sChan, CString& sMessage) { - CChan* pChan = m_pNetwork->FindChan(sChan); +bool CIRCSock::OnChanMsg(CMessage& Message) { + CChanMessage& ChanMsg = static_cast(Message); + CChan* pChan = m_pNetwork->FindChan(ChanMsg.GetParam(0)); if (pChan) { bool bResult = false; - IRCSOCKMODULECALL(OnChanMsg(Nick, *pChan, sMessage), &bResult); + ChanMsg.SetChan(pChan); + IRCSOCKMODULECALL(OnChanMessage(ChanMsg), &bResult); if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :{text}", sMessage); + pChan->AddBuffer(":" + _NAMEDFMT(ChanMsg.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanMsg.GetText()); } } diff --git a/src/Modules.cpp b/src/Modules.cpp index 2ce73a16..3b7f1578 100644 --- a/src/Modules.cpp +++ b/src/Modules.cpp @@ -636,11 +636,16 @@ void CModule::OnUnknownModCommand(const CString& sLine) { } void CModule::OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) {} +void CModule::OnQuitMessage(CQuitMessage& Message, const vector& vChans) { OnQuit(Message.GetNick(), Message.GetReason(), vChans); } void CModule::OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) {} +void CModule::OnNickMessage(CNickMessage& Message, const vector& vChans) { OnNick(Message.GetNick(), Message.GetNewNick(), vChans); } void CModule::OnKick(const CNick& Nick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) {} +void CModule::OnKickMessage(CKickMessage& Message) { OnKick(Message.GetNick(), Message.GetKickedNick(), *Message.GetChan(), Message.GetReason()); } CModule::EModRet CModule::OnJoining(CChan& Channel) { return CONTINUE; } void CModule::OnJoin(const CNick& Nick, CChan& Channel) {} +void CModule::OnJoinMessage(CJoinMessage& Message) { OnJoin(Message.GetNick(), *Message.GetChan()); } void CModule::OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) {} +void CModule::OnPartMessage(CPartMessage& Message) { OnPart(Message.GetNick(), *Message.GetChan(), Message.GetReason()); } CModule::EModRet CModule::OnInvite(const CNick& Nick, const CString& sChan) { return CONTINUE; } CModule::EModRet CModule::OnChanBufferStarting(CChan& Chan, CClient& Client) { return CONTINUE; } @@ -671,14 +676,68 @@ CModule::EModRet CModule::OnUserQuit(CString& sMessage) { return CONTINUE; } CModule::EModRet CModule::OnCTCPReply(CNick& Nick, CString& sMessage) { return CONTINUE; } CModule::EModRet CModule::OnPrivCTCP(CNick& Nick, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnPrivCTCPMessage(CPrivCTCP& Message) { + CString sText = Message.GetText(); + EModRet ret = OnPrivCTCP(Message.GetNick(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnChanCTCP(CNick& Nick, CChan& Channel, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnChanCTCPMessage(CChanCTCP& Message) { + CString sText = Message.GetText(); + EModRet ret = OnChanCTCP(Message.GetNick(), *Message.GetChan(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnPrivAction(CNick& Nick, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnPrivActionMessage(CPrivAction& Message) { + CString sText = Message.GetText(); + EModRet ret = OnPrivAction(Message.GetNick(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnChanActionMessage(CChanAction& Message) { + CString sText = Message.GetText(); + EModRet ret = OnChanAction(Message.GetNick(), *Message.GetChan(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnPrivMsg(CNick& Nick, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnPrivMessage(CPrivMessage& Message) { + CString sText = Message.GetText(); + EModRet ret = OnPrivMsg(Message.GetNick(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnChanMessage(CChanMessage& Message) { + CString sText = Message.GetText(); + EModRet ret = OnChanMsg(Message.GetNick(), *Message.GetChan(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnPrivNotice(CNick& Nick, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnPrivNoticeMessage(CPrivNotice& Message) { + CString sText = Message.GetText(); + EModRet ret = OnPrivNotice(Message.GetNick(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage) { return CONTINUE; } +CModule::EModRet CModule::OnChanNoticeMessage(CChanNotice& Message) { + CString sText = Message.GetText(); + EModRet ret = OnChanNotice(Message.GetNick(), *Message.GetChan(), sText); + Message.SetText(sText); + return ret; +} CModule::EModRet CModule::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) { return CONTINUE; } +CModule::EModRet CModule::OnTopicMessage(CTopicMessage& Message) { + CString sTopic = Message.GetTopic(); + EModRet ret = OnTopic(Message.GetNick(), *Message.GetChan(), sTopic); + Message.SetTopic(sTopic); + return ret; +} 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; } @@ -829,11 +888,16 @@ bool CModules::OnUserTopicRequest(CString& sChannel) { MODHALTCHK(OnUserTopicReq bool CModules::OnUserQuit(CString& sMessage) { MODHALTCHK(OnUserQuit(sMessage)); } bool CModules::OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) { MODUNLOADCHK(OnQuit(Nick, sMessage, vChans)); return false; } +bool CModules::OnQuitMessage(CQuitMessage& Message, const vector& vChans) { MODUNLOADCHK(OnQuitMessage(Message, vChans)); return false; } bool CModules::OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) { MODUNLOADCHK(OnNick(Nick, sNewNick, vChans)); return false; } +bool CModules::OnNickMessage(CNickMessage& Message, const vector& vChans) { MODUNLOADCHK(OnNickMessage(Message, 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::OnKickMessage(CKickMessage& Message) { MODUNLOADCHK(OnKickMessage(Message)); 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::OnJoinMessage(CJoinMessage& Message) { MODUNLOADCHK(OnJoinMessage(Message)); return false; } bool CModules::OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) { MODUNLOADCHK(OnPart(Nick, Channel, sMessage)); return false; } +bool CModules::OnPartMessage(CPartMessage& Message) { MODUNLOADCHK(OnPartMessage(Message)); return false; } bool CModules::OnInvite(const CNick& Nick, const CString& sChan) { MODHALTCHK(OnInvite(Nick, sChan)); } bool CModules::OnChanBufferStarting(CChan& Chan, CClient& Client) { MODHALTCHK(OnChanBufferStarting(Chan, Client)); } bool CModules::OnChanBufferEnding(CChan& Chan, CClient& Client) { MODHALTCHK(OnChanBufferEnding(Chan, Client)); } @@ -843,14 +907,23 @@ bool CModules::OnPrivBufferPlayLine2(CClient& Client, CString& sLine, const time bool CModules::OnPrivBufferPlayLine(CClient& Client, CString& sLine) { MODHALTCHK(OnPrivBufferPlayLine(Client, sLine)); } bool CModules::OnCTCPReply(CNick& Nick, CString& sMessage) { MODHALTCHK(OnCTCPReply(Nick, sMessage)); } bool CModules::OnPrivCTCP(CNick& Nick, CString& sMessage) { MODHALTCHK(OnPrivCTCP(Nick, sMessage)); } +bool CModules::OnPrivCTCPMessage(CPrivCTCP& Message) { MODHALTCHK(OnPrivCTCPMessage(Message)); } bool CModules::OnChanCTCP(CNick& Nick, CChan& Channel, CString& sMessage) { MODHALTCHK(OnChanCTCP(Nick, Channel, sMessage)); } +bool CModules::OnChanCTCPMessage(CChanCTCP& Message) { MODHALTCHK(OnChanCTCPMessage(Message)); } bool CModules::OnPrivAction(CNick& Nick, CString& sMessage) { MODHALTCHK(OnPrivAction(Nick, sMessage)); } +bool CModules::OnPrivActionMessage(CPrivAction& Message) { MODHALTCHK(OnPrivActionMessage(Message)); } bool CModules::OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage) { MODHALTCHK(OnChanAction(Nick, Channel, sMessage)); } +bool CModules::OnChanActionMessage(CChanAction& Message) { MODHALTCHK(OnChanActionMessage(Message)); } bool CModules::OnPrivMsg(CNick& Nick, CString& sMessage) { MODHALTCHK(OnPrivMsg(Nick, sMessage)); } +bool CModules::OnPrivMessage(CPrivMessage& Message) { MODHALTCHK(OnPrivMessage(Message)); } bool CModules::OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) { MODHALTCHK(OnChanMsg(Nick, Channel, sMessage)); } +bool CModules::OnChanMessage(CChanMessage& Message) { MODHALTCHK(OnChanMessage(Message)); } bool CModules::OnPrivNotice(CNick& Nick, CString& sMessage) { MODHALTCHK(OnPrivNotice(Nick, sMessage)); } +bool CModules::OnPrivNoticeMessage(CPrivNotice& Message) { MODHALTCHK(OnPrivNoticeMessage(Message)); } bool CModules::OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage) { MODHALTCHK(OnChanNotice(Nick, Channel, sMessage)); } +bool CModules::OnChanNoticeMessage(CChanNotice& Message) { MODHALTCHK(OnChanNoticeMessage(Message)); } bool CModules::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) { MODHALTCHK(OnTopic(Nick, Channel, sTopic)); } +bool CModules::OnTopicMessage(CTopicMessage& Message) { MODHALTCHK(OnTopicMessage(Message)); } 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)); } diff --git a/test/MessageTest.cpp b/test/MessageTest.cpp index f9a73ec7..77d56a69 100644 --- a/test/MessageTest.cpp +++ b/test/MessageTest.cpp @@ -55,6 +55,149 @@ TEST(MessageTest, FormatFlags) { EXPECT_EQ("COMMAND param", msg.ToString(CMessage::ExcludePrefix|CMessage::ExcludeTags)); } +TEST(MessageTest, ChanAction) { + CMessage msg(":sender PRIVMSG #chan :\001ACTION text\001"); + CChanAction& chan = static_cast(msg); + EXPECT_EQ("sender", chan.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", chan.GetCommand()); + EXPECT_EQ("text", chan.GetText()); + + chan.SetText("foo bar"); + EXPECT_EQ("foo bar", chan.GetText()); + EXPECT_EQ(":sender PRIVMSG #chan :\001ACTION foo bar\001", chan.ToString()); +} + +TEST(MessageTest, ChanCTCP) { + CMessage msg(":sender PRIVMSG #chan :\001text\001"); + CChanCTCP& chan = static_cast(msg); + EXPECT_EQ("sender", chan.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", chan.GetCommand()); + EXPECT_EQ("text", chan.GetText()); + + chan.SetText("foo bar"); + EXPECT_EQ("foo bar", chan.GetText()); + EXPECT_EQ(":sender PRIVMSG #chan :\001foo bar\001", chan.ToString()); +} + +TEST(MessageTest, ChanMsg) { + CMessage msg(":sender PRIVMSG #chan :text"); + CChanMessage& priv = static_cast(msg); + EXPECT_EQ("sender", priv.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", priv.GetCommand()); + EXPECT_EQ("text", priv.GetText()); + + priv.SetText("foo bar"); + EXPECT_EQ("foo bar", priv.GetText()); + EXPECT_EQ(":sender PRIVMSG #chan :foo bar", priv.ToString()); +} + +TEST(MessageTest, Kick) { + CMessage msg(":nick KICK #chan person :reason"); + CKickMessage& kick = static_cast(msg); + EXPECT_EQ("nick", kick.GetNick().GetNick()); + EXPECT_EQ("KICK", kick.GetCommand()); + EXPECT_EQ("person", kick.GetKickedNick()); + EXPECT_EQ("reason", kick.GetReason()); + + kick.SetKickedNick("noone"); + EXPECT_EQ("noone", kick.GetKickedNick()); + kick.SetReason("test"); + EXPECT_EQ("test", kick.GetReason()); + EXPECT_EQ(":nick KICK #chan noone test", kick.ToString()); +} + +TEST(MessageTest, Join) { + CMessage msg(":nick JOIN #chan"); + EXPECT_EQ("nick", msg.GetNick().GetNick()); + EXPECT_EQ("JOIN", msg.GetCommand()); + EXPECT_EQ("#chan", msg.GetParam(0)); +} + +TEST(MessageTest, Nick) { + CMessage msg(":nick NICK person"); + CNickMessage& nick = static_cast(msg); + EXPECT_EQ("nick", nick.GetNick().GetNick()); + EXPECT_EQ("NICK", nick.GetCommand()); + EXPECT_EQ("nick", nick.GetOldNick()); + EXPECT_EQ("person", nick.GetNewNick()); + + nick.SetNewNick("test"); + EXPECT_EQ("test", nick.GetNewNick()); + EXPECT_EQ(":nick NICK test", nick.ToString()); +} + +TEST(MessageTest, Part) { + CMessage msg(":nick PART #chan :reason"); + CPartMessage& part = static_cast(msg); + EXPECT_EQ("nick", part.GetNick().GetNick()); + EXPECT_EQ("PART", part.GetCommand()); + EXPECT_EQ("reason", part.GetReason()); + + part.SetReason("test"); + EXPECT_EQ("test", part.GetReason()); + EXPECT_EQ(":nick PART #chan test", part.ToString()); +} + +TEST(MessageTest, PrivAction) { + CMessage msg(":sender PRIVMSG receiver :\001ACTION text\001"); + CPrivAction& priv = static_cast(msg); + EXPECT_EQ("sender", priv.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", priv.GetCommand()); + EXPECT_EQ("text", priv.GetText()); + + priv.SetText("foo bar"); + EXPECT_EQ("foo bar", priv.GetText()); + EXPECT_EQ(":sender PRIVMSG receiver :\001ACTION foo bar\001", priv.ToString()); +} + +TEST(MessageTest, PrivCTCP) { + CMessage msg(":sender PRIVMSG receiver :\001text\001"); + CPrivCTCP& priv = static_cast(msg); + EXPECT_EQ("sender", priv.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", priv.GetCommand()); + EXPECT_EQ("text", priv.GetText()); + + priv.SetText("foo bar"); + EXPECT_EQ("foo bar", priv.GetText()); + EXPECT_EQ(":sender PRIVMSG receiver :\001foo bar\001", priv.ToString()); +} + +TEST(MessageTest, PrivMsg) { + CMessage msg(":sender PRIVMSG receiver :text"); + CPrivMessage& priv = static_cast(msg); + EXPECT_EQ("sender", priv.GetNick().GetNick()); + EXPECT_EQ("PRIVMSG", priv.GetCommand()); + EXPECT_EQ("text", priv.GetText()); + + priv.SetText("foo bar"); + EXPECT_EQ("foo bar", priv.GetText()); + EXPECT_EQ(":sender PRIVMSG receiver :foo bar", priv.ToString()); +} + +TEST(MessageTest, Quit) { + CMessage msg(":nick QUIT :reason"); + CQuitMessage& quit = static_cast(msg); + EXPECT_EQ("nick", quit.GetNick().GetNick()); + EXPECT_EQ("QUIT", quit.GetCommand()); + EXPECT_EQ("reason", quit.GetReason()); + + quit.SetReason("test"); + EXPECT_EQ("test", quit.GetReason()); + EXPECT_EQ(":nick QUIT test", quit.ToString()); +} + +TEST(MessageTest, Topic) { + CMessage msg(":nick TOPIC #chan :topic"); + CTopicMessage& topic = static_cast(msg); + EXPECT_EQ("nick", topic.GetNick().GetNick()); + EXPECT_EQ("TOPIC", topic.GetCommand()); + EXPECT_EQ("topic", topic.GetTopic()); + + topic.SetTopic("test"); + EXPECT_EQ("test", topic.GetTopic()); + EXPECT_EQ(":nick TOPIC #chan test", topic.ToString()); +} + // The test data for MessageTest.Parse originates from https://github.com/SaberUK/ircparser // // IRCParser - Internet Relay Chat Message Parser