diff --git a/include/znc/Buffer.h b/include/znc/Buffer.h index 1314b028..17f33be1 100644 --- a/include/znc/Buffer.h +++ b/include/znc/Buffer.h @@ -29,7 +29,7 @@ class CClient; class CBufLine { public: CBufLine() : CBufLine("") { throw 0; } // shouldn't be called, but is needed for compilation - CBufLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr); + CBufLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap); ~CBufLine(); CString GetLine(const CClient& Client, const MCString& msParams) const; void UpdateTime(); @@ -38,12 +38,14 @@ public: void SetFormat(const CString& sFormat) { m_sFormat = sFormat; } void SetText(const CString& sText) { m_sText = sText; } void SetTime(const timeval& ts) { m_time = ts; } + void SetTags(const MCString& mssTags) { m_mssTags = mssTags; } // !Setters // Getters const CString& GetFormat() const { return m_sFormat; } const CString& GetText() const { return m_sText; } timeval GetTime() const { return m_time; } + const MCString& GetTags() const { return m_mssTags; } // !Getters private: @@ -51,6 +53,7 @@ protected: CString m_sFormat; CString m_sText; timeval m_time; + MCString m_mssTags; }; class CBuffer : private std::deque { @@ -58,7 +61,7 @@ public: CBuffer(unsigned int uLineCount = 100); ~CBuffer(); - size_type AddLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr); + size_type AddLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap); /// Same as AddLine, but replaces a line whose format string starts with sMatch if there is one. size_type UpdateLine(const CString& sMatch, const CString& sFormat, const CString& sText = ""); /// Same as UpdateLine, but does nothing if this exact line already exists. diff --git a/include/znc/Chan.h b/include/znc/Chan.h index 29fd12f1..033c5af0 100644 --- a/include/znc/Chan.h +++ b/include/znc/Chan.h @@ -98,7 +98,7 @@ public: bool SetBufferCount(unsigned int u, bool bForce = false) { m_bHasBufferCountSet = true; return m_Buffer.SetLineCount(u, bForce); } void InheritBufferCount(unsigned int u, bool bForce = false) { if (!m_bHasBufferCountSet) m_Buffer.SetLineCount(u, bForce); } void ResetBufferCount(); - size_t AddBuffer(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr) { return m_Buffer.AddLine(sFormat, sText, ts); } + size_t AddBuffer(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap) { return m_Buffer.AddLine(sFormat, sText, ts, mssTags); } void ClearBuffer() { m_Buffer.Clear(); } void SendBuffer(CClient* pClient); void SendBuffer(CClient* pClient, const CBuffer& Buffer); diff --git a/include/znc/Query.h b/include/znc/Query.h index 8627f9bd..8612cd88 100644 --- a/include/znc/Query.h +++ b/include/znc/Query.h @@ -38,7 +38,7 @@ public: const CBuffer& GetBuffer() const { return m_Buffer; } unsigned int GetBufferCount() const { return m_Buffer.GetLineCount(); } bool SetBufferCount(unsigned int u, bool bForce = false) { return m_Buffer.SetLineCount(u, bForce); } - size_t AddBuffer(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr) { return m_Buffer.AddLine(sFormat, sText, ts); } + size_t AddBuffer(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap) { return m_Buffer.AddLine(sFormat, sText, ts, mssTags); } void ClearBuffer() { m_Buffer.Clear(); } void SendBuffer(CClient* pClient); void SendBuffer(CClient* pClient, const CBuffer& Buffer); diff --git a/modules/buffextras.cpp b/modules/buffextras.cpp index 5f395f1b..9c6ec5b3 100644 --- a/modules/buffextras.cpp +++ b/modules/buffextras.cpp @@ -25,12 +25,12 @@ public: virtual ~CBuffExtras() {} - void AddBuffer(CChan& Channel, const CString& sMessage) { + void AddBuffer(CChan& Channel, const CString& sMessage, const timeval* tv = nullptr, const MCString& mssTags = MCString::EmptyMap) { // If they have AutoClearChanBuffer enabled, only add messages if no client is connected if (Channel.AutoClearChanBuffer() && GetNetwork()->IsUserOnline()) return; - Channel.AddBuffer(":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " + _NAMEDFMT(Channel.GetName()) + " :{text}", sMessage); + Channel.AddBuffer(":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " + _NAMEDFMT(Channel.GetName()) + " :{text}", sMessage, tv, mssTags); } void OnRawMode2(const CNick* pOpNick, CChan& Channel, const CString& sModes, const CString& sArgs) override { @@ -38,34 +38,50 @@ public: AddBuffer(Channel, sNickMask + " set mode: " + sModes + " " + sArgs); } - void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) override { - AddBuffer(Channel, OpNick.GetNickMask() + " kicked " + sKickedNick + " Reason: [" + sMessage + "]"); + void OnKickMessage(CKickMessage& Message) override { + const CNick& OpNick = Message.GetNick(); + const CString sKickedNick = Message.GetKickedNick(); + CChan& Channel = *Message.GetChan(); + const CString sMessage = Message.GetReason(); + AddBuffer(Channel, OpNick.GetNickMask() + " kicked " + sKickedNick + " Reason: [" + sMessage + "]", &Message.GetTime(), Message.GetTags()); } - void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) override { + void OnQuitMessage(CQuitMessage& Message, const vector& vChans) override { + const CNick& Nick = Message.GetNick(); + const CString sMessage = Message.GetReason(); CString sMsg = Nick.GetNickMask() + " quit with message: [" + sMessage + "]"; for (CChan* pChan : vChans) { - AddBuffer(*pChan, sMsg); + AddBuffer(*pChan, sMsg, &Message.GetTime(), Message.GetTags()); } } - void OnJoin(const CNick& Nick, CChan& Channel) override { - AddBuffer(Channel, Nick.GetNickMask() + " joined"); + void OnJoinMessage(CJoinMessage& Message) override { + const CNick& Nick = Message.GetNick(); + CChan& Channel = *Message.GetChan(); + AddBuffer(Channel, Nick.GetNickMask() + " joined", &Message.GetTime(), Message.GetTags()); } - void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) override { - AddBuffer(Channel, Nick.GetNickMask() + " parted with message: [" + sMessage + "]"); + void OnPartMessage(CPartMessage& Message) override { + const CNick& Nick = Message.GetNick(); + CChan& Channel = *Message.GetChan(); + const CString sMessage = Message.GetReason(); + AddBuffer(Channel, Nick.GetNickMask() + " parted with message: [" + sMessage + "]", &Message.GetTime(), Message.GetTags()); } - void OnNick(const CNick& OldNick, const CString& sNewNick, const vector& vChans) override { + void OnNickMessage(CNickMessage& Message, const vector& vChans) override { + const CNick& OldNick = Message.GetNick(); + const CString sNewNick = Message.GetNewNick(); CString sMsg = OldNick.GetNickMask() + " is now known as " + sNewNick; for (CChan* pChan : vChans) { - AddBuffer(*pChan, sMsg); + AddBuffer(*pChan, sMsg, &Message.GetTime(), Message.GetTags()); } } - EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) override { - AddBuffer(Channel, Nick.GetNickMask() + " changed the topic to: " + sTopic); + EModRet OnTopicMessage(CTopicMessage& Message) override { + const CNick& Nick = Message.GetNick(); + CChan& Channel = *Message.GetChan(); + const CString sTopic = Message.GetTopic(); + AddBuffer(Channel, Nick.GetNickMask() + " changed the topic to: " + sTopic, &Message.GetTime(), Message.GetTags()); return CONTINUE; } diff --git a/src/Buffer.cpp b/src/Buffer.cpp index dc14642c..f0102fea 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -19,7 +19,7 @@ #include #include -CBufLine::CBufLine(const CString& sFormat, const CString& sText, const timeval* ts) : m_sFormat(sFormat), m_sText(sText), m_time() { +CBufLine::CBufLine(const CString& sFormat, const CString& sText, const timeval* ts, const MCString& mssTags) : m_sFormat(sFormat), m_sText(sText), m_time(), m_mssTags(mssTags) { if (ts == nullptr) UpdateTime(); else @@ -54,7 +54,7 @@ CBuffer::CBuffer(unsigned int uLineCount) : m_uLineCount(uLineCount) { CBuffer::~CBuffer() {} -CBuffer::size_type CBuffer::AddLine(const CString& sFormat, const CString& sText, const timeval* ts) { +CBuffer::size_type CBuffer::AddLine(const CString& sFormat, const CString& sText, const timeval* ts, const MCString& mssTags) { if (!m_uLineCount) { return 0; } @@ -63,7 +63,7 @@ CBuffer::size_type CBuffer::AddLine(const CString& sFormat, const CString& sText erase(begin()); } - push_back(CBufLine(sFormat, sText, ts)); + push_back(CBufLine(sFormat, sText, ts, mssTags)); return size(); } diff --git a/src/Client.cpp b/src/Client.cpp index 1e87b191..d2f898dd 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -96,8 +96,9 @@ void CClient::ReadLine(const CString& sData) { DEBUG("(" << GetFullName() << ") CLI -> ZNC [" << sLine << "]"); + MCString mssTags; if (sLine.StartsWith("@")) { - // TODO support message-tags properly + mssTags = CUtils::GetMessageTags(sLine); sLine = sLine.Token(1, true); } @@ -262,7 +263,7 @@ void CClient::ReadLine(const CString& sData) { CChan* pChan = m_pNetwork->FindChan(sTarget); if ((pChan) && (!pChan->AutoClearChanBuffer())) { - pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " NOTICE " + _NAMEDFMT(sTarget) + " :{text}", sMsg); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " NOTICE " + _NAMEDFMT(sTarget) + " :{text}", sMsg, nullptr, mssTags); } // Relay to the rest of the clients that may be connected to this user @@ -313,13 +314,13 @@ void CClient::ReadLine(const CString& sData) { CChan* pChan = m_pNetwork->FindChan(sTarget); if (pChan && (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline())) { - pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage, nullptr, mssTags); } } else { if (!m_pUser->AutoClearQueryBuffer() || !m_pNetwork->IsUserOnline()) { CQuery* pQuery = m_pNetwork->AddQuery(sTarget); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage); + pQuery->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage, nullptr, mssTags); } } } @@ -368,13 +369,13 @@ void CClient::ReadLine(const CString& sData) { CChan* pChan = m_pNetwork->FindChan(sTarget); if ((pChan) && (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline())) { - pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMsg); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMsg, nullptr, mssTags); } } else { if (!m_pUser->AutoClearQueryBuffer() || !m_pNetwork->IsUserOnline()) { CQuery* pQuery = m_pNetwork->AddQuery(sTarget); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMsg); + pQuery->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMsg, nullptr, mssTags); } } } diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index 5e650143..422e5c04 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -932,7 +932,7 @@ bool CIRCSock::OnPrivCTCP(CMessage& Message) { const CNick& Nick = PrivAction.GetNick(); CQuery* pQuery = m_pNetwork->AddQuery(Nick.GetNick()); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION {text}\001", PrivAction.GetText()); + pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION {text}\001", PrivAction.GetText(), &PrivAction.GetTime(), PrivAction.GetTags()); } } } @@ -1011,7 +1011,7 @@ bool CIRCSock::OnPrivMsg(CMessage& Message) { const CNick& Nick = PrivMsg.GetNick(); CQuery* pQuery = m_pNetwork->AddQuery(Nick.GetNick()); if (pQuery) { - pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :{text}", PrivMsg.GetText()); + pQuery->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :{text}", PrivMsg.GetText(), &PrivMsg.GetTime(), PrivMsg.GetTags()); } } @@ -1034,7 +1034,7 @@ bool CIRCSock::OnChanCTCP(CMessage& Message) { IRCSOCKMODULECALL(OnChanActionMessage(ChanAction), &bResult); if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(Message.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :\001ACTION {text}\001", ChanAction.GetText()); + pChan->AddBuffer(":" + _NAMEDFMT(Message.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :\001ACTION {text}\001", ChanAction.GetText(), &ChanAction.GetTime(), ChanAction.GetTags()); } } } @@ -1055,7 +1055,7 @@ bool CIRCSock::OnChanNotice(CMessage& Message) { if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(ChanNotice.GetNick().GetNickMask()) + " NOTICE " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanNotice.GetText()); + pChan->AddBuffer(":" + _NAMEDFMT(ChanNotice.GetNick().GetNickMask()) + " NOTICE " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanNotice.GetText(), &ChanNotice.GetTime(), ChanNotice.GetTags()); } } @@ -1072,7 +1072,7 @@ bool CIRCSock::OnChanMsg(CMessage& Message) { if (bResult) return true; if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + _NAMEDFMT(ChanMsg.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanMsg.GetText()); + pChan->AddBuffer(":" + _NAMEDFMT(ChanMsg.GetNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(pChan->GetName()) + " :{text}", ChanMsg.GetText(), &ChanMsg.GetTime(), ChanMsg.GetTags()); } }