]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_lusers.cpp
Clean up the protocol interface
[user/henk/code/inspircd.git] / src / commands / cmd_lusers.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "inspircd.h"
22
23 struct LusersCounters
24 {
25         unsigned int max_local;
26         unsigned int max_global;
27         unsigned int invisible;
28
29         LusersCounters(unsigned int inv)
30                 : max_local(ServerInstance->Users->LocalUserCount())
31                 , max_global(ServerInstance->Users->RegisteredUserCount())
32                 , invisible(inv)
33         {
34         }
35
36         inline void UpdateMaxUsers()
37         {
38                 unsigned int current = ServerInstance->Users->LocalUserCount();
39                 if (current > max_local)
40                         max_local = current;
41
42                 current = ServerInstance->Users->RegisteredUserCount();
43                 if (current > max_global)
44                         max_global = current;
45         }
46 };
47
48 /** Handle /LUSERS. These command handlers can be reloaded by the core,
49  * and handle basic RFC1459 commands. Commands within modules work
50  * the same way, however, they can be fully unloaded, where these
51  * may not.
52  */
53 class CommandLusers : public Command
54 {
55         LusersCounters& counters;
56  public:
57         /** Constructor for lusers.
58          */
59         CommandLusers(Module* parent, LusersCounters& Counters)
60                 : Command(parent,"LUSERS",0,0), counters(Counters)
61         { }
62         /** Handle command.
63          * @param parameters The parameters to the comamnd
64          * @param pcnt The number of parameters passed to teh command
65          * @param user The user issuing the command
66          * @return A value from CmdResult to indicate command success or failure.
67          */
68         CmdResult Handle(const std::vector<std::string>& parameters, User *user);
69 };
70
71 /** Handle /LUSERS
72  */
73 CmdResult CommandLusers::Handle (const std::vector<std::string>&, User *user)
74 {
75         unsigned int n_users = ServerInstance->Users->RegisteredUserCount();
76         ProtocolInterface::ServerList serverlist;
77         ServerInstance->PI->GetServerList(serverlist);
78         unsigned int n_serv = serverlist.size();
79         unsigned int n_local_servs = 0;
80         for (ProtocolInterface::ServerList::const_iterator i = serverlist.begin(); i != serverlist.end(); ++i)
81         {
82                 if (i->parentname == ServerInstance->Config->ServerName)
83                         n_local_servs++;
84         }
85         // fix for default GetServerList not returning us
86         if (!n_serv)
87                 n_serv = 1;
88
89         counters.UpdateMaxUsers();
90
91         user->WriteNumeric(251, "%s :There are %d users and %d invisible on %d servers",user->nick.c_str(),
92                         n_users - counters.invisible, counters.invisible, n_serv);
93
94         if (ServerInstance->Users->OperCount())
95                 user->WriteNumeric(252, "%s %d :operator(s) online",user->nick.c_str(),ServerInstance->Users->OperCount());
96
97         if (ServerInstance->Users->UnregisteredUserCount())
98                 user->WriteNumeric(253, "%s %d :unknown connections",user->nick.c_str(),ServerInstance->Users->UnregisteredUserCount());
99
100         user->WriteNumeric(254, "%s %ld :channels formed",user->nick.c_str(),ServerInstance->ChannelCount());
101         user->WriteNumeric(255, "%s :I have %d clients and %d servers",user->nick.c_str(),ServerInstance->Users->LocalUserCount(),n_local_servs);
102         user->WriteNumeric(265, "%s :Current Local Users: %d  Max: %d", user->nick.c_str(), ServerInstance->Users->LocalUserCount(), counters.max_local);
103         user->WriteNumeric(266, "%s :Current Global Users: %d  Max: %d", user->nick.c_str(), n_users, counters.max_global);
104
105         return CMD_SUCCESS;
106 }
107
108 class InvisibleWatcher : public ModeWatcher
109 {
110         unsigned int& invisible;
111 public:
112         InvisibleWatcher(Module* mod, unsigned int& Invisible)
113                 : ModeWatcher(mod, "invisible", MODETYPE_USER), invisible(Invisible)
114         {
115         }
116
117         void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding)
118         {
119                 if (dest->registered != REG_ALL)
120                         return;
121
122                 if (adding)
123                         invisible++;
124                 else
125                         invisible--;
126         }
127 };
128
129 class ModuleLusers : public Module
130 {
131         UserModeReference invisiblemode;
132         LusersCounters counters;
133         CommandLusers cmd;
134         InvisibleWatcher mw;
135
136         unsigned int CountInvisible()
137         {
138                 unsigned int c = 0;
139                 for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); ++i)
140                 {
141                         User* u = i->second;
142                         if (u->IsModeSet(invisiblemode))
143                                 c++;
144                 }
145                 return c;
146         }
147
148  public:
149         ModuleLusers()
150                 : invisiblemode(this, "invisible")
151                 , counters(CountInvisible())
152                 , cmd(this, counters)
153                 , mw(this, counters.invisible)
154         {
155         }
156
157         void init()
158         {
159                 ServerInstance->Modules->AddService(cmd);
160                 ServerInstance->Modes->AddModeWatcher(&mw);
161         }
162
163         void OnPostConnect(User* user)
164         {
165                 counters.UpdateMaxUsers();
166                 if (user->IsModeSet(invisiblemode))
167                         counters.invisible++;
168         }
169
170         void OnUserQuit(User* user, const std::string& message, const std::string& oper_message)
171         {
172                 if (user->IsModeSet(invisiblemode))
173                         counters.invisible--;
174         }
175
176         ~ModuleLusers()
177         {
178                 ServerInstance->Modes->DelModeWatcher(&mw);
179         }
180
181         Version GetVersion()
182         {
183                 return Version("LUSERS", VF_VENDOR | VF_CORE);
184         }
185 };
186
187 MODULE_INIT(ModuleLusers)