X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcoremods%2Fcore_channel%2Fcmd_names.cpp;h=21fe43ccab69e5414c06ca4fbefa0cb54b765479;hb=dcd3438011d59aa4de4df64abf06bca1cbf36859;hp=20faae7744bcd73d488cd35e23bd8841cea1abba;hpb=f62654a6859998f9d63eb22702c572d5ebcff15c;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/coremods/core_channel/cmd_names.cpp b/src/coremods/core_channel/cmd_names.cpp index 20faae774..21fe43cca 100644 --- a/src/coremods/core_channel/cmd_names.cpp +++ b/src/coremods/core_channel/cmd_names.cpp @@ -22,21 +22,23 @@ #include "core_channel.h" CommandNames::CommandNames(Module* parent) - : Command(parent, "NAMES", 0, 0) + : SplitCommand(parent, "NAMES", 0, 0) , secretmode(parent, "secret") + , privatemode(parent, "private") + , invisiblemode(parent, "invisible") { syntax = "{{,}}"; } /** Handle /NAMES */ -CmdResult CommandNames::Handle (const std::vector& parameters, User *user) +CmdResult CommandNames::HandleLocal(const std::vector& parameters, LocalUser* user) { Channel* c; if (!parameters.size()) { - user->WriteNumeric(RPL_ENDOFNAMES, "* :End of /NAMES list."); + user->WriteNumeric(RPL_ENDOFNAMES, '*', "End of /NAMES list."); return CMD_SUCCESS; } @@ -51,14 +53,62 @@ CmdResult CommandNames::Handle (const std::vector& parameters, User // - the user doing the /NAMES is inside the channel // - the user doing the /NAMES has the channels/auspex privilege - bool has_user = c->HasUser(user); - if ((!c->IsModeSet(secretmode)) || (has_user) || (user->HasPrivPermission("channels/auspex"))) + // If the user is inside the channel or has privs, instruct SendNames() to show invisible (+i) members + bool show_invisible = ((c->HasUser(user)) || (user->HasPrivPermission("channels/auspex"))); + if ((show_invisible) || (!c->IsModeSet(secretmode))) { - c->UserList(user, has_user); + SendNames(user, c, show_invisible); return CMD_SUCCESS; } } - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + user->WriteNumeric(Numerics::NoSuchNick(parameters[0])); return CMD_FAILURE; } + +void CommandNames::SendNames(LocalUser* user, Channel* chan, bool show_invisible) +{ + Numeric::Builder<' '> reply(user, RPL_NAMREPLY, false, chan->name.size() + 3); + Numeric::Numeric& numeric = reply.GetNumeric(); + if (chan->IsModeSet(secretmode)) + numeric.push(std::string(1, '@')); + else if (chan->IsModeSet(privatemode)) + numeric.push(std::string(1, '*')); + else + numeric.push(std::string(1, '=')); + + numeric.push(chan->name); + numeric.push(std::string()); + + std::string prefixlist; + std::string nick; + const Channel::MemberMap& members = chan->GetUsers(); + for (Channel::MemberMap::const_iterator i = members.begin(); i != members.end(); ++i) + { + if ((!show_invisible) && (i->first->IsModeSet(invisiblemode))) + { + // Member is invisible and we are not supposed to show them + continue; + } + + Membership* const memb = i->second; + + prefixlist.clear(); + char prefix = memb->GetPrefixChar(); + if (prefix) + prefixlist.push_back(prefix); + nick = i->first->nick; + + ModResult res; + FIRST_MOD_RESULT(OnNamesListItem, res, (user, memb, prefixlist, nick)); + + // See if a module wants us to exclude this user from NAMES + if (res == MOD_RES_DENY) + continue; + + reply.Add(prefixlist, nick); + } + + reply.Flush(); + user->WriteNumeric(RPL_ENDOFNAMES, chan->name, "End of /NAMES list."); +}