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