void Cleanup() { Limits::iterator it; time_t now = time(nullptr); for (it = m_chans.begin(); it != m_chans.end(); ++it) { // The timeout for this channel did not expire yet? if (it->second.first + (time_t)m_iThresholdSecs >= now) continue; CChan* pChan = GetNetwork()->FindChan(it->first); if (it->second.second >= m_iThresholdMsgs && pChan && pChan->IsDetached()) { // The channel is detached and it is over the // messages limit. Since we only track those // limits for non-detached channels or for // channels which we detached, this means that // we detached because of a flood. if (!GetNV("silent").ToBool()) { PutModule(t_f("Flood in {1} is over, reattaching...")( pChan->GetName())); } // No buffer playback, makes sense, doesn't it? pChan->ClearBuffer(); pChan->AttachUser(); } Limits::iterator it2 = it++; m_chans.erase(it2); // Without this Bad Things (tm) could happen if (it == m_chans.end()) break; } }
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] : ""); if (m_pNetwork) { // May be nullptr. Message.SetChan(m_pNetwork->FindChan(vsChans[a])); } bool bContinue = false; NETWORKMODULECALL(OnUserJoinMessage(Message), m_pUser, m_pNetwork, this, &bContinue); if (bContinue) continue; CString sChannel = Message.GetTarget(); CString sKey = Message.GetKey(); if (m_pNetwork) { CChan* pChan = m_pNetwork->FindChan(sChannel); if (pChan) { if (pChan->IsDetached()) pChan->AttachUser(this); else pChan->JoinUser(sKey); continue; } else if (!sChannel.empty()) { pChan = new CChan(sChannel, m_pNetwork, false); if (m_pNetwork->AddChan(pChan)) { pChan->SetKey(sKey); } } } 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(); }
void SetChan(const CString& sLine) { const CString var = sLine.Token(1).AsLower(); CString username = sLine.Token(2); CString chan = sLine.Token(3); CString value = sLine.Token(4, true); if (value.empty()) { PutModule("Usage: setchan <variable> <username> <chan> <value>"); return; } CUser* user = GetUser(username); if (!user) return; CChan* pChan = user->FindChan(chan); if (!pChan) { PutModule("Error: Channel not found: " + chan); return; } if (var == "defmodes") { pChan->SetDefaultModes(value); PutModule("DefModes = " + value); } else if (var == "buffer") { unsigned int i = value.ToUInt(); pChan->SetBufferCount(i); PutModule("Buffer = " + CString(i)); } else if (var == "inconfig") { bool b = value.ToBool(); pChan->SetInConfig(b); PutModule("InConfig = " + CString(b)); } else if (var == "keepbuffer") { bool b = value.ToBool(); pChan->SetKeepBuffer(b); PutModule("KeepBuffer = " + CString(b)); } else if (var == "detached") { bool b = value.ToBool(); if (pChan->IsDetached() != b) { if (b) pChan->DetachUser(); else pChan->AttachUser(); } PutModule("Detached = " + CString(b)); } else PutModule("Error: Unknown variable"); }
void TryAttach(const CNick& Nick, CChan& Channel, CString& Message) { const CString& sChan = Channel.GetName(); const CString& sHost = Nick.GetHostMask(); const CString& sMessage = Message; VAttachIter it; if (!Channel.IsDetached()) return; // Any negated match? for (it = m_vMatches.begin(); it != m_vMatches.end(); ++it) { if (it->IsNegated() && it->IsMatch(sChan, sHost, sMessage)) return; } // Now check for a positive match for (it = m_vMatches.begin(); it != m_vMatches.end(); ++it) { if (!it->IsNegated() && it->IsMatch(sChan, sHost, sMessage)) { Channel.AttachUser(); return; } } }