From 1c1645096f953aa06b5809be6b302015b5bc73d6 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Thu, 29 Feb 2024 21:56:14 +0000 Subject: If a user runs an invalid command try to suggest a valid one. --- src/command.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) (limited to 'src/command.cpp') diff --git a/src/command.cpp b/src/command.cpp index c9372c40f..e7912864c 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -201,11 +201,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("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 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; @@ -222,10 +264,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; } @@ -233,10 +272,7 @@ void Command::Run(CommandSource &source, const Anope::string &message) ServiceReference 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; } -- cgit