Example #1
0
void CChan::SendBuffer(CClient* pClient) {
	if (m_pNetwork && m_pNetwork->IsUserAttached()) {
		// in the event that pClient is NULL, need to send this to all clients for the user
		// I'm presuming here that pClient is listed inside vClients thus vClients at this
		// point can't be empty.
		//
		// This loop has to be cycled twice to maintain the existing behavior which is
		// 1. OnChanBufferStarting
		// 2. OnChanBufferPlayLine
		// 3. ClearBuffer() if not keeping the buffer
		// 4. OnChanBufferEnding
		//
		// With the exception of ClearBuffer(), this needs to happen per client, and
		// if pClient is not NULL, the loops break after the first iteration.
		//
		// Rework this if you like ...
		if (!m_Buffer.IsEmpty()) {
			const vector<CClient*> & vClients = m_pNetwork->GetClients();
			for (size_t uClient = 0; uClient < vClients.size(); ++uClient) {
				CClient * pUseClient = (pClient ? pClient : vClients[uClient]);

				bool bSkipStatusMsg = pUseClient->HasServerTime();
				NETWORKMODULECALL(OnChanBufferStarting(*this, *pUseClient), m_pNetwork->GetUser(), m_pNetwork, NULL, &bSkipStatusMsg);

				if (!bSkipStatusMsg) {
					m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() + " :Buffer Playback...", pUseClient);
				}

				unsigned int uSize = m_Buffer.Size();
				for (unsigned int uIdx = 0; uIdx < uSize; uIdx++) {
					CString sLine = m_Buffer.GetLine(uIdx, *pUseClient);
					bool bNotShowThisLine = false;
					NETWORKMODULECALL(OnChanBufferPlayLine(*this, *pUseClient, sLine), m_pNetwork->GetUser(), m_pNetwork, NULL, &bNotShowThisLine);
					if (bNotShowThisLine) continue;
					m_pNetwork->PutUser(sLine, pUseClient);
				}

				bSkipStatusMsg = pUseClient->HasServerTime();
				NETWORKMODULECALL(OnChanBufferEnding(*this, *pUseClient), m_pNetwork->GetUser(), m_pNetwork, NULL, &bSkipStatusMsg);
				if (!bSkipStatusMsg) {
					m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() + " :Playback Complete.", pUseClient);
				}

				if (pClient)
					break;
			}

			if (AutoClearChanBuffer()) {
 				ClearBuffer();
			}
		}
	}
}
Example #2
0
CString CBufLine::GetLine(const CClient& Client, const MCString& msParams) const {
	MCString msThisParams = msParams;

	if (Client.HasServerTime()) {
		msThisParams["text"] = m_sText;
		CString sStr = CString::NamedFormat(m_sFormat, msThisParams);
		return "@time=" + CUtils::FormatServerTime(m_time) + " " + sStr;
	} else {
		msThisParams["text"] = Client.GetUser()->AddTimestamp(m_time.tv_sec, m_sText);
		return CString::NamedFormat(m_sFormat, msThisParams);
	}
}
Example #3
0
CString CBufLine::GetLine(const CClient& Client,
                          const MCString& mssParams) const {
    CMessage Line = ToMessage(Client, mssParams);

    // Note: Discard all tags (except the time tag, conditionally) to
    // keep the same behavior as ZNC versions 1.6 and earlier had. See
    // CClient::PutClient(CMessage) documentation for more details.
    Line.SetTags(MCString::EmptyMap);

    if (Client.HasServerTime()) {
        CString sTime = m_Message.GetTag("time");
        if (sTime.empty()) {
            sTime = CUtils::FormatServerTime(m_Message.GetTime());
        }
        Line.SetTag("time", sTime);
    }

    return Line.ToString();
}
Example #4
0
CString CBufLine::GetLine(const CClient& Client, const MCString& msParams) const {
	MCString msThisParams = msParams;

	if (Client.HasServerTime()) {
		msThisParams["text"] = m_sText;
		CString sStr = CString::NamedFormat(m_sFormat, msThisParams);
		CString s_msec(m_time.tv_usec / 1000);
		while (s_msec.length() < 3) {
			s_msec = "0" + s_msec;
		}
		// TODO support leap seconds properly
		// TODO support message-tags properly
		struct tm stm;
		memset(&stm, 0, sizeof(stm));
		gmtime_r(&m_time.tv_sec, &stm);
		char sTime[20] = {};
		strftime(sTime, sizeof(sTime), "%Y-%m-%dT%H:%M:%S", &stm);
		return "@time=" + CString(sTime) + "." + s_msec + "Z " + sStr;
	} else {
		msThisParams["text"] = Client.GetUser()->AddTimestamp(m_time.tv_sec, m_sText);
		return CString::NamedFormat(m_sFormat, msThisParams);
	}
}
Example #5
0
CMessage CBufLine::ToMessage(const CClient& Client,
                             const MCString& mssParams) const {
    CMessage Line = m_Message;

    CString sSender = Line.GetNick().GetNickMask();
    Line.SetNick(CNick(CString::NamedFormat(sSender, mssParams)));

    MCString mssThisParams = mssParams;
    if (Client.HasServerTime()) {
        mssThisParams["text"] = m_sText;
    } else {
        mssThisParams["text"] =
            Client.GetUser()->AddTimestamp(Line.GetTime().tv_sec, m_sText);
    }

    // make a copy of params, because the following loop modifies the original
    VCString vsParams = Line.GetParams();
    for (unsigned int uIdx = 0; uIdx < vsParams.size(); ++uIdx) {
        Line.SetParam(uIdx,
                      CString::NamedFormat(vsParams[uIdx], mssThisParams));
    }

    return Line;
}
Example #6
0
void CChan::SendBuffer(CClient* pClient, const CBuffer& Buffer) {
    if (m_pNetwork && m_pNetwork->IsUserAttached()) {
        // in the event that pClient is nullptr, need to send this to all
        // clients for the user I'm presuming here that pClient is listed
        // inside vClients thus vClients at this point can't be empty.
        //
        // This loop has to be cycled twice to maintain the existing behavior
        // which is
        // 1. OnChanBufferStarting
        // 2. OnChanBufferPlayLine
        // 3. ClearBuffer() if not keeping the buffer
        // 4. OnChanBufferEnding
        //
        // With the exception of ClearBuffer(), this needs to happen per
        // client, and if pClient is not nullptr, the loops break after the
        // first iteration.
        //
        // Rework this if you like ...
        if (!Buffer.IsEmpty()) {
            const vector<CClient*>& vClients = m_pNetwork->GetClients();
            for (CClient* pEachClient : vClients) {
                CClient* pUseClient = (pClient ? pClient : pEachClient);

                bool bWasPlaybackActive = pUseClient->IsPlaybackActive();
                pUseClient->SetPlaybackActive(true);

                bool bSkipStatusMsg = pUseClient->HasServerTime();
                NETWORKMODULECALL(OnChanBufferStarting(*this, *pUseClient),
                                  m_pNetwork->GetUser(), m_pNetwork, nullptr,
                                  &bSkipStatusMsg);

                if (!bSkipStatusMsg) {
                    m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() +
                                            " :Buffer Playback...",
                                        pUseClient);
                }

                bool bBatch = pUseClient->HasBatch();
                CString sBatchName = GetName().MD5();

                if (bBatch) {
                    m_pNetwork->PutUser(":znc.in BATCH +" + sBatchName +
                                            " znc.in/playback " + GetName(),
                                        pUseClient);
                }

                size_t uSize = Buffer.Size();
                for (size_t uIdx = 0; uIdx < uSize; uIdx++) {
                    const CBufLine& BufLine = Buffer.GetBufLine(uIdx);
                    CMessage Message =
                        BufLine.ToMessage(*pUseClient, MCString::EmptyMap);
                    Message.SetChan(this);
                    Message.SetNetwork(m_pNetwork);
                    Message.SetClient(pUseClient);
                    if (bBatch) {
                        Message.SetTag("batch", sBatchName);
                    }
                    bool bNotShowThisLine = false;
                    NETWORKMODULECALL(OnChanBufferPlayMessage(Message),
                                      m_pNetwork->GetUser(), m_pNetwork,
                                      nullptr, &bNotShowThisLine);
                    if (bNotShowThisLine) continue;
                    m_pNetwork->PutUser(Message, pUseClient);
                }

                bSkipStatusMsg = pUseClient->HasServerTime();
                NETWORKMODULECALL(OnChanBufferEnding(*this, *pUseClient),
                                  m_pNetwork->GetUser(), m_pNetwork, nullptr,
                                  &bSkipStatusMsg);
                if (!bSkipStatusMsg) {
                    m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() +
                                            " :Playback Complete.",
                                        pUseClient);
                }

                if (bBatch) {
                    m_pNetwork->PutUser(":znc.in BATCH -" + sBatchName,
                                        pUseClient);
                }

                pUseClient->SetPlaybackActive(bWasPlaybackActive);

                if (pClient) break;
            }
        }
    }
}