mirror of
https://github.com/znc/znc.git
synced 2026-03-28 17:42:41 +01:00
CClient: message handlers
This commit is contained in:
749
src/Client.cpp
749
src/Client.cpp
@@ -171,342 +171,46 @@ void CClient::ReadLine(const CString& sData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sCommand.Equals("ZNC")) {
|
||||
CString sTarget = Message.GetParam(0);
|
||||
CString sModCommand;
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
sModCommand = Message.GetParams(1);
|
||||
} else {
|
||||
sTarget = "status";
|
||||
sModCommand = Message.GetParams(0);
|
||||
}
|
||||
|
||||
if (sTarget.Equals("status")) {
|
||||
if (sModCommand.empty())
|
||||
PutStatus("Hello. How may I help you?");
|
||||
else
|
||||
UserCommand(sModCommand);
|
||||
} else {
|
||||
if (sModCommand.empty())
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, PutModule("Hello. How may I help you?"))
|
||||
else
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModCommand(sModCommand))
|
||||
}
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::Ping) {
|
||||
// All PONGs are generated by ZNC. We will still forward this to
|
||||
// the ircd, but all PONGs from irc will be blocked.
|
||||
if (!Message.GetParams().empty())
|
||||
PutClient(":irc.znc.in PONG irc.znc.in " + Message.GetParams(0));
|
||||
else
|
||||
PutClient(":irc.znc.in PONG irc.znc.in");
|
||||
} else if (Message.GetType() == CMessage::Type::Pong) {
|
||||
// Block PONGs, we already responded to the pings
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::Quit) {
|
||||
CQuitMessage& QuitMsg = static_cast<CQuitMessage&>(Message);
|
||||
NETWORKMODULECALL(OnUserQuitMessage(QuitMsg), m_pUser, m_pNetwork, this, &bReturn);
|
||||
if (bReturn) return;
|
||||
Close(Csock::CLT_AFTERWRITE); // Treat a client quit as a detach
|
||||
return; // Don't forward this msg. We don't want the client getting us disconnected.
|
||||
} else if (sCommand.Equals("PROTOCTL")) {
|
||||
for (const CString& sParam : Message.GetParams()) {
|
||||
if (sParam == "NAMESX") {
|
||||
m_bNamesx = true;
|
||||
} else if (sParam == "UHNAMES") {
|
||||
m_bUHNames = true;
|
||||
}
|
||||
}
|
||||
return; // If the server understands it, we already enabled namesx / uhnames
|
||||
} else if (Message.GetType() == CMessage::Type::Notice) {
|
||||
CNoticeMessage& NoticeMsg = static_cast<CNoticeMessage&>(Message);
|
||||
CString sTargets = NoticeMsg.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
NoticeMsg.SetTarget(sTarget);
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
if (!sTarget.Equals("status")) {
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModNotice(NoticeMsg.GetText()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserNoticeMessage(NoticeMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a NOTICE to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your notice to [" + NoticeMsg.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(NoticeMsg);
|
||||
EchoMessage(NoticeMsg);
|
||||
PutIRC(NoticeMsg.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::CTCP) {
|
||||
CCTCPMessage& CTCPMsg = static_cast<CCTCPMessage&>(Message);
|
||||
CString sTargets = CTCPMsg.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
if (CTCPMsg.IsReply()) {
|
||||
CString sCTCP = CTCPMsg.GetText();
|
||||
if (sCTCP.Token(0) == "VERSION") {
|
||||
CTCPMsg.SetText(sCTCP + " via " + CZNC::GetTag(false));
|
||||
}
|
||||
}
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
CTCPMsg.SetTarget(sTarget);
|
||||
|
||||
bool bContinue = false;
|
||||
if (CTCPMsg.IsReply()) {
|
||||
NETWORKMODULECALL(OnUserCTCPReplyMessage(CTCPMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
} else {
|
||||
NETWORKMODULECALL(OnUserCTCPMessage(CTCPMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
}
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a NOTICE to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your CTCP to [" + CTCPMsg.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(CTCPMsg);
|
||||
EchoMessage(CTCPMsg);
|
||||
PutIRC(CTCPMsg.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::Text) {
|
||||
CTextMessage& TextMsg = static_cast<CTextMessage&>(Message);
|
||||
CString sTargets = TextMsg.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
TextMsg.SetTarget(sTarget);
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
EchoMessage(Message);
|
||||
if (sTarget.Equals("status")) {
|
||||
CString sMsg = TextMsg.GetText();
|
||||
UserCommand(sMsg);
|
||||
} else {
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModCommand(TextMsg.GetText()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserTextMessage(TextMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a PRIVMSG to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your message to [" + TextMsg.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(TextMsg);
|
||||
EchoMessage(TextMsg);
|
||||
PutIRC(TextMsg.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::Action) {
|
||||
CActionMessage& ActionMsg = static_cast<CActionMessage&>(Message);
|
||||
CString sTargets = ActionMsg.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
ActionMsg.SetTarget(sTarget);
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserActionMessage(ActionMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(ActionMsg);
|
||||
EchoMessage(ActionMsg);
|
||||
PutIRC(ActionMsg.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
switch (Message.GetType()) {
|
||||
case CMessage::Type::Action:
|
||||
bReturn = OnActionMessage(static_cast<CActionMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::CTCP:
|
||||
bReturn = OnCTCPMessage(static_cast<CCTCPMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Join:
|
||||
bReturn = OnJoinMessage(static_cast<CJoinMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Mode:
|
||||
bReturn = OnModeMessage(static_cast<CModeMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Notice:
|
||||
bReturn = OnNoticeMessage(static_cast<CNoticeMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Part:
|
||||
bReturn = OnPartMessage(static_cast<CPartMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Ping:
|
||||
bReturn = OnPingMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::Pong:
|
||||
bReturn = OnPongMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::Quit:
|
||||
bReturn = OnQuitMessage(static_cast<CQuitMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Text:
|
||||
bReturn = OnTextMessage(static_cast<CTextMessage&>(Message));
|
||||
break;
|
||||
case CMessage::Type::Topic:
|
||||
bReturn = OnTopicMessage(static_cast<CTopicMessage&>(Message));
|
||||
break;
|
||||
default:
|
||||
bReturn = OnOtherMessage(Message);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sCommand.Equals("ATTACH")) {
|
||||
CString sPatterns = sLine.Token(1, true);
|
||||
|
||||
if (sPatterns.empty()) {
|
||||
PutStatusNotice("Usage: /attach <#chans|queries>");
|
||||
return;
|
||||
}
|
||||
|
||||
set<CChan*> sChans = MatchChans(sPatterns);
|
||||
unsigned int uAttachedChans = AttachChans(sChans);
|
||||
|
||||
PutStatusNotice("There were [" + CString(sChans.size()) + "] channels matching [" + sPatterns + "]");
|
||||
PutStatusNotice("Attached [" + CString(uAttachedChans) + "] channels");
|
||||
|
||||
return;
|
||||
} else if (sCommand.Equals("DETACH")) {
|
||||
if (!m_pNetwork) {
|
||||
return;
|
||||
}
|
||||
|
||||
CString sPatterns = Message.GetParams(0);
|
||||
|
||||
if (sPatterns.empty()) {
|
||||
PutStatusNotice("Usage: /detach <#chans>");
|
||||
return;
|
||||
}
|
||||
|
||||
set<CChan*> sChans = MatchChans(sPatterns);
|
||||
unsigned int uDetached = DetachChans(sChans);
|
||||
|
||||
PutStatusNotice("There were [" + CString(sChans.size()) + "] channels matching [" + sPatterns + "]");
|
||||
PutStatusNotice("Detached [" + CString(uDetached) + "] channels");
|
||||
|
||||
return;
|
||||
} else if (Message.GetType() == CMessage::Type::Join) {
|
||||
CJoinMessage& JoinMsg = static_cast<CJoinMessage&>(Message);
|
||||
CString sChans = JoinMsg.GetTarget();
|
||||
CString sKeys = JoinMsg.GetKey();
|
||||
|
||||
VCString vsChans;
|
||||
sChans.Split(",", vsChans, false);
|
||||
sChans.clear();
|
||||
|
||||
VCString vsKeys;
|
||||
sKeys.Split(",", vsKeys, true);
|
||||
sKeys.clear();
|
||||
|
||||
for (unsigned int a = 0; a < vsChans.size(); a++) {
|
||||
JoinMsg.SetTarget(vsChans[a]);
|
||||
JoinMsg.SetKey((a < vsKeys.size()) ? vsKeys[a] : "");
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserJoinMessage(JoinMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
CString sChannel = JoinMsg.GetTarget();
|
||||
CString sKey = JoinMsg.GetKey();
|
||||
|
||||
CChan* pChan = m_pNetwork ? m_pNetwork->FindChan(sChannel) : nullptr;
|
||||
if (pChan) {
|
||||
if (pChan->IsDetached())
|
||||
pChan->AttachUser(this);
|
||||
else
|
||||
pChan->JoinUser(sKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sChannel.empty()) {
|
||||
sChans += (sChans.empty()) ? sChannel : CString("," + sChannel);
|
||||
|
||||
if (!vsKeys.empty()) {
|
||||
sKeys += (sKeys.empty()) ? sKey : CString("," + sKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sChans.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JoinMsg.SetTarget(sChans);
|
||||
JoinMsg.SetKey(sKeys);
|
||||
} else if (Message.GetType() == CMessage::Type::Part) {
|
||||
CPartMessage& PartMsg = static_cast<CPartMessage&>(Message);
|
||||
CString sChans = PartMsg.GetTarget();
|
||||
|
||||
VCString vsChans;
|
||||
sChans.Split(",", vsChans, false);
|
||||
sChans.clear();
|
||||
|
||||
for (CString& sChan : vsChans) {
|
||||
bool bContinue = false;
|
||||
PartMsg.SetTarget(sChan);
|
||||
NETWORKMODULECALL(OnUserPartMessage(PartMsg), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
sChan = PartMsg.GetTarget();
|
||||
|
||||
CChan* pChan = m_pNetwork ? m_pNetwork->FindChan(sChan) : nullptr;
|
||||
|
||||
if (pChan && !pChan->IsOn()) {
|
||||
PutStatusNotice("Removing channel [" + sChan + "]");
|
||||
m_pNetwork->DelChan(sChan);
|
||||
} else {
|
||||
sChans += (sChans.empty()) ? sChan : CString("," + sChan);
|
||||
}
|
||||
}
|
||||
|
||||
if (sChans.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PartMsg.SetTarget(sChans);
|
||||
} else if (Message.GetType() == CMessage::Type::Topic) {
|
||||
CTopicMessage& TopicMsg = static_cast<CTopicMessage&>(Message);
|
||||
CString sChan = TopicMsg.GetTarget();
|
||||
CString sTopic = TopicMsg.GetTopic();
|
||||
|
||||
if (!sTopic.empty()) {
|
||||
NETWORKMODULECALL(OnUserTopicMessage(TopicMsg), m_pUser, m_pNetwork, this, &bReturn);
|
||||
if (bReturn) return;
|
||||
} else {
|
||||
NETWORKMODULECALL(OnUserTopicRequest(sChan), m_pUser, m_pNetwork, this, &bReturn);
|
||||
if (bReturn) return;
|
||||
TopicMsg.SetTarget(sChan);
|
||||
}
|
||||
} else if (Message.GetType() == CMessage::Type::Mode) {
|
||||
CModeMessage& ModeMsg = static_cast<CModeMessage&>(Message);
|
||||
CString sTarget = ModeMsg.GetTarget();
|
||||
CString sModes = ModeMsg.GetModes();
|
||||
|
||||
if (m_pNetwork && m_pNetwork->IsChan(sTarget) && sModes.empty()) {
|
||||
// If we are on that channel and already received a
|
||||
// /mode reply from the server, we can answer this
|
||||
// request ourself.
|
||||
|
||||
CChan *pChan = m_pNetwork->FindChan(sTarget);
|
||||
if (pChan && pChan->IsOn() && !pChan->GetModeString().empty()) {
|
||||
PutClient(":" + m_pNetwork->GetIRCServer() + " 324 " + GetNick() + " " + sTarget + " " + pChan->GetModeString());
|
||||
if (pChan->GetCreationDate() > 0) {
|
||||
PutClient(":" + m_pNetwork->GetIRCServer() + " 329 " + GetNick() + " " + sTarget + " " + CString(pChan->GetCreationDate()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bReturn) return;
|
||||
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
@@ -1174,3 +878,380 @@ unsigned int CClient::DetachChans(const std::set<CChan*>& sChans)
|
||||
}
|
||||
return uDetached;
|
||||
}
|
||||
|
||||
bool CClient::OnActionMessage(CActionMessage& Message)
|
||||
{
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
Message.SetTarget(sTarget);
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserActionMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnCTCPMessage(CCTCPMessage& Message)
|
||||
{
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
if (Message.IsReply()) {
|
||||
CString sCTCP = Message.GetText();
|
||||
if (sCTCP.Token(0) == "VERSION") {
|
||||
Message.SetText(sCTCP + " via " + CZNC::GetTag(false));
|
||||
}
|
||||
}
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
Message.SetTarget(sTarget);
|
||||
|
||||
bool bContinue = false;
|
||||
if (Message.IsReply()) {
|
||||
NETWORKMODULECALL(OnUserCTCPReplyMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
} else {
|
||||
NETWORKMODULECALL(OnUserCTCPMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
}
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a NOTICE to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your CTCP to [" + Message.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnJoinMessage(CJoinMessage& Message)
|
||||
{
|
||||
CString sChans = Message.GetTarget();
|
||||
CString sKeys = Message.GetKey();
|
||||
|
||||
VCString vsChans;
|
||||
sChans.Split(",", vsChans, false);
|
||||
sChans.clear();
|
||||
|
||||
VCString vsKeys;
|
||||
sKeys.Split(",", vsKeys, true);
|
||||
sKeys.clear();
|
||||
|
||||
for (unsigned int a = 0; a < vsChans.size(); a++) {
|
||||
Message.SetTarget(vsChans[a]);
|
||||
Message.SetKey((a < vsKeys.size()) ? vsKeys[a] : "");
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserJoinMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
CString sChannel = Message.GetTarget();
|
||||
CString sKey = Message.GetKey();
|
||||
|
||||
CChan* pChan = m_pNetwork ? m_pNetwork->FindChan(sChannel) : nullptr;
|
||||
if (pChan) {
|
||||
if (pChan->IsDetached())
|
||||
pChan->AttachUser(this);
|
||||
else
|
||||
pChan->JoinUser(sKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sChannel.empty()) {
|
||||
sChans += (sChans.empty()) ? sChannel : CString("," + sChannel);
|
||||
|
||||
if (!vsKeys.empty()) {
|
||||
sKeys += (sKeys.empty()) ? sKey : CString("," + sKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Message.SetTarget(sChans);
|
||||
Message.SetKey(sKeys);
|
||||
|
||||
return sChans.empty();
|
||||
}
|
||||
|
||||
bool CClient::OnModeMessage(CModeMessage& Message)
|
||||
{
|
||||
CString sTarget = Message.GetTarget();
|
||||
CString sModes = Message.GetModes();
|
||||
|
||||
if (m_pNetwork && m_pNetwork->IsChan(sTarget) && sModes.empty()) {
|
||||
// If we are on that channel and already received a
|
||||
// /mode reply from the server, we can answer this
|
||||
// request ourself.
|
||||
|
||||
CChan *pChan = m_pNetwork->FindChan(sTarget);
|
||||
if (pChan && pChan->IsOn() && !pChan->GetModeString().empty()) {
|
||||
PutClient(":" + m_pNetwork->GetIRCServer() + " 324 " + GetNick() + " " + sTarget + " " + pChan->GetModeString());
|
||||
if (pChan->GetCreationDate() > 0) {
|
||||
PutClient(":" + m_pNetwork->GetIRCServer() + " 329 " + GetNick() + " " + sTarget + " " + CString(pChan->GetCreationDate()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CClient::OnNoticeMessage(CNoticeMessage& Message)
|
||||
{
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
Message.SetTarget(sTarget);
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
if (!sTarget.Equals("status")) {
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModNotice(Message.GetText()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserNoticeMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a NOTICE to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your notice to [" + Message.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnPartMessage(CPartMessage& Message)
|
||||
{
|
||||
CString sChans = Message.GetTarget();
|
||||
|
||||
VCString vsChans;
|
||||
sChans.Split(",", vsChans, false);
|
||||
sChans.clear();
|
||||
|
||||
for (CString& sChan : vsChans) {
|
||||
bool bContinue = false;
|
||||
Message.SetTarget(sChan);
|
||||
NETWORKMODULECALL(OnUserPartMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
sChan = Message.GetTarget();
|
||||
|
||||
CChan* pChan = m_pNetwork ? m_pNetwork->FindChan(sChan) : nullptr;
|
||||
|
||||
if (pChan && !pChan->IsOn()) {
|
||||
PutStatusNotice("Removing channel [" + sChan + "]");
|
||||
m_pNetwork->DelChan(sChan);
|
||||
} else {
|
||||
sChans += (sChans.empty()) ? sChan : CString("," + sChan);
|
||||
}
|
||||
}
|
||||
|
||||
if (sChans.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Message.SetTarget(sChans);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CClient::OnPingMessage(CMessage& Message)
|
||||
{
|
||||
// All PONGs are generated by ZNC. We will still forward this to
|
||||
// the ircd, but all PONGs from irc will be blocked.
|
||||
if (!Message.GetParams().empty())
|
||||
PutClient(":irc.znc.in PONG irc.znc.in " + Message.GetParams(0));
|
||||
else
|
||||
PutClient(":irc.znc.in PONG irc.znc.in");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CClient::OnPongMessage(CMessage& Message)
|
||||
{
|
||||
// Block PONGs, we already responded to the pings
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnQuitMessage(CQuitMessage& Message)
|
||||
{
|
||||
bool bReturn = false;
|
||||
NETWORKMODULECALL(OnUserQuitMessage(Message), m_pUser, m_pNetwork, this, &bReturn);
|
||||
if (!bReturn) {
|
||||
Close(Csock::CLT_AFTERWRITE); // Treat a client quit as a detach
|
||||
}
|
||||
// Don't forward this msg. We don't want the client getting us disconnected.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnTextMessage(CTextMessage& Message)
|
||||
{
|
||||
CString sTargets = Message.GetTarget();
|
||||
|
||||
VCString vTargets;
|
||||
sTargets.Split(",", vTargets, false);
|
||||
|
||||
for (CString& sTarget : vTargets) {
|
||||
Message.SetTarget(sTarget);
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
EchoMessage(Message);
|
||||
if (sTarget.Equals("status")) {
|
||||
CString sMsg = Message.GetText();
|
||||
UserCommand(sMsg);
|
||||
} else {
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModCommand(Message.GetText()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bContinue = false;
|
||||
NETWORKMODULECALL(OnUserTextMessage(Message), m_pUser, m_pNetwork, this, &bContinue);
|
||||
if (bContinue) continue;
|
||||
|
||||
if (!GetIRCSock()) {
|
||||
// Some lagmeters do a PRIVMSG to their own nick, ignore those.
|
||||
if (!sTarget.Equals(m_sNick))
|
||||
PutStatus("Your message to [" + Message.GetTarget() + "] got lost, "
|
||||
"you are not connected to IRC!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_pNetwork) {
|
||||
AddBuffer(Message);
|
||||
EchoMessage(Message);
|
||||
PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::OnTopicMessage(CTopicMessage& Message)
|
||||
{
|
||||
bool bReturn = false;
|
||||
CString sChan = Message.GetTarget();
|
||||
CString sTopic = Message.GetTopic();
|
||||
|
||||
if (!sTopic.empty()) {
|
||||
NETWORKMODULECALL(OnUserTopicMessage(Message), m_pUser, m_pNetwork, this, &bReturn);
|
||||
} else {
|
||||
NETWORKMODULECALL(OnUserTopicRequest(sChan), m_pUser, m_pNetwork, this, &bReturn);
|
||||
Message.SetTarget(sChan);
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
bool CClient::OnOtherMessage(CMessage& Message)
|
||||
{
|
||||
const CString& sCommand = Message.GetCommand();
|
||||
|
||||
if (sCommand.Equals("ZNC")) {
|
||||
CString sTarget = Message.GetParam(0);
|
||||
CString sModCommand;
|
||||
|
||||
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
|
||||
sModCommand = Message.GetParams(1);
|
||||
} else {
|
||||
sTarget = "status";
|
||||
sModCommand = Message.GetParams(0);
|
||||
}
|
||||
|
||||
if (sTarget.Equals("status")) {
|
||||
if (sModCommand.empty())
|
||||
PutStatus("Hello. How may I help you?");
|
||||
else
|
||||
UserCommand(sModCommand);
|
||||
} else {
|
||||
if (sModCommand.empty())
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, PutModule("Hello. How may I help you?"))
|
||||
else
|
||||
CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModCommand(sModCommand))
|
||||
}
|
||||
return true;
|
||||
} else if (sCommand.Equals("ATTACH")) {
|
||||
if (!m_pNetwork) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CString sPatterns = Message.GetParams(0);
|
||||
|
||||
if (sPatterns.empty()) {
|
||||
PutStatusNotice("Usage: /attach <#chans|queries>");
|
||||
return true;
|
||||
}
|
||||
|
||||
set<CChan*> sChans = MatchChans(sPatterns);
|
||||
unsigned int uAttachedChans = AttachChans(sChans);
|
||||
|
||||
PutStatusNotice("There were [" + CString(sChans.size()) + "] channels matching [" + sPatterns + "]");
|
||||
PutStatusNotice("Attached [" + CString(uAttachedChans) + "] channels");
|
||||
|
||||
return true;
|
||||
} else if (sCommand.Equals("DETACH")) {
|
||||
if (!m_pNetwork) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CString sPatterns = Message.GetParams(0);
|
||||
|
||||
if (sPatterns.empty()) {
|
||||
PutStatusNotice("Usage: /detach <#chans>");
|
||||
return true;
|
||||
}
|
||||
|
||||
set<CChan*> sChans = MatchChans(sPatterns);
|
||||
unsigned int uDetached = DetachChans(sChans);
|
||||
|
||||
PutStatusNotice("There were [" + CString(sChans.size()) + "] channels matching [" + sPatterns + "]");
|
||||
PutStatusNotice("Detached [" + CString(uDetached) + "] channels");
|
||||
|
||||
return true;
|
||||
} else if (sCommand.Equals("PROTOCTL")) {
|
||||
for (const CString& sParam : Message.GetParams()) {
|
||||
if (sParam == "NAMESX") {
|
||||
m_bNamesx = true;
|
||||
} else if (sParam == "UHNAMES") {
|
||||
m_bUHNames = true;
|
||||
}
|
||||
}
|
||||
return true; // If the server understands it, we already enabled namesx / uhnames
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user