help.cpp

Go to the documentation of this file.
00001 /* Core functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  */
00011 
00012 /*************************************************************************/
00013 
00014 #include "module.h"
00015 
00016 class CommandHelp : public Command
00017 {
00018         static const unsigned help_wrap_len = 40;
00019 
00020         static CommandGroup *FindGroup(const Anope::string &name)
00021         {
00022                 for (unsigned i = 0; i < Config->CommandGroups.size(); ++i)
00023                 {
00024                         CommandGroup &gr = Config->CommandGroups[i];
00025                         if (gr.name == name)
00026                                 return &gr;
00027                 }
00028 
00029                 return NULL;
00030         }
00031 
00032  public:
00033         CommandHelp(Module *creator) : Command(creator, "generic/help", 0)
00034         {
00035                 this->SetDesc(_("Displays this list and give information about commands"));
00036                 this->AllowUnregistered(true);
00037         }
00038 
00039         void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
00040         {
00041                 EventReturn MOD_RESULT;
00042                 FOREACH_RESULT(I_OnPreHelp, OnPreHelp(source, params));
00043                 if (MOD_RESULT == EVENT_STOP)
00044                         return;
00045         
00046                 Anope::string source_command = source.command;
00047                 const BotInfo *bi = source.service;
00048                 const CommandInfo::map &map = source.c ? Config->Fantasy : bi->commands;
00049 
00050                 if (params.empty() || params[0].equals_ci("ALL"))
00051                 {
00052                         bool all = !params.empty() && params[0].equals_ci("ALL");
00053                         typedef std::map<CommandGroup *, std::list<Anope::string> > GroupInfo;
00054                         GroupInfo groups;
00055 
00056                         if (all)
00057                                 source.Reply(_("All available commands for \002%s\002:"), source.service->nick.c_str());
00058 
00059                         for (CommandInfo::map::const_iterator it = map.begin(), it_end = map.end(); it != it_end; ++it)
00060                         {
00061                                 const Anope::string &c_name = it->first;
00062                                 const CommandInfo &info = it->second;
00063 
00064                                 if (info.hide)
00065                                         continue;
00066 
00067                                 // Smaller command exists
00068                                 Anope::string cmd;
00069                                 spacesepstream(c_name).GetToken(cmd, 0);
00070                                 if (cmd != it->first && map.count(cmd))
00071                                         continue;
00072 
00073                                 ServiceReference<Command> c("Command", info.name);
00074                                 if (!c)
00075                                         continue;
00076                                 else if (!Config->HidePrivilegedCommands)
00077                                         ; // Always show with HidePrivilegedCommands disabled
00078                                 else if (!c->AllowUnregistered() && !source.GetAccount())
00079                                         continue;
00080                                 else if (!info.permission.empty() && !source.HasCommand(info.permission))
00081                                         continue;
00082 
00083                                 if (!info.group.empty() && !all)
00084                                 {
00085                                         CommandGroup *gr = FindGroup(info.group);
00086                                         if (gr != NULL)
00087                                         {
00088                                                 groups[gr].push_back(c_name);
00089                                                 continue;
00090                                         }
00091                                 }
00092 
00093                                 source.command = c_name;
00094                                 c->OnServHelp(source);
00095 
00096                         }
00097 
00098                         for (GroupInfo::iterator it = groups.begin(), it_end = groups.end(); it != it_end; ++it)
00099                         {
00100                                 CommandGroup *gr = it->first;
00101 
00102                                 source.Reply(" ");
00103                                 source.Reply("%s", gr->description.c_str());
00104 
00105                                 Anope::string buf;
00106                                 for (std::list<Anope::string>::iterator it2 = it->second.begin(), it2_end = it->second.end(); it2 != it2_end; ++it2)
00107                                 {
00108                                         const Anope::string &c_name = *it2;
00109 
00110                                         buf += ", " + c_name;
00111 
00112                                         if (buf.length() > help_wrap_len)
00113                                         {
00114                                                 source.Reply("  %s", buf.substr(2).c_str());
00115                                                 buf.clear();
00116                                         }
00117                                 }
00118                                 if (buf.length() > 2)
00119                                 {
00120                                         source.Reply("  %s", buf.substr(2).c_str());
00121                                         buf.clear();
00122                                 }
00123                         }
00124                         if (!groups.empty())
00125                         {
00126                                 source.Reply(" ");
00127                                 source.Reply(_("Use the \002%s ALL\002 command to list all commands and their descriptions."), source_command.c_str());
00128                         }
00129                 }
00130                 else
00131                 {
00132                         bool helped = false;
00133                         for (unsigned max = params.size(); max > 0; --max)
00134                         {
00135                                 Anope::string full_command;
00136                                 for (unsigned i = 0; i < max; ++i)
00137                                         full_command += " " + params[i];
00138                                 full_command.erase(full_command.begin());
00139 
00140                                 CommandInfo::map::const_iterator it = map.find(full_command);
00141                                 if (it == map.end())
00142                                         continue;
00143 
00144                                 const CommandInfo &info = it->second;
00145 
00146                                 ServiceReference<Command> c("Command", info.name);
00147                                 if (!c)
00148                                         continue;
00149                                 else if (!Config->HidePrivilegedCommands)
00150                                         ; // Always show with HidePrivilegedCommands disabled
00151                                 else if (!info.permission.empty() && !source.HasCommand(info.permission))
00152                                         continue;
00153                                 
00154                                 // Allow unregistered users to see help for commands that they explicitly request help for
00155 
00156                                 const Anope::string &subcommand = params.size() > max ? params[max] : "";
00157                                 source.command = full_command;
00158                                 if (!c->OnHelp(source, subcommand))
00159                                         continue;
00160 
00161                                 helped = true;
00162 
00163                                 /* Inform the user what permission is required to use the command */
00164                                 if (!info.permission.empty())
00165                                 {
00166                                         source.Reply(" ");
00167                                         source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), info.permission.c_str());
00168                                 }
00169                                 if (!c->AllowUnregistered() && !source.nc)
00170                                 {
00171                                         if (info.permission.empty())
00172                                                 source.Reply(" ");
00173                                         source.Reply( _("You need to be identified to use this command."));
00174                                 }
00175                                 /* User doesn't have the proper permission to use this command */
00176                                 else if (!info.permission.empty() && !source.HasCommand(info.permission))
00177                                 {
00178                                         source.Reply(_("You cannot use this command."));
00179                                 }
00180 
00181                                 break;
00182                         }
00183 
00184                         if (helped == false)
00185                                 source.Reply(_("No help available for \002%s\002."), params[0].c_str());
00186                 }
00187         
00188                 FOREACH_MOD(I_OnPostHelp, OnPostHelp(source, params));
00189 
00190                 return;
00191         }
00192 };
00193 
00194 class Help : public Module
00195 {
00196         CommandHelp commandhelp;
00197 
00198  public:
00199         Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00200                 commandhelp(this)
00201         {
00202                 this->SetAuthor("Anope");
00203 
00204         }
00205 };
00206 
00207 MODULE_INIT(Help)