multiple channels
This commit is contained in:
parent
671e01d8a0
commit
9f12e9721f
2 changed files with 210 additions and 124 deletions
|
@ -1,12 +1,11 @@
|
||||||
# znc-idlerpg
|
# znc-idlerpg
|
||||||
ZNC module to handle logins to an IdleRPG game/channel on IRC automatically
|
ZNC module to handle logins to IdleRPG games/channels on IRC automatically. It can handle multiple channels on a network at the same time.
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
- Can be loaded as a network module
|
|
||||||
- Compile the module with `znc-buildmod idlerpg.cpp` and copy it to your modules directory (and/or refer to https://wiki.znc.in/Compiling_modules for help)
|
- Compile the module with `znc-buildmod idlerpg.cpp` and copy it to your modules directory (and/or refer to https://wiki.znc.in/Compiling_modules for help)
|
||||||
- Load the mod in each network your want it to be active via `/znc loadmod idlerpg`
|
- Load the mod in each network your want it to be active via `/znc loadmod idlerpg`
|
||||||
- Setup your IRPG account via `/znc *idlerpg set #channel irpgbotnickname username password`
|
- Setup your IRPG account(s) via `/znc *idlerpg add #channel irpgbotnickname username password`
|
||||||
- That's it!
|
- That's it!
|
||||||
|
|
||||||
## Functionality
|
## Functionality
|
||||||
Trying to login if the bot joins the channel or if you join the channel (possibly after a disconnect of either). It'll wait 10 seconds before it does after the join and only does so if the botnick is on the channel and has operator status (to make sure you are not sending your login to an imposter). Technically, most of it can be done via the perform module already, but this won't check if the bot actually is online and has operator status and also won't work if the bot reconnects and doesn't log you in automatically.
|
It'll try to login when the bot joins the channel or if you join the channel (possibly after a reconnect of either). It'll wait 10 seconds after the join to login and only does so if the botnick is on the channel and has operator status (to make sure you are not sending your login to an imposter). Technically, most of it can be done via the perform module already, but this won't check if the bot actually is online and has operator status and also won't work if the bot reconnects and doesn't log you in automatically.
|
327
idlerpg.cpp
327
idlerpg.cpp
|
@ -1,179 +1,269 @@
|
||||||
#include <znc/IRCNetwork.h>
|
#include <znc/IRCNetwork.h>
|
||||||
#include <znc/Chan.h>
|
#include <znc/Chan.h>
|
||||||
|
|
||||||
#define IDLERPG_JOIN_LOGIN_WAIT_TIME 10
|
using std::map;
|
||||||
|
|
||||||
class CIdleRPGMod;
|
class CIdleRPGMod;
|
||||||
|
|
||||||
|
#define IDLERPG_JOIN_LOGIN_WAIT_TIME 10
|
||||||
|
|
||||||
|
class CIdleRPGChannel {
|
||||||
|
public:
|
||||||
|
CIdleRPGChannel() {}
|
||||||
|
CIdleRPGChannel(const CString& sLine) {
|
||||||
|
FromString(sLine);
|
||||||
|
}
|
||||||
|
virtual ~CIdleRPGChannel() {}
|
||||||
|
|
||||||
|
const CString& GetChannel() const {
|
||||||
|
return m_Channel;
|
||||||
|
}
|
||||||
|
const CString& GetBotnick() const {
|
||||||
|
return m_Botnick;
|
||||||
|
}
|
||||||
|
const CString& GetUsername() const {
|
||||||
|
return m_Username;
|
||||||
|
}
|
||||||
|
const CString& GetPassword() const {
|
||||||
|
return m_Password;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FromString(const CString& sLine) {
|
||||||
|
m_Channel = sLine.Token(0).AsLower();
|
||||||
|
m_Botnick = sLine.Token(1);
|
||||||
|
m_Username = sLine.Token(2);
|
||||||
|
m_Password = sLine.Token(3);
|
||||||
|
|
||||||
|
return !m_Channel.empty() && !m_Botnick.empty() && !m_Username.empty() && !m_Password.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
CString ToString() const {
|
||||||
|
return GetChannel() + " " + GetBotnick() + " " + GetUsername() + " " + GetPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
protected:
|
||||||
|
CString m_Channel;
|
||||||
|
CString m_Botnick;
|
||||||
|
CString m_Username;
|
||||||
|
CString m_Password;
|
||||||
|
};
|
||||||
|
|
||||||
class CIdleRPGModTimer : public CTimer {
|
class CIdleRPGModTimer : public CTimer {
|
||||||
public:
|
public:
|
||||||
CIdleRPGModTimer(CModule* pModule, unsigned int uInterval,
|
CIdleRPGModTimer(CModule* pModule, CIdleRPGChannel* sChannel, unsigned int uInterval,
|
||||||
unsigned int uCycles, const CString& sLabel,
|
unsigned int uCycles, const CString& sLabel,
|
||||||
const CString& sDescription)
|
const CString& sDescription)
|
||||||
: CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
|
: CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {
|
||||||
|
pChannel = sChannel;
|
||||||
|
}
|
||||||
|
|
||||||
~CIdleRPGModTimer() override {}
|
~CIdleRPGModTimer() override {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void RunJob() override;
|
void RunJob() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CIdleRPGChannel* pChannel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CIdleRPGMod : public CModule {
|
class CIdleRPGMod : public CModule {
|
||||||
void Set (const CString& sCommand) {
|
|
||||||
if (sCommand.Token(1).empty()) {
|
|
||||||
PutModule(t_s("Usage: <#channel> <botnick> <username> <password>"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CString sChannel = sCommand.Token(1);
|
|
||||||
CString sBotnick = sCommand.Token(2);
|
|
||||||
CString sUsername = sCommand.Token(3);
|
|
||||||
CString sPassword = sCommand.Token(4);
|
|
||||||
|
|
||||||
if (sChannel.empty()) {
|
|
||||||
PutModule("Channel not supplied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sBotnick.empty()) {
|
|
||||||
PutModule("Botnick not supplied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sUsername.empty()) {
|
|
||||||
PutModule("Username not supplied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sPassword.empty()) {
|
|
||||||
PutModule("Password not supplied");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_channel = sChannel;
|
|
||||||
m_botnick = sBotnick;
|
|
||||||
m_username = sUsername;
|
|
||||||
m_password = sPassword;
|
|
||||||
Save();
|
|
||||||
|
|
||||||
PutModule(t_s("Settings saved!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Get (const CString& sCommand) {
|
|
||||||
if (m_channel.empty()) {
|
|
||||||
PutModule(t_s("No settings found."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PutModule(t_s("Current settings are as following:"));
|
|
||||||
PutModule(t_f("Channel: {1} - Botnick: {2} - Username: {3} - Password: {4}")(m_channel, m_botnick, m_username, m_password));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear (const CString& sCommand) {
|
|
||||||
m_channel = "";
|
|
||||||
m_botnick = "";
|
|
||||||
m_username = "";
|
|
||||||
m_password = "";
|
|
||||||
Save();
|
|
||||||
|
|
||||||
PutModule(t_s("All settings cleared."));
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoginCommand (const CString& sCommand) {
|
|
||||||
if (m_channel.empty()) {
|
|
||||||
PutModule(t_s("You need to configure this module first. Try: help set"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueLogin(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MODCONSTRUCTOR(CIdleRPGMod) {
|
MODCONSTRUCTOR(CIdleRPGMod) {
|
||||||
AddHelpCommand();
|
AddHelpCommand();
|
||||||
|
|
||||||
AddCommand("Set", t_d("<#channel> <botnick> <username> <password>"), t_d("Sets all the required information to function."), [=](const CString& sLine) { Set(sLine); });
|
AddCommand("Add", t_d("<#channel> <botnick> <username> <password>"), t_d("Adds a new channel or updates a channel"), [=](const CString& sLine) { CommandAdd(sLine); });
|
||||||
AddCommand("Get", "", t_d("Displays current saved settings"), [=](const CString& sLine) { Get(sLine); });
|
AddCommand("Del", t_d("<#channel>"), t_d("Removes a channel"), [=](const CString& sLine) { CommandDel(sLine); });
|
||||||
AddCommand("Clear", "", t_d("Resets all settings"), [=](const CString& sLine) { Clear(sLine); });
|
AddCommand("Clear", "", t_d("Clears all current settings"), [=](const CString& sLine) { CommandClear(); });
|
||||||
AddCommand("Login", "", t_d("Manually triggers login now"), [=](const CString& sLine) { LoginCommand(sLine); });
|
AddCommand("List", "", t_d("Displays current settings"), [=](const CString& sLine) { CommandList(); });
|
||||||
|
AddCommand("Login", t_d("[<#channel>]"), t_d("Manually triggers login now (either for specific channel or all channels)"), [=](const CString& sLine) { CommandLogin(sLine); });
|
||||||
}
|
}
|
||||||
|
|
||||||
~CIdleRPGMod() override {}
|
~CIdleRPGMod() override {}
|
||||||
|
|
||||||
bool OnLoad(const CString& sArgs, CString& sMessage) override {
|
bool OnLoad(const CString& sArgs, CString& sMessage) override {
|
||||||
m_channel = GetNV("channel");
|
// Load current channels
|
||||||
m_botnick = GetNV("botnick");
|
for (MCString::iterator it = BeginNV(); it != EndNV(); ++it) {
|
||||||
m_username = GetNV("username");
|
const CString& sLine = it->second;
|
||||||
m_password = GetNV("password");
|
CIdleRPGChannel* pChannel = new CIdleRPGChannel;
|
||||||
|
|
||||||
|
if (!pChannel->FromString(sLine) || FindChannel(pChannel->GetChannel())) {
|
||||||
|
delete pChannel;
|
||||||
|
} else {
|
||||||
|
m_Channels[pChannel->GetChannel()] = pChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnJoin(const CNick& Nick, CChan& Channel) override {
|
CIdleRPGChannel* FindChannel(const CString& sChannel) {
|
||||||
// Setup done?
|
map<CString, CIdleRPGChannel*>::iterator it =
|
||||||
if (m_channel.empty()) {
|
m_Channels.find(sChannel);
|
||||||
|
|
||||||
|
return (it != m_Channels.end()) ? it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandList () {
|
||||||
|
if (m_Channels.empty()) {
|
||||||
|
PutModule(t_s("No channels setup yet. Try: help add"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTable Table;
|
||||||
|
Table.AddColumn(t_s("Channel"));
|
||||||
|
Table.AddColumn(t_s("Botnick"));
|
||||||
|
Table.AddColumn(t_s("Username"));
|
||||||
|
Table.AddColumn(t_s("Password"));
|
||||||
|
|
||||||
|
for (const auto& it : m_Channels) {
|
||||||
|
Table.AddRow();
|
||||||
|
Table.SetCell(t_s("Channel"), it.second->GetChannel());
|
||||||
|
Table.SetCell(t_s("Botnick"), it.second->GetBotnick());
|
||||||
|
Table.SetCell(t_s("Username"), it.second->GetUsername());
|
||||||
|
Table.SetCell(t_s("Password"), it.second->GetPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
PutModule(Table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandAdd (const CString& sLine) {
|
||||||
|
if (sLine.Token(1).empty()) {
|
||||||
|
PutModule(t_s("Usage: Add <#channel> <botnick> <username> <password>"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct channel?
|
CString sChannel = sLine.Token(1).AsLower();
|
||||||
if (Channel.GetName().AsLower() != m_channel.AsLower()) {
|
CString sBotnick = sLine.Token(2);
|
||||||
|
CString sUsername = sLine.Token(3);
|
||||||
|
CString sPassword = sLine.Token(4);
|
||||||
|
|
||||||
|
if (sChannel.empty()) {
|
||||||
|
PutModule("Channel not supplied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sBotnick.empty()) {
|
||||||
|
PutModule("Botnick not supplied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sUsername.empty()) {
|
||||||
|
PutModule("Username not supplied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sPassword.empty()) {
|
||||||
|
PutModule("Password not supplied");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either Bot or user joins
|
CIdleRPGChannel* pChannel = new CIdleRPGChannel();
|
||||||
if (Nick.GetNick() != m_botnick && !GetNetwork()->GetCurNick().Equals(Nick.GetNick())) {
|
pChannel->FromString(sChannel+" "+sBotnick+" "+sUsername+" "+sPassword);
|
||||||
|
m_Channels[pChannel->GetChannel()] = pChannel;
|
||||||
|
SetNV(pChannel->GetChannel(), pChannel->ToString());
|
||||||
|
|
||||||
|
PutModule(t_f("Saved settings for channel {1}")(pChannel->GetChannel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandDel (const CString& sLine) {
|
||||||
|
if (sLine.Token(1).empty()) {
|
||||||
|
PutModule(t_s("Usage: Del <#channel>"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
CString sChannel = sLine.Token(1).AsLower();
|
||||||
|
|
||||||
QueueLogin(IDLERPG_JOIN_LOGIN_WAIT_TIME);
|
map<CString, CIdleRPGChannel*>::iterator it =
|
||||||
}
|
m_Channels.find(sChannel);
|
||||||
|
|
||||||
void Login () {
|
if (it == m_Channels.end()) {
|
||||||
// Valid channel?
|
PutModule(t_f("Channel {1} not found")(sChannel));
|
||||||
CChan* pChan = this->GetNetwork()->FindChan(m_channel);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete it->second;
|
||||||
|
m_Channels.erase(it);
|
||||||
|
DelNV(sChannel);
|
||||||
|
PutModule(t_f("Channel {1} removed")(sChannel));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLogin (const CString& sLine) {
|
||||||
|
CString sChannel = sLine.Token(1).AsLower();
|
||||||
|
if (!sChannel.empty()) {
|
||||||
|
CIdleRPGChannel* fChannel = FindChannel(sChannel);
|
||||||
|
if (!fChannel) {
|
||||||
|
PutModule(t_f("Invalid channel {1}")(sChannel));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Login(fChannel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through all channels and login
|
||||||
|
for (const auto& it : m_Channels) {
|
||||||
|
Login(it.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandClear () {
|
||||||
|
ClearNV();
|
||||||
|
m_Channels.clear();
|
||||||
|
PutModule(t_s("All settings cleared!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueueLogin(CIdleRPGChannel* sChan) {
|
||||||
|
RemTimer("idlerpg_login_timer_"+sChan->GetChannel());
|
||||||
|
AddTimer(new CIdleRPGModTimer(this, sChan, IDLERPG_JOIN_LOGIN_WAIT_TIME, 1, "idlerpg_login_timer_"+sChan->GetChannel(), "Tries login to IdleRPG bot"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Login(CIdleRPGChannel* sChan) {
|
||||||
|
// Valid channel?
|
||||||
|
CChan* pChan = this->GetNetwork()->FindChan(sChan->GetChannel());
|
||||||
if (!pChan) {
|
if (!pChan) {
|
||||||
PutModule(t_f("Error logging in: Invalid channel [{1}]")(m_channel));
|
PutModule(t_f("Error logging in: Invalid channel [{1}]")(sChan->GetChannel()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Botnick on channel?
|
// Botnick on channel?
|
||||||
CNick* pBot = pChan->FindNick(m_botnick);
|
CNick* pBot = pChan->FindNick(sChan->GetBotnick());
|
||||||
if (!pBot) {
|
if (!pBot) {
|
||||||
PutModule(t_f("Error logging in: Bot [{1}] not found in channel [{2}]")(m_botnick, m_channel));
|
PutModule(t_f("Error logging in: Bot [{1}] not found in channel [{2}]")(sChan->GetBotnick(), sChan->GetChannel()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bot has op?
|
// Bot has op?
|
||||||
if (!pBot->HasPerm(CChan::Op)) {
|
if (!pBot->HasPerm(CChan::Op)) {
|
||||||
PutModule(t_f("Error logging in: Bot [{1}] not operator in in channel [{2}]")(m_botnick, m_channel));
|
PutModule(t_f("Error logging in: Bot [{1}] not operator in in channel [{2}]")(sChan->GetBotnick(), sChan->GetChannel()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PutIRC("PRIVMSG " + m_botnick + " :login " + m_username + " " + m_password);
|
PutIRC("PRIVMSG " + sChan->GetBotnick() + " :login " + sChan->GetUsername() + " " + sChan->GetPassword());
|
||||||
PutModule(t_s("Logging you in..."));
|
PutModule(t_s("Logging you in with "+sChan->GetBotnick()+" on "+sChan->GetChannel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnJoin(const CNick& Nick, CChan& Channel) override {
|
||||||
|
// Setup done?
|
||||||
|
if (m_Channels.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correct channel?
|
||||||
|
CIdleRPGChannel* fChannel = FindChannel(Channel.GetName().AsLower());
|
||||||
|
if (!fChannel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either Bot or user joins
|
||||||
|
if (Nick.GetNick() != fChannel->GetBotnick() && !GetNetwork()->GetCurNick().Equals(Nick.GetNick())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueLogin(fChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CString m_channel;
|
map<CString, CIdleRPGChannel*> m_Channels;
|
||||||
CString m_botnick;
|
|
||||||
CString m_username;
|
|
||||||
CString m_password;
|
|
||||||
|
|
||||||
void QueueLogin(int seconds) {
|
|
||||||
if (m_channel.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemTimer("idlerpg_login_timer");
|
|
||||||
AddTimer(new CIdleRPGModTimer(this, seconds, 1, "idlerpg_login_timer", "Tries login to IdleRPG bot"));
|
|
||||||
}
|
|
||||||
void Save() {
|
|
||||||
SetNV("channel", m_channel);
|
|
||||||
SetNV("botnick", m_botnick);
|
|
||||||
SetNV("username", m_username);
|
|
||||||
SetNV("password", m_password);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void CIdleRPGModTimer::RunJob() { ((CIdleRPGMod*)GetModule())->Login(); }
|
void CIdleRPGModTimer::RunJob() { ((CIdleRPGMod*)GetModule())->Login(pChannel); }
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void TModInfo<CIdleRPGMod>(CModInfo& Info) {
|
void TModInfo<CIdleRPGMod>(CModInfo& Info) {
|
||||||
|
@ -181,7 +271,4 @@ void TModInfo<CIdleRPGMod>(CModInfo& Info) {
|
||||||
Info.SetWikiPage("idlerpg");
|
Info.SetWikiPage("idlerpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
NETWORKMODULEDEFS(
|
NETWORKMODULEDEFS(CIdleRPGMod, t_s("Automatically handles your login to IdleRPG games/channels"))
|
||||||
CIdleRPGMod,
|
|
||||||
t_s("Automatically handles your login to an IdleRPG game/channel")
|
|
||||||
)
|
|
Loading…
Add table
Reference in a new issue