Rewrite the JOIN channel logic, dropping MaxJoins

Instead we fill the JOIN line up with as many channels as we can fit in
an IRC line. Rate limiting is done per command now, making MaxJoins
unnecessary.
This commit is contained in:
Kyle Fuller
2012-03-21 16:55:13 +00:00
parent fb2b5193bc
commit db7c47f97d
6 changed files with 33 additions and 72 deletions

View File

@@ -640,67 +640,46 @@ bool CIRCNetwork::DelChan(const CString& sName) {
}
void CIRCNetwork::JoinChans() {
// Avoid divsion by zero, it's bad!
if (m_vChans.empty())
return;
// We start at a random offset into the channel list so that if your
// first 3 channels are invite-only and you got MaxJoins == 3, ZNC will
// still be able to join the rest of your channels.
unsigned int start = rand() % m_vChans.size();
unsigned int uJoins = m_pUser->MaxJoins();
set<CChan*> sChans;
for (unsigned int a = 0; a < m_vChans.size(); a++) {
unsigned int idx = (start + a) % m_vChans.size();
CChan* pChan = m_vChans[idx];
if (!pChan->IsOn() && !pChan->IsDisabled()) {
if (!JoinChan(pChan))
continue;
sChans.insert(pChan);
// Limit the number of joins
if (uJoins != 0 && --uJoins == 0)
break;
}
}
while (!sChans.empty())
JoinChans(sChans);
}
void CIRCNetwork::JoinChans(set<CChan*>& sChans) {
CString sKeys, sJoin;
bool bHaveKey = false;
size_t uiJoinLength = strlen("JOIN ");
size_t joinLength = 4; // join
CString sChannels, sKeys;
while (!sChans.empty()) {
set<CChan*>::iterator it = sChans.begin();
const CString& sName = (*it)->GetName();
const CString& sKey = (*it)->GetKey();
size_t len = sName.length() + sKey.length();
len += 2; // two comma
for (vector<CChan*>::iterator it = m_vChans.begin(); it != m_vChans.end(); ++it) {
CChan *pChan = *it;
if (!sKeys.empty() && uiJoinLength + len >= 512)
break;
if (pChan->IsOn() || pChan->IsDisabled() || !JoinChan(pChan)) {
continue;
}
if (!sJoin.empty()) {
sJoin += ",";
size_t length = pChan->GetName().length() + pChan->GetKey().length() + 2; // +2 for either space or commas
if ((joinLength + length) >= 510) {
// Sent what we got, and cleanup
PutIRC("JOIN " + sChannels + (bHaveKey ? (" " + sKeys) : ""));
sChannels = "";
sKeys = "";
joinLength = 4; // join
bHaveKey = false;
}
if (!sChannels.empty()) {
sChannels += ",";
sKeys += ",";
}
uiJoinLength += len;
sJoin += sName;
if (!sKey.empty()) {
sKeys += sKey;
if (!pChan->GetKey().empty()) {
bHaveKey = true;
sKeys += pChan->GetKey();
}
sChans.erase(it);
sChannels += pChan->GetName();
joinLength += length;
}
if (bHaveKey)
PutIRC("JOIN " + sJoin + " " + sKeys);
else
PutIRC("JOIN " + sJoin);
if (!sChannels.empty()) {
PutIRC("JOIN " + sChannels + (bHaveKey ? (" " + sKeys) : ""));
}
}
bool CIRCNetwork::JoinChan(CChan* pChan) {