mirror of
https://github.com/znc/znc.git
synced 2026-06-19 09:35:27 +02:00
Implement chghost capability
Interaction with extended-join doesn't yet work correctly, because ZNC doesn't keep track of everyone's real names
This commit is contained in:
+80
-2
@@ -185,6 +185,9 @@ void CIRCSock::ReadLine(const CString& sData) {
|
||||
case CMessage::Type::Capability:
|
||||
bReturn = OnCapabilityMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::ChgHost:
|
||||
bReturn = OnChgHostMessage(Message);
|
||||
break;
|
||||
case CMessage::Type::CTCP:
|
||||
bReturn = OnCTCPMessage(Message);
|
||||
break;
|
||||
@@ -380,8 +383,8 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) {
|
||||
{"userhost-in-names", [this](bool bVal) { m_bUHNames = bVal; }},
|
||||
{"cap-notify", [](bool bVal) {}},
|
||||
{"server-time", [this](bool bVal) { m_bServerTime = bVal; }},
|
||||
{"znc.in/server-time-iso",
|
||||
[this](bool bVal) { m_bServerTime = bVal; }},
|
||||
{"znc.in/server-time-iso", [this](bool bVal) { m_bServerTime = bVal; }},
|
||||
{"chghost", [](bool) {}},
|
||||
};
|
||||
|
||||
auto RemoveCap = [&](const CString& sCap) {
|
||||
@@ -514,6 +517,69 @@ bool CIRCSock::OnCTCPMessage(CCTCPMessage& Message) {
|
||||
return (pChan && pChan->IsDetached());
|
||||
}
|
||||
|
||||
bool CIRCSock::OnChgHostMessage(CChgHostMessage& Message) {
|
||||
// The emulation of QUIT+JOIN would be cleaner inside CClient::PutClient()
|
||||
// but computation of new modes is difficult enough so that I don't want to
|
||||
// repeat it for every client
|
||||
//
|
||||
// TODO: make CNick store modes (v, o) instead of perm chars (+, @), that
|
||||
// would simplify this
|
||||
bool bNeedEmulate = false;
|
||||
for (CClient* pClient : m_pNetwork->GetClients()) {
|
||||
if (pClient->HasChgHost()) {
|
||||
pClient->PutClient(Message);
|
||||
} else {
|
||||
bNeedEmulate = true;
|
||||
pClient->PutClient(CMessage(Message.GetNick(), "QUIT",
|
||||
{"Changing hostname"},
|
||||
Message.GetTags()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!bNeedEmulate) return true;
|
||||
|
||||
CNick NewNick = Message.GetNick();
|
||||
NewNick.SetIdent(Message.GetNewIdent());
|
||||
NewNick.SetHost(Message.GetNewHost());
|
||||
|
||||
for (CChan* pChan : m_pNetwork->GetChans()) {
|
||||
if (CNick* pNick = pChan->FindNick(Message.GetNick().GetNick())) {
|
||||
pNick->SetIdent(Message.GetNewIdent());
|
||||
pNick->SetHost(Message.GetNewHost());
|
||||
}
|
||||
|
||||
CTargetMessage ModeMsg;
|
||||
ModeMsg.SetNick(CNick(":irc.znc.in"));
|
||||
ModeMsg.SetTags(Message.GetTags());
|
||||
ModeMsg.SetCommand("MODE");
|
||||
VCString vsModeParams = {pChan->GetName(), "+"};
|
||||
if (CNick* pNick = pChan->FindNick(NewNick.GetNick())) {
|
||||
for (char cPerm : pNick->GetPermStr()) {
|
||||
char cMode = GetModeFromPerm(cPerm);
|
||||
if (cMode) {
|
||||
vsModeParams[1].append(1, cMode);
|
||||
vsModeParams.push_back(NewNick.GetNick());
|
||||
}
|
||||
}
|
||||
}
|
||||
ModeMsg.SetParams(std::move(vsModeParams));
|
||||
|
||||
for (CClient* pClient : m_pNetwork->GetClients()) {
|
||||
if (!pClient->HasChgHost()) {
|
||||
// TODO: send account name and real name too, for
|
||||
// extended-join
|
||||
pClient->PutClient(CMessage(NewNick, "JOIN", {pChan->GetName()},
|
||||
Message.GetTags()));
|
||||
if (ModeMsg.GetParams().size() > 2) {
|
||||
pClient->PutClient(ModeMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIRCSock::OnErrorMessage(CMessage& Message) {
|
||||
// ERROR :Closing Link: nick[24.24.24.24] (Excess Flood)
|
||||
CString sError = Message.GetParam(0);
|
||||
@@ -1517,6 +1583,18 @@ char CIRCSock::GetPermFromMode(char cMode) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char CIRCSock::GetModeFromPerm(char cPerm) const {
|
||||
if (m_sPermModes.size() == m_sPerms.size()) {
|
||||
for (unsigned int a = 0; a < m_sPermModes.size(); a++) {
|
||||
if (m_sPerms[a] == cPerm) {
|
||||
return m_sPermModes[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CIRCSock::EChanModeArgs CIRCSock::GetModeType(char cMode) const {
|
||||
map<char, EChanModeArgs>::const_iterator it =
|
||||
m_mceChanModes.find(cMode);
|
||||
|
||||
Reference in New Issue
Block a user