diff --git a/include/znc/Client.h b/include/znc/Client.h index f9ae87c2..2acba558 100644 --- a/include/znc/Client.h +++ b/include/znc/Client.h @@ -29,6 +29,7 @@ class CUser; class CIRCNetwork; class CIRCSock; class CClient; +class CMessage; // !Forward Declarations class CAuthBase { @@ -175,6 +176,7 @@ public: void PutIRC(const CString& sLine); void PutClient(const CString& sLine); + void PutClient(const CMessage& Message); unsigned int PutStatus(const CTable& table); void PutStatus(const CString& sLine); void PutStatusNotice(const CString& sLine); diff --git a/include/znc/IRCNetwork.h b/include/znc/IRCNetwork.h index d5016af4..3b7130c2 100644 --- a/include/znc/IRCNetwork.h +++ b/include/znc/IRCNetwork.h @@ -35,6 +35,7 @@ class CServer; class CIRCSock; class CIRCNetworkPingTimer; class CIRCNetworkJoinTimer; +class CMessage; class CIRCNetwork { public: @@ -90,6 +91,7 @@ public: // !Modules bool PutUser(const CString& sLine, CClient* pClient = nullptr, CClient* pSkipClient = nullptr); + bool PutUser(const CMessage& Message, CClient* pClient = nullptr, CClient* pSkipClient = nullptr); bool PutStatus(const CString& sLine, CClient* pClient = nullptr, CClient* pSkipClient = nullptr); bool PutModule(const CString& sModule, const CString& sLine, CClient* pClient = nullptr, CClient* pSkipClient = nullptr); diff --git a/include/znc/IRCSock.h b/include/znc/IRCSock.h index cf1fc0e9..0d7caa60 100644 --- a/include/znc/IRCSock.h +++ b/include/znc/IRCSock.h @@ -114,6 +114,7 @@ public: CString GetISupport(const CString& sKey, const CString& sDefault = "") const; // !Getters + // TODO: CMessage // This handles NAMESX and UHNAMES in a raw 353 reply void ForwardRaw353(const CString& sLine) const; void ForwardRaw353(const CString& sLine, CClient* pClient) const; diff --git a/src/Client.cpp b/src/Client.cpp index d2f898dd..9ab2cc50 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -794,6 +794,36 @@ void CClient::PutClient(const CString& sLine) { Write(sCopy + "\r\n"); } +void CClient::PutClient(const CMessage& Message) +{ + CString sLine = Message.ToString(CMessage::ExcludeTags); + + // TODO: introduce a module hook that gives control over the tags that are sent + MCString mssTags; + + if (HasServerTime()) { + CString sServerTime = Message.GetTag("time"); + if (!sServerTime.empty()) { + mssTags["time"] = sServerTime; + } else { + mssTags["time"] = CUtils::FormatServerTime(Message.GetTime()); + } + } + + if (HasBatch()) { + CString sBatch = Message.GetTag("batch"); + if (!sBatch.empty()) { + mssTags["batch"] = sBatch; + } + } + + if (!mssTags.empty()) { + CUtils::SetMessageTags(sLine, mssTags); + } + + PutClient(sLine); +} + void CClient::PutStatusNotice(const CString& sLine) { PutModNotice("status", sLine); } diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index c5ed38c8..452b7fd5 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -726,6 +726,20 @@ bool CIRCNetwork::PutUser(const CString& sLine, CClient* pClient, CClient* pSkip return (pClient == nullptr); } +bool CIRCNetwork::PutUser(const CMessage& Message, CClient* pClient, CClient* pSkipClient) { + for (CClient* pEachClient : m_vClients) { + if ((!pClient || pClient == pEachClient) && pSkipClient != pEachClient) { + pEachClient->PutClient(Message); + + if (pClient) { + return true; + } + } + } + + return (pClient == nullptr); +} + bool CIRCNetwork::PutStatus(const CString& sLine, CClient* pClient, CClient* pSkipClient) { for (CClient* pEachClient : m_vClients) { if ((!pClient || pClient == pEachClient) && pSkipClient != pEachClient) { diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index 422e5c04..77e0c391 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -369,7 +369,7 @@ void CIRCSock::ReadLine(const CString& sData) { const vector& vClients = m_pNetwork->GetClients(); for (CClient* pClient : vClients) { if (pClient->HasNamesx()) { - m_pNetwork->PutUser(sLine, pClient); + m_pNetwork->PutUser(Message, pClient); } else { // The client doesn't support multi-prefix so we need to remove // the other prefixes. @@ -379,6 +379,7 @@ void CIRCSock::ReadLine(const CString& sData) { if (pos >= 2 && pos != CString::npos) { sNewNick = sNick[0] + sNick.substr(pos); } + // TODO: CMessage CString sNewLine = sServer + " 352 " + sLine.Token(2) + " " + sChan + " " + sIdent + " " + sHost + " " + sLine.Token(6) + " " + sNewNick + " " + @@ -528,7 +529,7 @@ void CIRCSock::ReadLine(const CString& sData) { // We are changing our own nick, the clients always must see this! bIsVisible = false; SetNick(sNewNick); - m_pNetwork->PutUser(sLine); + m_pNetwork->PutUser(Message); } IRCSOCKMODULECALL(OnNickMessage(NickMsg, vFoundChans), NOTHING); @@ -749,8 +750,6 @@ void CIRCSock::ReadLine(const CString& sData) { if (pChan->IsDetached()) { return; // Don't forward this } - - sLine = ":" + Nick.GetNickMask() + " TOPIC " + pChan->GetName() + " :" + pChan->GetTopic(); } } else if (sCmd.Equals("PRIVMSG")) { // :nick!ident@host.com PRIVMSG #chan :Message @@ -878,7 +877,7 @@ void CIRCSock::ReadLine(const CString& sData) { } } - m_pNetwork->PutUser(sLine); + m_pNetwork->PutUser(Message); } void CIRCSock::SendNextCap() {