1
0
mirror of https://github.com/anope/anope.git synced 2026-06-28 11:26:37 +02:00

Rewrote how commands are handled within Anope.

This allows naming commands and having spaces within command names.
This commit is contained in:
Adam
2011-07-14 02:31:12 -04:00
parent 924f6849fe
commit f858164dee
227 changed files with 8808 additions and 12352 deletions
+118 -30
View File
@@ -8,6 +8,7 @@
#include "services.h"
#include "modules.h"
#include "commands.h"
#include "oper.h"
Anope::insensitive_map<BotInfo *> BotListByNick;
Anope::map<BotInfo *> BotListByUID;
@@ -35,30 +36,31 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_PROTECTED));
this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_GOD));
for (unsigned i = 0; i < Config->LogInfos.size(); ++i)
{
LogInfo *l = Config->LogInfos[i];
if (ircd && !ircd->join2msg && !l->Inhabit)
continue;
for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit)
if (Config)
for (unsigned i = 0; i < Config->LogInfos.size(); ++i)
{
const Anope::string &target = *sit;
LogInfo *l = Config->LogInfos[i];
if (target[0] == '#')
if (ircd && !ircd->join2msg && !l->Inhabit)
continue;
for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit)
{
Channel *c = findchan(target);
if (!c)
c = new Channel(target);
c->SetFlag(CH_LOGCHAN);
c->SetFlag(CH_PERSIST);
const Anope::string &target = *sit;
if (!c->FindUser(this))
this->Join(c, &Config->BotModeList);
if (target[0] == '#')
{
Channel *c = findchan(target);
if (!c)
c = new Channel(target);
c->SetFlag(CH_LOGCHAN);
c->SetFlag(CH_PERSIST);
if (!c->FindUser(this))
this->Join(c, &Config->BotModeList);
}
}
}
}
}
BotInfo::~BotInfo()
@@ -79,20 +81,20 @@ BotInfo::~BotInfo()
ci->bi = NULL;
}
for (CommandMap::const_iterator it = this->Commands.begin(), it_end = this->Commands.end(); it != it_end;)
{
Command *c = it->second;
++it;
if (c->module)
c->module->DelCommand(this, c);
}
BotListByNick.erase(this->nick);
if (!this->uid.empty())
BotListByUID.erase(this->uid);
}
void BotInfo::GenerateUID()
{
if (!this->uid.empty())
throw CoreException("Bot already has a uid?");
this->uid = ts6_uid_retrieve();
BotListByUID[this->uid] = this;
UserListByUID[this->uid] = this;
}
void BotInfo::SetNewNick(const Anope::string &newnick)
{
UserListByNick.erase(this->nick);
@@ -154,7 +156,7 @@ void BotInfo::UnAssign(User *u, ChannelInfo *ci)
void BotInfo::Join(Channel *c, ChannelStatus *status)
{
if (Config->BSSmartJoin)
if (Config && ircdproto && Config->BSSmartJoin)
{
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = c->GetModeList(CMODE_BAN);
@@ -179,7 +181,8 @@ void BotInfo::Join(Channel *c, ChannelStatus *status)
}
c->JoinUser(this);
ircdproto->SendJoin(this, c, status);
if (ircdproto)
ircdproto->SendJoin(this, c, status);
FOREACH_MOD(I_OnBotJoin, OnBotJoin(c, this));
}
@@ -198,6 +201,91 @@ void BotInfo::Part(Channel *c, const Anope::string &reason)
void BotInfo::OnMessage(User *u, const Anope::string &message)
{
mod_run_cmd(this, u, NULL, message);
std::vector<Anope::string> params = BuildStringVector(message);
command_map::iterator it = this->commands.end();
unsigned count = 0;
for (unsigned max = params.size(); it == this->commands.end() && max > 0; --max)
{
Anope::string full_command;
for (unsigned i = 0; i < max; ++i)
full_command += " " + params[i];
full_command.erase(full_command.begin());
++count;
it = this->commands.find(full_command);
}
if (it == this->commands.end())
{
u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str());
return;
}
service_reference<Command> c(it->second);
if (!c)
{
u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str());
Log(this) << "Command " << it->first << " exists on me, but its service " << it->second << " was not found!";
return;
}
// Command requires registered users only
if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified())
{
u->SendMessage(this, NICK_IDENTIFY_REQUIRED);
Log(LOG_COMMAND, "denied", this) << "Access denied for unregistered user " << u->GetMask() << " with command " << c->name;
return;
}
for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
params.erase(params.begin());
while (c->MaxParams > 0 && params.size() > c->MaxParams)
{
params[c->MaxParams - 1] += " " + params[c->MaxParams];
params.erase(params.begin() + c->MaxParams);
}
CommandSource source;
source.u = u;
source.c = NULL;
source.owner = this;
source.service = this;
source.command = it->first;
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params));
if (MOD_RESULT == EVENT_STOP)
{
source.DoReply();
return;
}
if (params.size() < c->MinParams)
{
c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
source.DoReply();
return;
}
// If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
if (!c->permission.empty() && !u->HasCommand(c->permission))
{
u->SendMessage(this, ACCESS_DENIED);
Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << c->name;
source.DoReply();
return;
}
dynamic_reference<User> user_reference(u);
c->Execute(source, params);
if (user_reference)
{
FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
if (user_reference)
source.DoReply();
}
}