diff options
Diffstat (limited to 'modules/help.cpp')
-rw-r--r-- | modules/help.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/modules/help.cpp b/modules/help.cpp new file mode 100644 index 000000000..8b8542fdf --- /dev/null +++ b/modules/help.cpp @@ -0,0 +1,199 @@ +/* Core functions + * + * (C) 2003-2024 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" + +class CommandHelp final + : public Command +{ + static const unsigned help_wrap_len = 40; + + static CommandGroup *FindGroup(const Anope::string &name) + { + for (auto &gr : Config->CommandGroups) + { + if (gr.name == name) + return &gr; + } + + return NULL; + } + +public: + CommandHelp(Module *creator) : Command(creator, "generic/help", 0) + { + this->SetDesc(_("Displays this list and give information about commands")); + this->AllowUnregistered(true); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + EventReturn MOD_RESULT; + FOREACH_RESULT(OnPreHelp, MOD_RESULT, (source, params)); + if (MOD_RESULT == EVENT_STOP) + return; + + Anope::string source_command = source.command; + const BotInfo *bi = source.service; + const CommandInfo::map &map = source.c ? Config->Fantasy : bi->commands; + bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), + hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); + + if (params.empty() || params[0].equals_ci("ALL")) + { + bool all = !params.empty() && params[0].equals_ci("ALL"); + typedef std::map<CommandGroup *, std::list<Anope::string> > GroupInfo; + GroupInfo groups; + + if (all) + source.Reply(_("All available commands for \002%s\002:"), source.service->nick.c_str()); + + for (const auto &[c_name, info] : map) + { + if (info.hide) + continue; + + // Smaller command exists + Anope::string cmd; + spacesepstream(c_name).GetToken(cmd, 0); + if (cmd != c_name && map.count(cmd)) + continue; + + ServiceReference<Command> c("Command", info.name); + if (!c) + continue; + + if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) + continue; + + if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) + continue; + + if (!info.group.empty() && !all) + { + CommandGroup *gr = FindGroup(info.group); + if (gr != NULL) + { + groups[gr].push_back(c_name); + continue; + } + } + + source.command = c_name; + c->OnServHelp(source); + + } + + for (auto &[gr, cmds] : groups) + { + source.Reply(" "); + source.Reply("%s", gr->description.c_str()); + + Anope::string buf; + for (const auto &c_name : cmds) + { + buf += ", " + c_name; + + if (buf.length() > help_wrap_len) + { + source.Reply(" %s", buf.substr(2).c_str()); + buf.clear(); + } + } + if (buf.length() > 2) + { + source.Reply(" %s", buf.substr(2).c_str()); + buf.clear(); + } + } + if (!groups.empty()) + { + source.Reply(" "); + source.Reply(_("Use the \002%s ALL\002 command to list all commands and their descriptions."), source_command.c_str()); + } + } + else + { + bool helped = false; + for (unsigned max = params.size(); max > 0; --max) + { + Anope::string full_command; + for (unsigned i = 0; i < max; ++i) + full_command += " " + params[i]; + full_command.erase(full_command.begin()); + + CommandInfo::map::const_iterator it = map.find(full_command); + if (it == map.end()) + continue; + + const CommandInfo &info = it->second; + + ServiceReference<Command> c("Command", info.name); + if (!c) + continue; + + if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) + continue; + + // Allow unregistered users to see help for commands that they explicitly request help for + + const Anope::string &subcommand = params.size() > max ? params[max] : ""; + source.command = it->first; + if (!c->OnHelp(source, subcommand)) + continue; + + helped = true; + + /* Inform the user what permission is required to use the command */ + if (!info.permission.empty()) + { + source.Reply(" "); + source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), info.permission.c_str()); + } + if (!c->AllowUnregistered() && !source.nc) + { + if (info.permission.empty()) + source.Reply(" "); + source.Reply( _("You need to be identified to use this command.")); + } + /* User doesn't have the proper permission to use this command */ + else if (!info.permission.empty() && !source.HasCommand(info.permission)) + { + source.Reply(_("You cannot use this command.")); + } + + break; + } + + if (!helped) + source.Reply(_("No help available for \002%s\002."), params[0].c_str()); + } + + FOREACH_MOD(OnPostHelp, (source, params)); + + return; + } +}; + +class Help final + : public Module +{ + CommandHelp commandhelp; + +public: + Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), + commandhelp(this) + { + + } +}; + +MODULE_INIT(Help) |