summaryrefslogtreecommitdiff
path: root/src/command.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/command.cpp')
-rw-r--r--src/command.cpp86
1 files changed, 62 insertions, 24 deletions
diff --git a/src/command.cpp b/src/command.cpp
index 9b5212879..e242b50fb 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -17,8 +17,19 @@
#include "regchannel.h"
#include "channels.h"
-CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r),
- c(NULL), service(bi)
+void CommandReply::SendMessage(CommandSource &source, const Anope::string &msg)
+{
+ SendMessage(source.service, msg);
+}
+
+CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi, const Anope::string &m)
+ : nick(n)
+ , u(user)
+ , nc(core)
+ , ip(user ? user->ip.str() : "")
+ , reply(r)
+ , service(bi)
+ , msgid(m)
{
}
@@ -114,7 +125,7 @@ void CommandSource::Reply(const Anope::string &message)
sepstream sep(translated_message, '\n', true);
Anope::string tok;
while (sep.GetToken(tok))
- this->reply->SendMessage(this->service, tok);
+ this->reply->SendMessage(*this, tok);
}
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o)
@@ -122,10 +133,6 @@ Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t
allow_unregistered = require_user = false;
}
-Command::~Command()
-{
-}
-
void Command::SetDesc(const Anope::string &d)
{
this->desc = d;
@@ -195,11 +202,53 @@ void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcomma
source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
}
+namespace
+{
+ void HandleUnknownCommand(CommandSource& source, const Anope::string &message)
+ {
+ // Try to find a similar command.
+ size_t distance = Config->GetBlock("options")->Get<size_t>("didyoumeandifference", "4");
+ Anope::string similar;
+ auto umessage = message.upper();
+ for (const auto &[command, info] : source.service->commands)
+ {
+ if (info.hide || command == message)
+ continue; // Don't suggest a hidden alias or a missing command.
+
+ size_t dist = Anope::Distance(umessage, command);
+ if (dist < distance)
+ {
+ distance = dist;
+ similar = command;
+ }
+ }
+
+ bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
+ if (has_help && similar.empty())
+ {
+ source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(),
+ Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ }
+ else if (has_help)
+ {
+ source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002? \"%s%s HELP\" for help."),
+ message.c_str(), similar.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ }
+ else if (similar.empty())
+ {
+ source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002?"), message.c_str(), similar.c_str());
+ }
+ else
+ {
+ source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ }
+ }
+}
+
void Command::Run(CommandSource &source, const Anope::string &message)
{
std::vector<Anope::string> params;
spacesepstream(message).GetTokens(params);
- bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
CommandInfo::map::const_iterator it = source.service->commands.end();
unsigned count = 0;
@@ -216,10 +265,7 @@ void Command::Run(CommandSource &source, const Anope::string &message)
if (it == source.service->commands.end())
{
- if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
- else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ HandleUnknownCommand(source, message);
return;
}
@@ -227,10 +273,7 @@ void Command::Run(CommandSource &source, const Anope::string &message)
ServiceReference<Command> c("Command", info.name);
if (!c)
{
- if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
- else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ HandleUnknownCommand(source, message);
Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
return;
}
@@ -288,19 +331,14 @@ void Command::Run(CommandSource &source, const Anope::string &cmdname, const Com
FOREACH_MOD(OnPostCommand, (source, this, params));
}
-bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo* &bot, Anope::string &name)
+bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo *&bot, Anope::string &name)
{
bot = NULL;
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (const auto &[_, bi] : *BotListByNick)
{
- BotInfo *bi = it->second;
-
- for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit)
+ for (const auto &[c_name, info] : bi->commands)
{
- const Anope::string &c_name = cit->first;
- const CommandInfo &info = cit->second;
-
if (info.name != command_service)
continue;