diff options
author | Attila Molnar <attilamolnar@hush.com> | 2015-05-19 23:10:21 +0200 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2015-05-19 23:10:21 +0200 |
commit | cd268bb2d5d1740233d150e2f3877f7f136d3512 (patch) | |
tree | 4d8d06072a0316f6ccf2ceb4d50763f4037bbe62 /src/coremods | |
parent | f3513de58a69cd396d1c108bb39bc0233e96049e (diff) | |
parent | c27122858bd8127112ad43caa3484fb2472f818f (diff) |
Merge branch 'master+movenames'
Diffstat (limited to 'src/coremods')
-rw-r--r-- | src/coremods/core_channel/cmd_names.cpp | 69 | ||||
-rw-r--r-- | src/coremods/core_channel/cmd_topic.cpp | 9 | ||||
-rw-r--r-- | src/coremods/core_channel/core_channel.cpp | 19 | ||||
-rw-r--r-- | src/coremods/core_channel/core_channel.h | 14 |
4 files changed, 106 insertions, 5 deletions
diff --git a/src/coremods/core_channel/cmd_names.cpp b/src/coremods/core_channel/cmd_names.cpp index 20faae774..3af99ed2b 100644 --- a/src/coremods/core_channel/cmd_names.cpp +++ b/src/coremods/core_channel/cmd_names.cpp @@ -24,6 +24,8 @@ CommandNames::CommandNames(Module* parent) : Command(parent, "NAMES", 0, 0) , secretmode(parent, "secret") + , privatemode(parent, "private") + , invisiblemode(parent, "invisible") { syntax = "{<channel>{,<channel>}}"; } @@ -51,10 +53,11 @@ CmdResult CommandNames::Handle (const std::vector<std::string>& 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; } } @@ -62,3 +65,63 @@ CmdResult CommandNames::Handle (const std::vector<std::string>& parameters, User user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); return CMD_FAILURE; } + +void CommandNames::SendNames(User* user, Channel* chan, bool show_invisible) +{ + std::string list; + if (chan->IsModeSet(secretmode)) + list.push_back('@'); + else if (chan->IsModeSet(privatemode)) + list.push_back('*'); + else + list.push_back('='); + + list.push_back(' '); + list.append(chan->name).append(" :"); + std::string::size_type pos = list.size(); + + const size_t maxlen = ServerInstance->Config->Limits.MaxLine - 10 - ServerInstance->Config->ServerName.size() - user->nick.size(); + 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; + + if (list.size() + prefixlist.length() + nick.length() + 1 > maxlen) + { + // List overflowed into multiple numerics + user->WriteNumeric(RPL_NAMREPLY, list); + + // Erase all nicks, keep the constant part + list.erase(pos); + } + + list.append(prefixlist).append(nick).push_back(' '); + } + + // Only send the user list numeric if there is at least one user in it + if (list.size() != pos) + user->WriteNumeric(RPL_NAMREPLY, list); + + user->WriteNumeric(RPL_ENDOFNAMES, "%s :End of /NAMES list.", chan->name.c_str()); +} diff --git a/src/coremods/core_channel/cmd_topic.cpp b/src/coremods/core_channel/cmd_topic.cpp index ea723c024..8d65d764a 100644 --- a/src/coremods/core_channel/cmd_topic.cpp +++ b/src/coremods/core_channel/cmd_topic.cpp @@ -51,8 +51,7 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters, if (c->topic.length()) { - user->WriteNumeric(RPL_TOPIC, "%s :%s", c->name.c_str(), c->topic.c_str()); - user->WriteNumeric(RPL_TOPICTIME, "%s %s %lu", c->name.c_str(), c->setby.c_str(), (unsigned long)c->topicset); + Topic::ShowTopic(user, c); } else { @@ -84,3 +83,9 @@ CmdResult CommandTopic::HandleLocal(const std::vector<std::string>& parameters, c->SetTopic(user, t); return CMD_SUCCESS; } + +void Topic::ShowTopic(LocalUser* user, Channel* chan) +{ + user->WriteNumeric(RPL_TOPIC, "%s :%s", chan->name.c_str(), chan->topic.c_str()); + user->WriteNumeric(RPL_TOPICTIME, "%s %s %lu", chan->name.c_str(), chan->setby.c_str(), (unsigned long)chan->topicset); +} diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index 47f722e1e..99ad74d3d 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -34,6 +34,25 @@ class CoreModChannel : public Module { } + void OnPostJoin(Membership* memb) CXX11_OVERRIDE + { + Channel* const chan = memb->chan; + LocalUser* const localuser = IS_LOCAL(memb->user); + if (localuser) + { + if (chan->topicset) + Topic::ShowTopic(localuser, chan); + + // Show all members of the channel, including invisible (+i) users + cmdnames.SendNames(localuser, chan, true); + } + } + + void Prioritize() CXX11_OVERRIDE + { + ServerInstance->Modules.SetPriority(this, I_OnPostJoin, PRIORITY_FIRST); + } + Version GetVersion() CXX11_OVERRIDE { return Version("Provides the INVITE, JOIN, KICK, NAMES, and TOPIC commands", VF_VENDOR|VF_CORE); diff --git a/src/coremods/core_channel/core_channel.h b/src/coremods/core_channel/core_channel.h index d3adbc9c9..755f876f6 100644 --- a/src/coremods/core_channel/core_channel.h +++ b/src/coremods/core_channel/core_channel.h @@ -21,6 +21,11 @@ #include "inspircd.h" +namespace Topic +{ + void ShowTopic(LocalUser* user, Channel* chan); +} + /** Handle /INVITE. */ class CommandInvite : public Command @@ -81,6 +86,8 @@ class CommandTopic : public SplitCommand class CommandNames : public Command { ChanModeReference secretmode; + ChanModeReference privatemode; + UserModeReference invisiblemode; public: /** Constructor for names. @@ -93,6 +100,13 @@ class CommandNames : public Command * @return A value from CmdResult to indicate command success or failure. */ CmdResult Handle(const std::vector<std::string>& parameters, User *user); + + /** Spool the NAMES list for a given channel to the given user + * @param user User to spool the NAMES list to + * @param chan Channel whose nicklist to send + * @param show_invisible True to show invisible (+i) members to the user, false to omit them from the list + */ + void SendNames(User* user, Channel* chan, bool show_invisible); }; /** Handle /KICK. |