diff --git a/modules/keepnick.cpp b/modules/keepnick.cpp new file mode 100644 index 00000000..2b56e7e5 --- /dev/null +++ b/modules/keepnick.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2004-2008 See the AUTHORS file for details. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include "Modules.h" +#include "User.h" +#include "IRCSock.h" + +class CKeepNickMod; + +class CKeepNickTimer : public CTimer { +public: + CKeepNickTimer(CKeepNickMod *pMod); + ~CKeepNickTimer() {} + + void RunJob(); + +private: + CKeepNickMod* m_pMod; +}; + +class CKeepNickMod : public CModule { +public: + MODCONSTRUCTOR(CKeepNickMod) {} + + ~CKeepNickMod() {} + + bool OnLoad(const CString& sArgs, CString& sMessage) { + // Check if we need to start the timer + if (m_pUser()->IsIRCConnected()) + OnIRCConnected(); + + return true; + } + + void KeepNick() { + if (!m_pTimer) + // No timer means we are turned off + return; + + CIRCSock* pIRCSock = GetUser()->GetIRCSock(); + + if (!pIRCSock) + return; + + // Do we already have the nick we want? + if (pIRCSock->GetNick().CaseCmp(GetNick()) == 0) + return; + + PutIRC("NICK " + GetNick()); + } + + CString GetNick() { + CString sConfNick = m_pUser->GetNick(); + CIRCSock* pIRCSock = GetUser()->GetIRCSock(); + + if (pIRCSock) + sConfNick = sConfNick.Left(pIRCSock->GetMaxNickLen()); + + return sConfNick; + } + + void OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) { + if (sNewNick == GetUser()->GetIRCSock()->GetNick()) { + // We are changing our own nick + if (Nick.GetNick().CaseCmp(GetNick()) == 0) { + // We are changing our nick away from the conf setting. + // Let's assume the user wants this and disable + // this module (to avoid fighting nickserv). + Disable(); + } else if (sNewNick.CaseCmp(GetNick()) == 0) { + // We are changing our nick to the conf setting, + // so we don't need that timer anymore. + Disable(); + } + return; + } + + // If the nick we want is free now, be fast and get the nick + if (Nick.GetNick().CaseCmp(GetNick()) == 0) { + KeepNick(); + } + } + + void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) { + // If someone with the nick we want quits, be fast and get the nick + if (Nick.GetNick().CaseCmp(GetNick()) == 0) { + KeepNick(); + } + } + + void OnIRCDisconnected() { + // No way we can do something if we aren't connected to IRC. + Disable(); + } + + void OnIRCConnected() { + if (GetUser()->GetIRCSock()->GetNick().CaseCmp(GetNick()) != 0) { + // We don't have the nick we want, try to get it + Enable(); + } + } + + void Enable() { + if (m_pTimer) + return; + + m_pTimer = new CKeepNickTimer(this); + AddTimer(m_pTimer); + } + + void Disable() { + if (!m_pTimer) + return; + + m_pTimer->Stop(); + RemTimer(m_pTimer->GetName()); + m_pTimer = NULL; + } + + void OnModCommand(const CString& sCommand) { + CString sCmd = sCommand.AsUpper(); + + if (sCmd == "ENABLE") { + Enable(); + PutModule("Trying to get your primary nick"); + } else if (sCmd == "DISABLE") { + Disable(); + PutModule("No longer trying to get your primary nick"); + } else if (sCmd == "STATE") { + if (m_pTimer) + PutUser("Currently trying to get your primary nick"); + else + PutUser("Currently disabled, try 'enable'"); + } else { + PutUser("Commands: Enable, Disable, State"); + } + } + +private: + // If this is NULL, we are turned off for some reason + CKeepNickTimer* m_pTimer; +}; + +CKeepNickTimer::CKeepNickTimer(CKeepNickMod *pMod) : CTimer(pMod, 30, 0, + "KeepNickTimer", "Tries to acquire this user's primary nick") { + m_pMod = pMod; +} + +void CKeepNickTimer::RunJob() { + m_pMod->KeepNick(); +} + +MODULEDEFS(CKeepNickMod, "Keep trying for your primary nick") +