anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

help.cpp (5454B)

      1 /* Core functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #include "module.h"
     13 
     14 class CommandHelp : public Command
     15 {
     16 	static const unsigned help_wrap_len = 40;
     17 
     18 	static CommandGroup *FindGroup(const Anope::string &name)
     19 	{
     20 		for (unsigned i = 0; i < Config->CommandGroups.size(); ++i)
     21 		{
     22 			CommandGroup &gr = Config->CommandGroups[i];
     23 			if (gr.name == name)
     24 				return &gr;
     25 		}
     26 
     27 		return NULL;
     28 	}
     29 
     30  public:
     31 	CommandHelp(Module *creator) : Command(creator, "generic/help", 0)
     32 	{
     33 		this->SetDesc(_("Displays this list and give information about commands"));
     34 		this->AllowUnregistered(true);
     35 	}
     36 
     37 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
     38 	{
     39 		EventReturn MOD_RESULT;
     40 		FOREACH_RESULT(OnPreHelp, MOD_RESULT, (source, params));
     41 		if (MOD_RESULT == EVENT_STOP)
     42 			return;
     43 
     44 		Anope::string source_command = source.command;
     45 		const BotInfo *bi = source.service;
     46 		const CommandInfo::map &map = source.c ? Config->Fantasy : bi->commands;
     47 		bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
     48 		     hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
     49 
     50 		if (params.empty() || params[0].equals_ci("ALL"))
     51 		{
     52 			bool all = !params.empty() && params[0].equals_ci("ALL");
     53 			typedef std::map<CommandGroup *, std::list<Anope::string> > GroupInfo;
     54 			GroupInfo groups;
     55 
     56 			if (all)
     57 				source.Reply(_("All available commands for \002%s\002:"), source.service->nick.c_str());
     58 
     59 			for (CommandInfo::map::const_iterator it = map.begin(), it_end = map.end(); it != it_end; ++it)
     60 			{
     61 				const Anope::string &c_name = it->first;
     62 				const CommandInfo &info = it->second;
     63 
     64 				if (info.hide)
     65 					continue;
     66 
     67 				// Smaller command exists
     68 				Anope::string cmd;
     69 				spacesepstream(c_name).GetToken(cmd, 0);
     70 				if (cmd != it->first && map.count(cmd))
     71 					continue;
     72 
     73 				ServiceReference<Command> c("Command", info.name);
     74 				if (!c)
     75 					continue;
     76 
     77 				if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
     78 					continue;
     79 
     80 				if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
     81 					continue;
     82 
     83 				if (!info.group.empty() && !all)
     84 				{
     85 					CommandGroup *gr = FindGroup(info.group);
     86 					if (gr != NULL)
     87 					{
     88 						groups[gr].push_back(c_name);
     89 						continue;
     90 					}
     91 				}
     92 
     93 				source.command = c_name;
     94 				c->OnServHelp(source);
     95 
     96 			}
     97 
     98 			for (GroupInfo::iterator it = groups.begin(), it_end = groups.end(); it != it_end; ++it)
     99 			{
    100 				CommandGroup *gr = it->first;
    101 
    102 				source.Reply(" ");
    103 				source.Reply("%s", gr->description.c_str());
    104 
    105 				Anope::string buf;
    106 				for (std::list<Anope::string>::iterator it2 = it->second.begin(), it2_end = it->second.end(); it2 != it2_end; ++it2)
    107 				{
    108 					const Anope::string &c_name = *it2;
    109 
    110 					buf += ", " + c_name;
    111 
    112 					if (buf.length() > help_wrap_len)
    113 					{
    114 						source.Reply("  %s", buf.substr(2).c_str());
    115 						buf.clear();
    116 					}
    117 				}
    118 				if (buf.length() > 2)
    119 				{
    120 					source.Reply("  %s", buf.substr(2).c_str());
    121 					buf.clear();
    122 				}
    123 			}
    124 			if (!groups.empty())
    125 			{
    126 				source.Reply(" ");
    127 				source.Reply(_("Use the \002%s ALL\002 command to list all commands and their descriptions."), source_command.c_str());
    128 			}
    129 		}
    130 		else
    131 		{
    132 			bool helped = false;
    133 			for (unsigned max = params.size(); max > 0; --max)
    134 			{
    135 				Anope::string full_command;
    136 				for (unsigned i = 0; i < max; ++i)
    137 					full_command += " " + params[i];
    138 				full_command.erase(full_command.begin());
    139 
    140 				CommandInfo::map::const_iterator it = map.find(full_command);
    141 				if (it == map.end())
    142 					continue;
    143 
    144 				const CommandInfo &info = it->second;
    145 
    146 				ServiceReference<Command> c("Command", info.name);
    147 				if (!c)
    148 					continue;
    149 
    150 				if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
    151 					continue;
    152 
    153 				// Allow unregistered users to see help for commands that they explicitly request help for
    154 
    155 				const Anope::string &subcommand = params.size() > max ? params[max] : "";
    156 				source.command = it->first;
    157 				if (!c->OnHelp(source, subcommand))
    158 					continue;
    159 
    160 				helped = true;
    161 
    162 				/* Inform the user what permission is required to use the command */
    163 				if (!info.permission.empty())
    164 				{
    165 					source.Reply(" ");
    166 					source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), info.permission.c_str());
    167 				}
    168 				if (!c->AllowUnregistered() && !source.nc)
    169 				{
    170 					if (info.permission.empty())
    171 						source.Reply(" ");
    172 					source.Reply( _("You need to be identified to use this command."));
    173 				}
    174 				/* User doesn't have the proper permission to use this command */
    175 				else if (!info.permission.empty() && !source.HasCommand(info.permission))
    176 				{
    177 					source.Reply(_("You cannot use this command."));
    178 				}
    179 
    180 				break;
    181 			}
    182 
    183 			if (helped == false)
    184 				source.Reply(_("No help available for \002%s\002."), params[0].c_str());
    185 		}
    186 
    187 		FOREACH_MOD(OnPostHelp, (source, params));
    188 
    189 		return;
    190 	}
    191 };
    192 
    193 class Help : public Module
    194 {
    195 	CommandHelp commandhelp;
    196 
    197  public:
    198 	Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    199 		commandhelp(this)
    200 	{
    201 
    202 	}
    203 };
    204 
    205 MODULE_INIT(Help)