mirror of
https://github.com/znc/znc.git
synced 2026-08-07 09:22:55 +02:00
Implement message-tags spec
Message tags were supported already, but not arbitrary tags, and not TAGMSG
This commit is contained in:
@@ -138,6 +138,8 @@ class CClient : public CIRCSocket {
|
||||
void SetPlaybackActive(bool bActive) { m_bPlaybackActive = bActive; }
|
||||
|
||||
void PutIRC(const CString& sLine);
|
||||
// Strips prefix and potentially tags before sending to server.
|
||||
void PutIRCStripping(CMessage Message);
|
||||
/** Sends a raw data line to the client.
|
||||
* @param sLine The line to be sent.
|
||||
*
|
||||
@@ -305,6 +307,7 @@ class CClient : public CIRCSocket {
|
||||
bool OnPingMessage(CMessage& Message);
|
||||
bool OnPongMessage(CMessage& Message);
|
||||
bool OnQuitMessage(CQuitMessage& Message);
|
||||
bool OnTagMessage(CTargetMessage& Message);
|
||||
bool OnTextMessage(CTextMessage& Message);
|
||||
bool OnTopicMessage(CTopicMessage& Message);
|
||||
bool OnOtherMessage(CMessage& Message);
|
||||
@@ -327,6 +330,7 @@ class CClient : public CIRCSocket {
|
||||
bool m_bBatch;
|
||||
bool m_bEchoMessage;
|
||||
bool m_bSelfMessage;
|
||||
bool m_bMessageTagCap;
|
||||
bool m_bSASLCap;
|
||||
bool m_bPlaybackActive;
|
||||
CUser* m_pUser;
|
||||
|
||||
@@ -153,9 +153,8 @@ class CIRCSock : public CIRCSocket {
|
||||
bool HasAccountNotify() const { return m_bAccountNotify; }
|
||||
bool HasExtendedJoin() const { return m_bExtendedJoin; }
|
||||
bool HasServerTime() const { return m_bServerTime; }
|
||||
const std::set<char>& GetUserModes() const {
|
||||
return m_scUserModes;
|
||||
}
|
||||
bool HasMessageTagCap() const { return m_bMessageTagCap; }
|
||||
const std::set<char>& GetUserModes() const { return m_scUserModes; }
|
||||
// This is true if we are past raw 001
|
||||
bool IsAuthed() const { return m_bAuthed; }
|
||||
const SCString& GetAcceptedCaps() const { return m_ssAcceptedCaps; }
|
||||
@@ -192,6 +191,7 @@ class CIRCSock : public CIRCSocket {
|
||||
bool OnPingMessage(CMessage& Message);
|
||||
bool OnPongMessage(CMessage& Message);
|
||||
bool OnQuitMessage(CQuitMessage& Message);
|
||||
bool OnTagMessage(CTargetMessage& Message);
|
||||
bool OnTextMessage(CTextMessage& Message);
|
||||
bool OnTopicMessage(CTopicMessage& Message);
|
||||
bool OnWallopsMessage(CMessage& Message);
|
||||
@@ -213,6 +213,7 @@ class CIRCSock : public CIRCSocket {
|
||||
bool m_bAccountNotify;
|
||||
bool m_bExtendedJoin;
|
||||
bool m_bServerTime;
|
||||
bool m_bMessageTagCap;
|
||||
CString m_sPerms;
|
||||
CString m_sPermModes;
|
||||
std::set<char> m_scUserModes;
|
||||
|
||||
@@ -82,6 +82,7 @@ class CMessage {
|
||||
Ping,
|
||||
Pong,
|
||||
Quit,
|
||||
TagMsg,
|
||||
Text,
|
||||
Topic,
|
||||
Wallops,
|
||||
@@ -139,6 +140,7 @@ class CMessage {
|
||||
void SetTime(const timeval& ts) { m_time = ts; }
|
||||
|
||||
const MCString& GetTags() const { return m_mssTags; }
|
||||
MCString& GetTags() { return m_mssTags; }
|
||||
void SetTags(const MCString& mssTags) { m_mssTags = mssTags; }
|
||||
|
||||
CString GetTag(const CString& sKey) const;
|
||||
|
||||
@@ -1079,6 +1079,25 @@ class CModule {
|
||||
/// @deprecated Use OnSendToIRCMessage() instead.
|
||||
virtual EModRet OnSendToIRC(CString& sLine);
|
||||
|
||||
/** This module hook is called when a user sends a TAGMSG message.
|
||||
* @since 1.10.0
|
||||
* @param Message The message which was sent.
|
||||
* @return See CModule::EModRet.
|
||||
*/
|
||||
virtual EModRet OnUserTagMessage(CTargetMessage& Message);
|
||||
/** Called when we receive a channel TAGMSG message <em>from IRC</em>.
|
||||
* @since 1.10.0
|
||||
* @param Message The channel message.
|
||||
* @return See CModule::EModRet.
|
||||
*/
|
||||
virtual EModRet OnChanTagMessage(CTargetMessage& Message);
|
||||
/** Called when we receive a private TAGMSG message <em>from IRC</em>.
|
||||
* @since 1.10.0
|
||||
* @param Message The message.
|
||||
* @return See CModule::EModRet.
|
||||
*/
|
||||
virtual EModRet OnPrivTagMessage(CTargetMessage& Message);
|
||||
|
||||
ModHandle GetDLL() { return m_pDLL; }
|
||||
|
||||
/** This function sends a given IRC line to the IRC server, if we
|
||||
@@ -1623,6 +1642,9 @@ class CModules : public std::vector<CModule*>, private CCoreTranslationMixin {
|
||||
bool OnUserTopicRequest(CString& sChannel);
|
||||
bool OnUserQuit(CString& sMessage);
|
||||
bool OnUserQuitMessage(CQuitMessage& Message);
|
||||
bool OnUserTagMessage(CTargetMessage& Message);
|
||||
bool OnChanTagMessage(CTargetMessage& Message);
|
||||
bool OnPrivTagMessage(CTargetMessage& Message);
|
||||
|
||||
bool OnCTCPReply(CNick& Nick, CString& sMessage);
|
||||
bool OnCTCPReplyMessage(CCTCPMessage& Message);
|
||||
|
||||
@@ -103,6 +103,9 @@ EModRet OnChanNoticeMessage(CNoticeMessage& Message)
|
||||
EModRet OnTopicMessage(CTopicMessage& Message)
|
||||
EModRet OnSendToClientMessage(CMessage& Message)
|
||||
EModRet OnSendToIRCMessage(CMessage& Message)
|
||||
EModRet OnUserTagMessage(CTargetMessage& Message)
|
||||
EModRet OnChanTagMessage(CTargetMessage& Message)
|
||||
EModRet OnPrivTagMessage(CTargetMessage& Message)
|
||||
|
||||
void OnClientGetSASLMechanisms(SCString& ssMechanisms)
|
||||
EModRet OnClientSASLServerInitialChallenge(const CString& sMechanism, CString& sResponse)
|
||||
|
||||
@@ -160,6 +160,9 @@ class ZNC_EXPORT_LIB_EXPORT CPerlModule : public CModule {
|
||||
EModRet OnTopicMessage(CTopicMessage& Message) override;
|
||||
EModRet OnSendToClientMessage(CMessage& Message) override;
|
||||
EModRet OnSendToIRCMessage(CMessage& Message) override;
|
||||
EModRet OnUserTagMessage(CTargetMessage& Message) override;
|
||||
EModRet OnChanTagMessage(CTargetMessage& Message) override;
|
||||
EModRet OnPrivTagMessage(CTargetMessage& Message) override;
|
||||
|
||||
void OnClientGetSASLMechanisms(SCString& ssMechanisms) override;
|
||||
EModRet OnClientSASLServerInitialChallenge(const CString& sMechanism,
|
||||
|
||||
@@ -589,6 +589,9 @@ sub OnTopicMessage {
|
||||
}
|
||||
sub OnSendToClientMessage {}
|
||||
sub OnSendToIRCMessage {}
|
||||
sub OnUserTagMessage {}
|
||||
sub OnChanTagMessage {}
|
||||
sub OnPrivTagMessage {}
|
||||
|
||||
# In Perl "undefined" is allowed value, so perl modules may continue using OnMode and not OnMode2
|
||||
sub OnChanPermission2 { my $self = shift; $self->OnChanPermission(@_) }
|
||||
|
||||
@@ -103,6 +103,9 @@ EModRet OnChanNoticeMessage(CNoticeMessage& Message)
|
||||
EModRet OnTopicMessage(CTopicMessage& Message)
|
||||
EModRet OnSendToClientMessage(CMessage& Message)
|
||||
EModRet OnSendToIRCMessage(CMessage& Message)
|
||||
EModRet OnUserTagMessage(CTargetMessage& Message)
|
||||
EModRet OnChanTagMessage(CTargetMessage& Message)
|
||||
EModRet OnPrivTagMessage(CTargetMessage& Message)
|
||||
|
||||
EModRet OnAddUser(CUser& User, CString& sErrorRet)
|
||||
EModRet OnDeleteUser(CUser& User)
|
||||
|
||||
@@ -180,6 +180,9 @@ class ZNC_EXPORT_LIB_EXPORT CPyModule : public CModule {
|
||||
EModRet OnTopicMessage(CTopicMessage& Message) override;
|
||||
EModRet OnSendToClientMessage(CMessage& Message) override;
|
||||
EModRet OnSendToIRCMessage(CMessage& Message) override;
|
||||
EModRet OnUserTagMessage(CTargetMessage& Message) override;
|
||||
EModRet OnChanTagMessage(CTargetMessage& Message) override;
|
||||
EModRet OnPrivTagMessage(CTargetMessage& Message) override;
|
||||
|
||||
// Global Modules
|
||||
EModRet OnAddUser(CUser& User, CString& sErrorRet) override;
|
||||
|
||||
@@ -704,6 +704,15 @@ class Module:
|
||||
def OnSendToIRCMessage(self, msg):
|
||||
pass
|
||||
|
||||
def OnUserTagMessage(self, msg):
|
||||
pass
|
||||
|
||||
def OnChanTagMessage(self, msg):
|
||||
pass
|
||||
|
||||
def OnPrivTagMessage(self, msg):
|
||||
pass
|
||||
|
||||
|
||||
class Command:
|
||||
command = ''
|
||||
|
||||
+93
-16
@@ -94,6 +94,7 @@ CClient::CClient()
|
||||
m_bBatch(false),
|
||||
m_bEchoMessage(false),
|
||||
m_bSelfMessage(false),
|
||||
m_bMessageTagCap(false),
|
||||
m_bSASLCap(false),
|
||||
m_bPlaybackActive(false),
|
||||
m_pUser(nullptr),
|
||||
@@ -258,6 +259,9 @@ void CClient::ReadLine(const CString& sData) {
|
||||
case CMessage::Type::Quit:
|
||||
bReturn = OnQuitMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::TagMsg:
|
||||
bReturn = OnTagMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::Text:
|
||||
bReturn = OnTextMessage(Message);
|
||||
break;
|
||||
@@ -271,7 +275,7 @@ void CClient::ReadLine(const CString& sData) {
|
||||
|
||||
if (bReturn) return;
|
||||
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
|
||||
void CClient::SetNick(const CString& s) { m_sNick = s; }
|
||||
@@ -560,6 +564,16 @@ void CClient::PutIRC(const CString& sLine) {
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::PutIRCStripping(CMessage Message) {
|
||||
if (CIRCSock* pSock = GetIRCSock()) {
|
||||
Message.SetNick(CNick{});
|
||||
if (!pSock->HasMessageTagCap()) {
|
||||
Message.SetTags({});
|
||||
}
|
||||
pSock->PutIRC(Message);
|
||||
}
|
||||
}
|
||||
|
||||
CString CClient::GetFullName() const {
|
||||
if (!m_pUser) return GetRemoteIP();
|
||||
CString sFullName = m_pUser->GetUsername();
|
||||
@@ -578,6 +592,9 @@ bool CClient::PutClient(const CMessage& Message) {
|
||||
} else if (!m_bAccountNotify &&
|
||||
Message.GetType() == CMessage::Type::Account) {
|
||||
return false;
|
||||
} else if (!m_bMessageTagCap &&
|
||||
Message.GetType() == CMessage::Type::TagMsg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CMessage Msg(Message);
|
||||
@@ -643,11 +660,14 @@ bool CClient::PutClient(const CMessage& Message) {
|
||||
}
|
||||
}
|
||||
|
||||
MCString mssTags;
|
||||
MCString mssNewTags;
|
||||
MCString& mssTags = m_bMessageTagCap ? Msg.GetTags() : mssNewTags;
|
||||
|
||||
for (const auto& it : Msg.GetTags()) {
|
||||
if (IsTagEnabled(it.first)) {
|
||||
mssTags[it.first] = it.second;
|
||||
if (!m_bMessageTagCap) {
|
||||
for (const auto& it : Msg.GetTags()) {
|
||||
if (IsTagEnabled(it.first)) {
|
||||
mssTags[it.first] = it.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,6 +836,10 @@ CClient::CoreCaps() {
|
||||
[](CClient* pClient, bool bVal) {
|
||||
pClient->m_bEchoMessage = bVal;
|
||||
}},
|
||||
{"message-tags",
|
||||
[](CClient* pClient, bool bVal) {
|
||||
pClient->m_bMessageTagCap = bVal;
|
||||
}},
|
||||
{"server-time",
|
||||
[](CClient* pClient, bool bVal) {
|
||||
pClient->m_bServerTime = bVal;
|
||||
@@ -1037,6 +1061,17 @@ void CClient::NotifyServerDependentCap(const CString& sCap, bool bValue, const C
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename X, class = void>
|
||||
struct message_has_text : std::false_type {};
|
||||
|
||||
template <typename X>
|
||||
struct message_has_text<
|
||||
X, std::void_t<decltype(std::declval<const X&>().GetText()),
|
||||
decltype(std::declval<X&>().SetText(""))>> : std::true_type {
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CClient::AddBuffer(const T& Message) {
|
||||
if (!m_pNetwork) {
|
||||
@@ -1048,18 +1083,27 @@ void CClient::AddBuffer(const T& Message) {
|
||||
Format.Clone(Message);
|
||||
Format.SetNick(CNick(_NAMEDFMT(GetNickMask())));
|
||||
Format.SetTarget(_NAMEDFMT(sTarget));
|
||||
Format.SetText("{text}");
|
||||
if constexpr (message_has_text<T>::value) {
|
||||
Format.SetText("{text}");
|
||||
}
|
||||
|
||||
CString sText;
|
||||
CChan* pChan = m_pNetwork->FindChan(sTarget);
|
||||
if (pChan) {
|
||||
if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline()) {
|
||||
pChan->AddBuffer(Format, Message.GetText());
|
||||
if constexpr (message_has_text<T>::value) {
|
||||
sText = Message.GetText();
|
||||
}
|
||||
pChan->AddBuffer(Format, sText);
|
||||
}
|
||||
} else if (Message.GetType() != CMessage::Type::Notice) {
|
||||
if (!m_pUser->AutoClearQueryBuffer() || !m_pNetwork->IsUserOnline()) {
|
||||
CQuery* pQuery = m_pNetwork->AddQuery(sTarget);
|
||||
if (pQuery) {
|
||||
pQuery->AddBuffer(Format, Message.GetText());
|
||||
if constexpr (message_has_text<T>::value) {
|
||||
sText = Message.GetText();
|
||||
}
|
||||
pQuery->AddBuffer(Format, sText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1134,8 +1178,7 @@ bool CClient::OnActionMessage(CActionMessage& Message) {
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix |
|
||||
CMessage::ExcludeTags));
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1352,8 +1395,7 @@ bool CClient::OnCTCPMessage(CCTCPMessage& Message) {
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix |
|
||||
CMessage::ExcludeTags));
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,6 +1498,8 @@ bool CClient::OnNoticeMessage(CNoticeMessage& Message) {
|
||||
}
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
EchoMessage(Message);
|
||||
|
||||
if (!sTarget.Equals("status")) {
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork,
|
||||
OnModNotice(Message.GetText()));
|
||||
@@ -1480,8 +1524,7 @@ bool CClient::OnNoticeMessage(CNoticeMessage& Message) {
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix |
|
||||
CMessage::ExcludeTags));
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1554,6 +1597,41 @@ bool CClient::OnQuitMessage(CQuitMessage& Message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnTagMessage(CTargetMessage& Message) {
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
Message.SetTarget(sTarget);
|
||||
if (m_pNetwork) {
|
||||
// May be nullptr.
|
||||
Message.SetChan(m_pNetwork->FindChan(sTarget));
|
||||
}
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
EchoMessage(Message);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserTagMessage(Message), m_pUser, m_pNetwork,
|
||||
this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
if (GetIRCSock()->HasMessageTagCap()) {
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnTextMessage(CTextMessage& Message) {
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
@@ -1597,8 +1675,7 @@ bool CClient::OnTextMessage(CTextMessage& Message) {
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix |
|
||||
CMessage::ExcludeTags));
|
||||
PutIRCStripping(Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+55
-5
@@ -69,6 +69,7 @@ CIRCSock::CIRCSock(CIRCNetwork* pNetwork)
|
||||
m_bAccountNotify(false),
|
||||
m_bExtendedJoin(false),
|
||||
m_bServerTime(false),
|
||||
m_bMessageTagCap(false),
|
||||
m_sPerms("*!@%+"),
|
||||
m_sPermModes("qaohv"),
|
||||
m_scUserModes(),
|
||||
@@ -227,6 +228,9 @@ void CIRCSock::ReadLine(const CString& sData) {
|
||||
case CMessage::Type::Quit:
|
||||
bReturn = OnQuitMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::TagMsg:
|
||||
bReturn = OnTagMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::Text:
|
||||
bReturn = OnTextMessage(Message);
|
||||
break;
|
||||
@@ -385,6 +389,7 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) {
|
||||
{"server-time", [this](bool bVal) { m_bServerTime = bVal; }},
|
||||
{"znc.in/server-time-iso", [this](bool bVal) { m_bServerTime = bVal; }},
|
||||
{"chghost", [](bool) {}},
|
||||
{"message-tags", [this](bool bVal) { m_bMessageTagCap = bVal; }},
|
||||
};
|
||||
|
||||
auto RemoveCap = [&](const CString& sCap) {
|
||||
@@ -1160,6 +1165,49 @@ bool CIRCSock::OnQuitMessage(CQuitMessage& Message) {
|
||||
return !bIsVisible;
|
||||
}
|
||||
|
||||
bool CIRCSock::OnTagMessage(CTargetMessage& Message) {
|
||||
bool bResult = false;
|
||||
CChan* pChan = nullptr;
|
||||
CString sTarget = Message.GetTarget();
|
||||
|
||||
if (sTarget.Equals(GetNick())) {
|
||||
IRCSOCKMODULECALL(OnPrivTagMessage(Message), &bResult);
|
||||
if (bResult) return true;
|
||||
|
||||
if (!m_pNetwork->IsUserOnline() ||
|
||||
!m_pNetwork->GetUser()->AutoClearQueryBuffer()) {
|
||||
const CNick& Nick = Message.GetNick();
|
||||
CQuery* pQuery = m_pNetwork->AddQuery(Nick.GetNick());
|
||||
if (pQuery) {
|
||||
CTargetMessage Format;
|
||||
Format.Clone(Message);
|
||||
Format.SetNick(_NAMEDFMT(Nick.GetNickMask()));
|
||||
Format.SetTarget("{target}");
|
||||
pQuery->AddBuffer(Format);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pChan = m_pNetwork->FindChan(sTarget);
|
||||
if (pChan) {
|
||||
Message.SetChan(pChan);
|
||||
FixupChanNick(Message.GetNick(), pChan);
|
||||
IRCSOCKMODULECALL(OnChanTagMessage(Message), &bResult);
|
||||
if (bResult) return true;
|
||||
|
||||
if (!pChan->AutoClearChanBuffer() || !m_pNetwork->IsUserOnline() ||
|
||||
pChan->IsDetached()) {
|
||||
CTargetMessage Format;
|
||||
Format.Clone(Message);
|
||||
Format.SetNick(_NAMEDFMT(Message.GetNick().GetNickMask()));
|
||||
Format.SetTarget(_NAMEDFMT(Message.GetTarget()));
|
||||
pChan->AddBuffer(Format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (pChan && pChan->IsDetached());
|
||||
}
|
||||
|
||||
bool CIRCSock::OnTextMessage(CTextMessage& Message) {
|
||||
bool bResult = false;
|
||||
CChan* pChan = nullptr;
|
||||
@@ -1271,13 +1319,15 @@ void CIRCSock::TrySend() {
|
||||
m_iSendsAllowed--;
|
||||
CMessage& Message = m_vSendQueue.front();
|
||||
|
||||
MCString mssTags;
|
||||
for (const auto& it : Message.GetTags()) {
|
||||
if (IsTagEnabled(it.first)) {
|
||||
mssTags[it.first] = it.second;
|
||||
if (!m_bMessageTagCap) {
|
||||
MCString mssTags;
|
||||
for (const auto& it : Message.GetTags()) {
|
||||
if (IsTagEnabled(it.first)) {
|
||||
mssTags[it.first] = it.second;
|
||||
}
|
||||
}
|
||||
Message.SetTags(mssTags);
|
||||
}
|
||||
Message.SetTags(mssTags);
|
||||
Message.SetNetwork(m_pNetwork);
|
||||
|
||||
bool bSkip = false;
|
||||
|
||||
@@ -292,6 +292,7 @@ void CMessage::InitType() {
|
||||
{"PING", Type::Ping},
|
||||
{"PONG", Type::Pong},
|
||||
{"QUIT", Type::Quit},
|
||||
{"TAGMSG", Type::TagMsg},
|
||||
{"TOPIC", Type::Topic},
|
||||
{"WALLOPS", Type::Wallops},
|
||||
};
|
||||
|
||||
@@ -881,6 +881,15 @@ CModule::EModRet CModule::OnUserNoticeMessage(CNoticeMessage& Message) {
|
||||
Message.SetText(sText);
|
||||
return ret;
|
||||
}
|
||||
CModule::EModRet CModule::OnUserTagMessage(CTargetMessage& Message) {
|
||||
return CONTINUE;
|
||||
}
|
||||
CModule::EModRet CModule::OnPrivTagMessage(CTargetMessage& Message) {
|
||||
return CONTINUE;
|
||||
}
|
||||
CModule::EModRet CModule::OnChanTagMessage(CTargetMessage& Message) {
|
||||
return CONTINUE;
|
||||
}
|
||||
CModule::EModRet CModule::OnUserJoin(CString& sChannel, CString& sKey) {
|
||||
return CONTINUE;
|
||||
}
|
||||
@@ -1430,6 +1439,15 @@ bool CModules::OnUserNotice(CString& sTarget, CString& sMessage) {
|
||||
bool CModules::OnUserNoticeMessage(CNoticeMessage& Message) {
|
||||
MODHALTCHK(OnUserNoticeMessage(Message));
|
||||
}
|
||||
bool CModules::OnUserTagMessage(CTargetMessage& Message) {
|
||||
MODHALTCHK(OnUserTagMessage(Message));
|
||||
}
|
||||
bool CModules::OnPrivTagMessage(CTargetMessage& Message) {
|
||||
MODHALTCHK(OnPrivTagMessage(Message));
|
||||
}
|
||||
bool CModules::OnChanTagMessage(CTargetMessage& Message) {
|
||||
MODHALTCHK(OnChanTagMessage(Message));
|
||||
}
|
||||
bool CModules::OnUserJoin(CString& sChannel, CString& sKey) {
|
||||
MODHALTCHK(OnUserJoin(sChannel, sKey));
|
||||
}
|
||||
|
||||
@@ -981,5 +981,53 @@ TEST_F(ZNCTest, SpacedServerPassword) {
|
||||
ircd3.ReadUntil("PASS a");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, TagMsg) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
ircd.Write("001 nick Welcome");
|
||||
|
||||
client.Write("@foo=bar PRIVMSG #foo hi");
|
||||
ircd.ReadUntil("\nPRIVMSG");
|
||||
|
||||
client.Write("TAGMSG #foo");
|
||||
ASSERT_THAT(ircd.ReadRemainder().toStdString(), Not(HasSubstr("TAGMSG")));
|
||||
|
||||
ircd.Write("@foo=bar :friend PRIVMSG #foo hi");
|
||||
client.ReadUntil("\n:friend PRIVMSG");
|
||||
|
||||
ircd.Write("TAGMSG #foo");
|
||||
ASSERT_THAT(client.ReadRemainder().toStdString(), Not(HasSubstr("TAGMSG")));
|
||||
|
||||
client.Write("CAP REQ :message-tags");
|
||||
client.ReadUntil("ACK");
|
||||
|
||||
ircd.Write("@foo TAGMSG #foo");
|
||||
client.ReadUntil("@foo TAGMSG #foo");
|
||||
|
||||
ircd.Write("CAP * ACK message-tags");
|
||||
// barrier to make client wait before sending TAGMSG
|
||||
ircd.Write(":friend PRIVMSG #foo hi");
|
||||
client.ReadUntil("friend");
|
||||
|
||||
client.Write("@foo=bar TAGMSG #foo");
|
||||
ircd.ReadUntil("@foo=bar TAGMSG #foo");
|
||||
|
||||
client.Write("CAP REQ echo-message");
|
||||
client.Write("@baz TAGMSG #foo");
|
||||
client.ReadUntil("@baz :nick TAGMSG #foo");
|
||||
|
||||
// Check buffers
|
||||
client.Write("znc addnetwork other");
|
||||
client.Write("znc jumpnetwork other");
|
||||
client.ReadUntil(":Switched to other");
|
||||
|
||||
ircd.Write(":nick JOIN #bar");
|
||||
ircd.Write("@bar TAGMSG #bar");
|
||||
ASSERT_THAT(client.ReadRemainder().toStdString(), Not(HasSubstr("TAGMSG")));
|
||||
client.Write("znc jumpnetwork test");
|
||||
client.ReadUntil("@bar TAGMSG #bar");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace znc_inttest
|
||||
|
||||
Reference in New Issue
Block a user