The complete source code of IdealIRC
http://www.idealirc.org/
64 lines
1.7 KiB
64 lines
1.7 KiB
#include "IRCMemberEntry.h"
|
|
#include "IRCBase.h"
|
|
#include <algorithm>
|
|
|
|
IRCMemberEntry::IRCMemberEntry(std::shared_ptr<IRCMember> member, IRCBase& owner)
|
|
: m_member(member)
|
|
, m_owner(&owner)
|
|
{}
|
|
|
|
std::shared_ptr<IRCMember> IRCMemberEntry::member() const
|
|
{
|
|
return m_member;
|
|
}
|
|
|
|
const std::string& IRCMemberEntry::modes() const
|
|
{
|
|
return m_modes;
|
|
}
|
|
|
|
void IRCMemberEntry::addMode(char m)
|
|
{
|
|
// Note: "PREFIX" is always present.
|
|
// Value example: (ohv)@%+
|
|
// Value is ordered with most significant first.
|
|
const std::string& prefix = m_owner->isupport().find("PREFIX")->second;
|
|
|
|
// Just interested in the mode letters (ie. ohv)
|
|
const std::string validModes(prefix.begin() + 1, std::find(prefix.begin(), prefix.end(), ')'));
|
|
auto order = [validModes](const char m) -> int {
|
|
auto ret = validModes.find(m);
|
|
return ret != std::string::npos ? static_cast<int>(ret)
|
|
: -1;
|
|
};
|
|
|
|
auto mOrd = order(m);
|
|
if (mOrd < 0)
|
|
return;
|
|
|
|
auto it = m_modes.begin();
|
|
for (auto& mode : m_modes) {
|
|
if (mode == m)
|
|
return;
|
|
else if (order(mode) >= mOrd)
|
|
break;
|
|
else
|
|
++it;
|
|
}
|
|
m_modes.insert(it, m);
|
|
}
|
|
|
|
void IRCMemberEntry::delMode(char m)
|
|
{
|
|
auto pos = m_modes.find_first_of(m);
|
|
|
|
/*
|
|
* Out-of-bounds can happen due to an IRC protocol bug. For example, where you join a channel which has
|
|
* members that got both op (@) and voice (+) but only one of the symbols is visible from NAMES message
|
|
* meaning that the client only picks up the "most significant" mode.
|
|
* IRCv3 implements a fix for this which this client support, but not all servers do.
|
|
* When a member then removes the unknown mode, we get this situation below;
|
|
*/
|
|
if (pos != std::string::npos)
|
|
m_modes.erase(pos, 1);
|
|
}
|
|
|