From 770bb160322f38536fcc6646dec92a472b1088aa Mon Sep 17 00:00:00 2001 From: prozacx Date: Wed, 12 Oct 2005 02:25:37 +0000 Subject: [PATCH] Internal channels and queries for users connected to znc git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@567 726aef4b-f618-498e-8847-2d620e286838 --- modules/partyline.cpp | 215 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 modules/partyline.cpp diff --git a/modules/partyline.cpp b/modules/partyline.cpp new file mode 100644 index 00000000..8492060a --- /dev/null +++ b/modules/partyline.cpp @@ -0,0 +1,215 @@ +#include "main.h" +#include "User.h" +#include "Nick.h" +#include "Modules.h" +#include "Chan.h" +#include "znc.h" +#include "HTTPSock.h" +#include "Server.h" + +class CPartylineMod : public CGlobalModule { +public: + GLOBALMODCONSTRUCTOR(CPartylineMod) {} + + virtual ~CPartylineMod() {} + + virtual bool OnBoot() { + return true; + } + + virtual bool OnLoad(const CString& sArgs) { + return true; + } + + virtual EModRet OnRaw(CString& sLine) { + if (sLine.Token(1) == "005") { + CString::size_type uPos = sLine.AsUpper().find("CHANTYPES="); + if (uPos != CString::npos) { + uPos = sLine.find(" ", uPos); + + sLine.insert(uPos, "~"); + m_spInjectedPrefixes.insert(m_pUser); + } + } + + return CONTINUE; + } + + virtual void OnIRCDisconnected() { + m_spInjectedPrefixes.erase(m_pUser); + } + + virtual void OnUserAttached() { + if (m_spInjectedPrefixes.find(m_pUser) == m_spInjectedPrefixes.end()) { + m_pUserSock->PutServ(":" + m_pUser->GetIRCServer() + " 005 " + m_pUser->GetIRCNick().GetNick() + " CHANTYPES=" + m_pUser->GetChanPrefixes() + "~ :are supported by this server."); + } + + for (map >::iterator it = m_msChans.begin(); it != m_msChans.end(); it++) { + set& ssNicks = it->second; + + if (ssNicks.find(m_pUser->GetUserName()) != ssNicks.end()) { + m_pUserSock->PutServ(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN " + it->first); + SendNickList(ssNicks, it->first); + } + } + } + + virtual void OnUserDetached() { + } + + virtual EModRet OnUserRaw(CString& sLine) { + if (sLine.Left(5).CaseCmp("WHO ~") == 0) { + return HALT; + } else if (sLine.Left(6).CaseCmp("MODE ~") == 0) { + return HALT; + } + + return CONTINUE; + } + + virtual EModRet OnUserPart(CString& sChannel, CString& sMessage) { + if (sChannel.Left(1) != "~") { + return CONTINUE; + } + + set& ssNicks = m_msChans[sChannel.AsLower()]; + const CString& sNick = m_pUser->GetUserName(); + + if (ssNicks.find(sNick) != ssNicks.end()) { + ssNicks.erase(sNick); + CString sHost = m_pUser->GetVHost(); + + if (sHost.empty()) { + sHost = m_pUser->GetIRCNick().GetHost(); + } + + m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " PART " + sChannel); + PutChan(ssNicks, ":?" + sNick + "!" + m_pUser->GetIdent() + "@" + sHost + " PART " + sChannel, false); + + if (ssNicks.empty()) { + m_msChans.erase(sChannel.AsLower()); + } + } + + return HALT; + } + + virtual EModRet OnUserJoin(CString& sChannel, CString& sKey) { + if (sChannel.Left(1) != "~") { + return CONTINUE; + } + + set& ssNicks = m_msChans[sChannel.AsLower()]; + const CString& sNick = m_pUser->GetUserName(); + + if (ssNicks.find(sNick) == ssNicks.end()) { + ssNicks.insert(sNick); + + CString sHost = m_pUser->GetVHost(); + + if (sHost.empty()) { + sHost = m_pUser->GetIRCNick().GetHost(); + } + + m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN " + sChannel); + PutChan(ssNicks, ":?" + sNick + "!" + m_pUser->GetIdent() + "@" + sHost + " JOIN " + sChannel, false); + SendNickList(ssNicks, sChannel); + + if (m_pUser->IsAdmin()) { + PutChan(ssNicks, ":*status!znc@rottenboy.com MODE " + sChannel + " +o ?" + sNick, false); + } + } + + return HALT; + } + + virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage) { + if (sTarget.empty()) { + return CONTINUE; + } + + char cPrefix = sTarget[0]; + + if (cPrefix != '~' && cPrefix != '?') { + return CONTINUE; + } + + CString sHost = m_pUser->GetVHost(); + + if (sHost.empty()) { + sHost = m_pUser->GetIRCNick().GetHost(); + } + + if (cPrefix == '~') { + PutChan(sTarget, ":?" + m_pUser->GetUserName() + "!" + m_pUser->GetIdent() + "@" + sHost + " PRIVMSG " + sTarget + " :" + sMessage, true, false); + } else { + CString sNick = sTarget.LeftChomp_n(1); + CUser* pUser = CZNC::Get().FindUser(sNick); + + if (pUser) { + pUser->PutUser(":?" + m_pUser->GetUserName() + "!" + m_pUser->GetIdent() + "@" + sHost + " PRIVMSG " + pUser->GetIRCNick().GetNick() + " :" + sMessage); + } else { + m_pUserSock->PutServ(":" + m_pUser->GetIRCServer() + " 403 " + m_pUser->GetIRCNick().GetNick() + " " + sTarget + " :No such znc user: " + sNick + ""); + } + } + + return HALT; + } + + bool PutChan(const CString& sChan, const CString& sLine, bool bIncludeCurUser = true, bool bIncludeClient = true) { + map >::iterator it = m_msChans.find(sChan.AsLower()); + + if (it != m_msChans.end()) { + PutChan(it->second, sLine, bIncludeCurUser, bIncludeClient); + return true; + } + + return false; + } + + void PutChan(const set& ssNicks, const CString& sLine, bool bIncludeCurUser = true, bool bIncludeClient = true) { + const map& msUsers = CZNC::Get().GetUserMap(); + + for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); it++) { + if (ssNicks.find(it->first) != ssNicks.end()) { + if (it->second == m_pUser) { + if (bIncludeCurUser) { + it->second->PutUser(sLine, NULL, (bIncludeClient ? NULL : m_pUserSock)); + } + } else { + it->second->PutUser(sLine); + } + } + } + } + + void SendNickList(set& ssNicks, const CString& sChan) { + CString sNickList; + for (set::iterator it = ssNicks.begin(); it != ssNicks.end(); it++) { + CUser* pChan = CZNC::Get().FindUser(*it); + + if (pChan && pChan->IsAdmin()) { + sNickList += "@"; + } + + sNickList += "?" + (*it) + " "; + + if (sNickList.size() >= 500) { + m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " @ " + sChan + " :" + sNickList); + sNickList.clear(); + } + } + + if (sNickList.size()) { + m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " @ " + sChan + " :" + sNickList); + } + + m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + sChan + " :End of /NAMES list."); + } + +private: + map > m_msChans; + set m_spInjectedPrefixes; +}; + +GLOBALMODULEDEFS(CPartylineMod, "Internal channels and queries for users connected to znc");